From 6dc264e7e5868e6084d574f5029bdd87b0fe2f15 Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 10 Jan 2023 19:28:02 +0100 Subject: [PATCH 001/424] OpenXR - Workaround for disfunctional depth buffer allocation --- Common/VR/VRBase.h | 3 +- Common/VR/VRFramebuffer.cpp | 88 +++++++++++++++---------------------- 2 files changed, 36 insertions(+), 55 deletions(-) diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index 25efb1b712..7ed105c846 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -62,9 +62,8 @@ typedef struct { uint32_t TextureSwapChainLength; uint32_t TextureSwapChainIndex; ovrSwapChain ColorSwapChain; - ovrSwapChain DepthSwapChain; void* ColorSwapChainImage; - void* DepthSwapChainImage; + unsigned int* GLDepthBuffers; unsigned int* GLFrameBuffers; VkFramebuffer* VKFrameBuffers; VkImageView* VKColorImages; diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 792dd5a879..95dfb85961 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -40,11 +40,8 @@ void ovrFramebuffer_Clear(ovrFramebuffer* frameBuffer) { frameBuffer->ColorSwapChain.Width = 0; frameBuffer->ColorSwapChain.Height = 0; frameBuffer->ColorSwapChainImage = NULL; - frameBuffer->DepthSwapChain.Handle = XR_NULL_HANDLE; - frameBuffer->DepthSwapChain.Width = 0; - frameBuffer->DepthSwapChain.Height = 0; - frameBuffer->DepthSwapChainImage = NULL; + frameBuffer->GLDepthBuffers = NULL; frameBuffer->GLFrameBuffers = NULL; frameBuffer->Acquired = false; } @@ -111,8 +108,6 @@ static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBu frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; - frameBuffer->DepthSwapChain.Width = swapChainCreateInfo.width; - frameBuffer->DepthSwapChain.Height = swapChainCreateInfo.height; // Create the color swapchain. swapChainCreateInfo.format = GL_SRGB8_ALPHA8; @@ -121,45 +116,55 @@ static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBu OXR(xrEnumerateSwapchainImages(frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); frameBuffer->ColorSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); - // Create the depth swapchain. - swapChainCreateInfo.format = GL_DEPTH24_STENCIL8; - swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->DepthSwapChain.Handle)); - frameBuffer->DepthSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageOpenGLESKHR)); - // Populate the swapchain image array. for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { ((XrSwapchainImageOpenGLESKHR*)frameBuffer->ColorSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; ((XrSwapchainImageOpenGLESKHR*)frameBuffer->ColorSwapChainImage)[i].next = NULL; - ((XrSwapchainImageOpenGLESKHR*)frameBuffer->DepthSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_ES_KHR; - ((XrSwapchainImageOpenGLESKHR*)frameBuffer->DepthSwapChainImage)[i].next = NULL; } OXR(xrEnumerateSwapchainImages( frameBuffer->ColorSwapChain.Handle, frameBuffer->TextureSwapChainLength, &frameBuffer->TextureSwapChainLength, (XrSwapchainImageBaseHeader*)frameBuffer->ColorSwapChainImage)); - OXR(xrEnumerateSwapchainImages( - frameBuffer->DepthSwapChain.Handle, - frameBuffer->TextureSwapChainLength, - &frameBuffer->TextureSwapChainLength, - (XrSwapchainImageBaseHeader*)frameBuffer->DepthSwapChainImage)); + frameBuffer->GLDepthBuffers = (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); frameBuffer->GLFrameBuffers = (GLuint*)malloc(frameBuffer->TextureSwapChainLength * sizeof(GLuint)); for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { + + // Create color texture. const GLuint colorTexture = ((XrSwapchainImageOpenGLESKHR*)frameBuffer->ColorSwapChainImage)[i].image; - const GLuint depthTexture = ((XrSwapchainImageOpenGLESKHR*)frameBuffer->DepthSwapChainImage)[i].image; + GLenum colorTextureTarget = multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D; + GL(glBindTexture(colorTextureTarget, colorTexture)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); + GL(glTexParameteri(colorTextureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); + GL(glBindTexture(colorTextureTarget, 0)); + + // Create depth buffer. + if (multiview) { + GL(glGenTextures(1, &frameBuffer->GLDepthBuffers[i])); + GL(glBindTexture(GL_TEXTURE_2D_ARRAY, frameBuffer->GLDepthBuffers[i])); + GL(glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_DEPTH24_STENCIL8, width, height, 2)); + GL(glBindTexture(GL_TEXTURE_2D_ARRAY, 0)); + } else { + GL(glGenRenderbuffers(1, &frameBuffer->GLDepthBuffers[i])); + GL(glBindRenderbuffer(GL_RENDERBUFFER, frameBuffer->GLDepthBuffers[i])); + GL(glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height)); + GL(glBindRenderbuffer(GL_RENDERBUFFER, 0)); + } + // Create the frame buffer. GL(glGenFramebuffers(1, &frameBuffer->GLFrameBuffers[i])); GL(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer->GLFrameBuffers[i])); if (multiview) { - GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, depthTexture, 0, 0, 2)); - GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthTexture, 0, 0, 2)); + GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, frameBuffer->GLDepthBuffers[i], 0, 0, 2)); + GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, frameBuffer->GLDepthBuffers[i], 0, 0, 2)); GL(glFramebufferTextureMultiviewOVR(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorTexture, 0, 0, 2)); } else { - GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0)); - GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0)); + GL(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, frameBuffer->GLDepthBuffers[i])); + GL(glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, frameBuffer->GLDepthBuffers[i])); GL(glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0)); } GL(GLenum renderFramebufferStatus = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER)); @@ -196,8 +201,6 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; - frameBuffer->DepthSwapChain.Width = swapChainCreateInfo.width; - frameBuffer->DepthSwapChain.Height = swapChainCreateInfo.height; // Create the color swapchain. swapChainCreateInfo.format = VK_FORMAT_R8G8B8A8_UNORM; @@ -206,29 +209,16 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff OXR(xrEnumerateSwapchainImages(frameBuffer->ColorSwapChain.Handle, 0, &frameBuffer->TextureSwapChainLength, NULL)); frameBuffer->ColorSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageVulkanKHR)); - // Create the depth swapchain. - swapChainCreateInfo.format = VK_FORMAT_D24_UNORM_S8_UINT; - swapChainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - OXR(xrCreateSwapchain(session, &swapChainCreateInfo, &frameBuffer->DepthSwapChain.Handle)); - frameBuffer->DepthSwapChainImage = malloc(frameBuffer->TextureSwapChainLength * sizeof(XrSwapchainImageVulkanKHR)); - // Populate the swapchain image array. for (uint32_t i = 0; i < frameBuffer->TextureSwapChainLength; i++) { ((XrSwapchainImageVulkanKHR*)frameBuffer->ColorSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; ((XrSwapchainImageVulkanKHR*)frameBuffer->ColorSwapChainImage)[i].next = NULL; - ((XrSwapchainImageVulkanKHR*)frameBuffer->DepthSwapChainImage)[i].type = XR_TYPE_SWAPCHAIN_IMAGE_VULKAN_KHR; - ((XrSwapchainImageVulkanKHR*)frameBuffer->DepthSwapChainImage)[i].next = NULL; } OXR(xrEnumerateSwapchainImages( frameBuffer->ColorSwapChain.Handle, frameBuffer->TextureSwapChainLength, &frameBuffer->TextureSwapChainLength, (XrSwapchainImageBaseHeader*)frameBuffer->ColorSwapChainImage)); - OXR(xrEnumerateSwapchainImages( - frameBuffer->DepthSwapChain.Handle, - frameBuffer->TextureSwapChainLength, - &frameBuffer->TextureSwapChainLength, - (XrSwapchainImageBaseHeader*)frameBuffer->DepthSwapChainImage)); frameBuffer->VKColorImages = new VkImageView[frameBuffer->TextureSwapChainLength]; frameBuffer->VKDepthImages = new VkImageView[frameBuffer->TextureSwapChainLength]; @@ -253,14 +243,6 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff return false; } - createInfo.image = ((XrSwapchainImageVulkanKHR*)frameBuffer->DepthSwapChainImage)[i].image; - createInfo.format = VK_FORMAT_D24_UNORM_S8_UINT; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - if (vkCreateImageView(frameBuffer->VKContext->device, &createInfo, nullptr, &frameBuffer->VKDepthImages[i]) != VK_SUCCESS) { - ALOGE("failed to create depth image view!"); - return false; - } - // Create the frame buffer. VkImageView attachments[] = { frameBuffer->VKColorImages[i], frameBuffer->VKDepthImages[i] }; VkFramebufferCreateInfo framebufferInfo{}; @@ -294,14 +276,14 @@ void ovrFramebuffer_Destroy(ovrFramebuffer* frameBuffer) { delete[] frameBuffer->VKFrameBuffers; } else { #if XR_USE_GRAPHICS_API_OPENGL_ES || XR_USE_GRAPHICS_API_OPENGL + GL(glDeleteRenderbuffers(frameBuffer->TextureSwapChainLength, frameBuffer->GLDepthBuffers)); GL(glDeleteFramebuffers(frameBuffer->TextureSwapChainLength, frameBuffer->GLFrameBuffers)); + free(frameBuffer->GLDepthBuffers); free(frameBuffer->GLFrameBuffers); #endif } OXR(xrDestroySwapchain(frameBuffer->ColorSwapChain.Handle)); - OXR(xrDestroySwapchain(frameBuffer->DepthSwapChain.Handle)); free(frameBuffer->ColorSwapChainImage); - free(frameBuffer->DepthSwapChainImage); ovrFramebuffer_Clear(frameBuffer); } @@ -356,10 +338,6 @@ void ovrFramebuffer_Acquire(ovrFramebuffer* frameBuffer) { void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { if (frameBuffer->Acquired) { - XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; - OXR(xrReleaseSwapchainImage(frameBuffer->ColorSwapChain.Handle, &releaseInfo)); - frameBuffer->Acquired = false; - // Clear the alpha channel, other way OpenXR would not transfer the framebuffer fully if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { //TODO:implement @@ -371,6 +349,10 @@ void ovrFramebuffer_Release(ovrFramebuffer* frameBuffer) { GL(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE)); #endif } + + XrSwapchainImageReleaseInfo releaseInfo = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO, NULL}; + OXR(xrReleaseSwapchainImage(frameBuffer->ColorSwapChain.Handle, &releaseInfo)); + frameBuffer->Acquired = false; } } From f9531af20068db841fa84ad67c02489c6b4b2aa5 Mon Sep 17 00:00:00 2001 From: Jaakko Saarikko <74954275+styxnix@users.noreply.github.com> Date: Mon, 30 Jan 2023 00:26:55 +0200 Subject: [PATCH 002/424] Update fi_FI.ini Initial commit --- assets/lang/fi_FI.ini | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index c05f596811..6617bdcd15 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1,18 +1,18 @@ [Audio] Alternate speed volume = Alternate speed volume -Audio backend = Audio backend (restart req.) -Audio Error = Audio Error -AudioBufferingForBluetooth = Bluetooth-friendly buffer (slower) -Auto = Auto -Device = Device -Disabled = Disabled -DSound (compatible) = DSound (compatible) +Audio backend = Äänen taustajärjestelmä (restart req.) +Audio Error = Äänivirhe +AudioBufferingForBluetooth = Bluetooth-ystävällinen puskuri (hitaampi) +Auto = Automaattinen +Device = Laite +Disabled = Poistettu käytöstä +DSound (compatible) = DSound (yhteensopiva) Enable Sound = Ota äänet käyttöön -Global volume = Global volume -Microphone = Microphone -Microphone Device = Microphone device -Mute = Mute -Reverb volume = Reverb volume +Global volume = Yleinen äänenvoimakkuus +Microphone = Mikrofoni +Microphone Device = Mikrofonin laite +Mute = Mykistä +Reverb volume = Kaikuefektin voimakkuus Use new audio devices automatically = Use new audio devices automatically Use global volume = Use global volume WASAPI (fast) = WASAPI (fast) @@ -623,12 +623,12 @@ www.ppsspp.org = www.ppsspp.org [MainSettings] Audio = Ääni -Controls = Kontrollit +Controls = Ohjaus Graphics = Grafiikka -Networking = Networking -Search = Search +Networking = Verkko +Search = Haku System = Järjestelmä -Tools = Tools +Tools = Työkalut [MappableControls] Alt speed 1 = Alt speed 1 @@ -810,7 +810,7 @@ WLAN Channel = WLAN channel You're in Offline Mode, go to lobby or online hall = You're in offline mode, go to lobby or online hall [Pause] -Cheats = Cheats +Cheats = Huijaukset Continue = Jatka Create Game Config = Create game config Delete Game Config = Delete game config From 50f3ff04cfd7fe1818894de411643975470cfa09 Mon Sep 17 00:00:00 2001 From: Jaakko Saarikko <74954275+styxnix@users.noreply.github.com> Date: Tue, 31 Jan 2023 12:00:25 +0200 Subject: [PATCH 003/424] Update fi_FI.ini --- assets/lang/fi_FI.ini | 124 +++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 62 deletions(-) diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 6617bdcd15..0518d65c61 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1,6 +1,6 @@ [Audio] -Alternate speed volume = Alternate speed volume -Audio backend = Äänen taustajärjestelmä (restart req.) +Alternate speed volume = Vaihtoehtoisen nopeuden äänenvoimakkuus +Audio backend = Äänen taustajärjestelmä (uudelleenkäynnistä) Audio Error = Äänivirhe AudioBufferingForBluetooth = Bluetooth-ystävällinen puskuri (hitaampi) Auto = Automaattinen @@ -13,9 +13,9 @@ Microphone = Mikrofoni Microphone Device = Mikrofonin laite Mute = Mykistä Reverb volume = Kaikuefektin voimakkuus -Use new audio devices automatically = Use new audio devices automatically -Use global volume = Use global volume -WASAPI (fast) = WASAPI (fast) +Use new audio devices automatically = Käytä uusia äänilaitteita automaattisesti +Use global volume = Käytä yleistä äänenvoimakkuutta +WASAPI (fast) = WASAPI (nopea) [Controls] Analog Binding = Analog Binding @@ -438,56 +438,56 @@ Use UI background = Use UI background %, 0:unlimited = %, 0 = unlimited (supersampling) = (supersampling) (upscaling) = (upscaling) -1x PSP = 1× PSP -2x = 2× -2x PSP = 2× PSP -3x = 3× -3x PSP = 3× PSP -4x = 4× -4x PSP = 4× PSP -5x = 5× -5x PSP = 5× PSP -6x PSP = 6× PSP -7x PSP = 7× PSP -8x = 8× -8x PSP = 8× PSP -9x PSP = 9× PSP -10x PSP = 10× PSP -16x = 16× -Aggressive = Aggressive +1x PSP = 1x PSP +2x = 2x +2x PSP = 2x PSP +3x = 3x +3x PSP = 3x PSP +4x = 4x +4x PSP = 4x PSP +5x = 5x +5x PSP = 5x PSP +6x PSP = 6x PSP +7x PSP = 7x PSP +8x = 8x +8x PSP = 8x PSP +9x PSP = 9x PSP +10x PSP = 10x PSP +16x = 16x +Aggressive = Aggressiivinen Alternative Speed = Vaihtoehtoinen nopeus -Alternative Speed 2 = Alternative speed 2 (in %, 0 = unlimited) +Alternative Speed 2 = Vaihtoehtoinen nopeus 2 (prosenteissa, 0 = rajoittamaton) Anisotropic Filtering = Anisotrooppisen suodatus Antialiasing (MSAA) = Antialiasing (MSAA) -Aspect Ratio = Aspect Ratio -Auto = Auto +Aspect Ratio = Kuvasuhde +Auto = Automaattinen Auto (1:1) = Auto (1:1) -Auto (same as Rendering) = Auto (same as rendering resolution) -Auto FrameSkip = Auto frameskip +Auto (same as Rendering) = Automaattinen (sama kuin renderöinti resoluutio) +Auto FrameSkip = Automaattinen ruudunohitus Auto Max Quality = Auto Max Quality -Auto Scaling = Auto scaling -Backend = Backend -Balanced = Balanced +Auto Scaling = Automaattinen skaalaus +Backend = Taustarajapinta +Balanced = Tasapainotettu Bicubic = Bicubic Both = Molemmat Buffer graphics commands (faster, input lag) = Buffer graphics commands (faster, input lag) BufferedRenderingRequired = Warning: This game requires "rendering mode" to be set to "buffered". -Camera = Camera -Camera Device = Camera device +Camera = Kamera +Camera Device = Kameralaite Cardboard Screen Size = Screen size (in % of the viewport) Cardboard Screen X Shift = X shift (in % of the blank space) Cardboard Screen Y Shift = Y shift (in % of the blank space) Cardboard VR Settings = Google Cardboard VR settings Cheats = Cheats CPU Core = CPU core -Debugging = Debugging +Debugging = Vian etsintä DefaultCPUClockRequired = Warning: This game requires the CPU clock to be set to default. Deposterize = Deposterize Deposterize Tip = Fixes visual banding glitches in upscaled textures -Device = Device +Device = Laite Direct3D 9 = Direct3D 9 Direct3D 11 = Direct3D 11 -Disabled = Disabled +Disabled = Poistettu käytöstä Display Layout && Effects = Display layout && effects Display Resolution (HW scaler) = Display resolution (HW scaler) Enable Cardboard VR = Enable Cardboard VR @@ -522,12 +522,12 @@ Must Restart = You must restart PPSSPP for this change to take effect. Native device resolution = Native device resolution Nearest = Lähin No buffer = No buffer -Show Battery % = Show Battery % -Show Speed = Show Speed +Show Battery % = Näytä akku % +Show Speed = Näytä nopeus Skip Buffer Effects = Skip buffer effects None = Ei mitään Number of Frames = Number of frames -Off = Off +Off = Pois OpenGL = OpenGL Overlay Information = Overlay information Partial Stretch = Partial stretch @@ -553,7 +553,7 @@ Speed = Nopeus Speed Hacks = Speed Hacks (can cause rendering errors!) Stereo display shader = Stereo display shader Stereo rendering = Stereo rendering -Stretch = Stretch +Stretch = Venytä Texture Filter = Tekstuurisuodatin Texture Filtering = Tekstuurin suodatus Texture Scaling = Tekstuurin skaalaus @@ -567,21 +567,21 @@ Upscale Type = Upscale type UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter Use all displays = Use all displays Vertex Cache = Verteksivälimuisti -VertexCache Tip = Faster, but may cause temporary flicker +VertexCache Tip = Nopeampi, mutta voi välillä aiheuttaa vilkkumista VSync = VSync Vulkan = Vulkan -Window Size = Window size +Window Size = Ikkunan koko xBRZ = xBRZ [InstallZip] -Delete ZIP file = Delete ZIP file -Install = Install -Install game from ZIP file? = Install game from ZIP file? -Install textures from ZIP file? = Install textures from ZIP file? -Installed! = Installed! -Texture pack doesn't support install = Texture pack doesn't support install -Zip archive corrupt = ZIP archive corrupt -Zip file does not contain PSP software = ZIP file does not contain PSP software +Delete ZIP file = Poista ZIP-tiedosto +Install = Asenna +Install game from ZIP file? = Asenna peli ZIP-tiedostosta? +Install textures from ZIP file? = Asenna tekstuureja ZIP-tiedostosta? +Installed! = Asenettu! +Texture pack doesn't support install = Tekstuuripakkaus ei tue asennusta +Zip archive corrupt = ZIP-arkisto on korruptoitunut +Zip file does not contain PSP software = ZIP-tiedosto ei sisällä PSP-ohjelmistoa [KeyMapping] Autoconfigure = Auto configure @@ -597,26 +597,26 @@ Show PSP = Show PSP You can press ESC to cancel. = You can press Esc to cancel. [MainMenu] -Browse = Browse... -Buy PPSSPP Gold = Buy PPSSPP Gold -Choose folder = Choose folder +Browse = Selaa... +Buy PPSSPP Gold = Osta PPSSPP Gold +Choose folder = Valitse kansio Credits = Tekijät -PPSSPP Homebrew Store = PPSSPP Homebrew Store +PPSSPP Homebrew Store = PPSSPP kotitekoisten pelien kauppa Exit = Sulje Game Settings = Peliasetukset Games = Pelit -Give PPSSPP permission to access storage = Give PPSSPP permission to access storage +Give PPSSPP permission to access storage = Anna PPSSPP lupa käyttää tallenustilaa Homebrew & Demos = Kotitekoiset ja demot -How to get games = Miten saadaan pelejä -How to get homebrew & demos = How can I get homebrew && demos? +How to get games = Miten pelejä saadaan +How to get homebrew & demos = Kuinka saada kotitekoisia pelejä ja demoja Load = Lataa... -Loading... = Loading... -PinPath = Pin -PPSSPP can't load games or save right now = PPSSPP can't load games or save right now +Loading... = Ladataan... +PinPath = PinPath +PPSSPP can't load games or save right now = PPSSPP ei voi ladata pelejä tai tallentaa juuri nyt Recent = Äskettäin -SavesAreTemporary = PPSSPP is saving in temporary storage -SavesAreTemporaryGuidance = Extract PPSSPP somewhere to save permanently -SavesAreTemporaryIgnore = Ignore warning +SavesAreTemporary = PPSSPP tallentaa tilapäiseen tallennustilaan +SavesAreTemporaryGuidance = Pura PPSSPP jonnekkin tallentaaksesi pysyvästi +SavesAreTemporaryIgnore = Jätä varoitus huomiotta UnpinPath = Unpin UseBrowseOrLoad = Use Browse to choose a folder, or Load to choose a file. www.ppsspp.org = www.ppsspp.org From 40d5867edd460a11a5209a6ad8e78c171eaab2eb Mon Sep 17 00:00:00 2001 From: Jaakko Saarikko <74954275+styxnix@users.noreply.github.com> Date: Wed, 1 Feb 2023 08:33:08 +0200 Subject: [PATCH 004/424] Update fi_FI.ini --- assets/lang/fi_FI.ini | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 0518d65c61..151e2ad794 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -111,12 +111,12 @@ X = X Y = Y [CwCheats] -Cheats = Cheats -Edit Cheat File = Edit cheat file -Enable/Disable All = Enable/Disable all Cheats -Import Cheats = Import from cheat.db -Options = Options -Refresh Rate = Refresh rate +Cheats = Huijaukset +Edit Cheat File = Muokkaa huijaus tiedostoa +Enable/Disable All = Ota/Poista käytöstä kaikki huijaukset +Import Cheats = Tuo huijauksia +Options = Asetukset +Refresh Rate = Ruudunpäivitysnopeus [DesktopUI] # If your language does not show well with the default font, you can use Font to specify a different one. @@ -338,11 +338,11 @@ Snap = Snap Space = Space SSID = SSID Submit = Submit -Supported = Supported +Supported = Tuettu There is no data = Dataa ei ole. Toggle All = Toggle all Toggle List = Toggle list -Unsupported = Unsupported +Unsupported = Ei tuettu When you save, it will load on a PSP, but not an older PPSSPP = When you save, it will load on a PSP, but not an older PPSSPP When you save, it will not work on outdated PSP Firmware anymore = When you save, it will not work on outdated PSP firmware anymore Yes = Kyllä @@ -406,29 +406,29 @@ ZIP file detected (Require UnRAR) = file is compressed (ZIP).\nPlease decompress ZIP file detected (Require WINRAR) = file is compressed (ZIP).\nPlease decompress first (try WinRAR). [Game] -Asia = Asia -Calculate CRC = Calculate CRC +Asia = Aasia +Calculate CRC = Laske CRC ConfirmDelete = Delete Create Game Config = Create game config Create Shortcut = Create shortcut -Delete Game = Delete game -Delete Game Config = Delete game config -Delete Save Data = Delete savedata -Europe = Europe -Game = Game -Game Settings = Game settings -Homebrew = Homebrew +Delete Game = Poista peli +Delete Game Config = Poista pelin asetus +Delete Save Data = Poista tallennustiedot +Europe = Eurooppa +Game = Peli +Game Settings = Peliasetukset +Homebrew = Kotitekoinenpeli Hong Kong = Hong Kong InstallData = Data install -Japan = Japan +Japan = Japani Korea = Korea MB = MB -One moment please... = One moment please... -Play = Play -Remove From Recent = Remove from "Recent" -SaveData = Savedata +One moment please... = Pieni hetki... +Play = Pelaa +Remove From Recent = Poista "äskettäin" listalta... +SaveData = Tallennustieto Setting Background = Setting background -Show In Folder = Show in folder +Show In Folder = Näytä kansiossa USA = USA Use UI background = Use UI background @@ -478,7 +478,7 @@ Cardboard Screen Size = Screen size (in % of the viewport) Cardboard Screen X Shift = X shift (in % of the blank space) Cardboard Screen Y Shift = Y shift (in % of the blank space) Cardboard VR Settings = Google Cardboard VR settings -Cheats = Cheats +Cheats = Huijaukset CPU Core = CPU core Debugging = Vian etsintä DefaultCPUClockRequired = Warning: This game requires the CPU clock to be set to default. From a715462b0fa7459cf48fc881bd4f119d16010ed2 Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Wed, 1 Feb 2023 09:23:41 -0800 Subject: [PATCH 005/424] Update to latest armips, with build fix for libretro mac --- ext/armips | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/armips b/ext/armips index 6719edebaa..a0e86643eb 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 6719edebaae03330ee5441d9b28280672edf00d5 +Subproject commit a0e86643eb0e2248f5b0742d60fee214aee0084e From 7e31ee1e2b26d30c9c923c24972c572ab54e2951 Mon Sep 17 00:00:00 2001 From: Serena Date: Wed, 1 Feb 2023 20:53:15 +0300 Subject: [PATCH 006/424] Remove SubtleVolume --- CMakeLists.txt | 2 - ios/SubtleVolume.h | 84 --------------- ios/SubtleVolume.mm | 238 ------------------------------------------ ios/ViewController.mm | 41 -------- 4 files changed, 365 deletions(-) delete mode 100644 ios/SubtleVolume.h delete mode 100644 ios/SubtleVolume.mm diff --git a/CMakeLists.txt b/CMakeLists.txt index fa8e4914fb..8c0b8bb601 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1145,8 +1145,6 @@ elseif(IOS) ios/PPSSPPUIApplication.mm ios/SmartKeyboardMap.cpp ios/SmartKeyboardMap.hpp - ios/SubtleVolume.h - ios/SubtleVolume.mm ios/iCade/iCadeReaderView.h ios/iCade/iCadeReaderView.m ios/iCade/iCadeState.h diff --git a/ios/SubtleVolume.h b/ios/SubtleVolume.h deleted file mode 100644 index 4b2ac8bb74..0000000000 --- a/ios/SubtleVolume.h +++ /dev/null @@ -1,84 +0,0 @@ -// -// SubtleVolume.h -// subtleVolumeObjC -// -// Created by iMokhles on 24/03/16. -// Copyright © 2016 iMokhles. All rights reserved. -// - -#import -#import -#import - -/** - The style of the volume indicator - - Plain: A plain bar - - RoundedLine: A plain bar with rounded corners - - Dashes: A bar divided in dashes - - Dots: A bar composed by a line of dots - */ -typedef NS_ENUM(NSInteger, SubtleVolumeStyle) { - SubtleVolumeStylePlain, - SubtleVolumeStyleRoundedLine, - SubtleVolumeStyleDashes, - SubtleVolumeStyleDots -}; - - -/** - The entry and exit animation of the volume indicator - - None: The indicator is always visible - - SlideDown: The indicator fades in/out and slides from/to the top into position - - FadeIn: The indicator fades in and out - */ -typedef NS_ENUM(NSInteger, SubtleVolumeAnimation) { - SubtleVolumeAnimationNone, - SubtleVolumeAnimationSlideDown, - SubtleVolumeAnimationFadeIn -}; - -@class SubtleVolume; -/** - Delegate protocol fo `SubtleVolume`. - Notifies the delegate when a change is about to happen (before the entry animation) - and when a change occurred (and the exit animation is complete) - */ -@protocol SubtleVolumeDelegate -/** - The volume is about to change. This is fired before performing any entry animation - - parameter subtleVolume: The current instance of `SubtleVolume` - - parameter value: The value of the volume (between 0 an 1.0) - */ -- (void)subtleVolume:(SubtleVolume *)volumeView willChange:(CGFloat)value; -/** - The volume did change. This is fired after the exit animation is done - - parameter subtleVolume: The current instance of `SubtleVolume` - - parameter value: The value of the volume (between 0 an 1.0) - */ -- (void)subtleVolume:(SubtleVolume *)volumeView didChange:(CGFloat)value; - -@end - -/** - Replace the system volume popup with a more subtle way to display the volume - when the user changes it with the volume rocker. - */ -@interface SubtleVolume : UIView -/** - The style of the volume indicator - */ -@property (nonatomic, assign) SubtleVolumeStyle style; -/** - The entry and exit animation of the indicator. The animation is triggered by the volume - If the animation is set to `SubtleVolumeAnimationNone`, the volume indicator is always visible - */ -@property (nonatomic, assign) SubtleVolumeAnimation animation; -@property (nonatomic, strong) UIColor *barBackgroundColor; -@property (nonatomic, strong) UIColor *barTintColor; -@property (nonatomic, assign) id delegate; -@property (nonatomic, assign) BOOL animatedByDefault; -@property (nonatomic, assign) CGFloat padding; - -- (instancetype)initWithStyle:(SubtleVolumeStyle)style; -- (instancetype)initWithStyle:(SubtleVolumeStyle)style frame:(CGRect)frame; -@end diff --git a/ios/SubtleVolume.mm b/ios/SubtleVolume.mm deleted file mode 100644 index 57296b738e..0000000000 --- a/ios/SubtleVolume.mm +++ /dev/null @@ -1,238 +0,0 @@ -// -// SubtleVolume.m -// subtleVolumeObjC -// -// Created by iMokhles on 24/03/16. -// Copyright © 2016 iMokhles. All rights reserved. -// - -#import "SubtleVolume.h" - -MPVolumeView *volume = [[MPVolumeView alloc] initWithFrame:CGRectZero]; -UIView *overlay = [[UIView alloc] init]; -CGFloat volumeLevel = 0; - -@interface SubtleVolume (){ - BOOL runningShowAnimation; - BOOL showing; - BOOL runningHideAnimation; - BOOL lastAnimated; -}; - -@property (nonatomic, strong) NSTimer *timer; - -- (void)timerComplete; -- (void)doHide:(BOOL)animated; -- (void)doShow:(BOOL)animated; -- (void)stopAnimations; - -@end - - -@implementation SubtleVolume - -- (instancetype)initWithStyle:(SubtleVolumeStyle)style frame:(CGRect)frame { - - self = [super initWithFrame:frame]; - - if (self) { - self.animatedByDefault = YES; - self.style = style; - [self setup]; - } - return self; -} - -- (instancetype)initWithStyle:(SubtleVolumeStyle)style { - return [self initWithStyle:style frame:CGRectZero]; -} - -- (instancetype)initWithCoder:(NSCoder *)aDecoder { - self = [super initWithCoder:aDecoder]; - if (self) { - [self setup]; - } - return self; -} - -- (instancetype)initWithFrame:(CGRect)frame { - - self = [super initWithFrame:frame]; - - if (self) { - [self setup]; - } - return self; -} - -- (instancetype)init { - self = nil; - NSAssert(false, @"To init this class please use the designated initializer: initWithStyle or initWithStyle:frame:"); - return nil; -} - -- (void)setup { - @try { - [[AVAudioSession sharedInstance] setActive:YES error:nil]; - } @catch (NSException *e) { - NSLog(@"Unable to initialize AVAudioSession"); - } - - volumeLevel = [[AVAudioSession sharedInstance] outputVolume]; - [[AVAudioSession sharedInstance] addObserver:self forKeyPath:@"outputVolume" options:NSKeyValueObservingOptionNew context:NULL]; - [volume setVolumeThumbImage:[[UIImage alloc] init] forState:UIControlStateNormal]; - [volume setUserInteractionEnabled:NO]; - [volume setAlpha:0.0001]; - [volume setShowsRouteButton:NO]; - self.alpha = 0.0001; - - [self addSubview:volume]; - - [self addSubview:overlay]; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - overlay.frame = CGRectMake( - self.padding, - self.padding, - (self.frame.size.width - (self.padding*2)) * volumeLevel, - self.frame.size.height - (self.padding*2) - ); - - self.backgroundColor = self.barBackgroundColor; - overlay.backgroundColor = self.barTintColor; - -} -- (void)updateVolume:(CGFloat)value animated:(BOOL)animated { - [self.delegate subtleVolume:self willChange:value]; - volumeLevel = value; - lastAnimated = animated; - [UIView animateWithDuration:(animated ? 0.1 : 0) animations:^{ - CGRect rectOverlayView = overlay.frame; - CGFloat overlyWidth = self.frame.size.width * volumeLevel; - rectOverlayView.size.width = overlyWidth; - overlay.frame = rectOverlayView; - }]; - - - if(self.timer) { - [self.timer invalidate]; - self.timer = nil; - } - - self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(timerComplete) userInfo:nil repeats:NO]; - [self doShow:animated]; - [self.delegate subtleVolume:self didChange:value]; -} - -- (void)timerComplete { - [self doHide:lastAnimated]; - self.timer = nil; -} - -- (void)doHide:(BOOL)animated { - if(!showing) { - return; - } - - if(runningHideAnimation && !animated) { - [self stopAnimations]; - } - - if(runningHideAnimation) { - return; - } - - if(animated) { - runningHideAnimation = YES; - [UIView animateWithDuration:0.333 animations:^{ - switch (self.animation) { - case SubtleVolumeAnimationNone: - break; - case SubtleVolumeAnimationFadeIn: - self.alpha = 0.0001; - break; - case SubtleVolumeAnimationSlideDown: - self.alpha = 0.0001; - self.transform = CGAffineTransformMakeTranslation(0, -self.frame.size.height); - break; - default: - break; - } - } completion:^(BOOL finished) { - showing = NO; - runningHideAnimation = NO; - }]; - } else { - showing = NO; - self.alpha = 0.0001; - if(self.animation == SubtleVolumeAnimationSlideDown) { - self.transform = CGAffineTransformMakeTranslation(0, -self.frame.size.height); - } - } -} - -- (void)doShow:(BOOL)animated { - if(showing) { - return; - } - - if(runningShowAnimation && !animated) { - [self stopAnimations]; - } - - if(runningShowAnimation) { - return; - } - - if(animated) { - // set up for first run, assuming the animation has changed - // between instantiation and first showing - if(self.animation == SubtleVolumeAnimationSlideDown) { - self.transform = CGAffineTransformMakeTranslation(0, -self.frame.size.height); - } - - runningShowAnimation = YES; - [UIView animateWithDuration:0.333 animations:^{ - switch (self.animation) { - case SubtleVolumeAnimationNone: - break; - case SubtleVolumeAnimationFadeIn: - self.alpha = 1; - break; - case SubtleVolumeAnimationSlideDown: - self.alpha = 1; - self.transform = CGAffineTransformIdentity; - break; - default: - break; - } - } completion:^(BOOL finished) { - showing = YES; - runningShowAnimation = NO; - }]; - } else { - showing = YES; - self.alpha = 1; - self.transform = CGAffineTransformIdentity; - } -} - -- (void)stopAnimations { - [self.layer removeAllAnimations]; - runningHideAnimation = NO; - runningShowAnimation = NO; -} - -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { - if ([keyPath isEqual:@"outputVolume"]) { - CGFloat value = [change[@"new"] floatValue]; - [self updateVolume:value animated:self.animatedByDefault]; - } else { - return; - } - -} - -@end diff --git a/ios/ViewController.mm b/ios/ViewController.mm index ed34f7391f..74852291d4 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -8,7 +8,6 @@ #import "AppDelegate.h" #import "ViewController.h" #import "DisplayManager.h" -#import "SubtleVolume.h" #import #include @@ -117,12 +116,6 @@ static LocationHelper *locationHelper; @end -@interface ViewController () { - SubtleVolume *volume; -} -@end - - @implementation ViewController -(id) init { @@ -157,11 +150,6 @@ static LocationHelper *locationHelper; return self; } -- (void)subtleVolume:(SubtleVolume *)volumeView willChange:(CGFloat)value { -} -- (void)subtleVolume:(SubtleVolume *)volumeView didChange:(CGFloat)value { -} - - (void)shareText:(NSString *)text { NSArray *items = @[text]; UIActivityViewController * viewController = [[UIActivityViewController alloc] initWithActivityItems:items applicationActivities:nil]; @@ -227,25 +215,6 @@ static LocationHelper *locationHelper; } } #endif - - CGFloat margin = 0; - CGFloat height = 16; - volume = [[SubtleVolume alloc] - initWithStyle:SubtleVolumeStylePlain - frame:CGRectMake( - margin, // X - 0, // Y - self.view.frame.size.width-(margin*2), // width - height // height - )]; - - volume.padding = 7; - volume.barTintColor = [UIColor blackColor]; - volume.barBackgroundColor = [UIColor whiteColor]; - volume.animation = SubtleVolumeAnimationSlideDown; - volume.delegate = self; - [self.view addSubview:volume]; - [self.view bringSubviewToFront:volume]; cameraHelper = [[CameraHelper alloc] init]; [cameraHelper setDelegate:self]; @@ -274,11 +243,6 @@ static LocationHelper *locationHelper; }); } -- (void)didReceiveMemoryWarning -{ - [super didReceiveMemoryWarning]; -} - - (void)appWillTerminate:(NSNotification *)notification { [self shutdown]; @@ -289,11 +253,6 @@ static LocationHelper *locationHelper; if (sharedViewController == nil) { return; } - - if(volume) { - [volume removeFromSuperview]; - volume = nil; - } Audio_Shutdown(); From 560d6f3b7ceca777df34a634f72c68eeb3c3bec9 Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Wed, 1 Feb 2023 12:19:02 -0800 Subject: [PATCH 007/424] Another libretro mac build fix --- ext/armips | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/armips b/ext/armips index a0e86643eb..7bd1ec93d4 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit a0e86643eb0e2248f5b0742d60fee214aee0084e +Subproject commit 7bd1ec93d4586985ba1ef420b43b5e620f68695e From 5ff6213b1a8965bdc26eb5c37a3f4991ccca765f Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Wed, 1 Feb 2023 13:36:14 -0800 Subject: [PATCH 008/424] Another (hopefully final) build fix for libretro mac x86_64 --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 84881497b9..d7bb40f1ee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -98,7 +98,7 @@ libretro-build-osx-x64: extends: - .libretro-osx-cmake-x86_64 - .core-defs - - .make-defs + - .cmake-defs # MacOS 64-bit libretro-build-osx-arm64: @@ -107,7 +107,7 @@ libretro-build-osx-arm64: extends: - .libretro-osx-cmake-arm64 - .core-defs - - .make-defs + - .cmake-defs ################################### CELLULAR ################################# # Android ARMv7a From 85401fd8b62c2da846cc6768675ee7be6ac64485 Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Wed, 1 Feb 2023 15:39:42 -0800 Subject: [PATCH 009/424] Hopefully last libretro mac build fix. --- CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c0b8bb601..105200b0ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -381,7 +381,11 @@ if(NOT MSVC) if(IOS) set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0") elseif(APPLE AND NOT CMAKE_CROSSCOMPILING) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") + if(LIBRETRO AND ARM64) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14") + else() + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.13") + endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -U__STRICT_ANSI__") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") elseif(NOT ANDROID) From 4aeb1ef703170a6437d6a3f2a412c8cba7ef6b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 1 Feb 2023 16:07:01 +0100 Subject: [PATCH 010/424] Better math, fix tilt calibration (was entirely broken) --- Core/Config.cpp | 4 +- Core/Config.h | 11 +++-- Core/TiltEventProcessor.cpp | 61 +++++++++++++++++++-------- Core/TiltEventProcessor.h | 15 +------ UI/NativeApp.cpp | 75 ++++++++------------------------- UI/TiltAnalogSettingsScreen.cpp | 24 ++++------- UI/TiltAnalogSettingsScreen.h | 6 +-- assets/lang/ar_AE.ini | 4 -- assets/lang/az_AZ.ini | 4 -- assets/lang/bg_BG.ini | 4 -- assets/lang/ca_ES.ini | 4 -- assets/lang/cz_CZ.ini | 4 -- assets/lang/da_DK.ini | 4 -- assets/lang/de_DE.ini | 4 -- assets/lang/dr_ID.ini | 4 -- assets/lang/en_US.ini | 4 -- assets/lang/es_ES.ini | 4 -- assets/lang/es_LA.ini | 4 -- assets/lang/fa_IR.ini | 4 -- assets/lang/fi_FI.ini | 4 -- assets/lang/fr_FR.ini | 4 -- assets/lang/gl_ES.ini | 4 -- assets/lang/gr_EL.ini | 4 -- assets/lang/he_IL.ini | 4 -- assets/lang/he_IL_invert.ini | 4 -- assets/lang/hr_HR.ini | 4 -- assets/lang/hu_HU.ini | 4 -- assets/lang/id_ID.ini | 4 -- assets/lang/it_IT.ini | 4 -- assets/lang/ja_JP.ini | 4 -- assets/lang/jv_ID.ini | 4 -- assets/lang/ko_KR.ini | 4 -- assets/lang/lo_LA.ini | 4 -- assets/lang/lt-LT.ini | 4 -- assets/lang/ms_MY.ini | 4 -- assets/lang/nl_NL.ini | 4 -- assets/lang/no_NO.ini | 4 -- assets/lang/pl_PL.ini | 4 -- assets/lang/pt_BR.ini | 4 -- assets/lang/pt_PT.ini | 4 -- assets/lang/ro_RO.ini | 4 -- assets/lang/ru_RU.ini | 4 -- assets/lang/sv_SE.ini | 4 -- assets/lang/tg_PH.ini | 4 -- assets/lang/th_TH.ini | 4 -- assets/lang/tr_TR.ini | 4 -- assets/lang/uk_UA.ini | 4 -- assets/lang/vi_VN.ini | 4 -- assets/lang/zh_CN.ini | 4 -- assets/lang/zh_TW.ini | 4 -- 50 files changed, 80 insertions(+), 288 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 8a6f4a9974..2884b4a04b 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -970,9 +970,7 @@ static const ConfigSetting controlSettings[] = { // ConfigSetting("KeyMapping", &g_Config.iMappingMap, 0), #ifdef MOBILE_DEVICE - ConfigSetting("TiltBaseX", &g_Config.fTiltBaseX, 0.0f, true, true), - ConfigSetting("TiltBaseY", &g_Config.fTiltBaseY, 0.0f, true, true), - ConfigSetting("TiltOrientation", &g_Config.iTiltOrientation, 0, true, true), + ConfigSetting("TiltBaseAngleY", &g_Config.fTiltBaseAngleY, 0.0f, true, true), ConfigSetting("InvertTiltX", &g_Config.bInvertTiltX, false, true, true), ConfigSetting("InvertTiltY", &g_Config.bInvertTiltY, true, true, true), ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 50, true, true), diff --git a/Core/Config.h b/Core/Config.h index c6f0f1673e..7b6422f037 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -285,12 +285,11 @@ public: bool bShowAudioDebug; bool bShowGpuProfile; - //Analog stick tilting - //the base x and y tilt. this inclination is treated as (0,0) and the tilt input - //considers this orientation to be equal to no movement of the analog stick. - float fTiltBaseX, fTiltBaseY; - int iTiltOrientation; - //whether the x axes and y axes should invert directions (left becomes right, top becomes bottom.) + // Analog stick tilting + // This is the held base angle, that we compute the tilt relative from. + float fTiltBaseAngleY; + // whether the x axes and y axes should invert directions (left becomes right, top becomes bottom.) + // TODO: Do we really need these? bool bInvertTiltX, bInvertTiltY; //the sensitivity of the tilt in the x direction int iTiltSensitivityX; diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 832f951e62..58620b6f83 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -2,6 +2,11 @@ #include +#include "Common/Math/math_util.h" +#include "Common/Math/lin/vec3.h" +#include "Common/Math/lin/matrix4x4.h" +#include "Common/Log.h" + #include "Core/Config.h" #include "Core/HLE/sceCtrl.h" #include "Core/TiltEventProcessor.h" @@ -12,6 +17,13 @@ static u32 tiltButtonsDown = 0; float rawTiltAnalogX; float rawTiltAnalogY; +// These functions generate tilt events given the current Tilt amount, +// and the deadzone radius. +void GenerateAnalogStickEvent(const Tilt &tilt); +void GenerateDPadEvent(const Tilt &tilt); +void GenerateActionButtonEvent(const Tilt &tilt); +void GenerateTriggerButtonEvent(const Tilt &tilt); + //deadzone is normalized - 0 to 1 //sensitivity controls how fast the deadzone reaches max value inline float tiltInputCurve(float x, float deadzone, float sensitivity) { @@ -40,23 +52,39 @@ inline float clamp(float f) { return f; } -Tilt NormalizeTilt(const Tilt &tilt) { - // Normalise the accelerometer manually per-platform, to 'g' -#if defined(__ANDROID__) - // Values are in metres per second. Divide by 9.8 to get 'g' value - float maxX = 9.8f, maxY = 9.8f; -#else - float maxX = 1.0f, maxY = 1.0f; -#endif +// Landscape liggande: +// x = 0 +// y = 0 +// z = 1 +// Landscape stående: +// x = 1 +// y = 0 +// z = 0 +// Landscape vänster kortsida: +// x = 0 +// y = -1 +// z = 0 +// Landscape liggande upp och ner +// x = 0 +// y = 0 +// z = -1 - return Tilt(tilt.x_ / maxX, tilt.y_ / maxY); -} -Tilt GenTilt(const Tilt &baseTilt, const Tilt ¤tTilt, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity) { - //first convert to the correct coordinate system - Tilt transformedTilt(currentTilt.x_ - baseTilt.x_, currentTilt.y_ - baseTilt.y_); +Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity) { + if (landscape) { + std::swap(x, y); + } - //invert x and y axes if needed + Lin::Vec3 down(x, y, z); + down.normalize(); + + float angleAroundX = atan2(down.z, down.y); + float yAngle = angleAroundX - calibrationAngle; + float xAngle = asinf(down.x); + + Tilt transformedTilt(xAngle, -yAngle); + + // invert x and y axes if requested. Can probably remove this. if (invertX) { transformedTilt.x_ *= -1.0f; } @@ -65,10 +93,7 @@ Tilt GenTilt(const Tilt &baseTilt, const Tilt ¤tTilt, bool invertX, bool i transformedTilt.y_ *= -1.0f; } - //next, normalize the tilt values - transformedTilt = NormalizeTilt(transformedTilt); - - //finally, dampen the tilt according to our curve. + // finally, dampen the tilt according to our curve. return dampTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); } diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index 8e613d00e9..0279188032 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -18,25 +18,14 @@ struct Tilt { float x_, y_; }; - - -Tilt NormalizeTilt(const Tilt &tilt); // generates a tilt in the correct coordinate system based on -// calibration. BaseTilt is the "base" / "zero" tilt. currentTilt is the -// sensor tilt reading at this moment. +// calibration. x, y, z is the current accelerometer reading. // NOTE- both base and current tilt *MUST BE NORMALIZED* by calling the NormalizeTilt() function. -Tilt GenTilt(const Tilt &baseTilt, const Tilt ¤tTilt, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity); +Tilt GenTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity); void TranslateTiltToInput(const Tilt &tilt); -// These functions generate tilt events given the current Tilt amount, -// and the deadzone radius. -void GenerateAnalogStickEvent(const Tilt &tilt); -void GenerateDPadEvent(const Tilt &tilt); -void GenerateActionButtonEvent(const Tilt &tilt); -void GenerateTriggerButtonEvent(const Tilt &tilt); - void ResetTiltEvents(); // Lets you preview the amount of tilt in TiltAnalogSettingsScreen. diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index bde7dbb129..8383347e28 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1372,78 +1372,35 @@ void NativeAxis(const AxisInput &axis) { using namespace TiltEventProcessor; - // only handle tilt events if tilt is enabled. + // only do special handling of tilt events if tilt is enabled. + HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; + screenManager->axis(axis); + if (g_Config.iTiltInputType == TILT_NULL) { - // if tilt events are disabled, then run it through the usual way. - HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; - screenManager->axis(axis); + // if tilt events are disabled, don't do anything special. return; } // create the base coordinate tilt system from the calibration data. - Tilt baseTilt; - baseTilt.x_ = g_Config.fTiltBaseX; - baseTilt.y_ = g_Config.fTiltBaseY; + float tiltBaseAngleY = g_Config.fTiltBaseAngleY; // figure out what the current tilt orientation is by checking the axis event // This is static, since we need to remember where we last were (in terms of orientation) - static Tilt currentTilt; - - // tilt on x or y? - static bool verticalTilt; - if (g_Config.iTiltOrientation == 0) - verticalTilt = false; - else if (g_Config.iTiltOrientation == 1) - verticalTilt = true; + static float tiltX; + static float tiltY; + static float tiltZ; // x and y are flipped if we are in landscape orientation. The events are // sent with respect to the portrait coordinate system, while we // take all events in landscape. // see [http://developer.android.com/guide/topics/sensors/sensors_overview.html] for details - bool portrait = dp_yres > dp_xres; + bool landscape = dp_yres < dp_xres; switch (axis.axisId) { //TODO: make this generic. - case JOYSTICK_AXIS_ACCELEROMETER_X: - if (verticalTilt) { - if (fabs(axis.value) < 0.8f && g_Config.iTiltOrientation == 2) // Auto tilt switch - verticalTilt = false; - else - return; // Tilt on Z instead - } - if (portrait) { - currentTilt.x_ = axis.value; - } else { - currentTilt.y_ = axis.value; - } - break; - - case JOYSTICK_AXIS_ACCELEROMETER_Y: - if (portrait) { - currentTilt.y_ = axis.value; - } else { - currentTilt.x_ = axis.value; - } - break; - - case JOYSTICK_AXIS_ACCELEROMETER_Z: - if (!verticalTilt) { - if (fabs(axis.value) < 0.8f && g_Config.iTiltOrientation == 2) // Auto tilt switch - verticalTilt = true; - else - return; // Tilt on X instead - } - if (portrait) { - currentTilt.x_ = -axis.value; - } else { - currentTilt.y_ = -axis.value; - } - break; - - default: - HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; - // Don't take over completely! - screenManager->axis(axis); - return; + case JOYSTICK_AXIS_ACCELEROMETER_X: tiltX = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Y: tiltY = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Z: tiltZ = axis.value; break; + default: break; } // Figure out the sensitivity of the tilt. (sensitivity is originally 0 - 100) @@ -1455,7 +1412,9 @@ void NativeAxis(const AxisInput &axis) { float ySensitivity = g_Config.iTiltSensitivityY / 50.0; // now transform out current tilt to the calibrated coordinate system - Tilt trueTilt = GenTilt(baseTilt, currentTilt, g_Config.bInvertTiltX, g_Config.bInvertTiltY, g_Config.fDeadzoneRadius, xSensitivity, ySensitivity); + Tilt trueTilt = GenTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, + g_Config.bInvertTiltX, g_Config.bInvertTiltY, g_Config.fDeadzoneRadius, + xSensitivity, ySensitivity); TranslateTiltToInput(trueTilt); } diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index d110d694dc..ef15ac60f3 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -20,7 +20,7 @@ #include "Core/TiltEventProcessor.h" #include "Common/Math/math_util.h" - +#include "Common/Log.h" #include "Common/Data/Text/I18n.h" #include "UI/JoystickHistoryView.h" @@ -56,8 +56,6 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new ItemHeader(co->T("Invert Axes"))); settings->Add(new CheckBox(&g_Config.bInvertTiltX, co->T("Invert Tilt along X axis"))); settings->Add(new CheckBox(&g_Config.bInvertTiltY, co->T("Invert Tilt along Y axis"))); - static const char* tiltMode[] = { "Screen aligned to ground", "Screen at right angle to ground", "Auto-switch" }; - settings->Add(new PopupMultiChoice(&g_Config.iTiltOrientation, co->T("Base tilt position"), tiltMode, 0, ARRAY_SIZE(tiltMode), co->GetName(), screenManager())); settings->Add(new ItemHeader(co->T("Sensitivity"))); //TODO: allow values greater than 100? I'm not sure if that's needed. @@ -73,30 +71,26 @@ void TiltAnalogSettingsScreen::CreateViews() { } void TiltAnalogSettingsScreen::axis(const AxisInput &axis) { - // TODO: This code should probably be moved to TiltEventProcessor. + UIDialogScreenWithGameBackground::axis(axis); if (axis.deviceId == DEVICE_ID_ACCELEROMETER) { - // Historically, we've had X and Y swapped, likely due to portrait vs landscape. - // TODO: We may want to configure this based on screen orientation. - if (axis.axisId == JOYSTICK_AXIS_ACCELEROMETER_X) { - currentTiltY_ = axis.value; - } - if (axis.axisId == JOYSTICK_AXIS_ACCELEROMETER_Y) { - currentTiltX_ = axis.value; + switch (axis.axisId) { + case JOYSTICK_AXIS_ACCELEROMETER_X: down_.x = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Y: down_.y = axis.value; break; + case JOYSTICK_AXIS_ACCELEROMETER_Z: down_.z = axis.value; break; } } } UI::EventReturn TiltAnalogSettingsScreen::OnCalibrate(UI::EventParams &e) { - g_Config.fTiltBaseX = currentTiltX_; - g_Config.fTiltBaseY = currentTiltY_; - + Lin::Vec3 down = down_.normalized(); + g_Config.fTiltBaseAngleY = atan2(down.z, down.x); + INFO_LOG(SCECTRL, "Setting base angle to %f from x=%f y=%f z=%f", g_Config.fTiltBaseAngleY, down.x, down.y, down.z); return UI::EVENT_DONE; } void TiltAnalogSettingsScreen::update() { UIDialogScreenWithGameBackground::update(); - tilt_->SetXY( Clamp(TiltEventProcessor::rawTiltAnalogX, -1.0f, 1.0f), Clamp(TiltEventProcessor::rawTiltAnalogY, -1.0f, 1.0f)); diff --git a/UI/TiltAnalogSettingsScreen.h b/UI/TiltAnalogSettingsScreen.h index 95bb335098..bcbc5ae446 100644 --- a/UI/TiltAnalogSettingsScreen.h +++ b/UI/TiltAnalogSettingsScreen.h @@ -17,6 +17,7 @@ #pragma once +#include "Common/Math/math_util.h" #include "Common/UI/View.h" #include "MiscScreens.h" @@ -33,8 +34,7 @@ public: private: UI::EventReturn OnCalibrate(UI::EventParams &e); - float currentTiltX_ = 0.0f; - float currentTiltY_ = 0.0f; - + + Lin::Vec3 down_{}; JoystickHistoryView *tilt_ = nullptr; }; diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 2ee38a6181..281bf8587a 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -36,8 +36,6 @@ Auto = ‎تلقائي Auto-centering analog stick = ‎تنصيف العصا التناظرية تلقائياً Auto-hide buttons after seconds = ‎إخفاء الأزرار تلقائياً بعد ثواني Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = ‎شفافية الأزرار @@ -92,8 +90,6 @@ PSP Action Buttons = ‎PSP أزرار الأفعال الخاصة بـ Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = ‎تدوير الشاشة seconds, 0 : off = ثواني, 0 = ‎مغلق Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 65b88e7084..fec91a6ffb 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Buttons opacity @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index eb76570192..a2aa0b3ee3 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -28,8 +28,6 @@ Auto = Автоматично Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Прозрачност на бутоните @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Въртене на екрана seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 0b8c81650f..87d27a7bde 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -28,8 +28,6 @@ Auto = Automàtic Auto-centering analog stick = Auto centrat de l'stick Auto-hide buttons after seconds = Ocultar els botons després de Auto-rotation speed = Velocitat auto rotació de l'stick -Auto-switch = Canvi automàtic -Base tilt position = Posició d'inclinació de la base Binds = Assignacions Button Binding = Assignat de botons Button Opacity = Transparència dels botons @@ -84,8 +82,6 @@ PSP Action Buttons = Botons d'acció Raw input = Raw input Repeat mode = Mode repetició Reset to defaults = Restaurar paràmetres -Screen aligned to ground = Pantalla alineada a terra -Screen at right angle to ground = Pantalla en angle recte amb el terra Screen Rotation = Rotació de pantalla seconds, 0 : off = segons, 0 = no Sensitivity (scale) = Sensibilitat (escala) diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 907d469304..9c6d952c6d 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Automatické vystředění analogové páčky Auto-hide buttons after seconds = Automaticky skrýt tlačítka po určité době Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Průhlednost tlačítek @@ -84,8 +82,6 @@ PSP Action Buttons = Tlačítka činností PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Otočení obrazovky seconds, 0 : off = vteřin, 0 = vypnuto Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 6343469448..d67e60a89d 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -28,8 +28,6 @@ Auto = Automatisk Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-gem knapper efter sekunder Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Knapgennemsigtighed @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action knapper Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Skærm rotation seconds, 0 : off = sekunder, 0 = slukket Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index 6584259094..eabb4dcb00 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -28,8 +28,6 @@ Auto = Automatisch Auto-centering analog stick = Analogstick automatisch zentrieren Auto-hide buttons after seconds = Steuerung ausblenden nach ... Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Verbindungen Button Binding = Button Verbindung Button Opacity = Tastentransparenz @@ -84,8 +82,6 @@ PSP Action Buttons = PSP Aktionstasten Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Bildschirmausrichtung seconds, 0 : off = Sekunden, 0 = Aus Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 975679fe6e..3b575b68f9 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Patembussi dikita tombolo'na @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 931b5f0b68..17a40bada2 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -52,8 +52,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Buttons opacity @@ -107,8 +105,6 @@ Portrait Reversed = Portrait reversed PSP Action Buttons = PSP action buttons Raw input = Raw input Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity = Sensitivity diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 682059183e..46a6183fbe 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = Cuando se pulsa el botón del limitador del stick Auto = Automática Auto-centering analog stick = Auto centrado del stick Auto-hide buttons after seconds = Ocultar botones después de (en segundos) -Auto-switch = Cambio automático -Base tilt position = Posición de inclinación de la base Binds = Asignaciones Button Binding = Asignado de botones Button Opacity = Transparencia de botones @@ -84,8 +82,6 @@ PSP Action Buttons = Botones de acción Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Restaurar ajustes -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotación de pantalla seconds, 0 : off = segundos, 0 = no Sensitivity (scale) = Sensibilidad (escala) diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 94a87e0f04..3899ac30a8 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = Cuando se presiona el botón del limitador del análogo Auto = Automática Auto-centering analog stick = Auto-centrado del análogo Auto-hide buttons after seconds = Ocultar botones después de (en segundos) -Auto-switch = Auto-switch -Base tilt position = Posición de inclinación de la base Binds = Asignaciones Button Binding = Vincular botones Button Opacity = Transparencia de botones @@ -84,8 +82,6 @@ PSP Action Buttons = Botones de acción PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Restaurar config. -Screen aligned to ground = Pantalla alineada al suelo -Screen at right angle to ground = Ángulo correcto de pantalla al suelo Screen Rotation = Rotación de pantalla seconds, 0 : off = Segundos, 0 = No Sensitivity (scale) = Sensibilidad (escala) diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 578b6fc90c..5d3db3b655 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -28,8 +28,6 @@ Auto = ‎اتوماتیک Auto-centering analog stick = ‎تنظیم مرکز آنالوگ به صورت خودکار Auto-hide buttons after seconds = ‎مخفی کردن دکمه ها به صورت خودکار (به ثانیه) Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = اتصال دکمه ها Button Opacity = ‎شفافیت دکمه ها @@ -84,8 +82,6 @@ PSP Action Buttons = ‎اکشن دکمه های Raw input = ورودی راو Repeat mode = حالت تکرار Reset to defaults = ریست کردن پیشفرض -Screen aligned to ground = صفحه نمایش به زمین متصل است -Screen at right angle to ground = صفحه نمایش در زاویه راست به زمین Screen Rotation = ‎چرخش صفحه seconds, 0 : off = ‎به ثانیه، 0 : خاموش Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 911b1650f8..d0e7f26ff0 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Painikkeiden peittävyys @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 1fb9c2fe3e..9a8391b161 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = Quand le bouton "Limiteur analogique" est pressé Auto = Automatique Auto-centering analog stick = Centrage automatique du stick analogique Auto-hide buttons after seconds = Cacher automatiquement les boutons après... -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Assignation Button Binding = Button Binding Button Opacity = Transparence des boutons @@ -84,8 +82,6 @@ PSP Action Buttons = Boutons d'action Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotation de l'écran seconds, 0 : off = secondes, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 5db6ca75cc..d14b52de31 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -28,8 +28,6 @@ Auto = Automática Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Transparencia de botóns @@ -84,8 +82,6 @@ PSP Action Buttons = Botóns de acción Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotación de pantalla seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index fbeccf3e2c..9f4bc92be6 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -28,8 +28,6 @@ Auto = Αυτόματο Auto-centering analog stick = Αυτόματος κεντρισμός αναλογικού μοχλού Auto-hide buttons after seconds = Αυτόματη απόκρυψη κουμπιών (χρονικό όριο) Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Διαφάνεια Κουμπιών @@ -84,8 +82,6 @@ PSP Action Buttons = Πλήκτρα δράσης PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Περιστροφή οθόνης seconds, 0 : off = δευτερόλεπτα, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index bc2e8217db..859e3e7e41 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = אטימות מקשים @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 333b64207b..d1ff09d9f6 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = םישקמ תומיטא @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index b5c6e09474..4d49e70992 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = Kada je analog limiter tipka pritisnuta Auto = Automatski Auto-centering analog stick = Auto-centriranje analog stick-a Auto-hide buttons after seconds = Auto-sakrij tipke nakon sekundi -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Prozirnost tipki @@ -84,8 +82,6 @@ PSP Action Buttons = PSP akcijske kontrole Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotacija ekrana seconds, 0 : off = sekunde, 0 = isključeno Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 0554fcf783..456ac75453 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = Miközben az Analóg Korlátozó gombot nyomva tartod Auto = Auto Auto-centering analog stick = Analóg kar visszaállítása középre Auto-hide buttons after seconds = Gombok elrejtése X másodperc után -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Gombok Button Binding = Button Binding Button Opacity = Gombok átlátszósága @@ -84,8 +82,6 @@ PSP Action Buttons = PSP akció gombok Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Képernyő elforgatása seconds, 0 : off = másodperc, 0 = ki Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index a890ee1479..47d015c2cf 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -28,8 +28,6 @@ Auto = Otomatis Auto-centering analog stick = Penengahan otomatis stik analog Auto-hide buttons after seconds = Sembunyikan tombol setelah beberapa detik Auto-rotation speed = Kecepatan rotasi otomatis -Auto-switch = Pengalihan otomatis -Base tilt position = Posisi kemiringan dasar Binds = Pengikat Button Binding = Pengikat tombol Button Opacity = Kegelapan tombol @@ -84,8 +82,6 @@ PSP Action Buttons = Tombol aksi PSP Raw input = Masukan mentah Repeat mode = Repeat mode Reset to defaults = Atur ulang ke pengaturan awal -Screen aligned to ground = Layar sejajar kebawah -Screen at right angle to ground = Layar pada sudut kanan kebawah Screen Rotation = Rotasi layar seconds, 0 : off = detik, 0 = mati Sensitivity (scale) = Sensitivitas (skala) diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index e35306d209..4b83d21d9a 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -28,8 +28,6 @@ Auto = Automatico Auto-centering analog stick = Auto-centramento dello stick analogico Auto-hide buttons after seconds = Nascondi automat. i pulsanti dopo 2 secondi Auto-rotation speed = Velocità rotazione automat. analogico -Auto-switch = Auto-switch -Base tilt position = Posizione inclinazione di base Binds = Assegnazioni Button Binding = Mappatura Pulsante Button Opacity = Opacità Tasti @@ -83,8 +81,6 @@ Portrait Reversed = Ritratto invertito PSP Action Buttons = Pulsanti Azione PSP (△◯✕☐) Raw input = Input grezzo Reset to defaults = Reset ai predefiniti -Screen aligned to ground = Schermo allineato a terra -Screen at right angle to ground = Schermo perpendicolare a terra Screen Rotation = Rotazione Schermo seconds, 0 : off = secondi, 0 = disattiva Sensitivity (scale) = Sensibilità (scala) diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 3a39853d80..4460e1b9ca 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = アナログリミッタボタンが押されたとき Auto = 自動 Auto-centering analog stick = アナログパッドを自動でセンタリングする Auto-hide buttons after seconds = 指定した秒数後に自動でボタンを隠す -Auto-switch = 自動切替 -Base tilt position = 傾き入力ポジション(画面の向き) Binds = 割り当て Button Binding = 対応ボタンの割り当て(複数同時設定可能) Button Opacity = ボタンの透明度 @@ -84,8 +82,6 @@ PSP Action Buttons = PSPアクションボタン Raw input = 現実の入力 Repeat mode = Repeat mode Reset to defaults = デフォルトに戻す -Screen aligned to ground = 画面水平状態で使用する -Screen at right angle to ground = 画面直立状態で使用する Screen Rotation = 画面の向き seconds, 0 : off = 秒数, 0 = オフ Sensitivity (scale) = 反応感度 (比率) diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index f9b692139c..cbac8f7c09 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -28,8 +28,6 @@ Auto = Otomatis Auto-centering analog stick = Otomatis Analog stick nang tengah Auto-hide buttons after seconds = Otomatis tombol ilang Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Ketebelan warna tombol @@ -84,8 +82,6 @@ PSP Action Buttons = PSP Aksi tombol Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotasi layar seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 4518622f03..526bf16ff8 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -28,8 +28,6 @@ Auto = 자동 Auto-centering analog stick = 자동 센터링 아날로그 스틱 Auto-hide buttons after seconds = 몇 초 후 버튼 자동 숨기기 Auto-rotation speed = 자동 회전 속도 -Auto-switch = 자동 스위치 -Base tilt position = 기본 기울기 위치 Binds = 바인드 Button Binding = 버튼 바인딩 Button Opacity = 버튼 불투명도 @@ -83,8 +81,6 @@ Portrait Reversed = 세로 방향 반전 PSP Action Buttons = PSP 액션 버튼 Raw input = 원시 입력 Reset to defaults = 기본값으로 재설정 -Screen aligned to ground = 지면에 맞춰진 화면 -Screen at right angle to ground = 지면과 직각의 스크린 Screen Rotation = 화면 회전 seconds, 0 : off = 초 단위, 0 = 끔 Sensitivity = 감도 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 10431e289c..bfcbd6be40 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -28,8 +28,6 @@ Auto = ອັດຕະໂນມັດ Auto-centering analog stick = ອະນາລ໋ອກກັບຄືນຈຸດສູນກາງອັດຕະໂນມັດ Auto-hide buttons after seconds = ເຊື່ອງປຸ່ມທັນທີຫຼັງຈາກ ວິນາທີ Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = ຄວາມເຂັ້ມຂອງປຸ່ມ @@ -84,8 +82,6 @@ PSP Action Buttons = ປຸ່ມກົດຂອງ PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = ການໝຸນໜ້າຈໍ seconds, 0 : off = ວິນາທີ, 0 = ປິດ Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 15c2376d12..84f9317d16 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -28,8 +28,6 @@ Auto = Automatinis Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Mygtukų opacity @@ -84,8 +82,6 @@ PSP Action Buttons = PSP konsolės veiksmų mygtukai Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Ekramo pasukimas seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 42fbbb2418..53afe2bf66 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Sembunyikan butang secara automatik selepas Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Kelegapan butang @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 014203d042..083cd7c423 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -28,8 +28,6 @@ Auto = Automatisch Auto-centering analog stick = Analoge stick automatisch centreren Auto-hide buttons after seconds = Toetsen verbergen na seconden Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Toetsdekking @@ -84,8 +82,6 @@ PSP Action Buttons = PSP-actietoetsen Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Schermrotatie seconds, 0 : off = seconden, 0 = uit Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 470da50169..2600929181 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Knappgenomsiktighet @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Screen rotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 46715897cd..579a848135 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -28,8 +28,6 @@ Auto = Automatyczny Auto-centering analog stick = Autocentrowanie analoga Auto-hide buttons after seconds = Automatyczne ukrywanie przycisków po: Auto-rotation speed = Prędkość automatycznego obracania -Auto-switch = Auto-switch -Base tilt position = Domyślna pozycja tytułu Binds = Powiązania Button Binding = Konfiguracja przycisków Button Opacity = Przeźroczystość przycisków @@ -84,8 +82,6 @@ PSP Action Buttons = Klawisze akcji PSP Raw input = Zwykłe wejście Repeat mode = Tryb powtarzania Reset to defaults = Domyślne -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Obrót ekranu seconds, 0 : off = sekundy, 0 = wył. Sensitivity (scale) = Czułość (dostosuj) diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 8c13aff23d..28c82d6071 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -52,8 +52,6 @@ Auto = Automático Auto-centering analog stick = Auto-centralizar o direcional analógico Auto-hide buttons after seconds = Auto-esconder os botões após segundos Auto-rotation speed = Velocidade da auto-rotação -Auto-switch = Auto-trocar -Base tilt position = Posição da inclinação base Binds = Vinculados Button Binding = Vinculação dos botões Button Opacity = Opacidade dos botões @@ -107,8 +105,6 @@ Portrait Reversed = Retrato invertido PSP Action Buttons = Botões de ação do PSP Raw input = Entrada natural dos dados Reset to defaults = Resetar para os padrões -Screen aligned to ground = Tela alinhada ao solo -Screen at right angle to ground = Tela no ângulo direito do solo Screen Rotation = Rotação da tela seconds, 0 : off = segundos, 0 = desligado Sensitivity = Sensibilidade diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 1c343b8cc8..8aea5aba38 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -52,8 +52,6 @@ Auto = Automático Auto-centering analog stick = Auto-centralização do analógico Auto-hide buttons after seconds = Auto-esconder os botões após segundos Auto-rotation speed = Velocidade da auto-rotação -Auto-switch = Auto-trocar -Base tilt position = Posição da inclinação base Binds = Vinculados Button Binding = Vinculação dos botões Button Opacity = Opacidade dos botões @@ -107,8 +105,6 @@ Portrait Reversed = Retrato invertido PSP Action Buttons = Botões de ação do PSP Raw input = Entrada natural dos dados Reset to defaults = Restaurar para os padrões -Screen aligned to ground = Tela alinhada ao solo -Screen at right angle to ground = Tela no ângulo direito do solo Screen Rotation = Rotação do ecrã seconds, 0 : off = segundos, 0 = desligado Sensitivity = Sensibilidade diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 8e4b459c55..0a2c5c7676 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -28,8 +28,6 @@ Auto = Automat Auto-centering analog stick = Centrare automată a butonului analog Auto-hide buttons after seconds = Ascunde automate butoanele după secunde Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Opacitatea butoanelor @@ -84,8 +82,6 @@ PSP Action Buttons = Butoane acțiune PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotație ecran seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 32ffececfd..e48cedf7a4 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -28,8 +28,6 @@ Auto = Авто Auto-centering analog stick = Автоцентрируемый стик Auto-hide buttons after seconds = Скрывать кнопки через Auto-rotation speed = Скорость автовращения аналогового стика -Auto-switch = Авто-смена -Base tilt position = Начальная позиция наклона Binds = Привязки Button Binding = Привязка кнопок Button Opacity = Прозрачность кнопок @@ -84,8 +82,6 @@ PSP Action Buttons = Кнопки действий PSP Raw input = Прямой ввод Repeat mode = Режим повтора Reset to defaults = По умолчанию -Screen aligned to ground = Экран повёрнут к земле -Screen at right angle to ground = Экран повёрнут под прямым углом к земле Screen Rotation = Ориентация экрана seconds, 0 : off = секунд, 0 = выкл. Sensitivity (scale) = Чувствительность (шкала) diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index a9ccf03767..684daf97a5 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -28,8 +28,6 @@ Auto = Auto Auto-centering analog stick = Auto-centering analog stick Auto-hide buttons after seconds = Auto-hide buttons after seconds Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Knapp-bindning Button Opacity = Knappgenomskinlighet @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action-knappar Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Återställ till standardvärden -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Skärmrotation seconds, 0 : off = seconds, 0 = off Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index aebaad5d72..9256f4ca98 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -28,8 +28,6 @@ Auto = Awto Auto-centering analog stick = Awtomatikong-isentro ang analog stick Auto-hide buttons after seconds = Awtomatikong-itago ang mga pindutan makalipas ang ilang segundo Auto-rotation speed = Awto-rotasyon ng bilis -Auto-switch = Awtomatikong-pagpalit -Base tilt position = Base itagilid ang posisyon Binds = Bigkisin Button Binding = Bigkisin ang pindutan Button Opacity = Kalinawan ng mga pindutan @@ -84,8 +82,6 @@ PSP Action Buttons = PSP action buttons Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Rotasyon ng screen seconds, 0 : off = segundo, 0 = patay Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index bd0be91fdc..bf0f5db463 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -28,8 +28,6 @@ Auto = อัตโนมัติ Auto-centering analog stick = อนาล็อกกลับคืนจุดศูนย์กลางอัตโนมัติ Auto-hide buttons after seconds = ซ่อนปุ่มทันทีหลังจาก/วินาที Auto-rotation speed = ความเร็วหมุนอัตโนมัติ -Auto-switch = สลับอัตโนมัติ -Base tilt position = ตำแหน่งฐานของการเอียง Binds = เซ็ตปุ่ม Button Binding = เซ็ตปุ่มควบคุม Button Opacity = ความชัดของปุ่มกด @@ -84,8 +82,6 @@ PSP Action Buttons = ปุ่มแอ็คชั่นของ PSP Raw input = ค่าตั้งต้น Repeat mode = โหมดปุ่มย้ำ Reset to defaults = คืนค่าเริ่มต้น -Screen aligned to ground = หน้าจอชิดกับพื้น -Screen at right angle to ground = หน้าจอที่มุมขวากับพื้น Screen Rotation = การหมุนหน้าจอ seconds, 0 : off = วินาที, 0 = ปิด Sensitivity = ความไวต่อการตอบสนอง diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 5ab048b14b..70729a4d6a 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -28,8 +28,6 @@ Auto = Otomatik Auto-centering analog stick = Analog çubuğu otomatik ortala Auto-hide buttons after seconds = Belirli bir süre sonra tuşları otomatik sakla Auto-rotation speed = Otomatik rotasyon hızı -Auto-switch = Oto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Düğme Bağlama Button Opacity = Tuş görünürlüğü @@ -84,8 +82,6 @@ PSP Action Buttons = PSP eylem tuşları Raw input = Saf girdi Repeat mode = Tekrar modu Reset to defaults = Varsayılanlara sıfırla -Screen aligned to ground = Ekran yere hizalansın -Screen at right angle to ground = Yere dik açıda ekran Screen Rotation = Ekran rotasyonu seconds, 0 : off = saniyeler, 0 = kapalı Sensitivity (scale) = Hassasiyet (ölçek) diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index a64a2ee26b..2a1e798d84 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = Коли натиснена кнопка аналогово Auto = Авто Auto-centering analog stick = Автоматичне центрування аналогового стіку Auto-hide buttons after seconds = Приховувати кнопки через -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Прив'язка Button Binding = Button Binding Button Opacity = Прозорість кнопок @@ -84,8 +82,6 @@ PSP Action Buttons = Кнопки дій PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Орієнтація екрану seconds, 0 : off = сек., 0 = вимкнено Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index d9156b0252..fd2b84fc8b 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -28,8 +28,6 @@ Auto = Tự động Auto-centering analog stick = Cần Analog auto định tâm Auto-hide buttons after seconds = Thời gian Auto ẩn nút (giây) Auto-rotation speed = Auto-rotation speed -Auto-switch = Auto-switch -Base tilt position = Base tilt position Binds = Binds Button Binding = Button Binding Button Opacity = Độ trong suốt @@ -84,8 +82,6 @@ PSP Action Buttons = Nút hành động của PSP Raw input = Raw input Repeat mode = Repeat mode Reset to defaults = Reset to defaults -Screen aligned to ground = Screen aligned to ground -Screen at right angle to ground = Screen at right angle to ground Screen Rotation = Xoay màn hình seconds, 0 : off = giây, 0 : tắt Sensitivity (scale) = Sensitivity (scale) diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index f490dd33f9..c15f4f3a0b 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -28,8 +28,6 @@ AnalogLimiter Tip = 按下限制键时摇杆的最大移动范围 Auto = 自动 Auto-centering analog stick = 摇杆自动跟手 Auto-hide buttons after seconds = 自动隐藏按键 -Auto-switch = 自动切换 -Base tilt position = 标准体感位置 Binds = 绑定 Button Binding = 按键绑定 Button Opacity = 按键透明度 @@ -84,8 +82,6 @@ PSP Action Buttons = PSP 动作键 Raw input = 原始输入 Repeat mode = 连发模式 Reset to defaults = 重置为默认 -Screen aligned to ground = 屏幕水平地面 -Screen at right angle to ground = 屏幕垂直地面 Screen Rotation = 屏幕旋转 seconds, 0 : off = 秒, 0=不隐藏 Sensitivity (scale) = 灵敏度(倍率) diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 9abaa7b49a..30c256c9d5 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -28,8 +28,6 @@ Auto = 自動 Auto-centering analog stick = 自動置中類比搖桿 Auto-hide buttons after seconds = 數秒後自動隱藏按鈕 Auto-rotation speed = 自動旋轉速度 -Auto-switch = 自動切換 -Base tilt position = 基準傾斜位置 Binds = 繫結 Button Binding = 按鈕繫結 Button Opacity = 按鈕不透明度 @@ -83,8 +81,6 @@ Portrait Reversed = 直向反轉 PSP Action Buttons = PSP 動作按鈕 Raw input = 原始輸入 Reset to defaults = 重設為預設值 -Screen aligned to ground = 螢幕與地面水平對齊 -Screen at right angle to ground = 螢幕與地面垂直對齊 Screen Rotation = 螢幕旋轉 seconds, 0 : off = 秒,0 = 關閉 Sensitivity = 敏感度 From 1f51a3154400b791295c6d365d2d8a4ff88e5bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 1 Feb 2023 23:47:42 +0100 Subject: [PATCH 011/424] Remove the separate deadzone-skip value. --- Core/Config.cpp | 3 +-- Core/Config.h | 2 -- Core/TiltEventProcessor.cpp | 30 ++++++------------------------ Core/TiltEventProcessor.h | 12 ++++-------- UI/NativeApp.cpp | 11 +++++------ UI/TiltAnalogSettingsScreen.cpp | 11 ++++------- assets/lang/ar_AE.ini | 1 - assets/lang/az_AZ.ini | 1 - assets/lang/bg_BG.ini | 1 - assets/lang/ca_ES.ini | 1 - assets/lang/cz_CZ.ini | 1 - assets/lang/da_DK.ini | 1 - assets/lang/de_DE.ini | 1 - assets/lang/dr_ID.ini | 1 - assets/lang/en_US.ini | 1 - assets/lang/es_ES.ini | 1 - assets/lang/es_LA.ini | 1 - assets/lang/fa_IR.ini | 1 - assets/lang/fi_FI.ini | 1 - assets/lang/fr_FR.ini | 1 - assets/lang/gl_ES.ini | 1 - assets/lang/gr_EL.ini | 1 - assets/lang/he_IL.ini | 1 - assets/lang/he_IL_invert.ini | 1 - assets/lang/hr_HR.ini | 1 - assets/lang/hu_HU.ini | 1 - assets/lang/id_ID.ini | 1 - assets/lang/it_IT.ini | 1 - assets/lang/ja_JP.ini | 1 - assets/lang/jv_ID.ini | 1 - assets/lang/ko_KR.ini | 1 - assets/lang/lo_LA.ini | 1 - assets/lang/lt-LT.ini | 1 - assets/lang/ms_MY.ini | 1 - assets/lang/nl_NL.ini | 1 - assets/lang/no_NO.ini | 1 - assets/lang/pl_PL.ini | 1 - assets/lang/pt_BR.ini | 1 - assets/lang/pt_PT.ini | 1 - assets/lang/ro_RO.ini | 1 - assets/lang/ru_RU.ini | 1 - assets/lang/sv_SE.ini | 1 - assets/lang/tg_PH.ini | 1 - assets/lang/th_TH.ini | 1 - assets/lang/tr_TR.ini | 1 - assets/lang/uk_UA.ini | 1 - assets/lang/vi_VN.ini | 1 - assets/lang/zh_CN.ini | 1 - assets/lang/zh_TW.ini | 1 - 49 files changed, 20 insertions(+), 92 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 2884b4a04b..322a7a473d 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -975,8 +975,7 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("InvertTiltY", &g_Config.bInvertTiltY, true, true, true), ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 50, true, true), ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 50, true, true), - ConfigSetting("DeadzoneRadius", &g_Config.fDeadzoneRadius, 0.05f, true, true), - ConfigSetting("TiltDeadzoneSkip", &g_Config.fTiltDeadzoneSkip, 0.0f, true, true), + ConfigSetting("DeadzoneRadius", &g_Config.fDeadzoneRadius, 0.0f, true, true), ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, true, true), #endif diff --git a/Core/Config.h b/Core/Config.h index 7b6422f037..dc2f1a8ca7 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -297,8 +297,6 @@ public: int iTiltSensitivityY; //the deadzone radius of the tilt float fDeadzoneRadius; - // deadzone skip - float fTiltDeadzoneSkip; //type of tilt input currently selected: Defined in TiltEventProcessor.h //0 - no tilt, 1 - analog stick, 2 - D-Pad, 3 - Action Buttons (Tri, Cross, Square, Circle) int iTiltInputType; diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 58620b6f83..816211b738 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -24,21 +24,21 @@ void GenerateDPadEvent(const Tilt &tilt); void GenerateActionButtonEvent(const Tilt &tilt); void GenerateTriggerButtonEvent(const Tilt &tilt); -//deadzone is normalized - 0 to 1 -//sensitivity controls how fast the deadzone reaches max value +// deadzone is normalized - 0 to 1 +// sensitivity controls how fast the deadzone reaches max value inline float tiltInputCurve(float x, float deadzone, float sensitivity) { const float factor = sensitivity * 1.0f / (1.0f - deadzone); if (x > deadzone) { - return (x - deadzone) * factor * factor + g_Config.fTiltDeadzoneSkip; + return (x - deadzone) * factor + deadzone; } else if (x < -deadzone) { - return (x + deadzone) * factor * factor - g_Config.fTiltDeadzoneSkip; + return (x + deadzone) * factor - deadzone; } else { return 0.0f; } } -//dampen the tilt according to the given deadzone amount. +// dampen the tilt according to the given deadzone amount. inline Tilt dampTilt(const Tilt &tilt, float deadzone, float xSensitivity, float ySensitivity) { //multiply sensitivity by 2 so that "overshoot" is possible. I personally prefer a //sensitivity >1 for kingdom hearts and < 1 for Gods Eater. so yes, overshoot is nice @@ -52,24 +52,6 @@ inline float clamp(float f) { return f; } -// Landscape liggande: -// x = 0 -// y = 0 -// z = 1 -// Landscape stående: -// x = 1 -// y = 0 -// z = 0 -// Landscape vänster kortsida: -// x = 0 -// y = -1 -// z = 0 -// Landscape liggande upp och ner -// x = 0 -// y = 0 -// z = -1 - - Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity) { if (landscape) { std::swap(x, y); @@ -82,7 +64,7 @@ Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, float yAngle = angleAroundX - calibrationAngle; float xAngle = asinf(down.x); - Tilt transformedTilt(xAngle, -yAngle); + Tilt transformedTilt(xAngle, yAngle); // invert x and y axes if requested. Can probably remove this. if (invertX) { diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index 0279188032..ef298384aa 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -2,7 +2,7 @@ namespace TiltEventProcessor { -enum TiltTypes{ +enum TiltTypes { TILT_NULL = 0, TILT_ANALOG, TILT_DPAD, @@ -10,22 +10,18 @@ enum TiltTypes{ TILT_TRIGGER_BUTTON, }; - -//Represents a generic Tilt event +// Represents a generic Tilt event struct Tilt { Tilt() : x_(0), y_(0) {} Tilt(const float x, const float y) : x_(x), y_(y) {} - float x_, y_; }; - + // generates a tilt in the correct coordinate system based on -// calibration. x, y, z is the current accelerometer reading. -// NOTE- both base and current tilt *MUST BE NORMALIZED* by calling the NormalizeTilt() function. +// calibration. x, y, z is the current accelerometer reading (with no conversion). Tilt GenTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity); void TranslateTiltToInput(const Tilt &tilt); - void ResetTiltEvents(); // Lets you preview the amount of tilt in TiltAnalogSettingsScreen. diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 8383347e28..e80f14d926 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1390,13 +1390,7 @@ void NativeAxis(const AxisInput &axis) { static float tiltY; static float tiltZ; - // x and y are flipped if we are in landscape orientation. The events are - // sent with respect to the portrait coordinate system, while we - // take all events in landscape. - // see [http://developer.android.com/guide/topics/sensors/sensors_overview.html] for details - bool landscape = dp_yres < dp_xres; switch (axis.axisId) { - //TODO: make this generic. case JOYSTICK_AXIS_ACCELEROMETER_X: tiltX = axis.value; break; case JOYSTICK_AXIS_ACCELEROMETER_Y: tiltY = axis.value; break; case JOYSTICK_AXIS_ACCELEROMETER_Z: tiltZ = axis.value; break; @@ -1411,6 +1405,11 @@ void NativeAxis(const AxisInput &axis) { float xSensitivity = g_Config.iTiltSensitivityX / 50.0; float ySensitivity = g_Config.iTiltSensitivityY / 50.0; + // x and y are flipped if we are in landscape orientation. The events are + // sent with respect to the portrait coordinate system, while we + // take all events in landscape. + // see [http://developer.android.com/guide/topics/sensors/sensors_overview.html] for details + bool landscape = dp_yres < dp_xres; // now transform out current tilt to the calibrated coordinate system Tilt trueTilt = GenTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, g_Config.bInvertTiltX, g_Config.bInvertTiltY, g_Config.fDeadzoneRadius, diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index ef15ac60f3..2b2f794eea 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -35,7 +35,7 @@ void TiltAnalogSettingsScreen::CreateViews() { root_ = new LinearLayout(ORIENT_HORIZONTAL); root_->SetTag("TiltAnalogSettings"); - ScrollView *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(650, FILL_PARENT)); + ScrollView *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(600, FILL_PARENT)); root_->Add(menuRoot); // AnchorLayout *rightSide = new AnchorLayout(new LinearLayoutParams(1.0)); @@ -58,11 +58,9 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new CheckBox(&g_Config.bInvertTiltY, co->T("Invert Tilt along Y axis"))); settings->Add(new ItemHeader(co->T("Sensitivity"))); - //TODO: allow values greater than 100? I'm not sure if that's needed. - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(),"%")); - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(),"%")); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone radius"), 0.01f, screenManager(),"/ 1.0")); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltDeadzoneSkip, 0.0, 1.0, co->T("Tilt Base Radius"), 0.01f, screenManager(),"/ 1.0")); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(), "%")); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%")); + settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0")); menuRoot->Add(settings); @@ -85,7 +83,6 @@ void TiltAnalogSettingsScreen::axis(const AxisInput &axis) { UI::EventReturn TiltAnalogSettingsScreen::OnCalibrate(UI::EventParams &e) { Lin::Vec3 down = down_.normalized(); g_Config.fTiltBaseAngleY = atan2(down.z, down.x); - INFO_LOG(SCECTRL, "Setting base angle to %f from x=%f y=%f z=%f", g_Config.fTiltBaseAngleY, down.x, down.y, down.z); return UI::EVENT_DONE; } diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 281bf8587a..63a606ba18 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -100,7 +100,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = ‎حدود رفيعة -Tilt Base Radius = Tilt base radius Tilt Input Type = ‎نوع الإدخال المنطقة Tilt Sensitivity along X axis = ‎X حساسية المنطقة علي طول محور Tilt Sensitivity along Y axis = ‎Y حساسية المنطقة علي طول محور diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index fec91a6ffb..4b7f6cf63d 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index a2aa0b3ee3..ffced9f819 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 87d27a7bde..90b77d8c2d 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -92,7 +92,6 @@ Swipe = Lliscar cap a Swipe sensitivity = Sensibilitat de lliscament Swipe smoothing = Fluïdesa del lliscat Thin borders = Vores fines -Tilt Base Radius = Ràdio base d'inclinació Tilt Input Type = Tipus de control de l'acceleròmetre Tilt Sensitivity along X axis = Sensibilitat d'inclinació de l'eix X Tilt Sensitivity along Y axis = Sensibilitat d'inclinació de l'eix Y diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 9c6d952c6d..3ca4742326 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tenké okraje -Tilt Base Radius = Tilt base radius Tilt Input Type = Typ vstupu náklonu Tilt Sensitivity along X axis = Citlivost náklonu podle osy X Tilt Sensitivity along Y axis = Citlivost náklonu podle osy Y diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index d67e60a89d..bc879541b8 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tynde rammer -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt følsomhed langs X aksen Tilt Sensitivity along Y axis = Tilt følsomhed langs Y aksen diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index eabb4dcb00..bdf459d498 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Dünne Ränder -Tilt Base Radius = Tilt base radius Tilt Input Type = Eingabetyp für Neigen Tilt Sensitivity along X axis = Neigungsempfindlichkeit über X-Achse Tilt Sensitivity along Y axis = Neigungsempfindlichkeit über Y-Achse diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 3b575b68f9..a94075c66a 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 17a40bada2..ca734db5c0 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -115,7 +115,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 46a6183fbe..7a9904ee04 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -92,7 +92,6 @@ Swipe = Deslizar hacia Swipe sensitivity = Sensibilidad del deslizado Swipe smoothing = Fluidez del deslizado Thin borders = Bordes finos -Tilt Base Radius = Radio base de inclinación Tilt Input Type = Tipo de control del acelerómetro Tilt Sensitivity along X axis = Sensibilidad de inclinación del eje X Tilt Sensitivity along Y axis = Sensibilidad de inclinación del eje Y diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 3899ac30a8..46b110b1b3 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -92,7 +92,6 @@ Swipe = Deslizar hacia Swipe sensitivity = Sensibilidad del deslizado Swipe smoothing = Fluidez del deslizado Thin borders = Bordes finos -Tilt Base Radius = Radio base de inclinación Tilt Input Type = Tipo de control del acelerómetro Tilt Sensitivity along X axis = Sensibilidad de inclinación del eje X Tilt Sensitivity along Y axis = Sensibilidad de inclinación del eje Y diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 5d3db3b655..24c7bad3f6 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -92,7 +92,6 @@ Swipe = حساسیت Swipe sensitivity = حساسیت کش رفتن Swipe smoothing = ضربه تند وشدید زدن Thin borders = ‎نوار نازک -Tilt Base Radius = شعاع پایه شیب Tilt Input Type = ‎...استفاده از شتاب سنج به عنوان Tilt Sensitivity along X axis = ‎X حساسیت شتاب سنج در جهت Tilt Sensitivity along Y axis = ‎Y حساسیت شتاب سنج در جهت diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index d0e7f26ff0..6ab613a0f0 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 9a8391b161..8282f860f7 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Bordures fines -Tilt Base Radius = Modifier la zone morte avec l'inclinaison analogique Tilt Input Type = Type inclinaison analogique Tilt Sensitivity along X axis = Sensibilité de l'inclinaison analogique sur l'axe X Tilt Sensitivity along Y axis = Sensibilité de l'inclinaison analogique sur l'axe Y diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index d14b52de31..a0d0d08fbf 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Bordes finos -Tilt Base Radius = Tilt base radius Tilt Input Type = Tipo de control do acelerómetro Tilt Sensitivity along X axis = Sensibilidade de inclinación do eixe X Tilt Sensitivity along Y axis = Sensibilidade de inclinación do eixe Y diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 9f4bc92be6..6f8721e3e3 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Λεπτά διαχωριστικά -Tilt Base Radius = Tilt base radius Tilt Input Type = Τύπο εισόδου κλίσης Tilt Sensitivity along X axis = Ευαισθησία οριζόντιου άξονα Tilt Sensitivity along Y axis = Ευαισθησία κάθετου άξονα diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index 859e3e7e41..ed9450790e 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index d1ff09d9f6..b593b24fcb 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 4d49e70992..04d54edf64 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tanki rubovi -Tilt Base Radius = Tilt base radius Tilt Input Type = Tip ulaza tilta Tilt Sensitivity along X axis = Tilt senzitivnost X osi Tilt Sensitivity along Y axis = Tilt senzitivnost Y osi diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 456ac75453..bb54e06831 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Vékony szélek -Tilt Base Radius = Döntés alapsugara Tilt Input Type = Döntési bevitel típusa Tilt Sensitivity along X axis = X tengely menti döntés érzékenysége Tilt Sensitivity along Y axis = X tengely menti döntés érzékenysége diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 47d015c2cf..f7b80d715b 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -92,7 +92,6 @@ Swipe = Geser Swipe sensitivity = Geser sensitivitas Swipe smoothing = Geser kehalusan Thin borders = Garis batas tipis -Tilt Base Radius = Radius kemiringan dasar Tilt Input Type = Jenis masukan kemiringan Tilt Sensitivity along X axis = Sensitivitas kemiringan sepanjang sumbu X Tilt Sensitivity along Y axis = Sensitivitas kemiringan sepanjang sumbu Y diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 4b83d21d9a..e6d4aeca51 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -91,7 +91,6 @@ Swipe = Scorrimento Swipe sensitivity = Sensibilità Scorrimento Swipe smoothing = Fluidità Scorrimento Thin borders = Bordi fini -Tilt Base Radius = Modifica zona morta con inclinazione analogica Tilt Input Type = Tipo di Input Inclinazione Tilt Sensitivity along X axis = Inverti Sensibilità sull'asse X Tilt Sensitivity along Y axis = Inverti Sensibilità sull'asse Y diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 4460e1b9ca..b1967d4733 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -92,7 +92,6 @@ Swipe = スワイプ Swipe sensitivity = スワイプの感度 Swipe smoothing = スワイプの滑らかさ Thin borders = 薄い枠線 -Tilt Base Radius = 傾きのベース半径 Tilt Input Type = 傾き入力のタイプ Tilt Sensitivity along X axis = X軸の傾きの感度 Tilt Sensitivity along Y axis = Y軸の傾きの感度 diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index cbac8f7c09..50ed265ce5 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Watesan lancip -Tilt Base Radius = Tilt base radius Tilt Input Type = Ngiringake Tipe input Tilt Sensitivity along X axis = Ngiringake sensitivitas bebarengan X sumbu Tilt Sensitivity along Y axis = Ngiringake sensitivitas bebarengan Y sumbu diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 526bf16ff8..2b7ad25e6f 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -91,7 +91,6 @@ Swipe = 스와이프 Swipe sensitivity = 스와이프 감도 Swipe smoothing = 스와이프 스무딩 Thin borders = 얇은 테두리 -Tilt Base Radius = 기울기 기반 반경 Tilt Input Type = 기울기 입력 유형 Tilt Sensitivity along X axis = X 축 기울기 감도 Tilt Sensitivity along Y axis = Y 축 기울기 감도 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index bfcbd6be40..e967b03ba1 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = ຂອບແບບບາງ -Tilt Base Radius = Tilt base radius Tilt Input Type = ນຳເຂົ້າຮູບແບບການອຽງ Tilt Sensitivity along X axis = ຄວາມໄວການອຽງຕາມແກນ X Tilt Sensitivity along Y axis = ຄວາມໄວການອຽງໄວຕາມແກນ Y diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 84f9317d16..dd5ce1b1af 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Ploni kraštai -Tilt Base Radius = Tilt base radius Tilt Input Type = Pakreipimo įvedimo įrenginio tipas Tilt Sensitivity along X axis = Pakreipimo sensitivacija palei X ašį Tilt Sensitivity along Y axis = Pakreipimo sensitivacija palei Y ašį diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 53afe2bf66..898e109a61 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tepian tipis -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 083cd7c423..2eb996ca98 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Dunne randen -Tilt Base Radius = Tilt base radius Tilt Input Type = Invoertype voor kantelen Tilt Sensitivity along X axis = Kantelgevoeligheid op X-as Tilt Sensitivity along Y axis = Kantelgevoeligheid op Y-as diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 2600929181..afd0f81d30 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 579a848135..0a788c74b3 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Cienkie krawędzie -Tilt Base Radius = Tilt base radius Tilt Input Type = Typ przechyłu Tilt Sensitivity along X axis = Czułość przechyłu wzdłuż osi X Tilt Sensitivity along Y axis = Czułość przechyłu wzdłuż osi Y diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 28c82d6071..dbdd9d02cb 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -115,7 +115,6 @@ Swipe = Deslizar Swipe sensitivity = Sensibilidade do deslizar Swipe smoothing = Suavidade do deslizar Thin borders = Bordas finas -Tilt Base Radius = Raio da base de inclinação Tilt Input Type = Controle da entrada da inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 8aea5aba38..03cb4bb3cf 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -115,7 +115,6 @@ Swipe = Deslizar Swipe sensitivity = Sensibilidade do deslizar Swipe smoothing = Suavidade do deslizar Thin borders = Bordas Finas -Tilt Base Radius = Raio da base de inclinação Tilt Input Type = Controlo da entrada de inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 0a2c5c7676..0bddfd1a36 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Margini subțiri -Tilt Base Radius = Tilt base radius Tilt Input Type = Tip intrare prin înclinare Tilt Sensitivity along X axis = Inversează sensitivitatea pe axa X Tilt Sensitivity along Y axis = Inversează sensitivitatea pe axa Y diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index e48cedf7a4..c23bc92d70 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -92,7 +92,6 @@ Swipe = Свайпы Swipe sensitivity = Чувствительность свайпов Swipe smoothing = Сглаживание свайпов Thin borders = Тонкие границы -Tilt Base Radius = Радиус наклона основания Tilt Input Type = Тип управления наклоном Tilt Sensitivity along X axis = Чувствительность наклона вдоль X Tilt Sensitivity along Y axis = Чувствительность наклона вдоль Y diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 684daf97a5..c50da361b5 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe-känslighet Swipe smoothing = Swipe-utjämning Thin borders = Tunna kanter -Tilt Base Radius = Tilt base radius Tilt Input Type = Lutningstyp Tilt Sensitivity along X axis = Lutningskänslighet X Tilt Sensitivity along Y axis = Lutningskänslighet Y diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index 9256f4ca98..d53616f88d 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -92,7 +92,6 @@ Swipe = Mahagip Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Manipis na gilid -Tilt Base Radius = Tilt base radius Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index bf0f5db463..5491e7175b 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -92,7 +92,6 @@ Swipe = ปัดหน้าจอ Swipe sensitivity = ความแรงที่ใช้ปัดหน้าจอ Swipe smoothing = ความลื่นไหลในการปัดหน้าจอ Thin borders = แบบขอบบาง -Tilt Base Radius = รัศมีของการเอียง Tilt Input Type = รูปแบบนำเข้าการเอียง Tilt Sensitivity along X axis = ความไวต่อการตอบสนองเอียงตามแกน X Tilt Sensitivity along Y axis = ความไวต่อการตอบสนองเอียงตามแกน Y diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 70729a4d6a..c4600b33a7 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -92,7 +92,6 @@ Swipe = Kaydır Swipe sensitivity = Kaydırma hassasiyeti Swipe smoothing = Pürüzsüz kaydırma Thin borders = İnce kenarlar -Tilt Base Radius = Eğim Taban Yarıçapı Tilt Input Type = Eğim giriş türü Tilt Sensitivity along X axis = X ekseni boyunca eğim hassasiyeti Tilt Sensitivity along Y axis = Y ekseni boyunca eğim hassasiyeti diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 2a1e798d84..55570aa4d2 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Тонкі границі (збільшення) -Tilt Base Radius = Радіус нахилу основи Tilt Input Type = Тип управління нахилом Tilt Sensitivity along X axis = Чутливість нахилу по осі X Tilt Sensitivity along Y axis = Чутливість нахилу по осі Y diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index fd2b84fc8b..7e8964304b 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -92,7 +92,6 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Viền mỏng -Tilt Base Radius = Tilt base radius Tilt Input Type = Đầu vào kiểu nghiêng Tilt Sensitivity along X axis = Độ nhạy nghiêng theo chiều x Tilt Sensitivity along Y axis = Độ nhạy nghiêng theo chiều y diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index c15f4f3a0b..dac0af37a2 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -92,7 +92,6 @@ Swipe = 滑动 Swipe sensitivity = 滑动灵敏度 Swipe smoothing = 滑动平滑度 Thin borders = 细边框 -Tilt Base Radius = 倾斜最小半径 Tilt Input Type = 重力感应按键 Tilt Sensitivity along X axis = 沿X轴倾斜灵敏度 Tilt Sensitivity along Y axis = 沿Y轴倾斜灵敏度 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 30c256c9d5..26efd6f82b 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -91,7 +91,6 @@ Swipe = 滑動 Swipe sensitivity = 滑動敏感度 Swipe smoothing = 滑動平滑度 Thin borders = 特細框線 -Tilt Base Radius = 傾斜基準半徑 Tilt Input Type = 傾斜輸入類型 Tilt Sensitivity along X axis = 沿 X 軸傾斜敏感度 Tilt Sensitivity along Y axis = 沿 Y 軸傾斜敏感度 From 59dec197d8db2926075b29cc8f11955a5574a14f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 00:59:29 +0100 Subject: [PATCH 012/424] Add previews for more types, fix mappings. --- Common/UI/View.cpp | 1 - Core/Config.cpp | 8 ++--- Core/ConfigValues.h | 9 +++++ Core/TiltEventProcessor.cpp | 11 ++++-- Core/TiltEventProcessor.h | 8 ----- UI/GamepadEmu.cpp | 4 +++ UI/GamepadEmu.h | 5 +++ UI/TiltAnalogSettingsScreen.cpp | 59 +++++++++++++++++++++++++++++---- UI/TiltAnalogSettingsScreen.h | 2 ++ assets/lang/ar_AE.ini | 2 +- assets/lang/az_AZ.ini | 2 +- assets/lang/bg_BG.ini | 2 +- assets/lang/ca_ES.ini | 2 +- assets/lang/cz_CZ.ini | 2 +- assets/lang/da_DK.ini | 2 +- assets/lang/de_DE.ini | 2 +- assets/lang/dr_ID.ini | 2 +- assets/lang/en_US.ini | 2 +- assets/lang/es_ES.ini | 2 +- assets/lang/es_LA.ini | 2 +- assets/lang/fa_IR.ini | 2 +- assets/lang/fi_FI.ini | 2 +- assets/lang/fr_FR.ini | 2 +- assets/lang/gl_ES.ini | 2 +- assets/lang/gr_EL.ini | 2 +- assets/lang/he_IL.ini | 2 +- assets/lang/he_IL_invert.ini | 2 +- assets/lang/hr_HR.ini | 2 +- assets/lang/hu_HU.ini | 2 +- assets/lang/id_ID.ini | 2 +- assets/lang/it_IT.ini | 2 +- assets/lang/ja_JP.ini | 2 +- assets/lang/jv_ID.ini | 2 +- assets/lang/ko_KR.ini | 2 +- assets/lang/lt-LT.ini | 2 +- assets/lang/ms_MY.ini | 2 +- assets/lang/nl_NL.ini | 2 +- assets/lang/no_NO.ini | 4 +-- assets/lang/pl_PL.ini | 2 +- assets/lang/pt_BR.ini | 2 +- assets/lang/pt_PT.ini | 2 +- assets/lang/ro_RO.ini | 2 +- assets/lang/ru_RU.ini | 2 +- assets/lang/sv_SE.ini | 2 +- assets/lang/th_TH.ini | 2 +- assets/lang/tr_TR.ini | 2 +- assets/lang/uk_UA.ini | 2 +- assets/lang/vi_VN.ini | 2 +- assets/lang/zh_CN.ini | 2 +- assets/lang/zh_TW.ini | 2 +- 50 files changed, 126 insertions(+), 65 deletions(-) diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index bef6320156..c48e7eca16 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -551,7 +551,6 @@ void InfoItem::Draw(UIContext &dc) { style = HasFocus() ? dc.theme->itemFocusedStyle : dc.theme->itemStyle; } - if (style.background.type == DRAW_SOLID_COLOR) { // For a smoother fade, using the same color with 0 alpha. if ((style.background.color & 0xFF000000) == 0) diff --git a/Core/Config.cpp b/Core/Config.cpp index 322a7a473d..b604d0232a 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -971,10 +971,10 @@ static const ConfigSetting controlSettings[] = { #ifdef MOBILE_DEVICE ConfigSetting("TiltBaseAngleY", &g_Config.fTiltBaseAngleY, 0.0f, true, true), - ConfigSetting("InvertTiltX", &g_Config.bInvertTiltX, false, true, true), - ConfigSetting("InvertTiltY", &g_Config.bInvertTiltY, true, true, true), - ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 50, true, true), - ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 50, true, true), + ConfigSetting("TiltInvertX", &g_Config.bInvertTiltX, false, true, true), + ConfigSetting("TiltInvertY", &g_Config.bInvertTiltY, false, true, true), + ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 70, true, true), + ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 70, true, true), ConfigSetting("DeadzoneRadius", &g_Config.fDeadzoneRadius, 0.0f, true, true), ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, true, true), #endif diff --git a/Core/ConfigValues.h b/Core/ConfigValues.h index f793e7ad07..6945dfacf0 100644 --- a/Core/ConfigValues.h +++ b/Core/ConfigValues.h @@ -144,3 +144,12 @@ enum class ShowStatusFlags { SPEED_COUNTER = 1 << 2, BATTERY_PERCENT = 1 << 3, }; + +// for iTiltInputType +enum TiltTypes { + TILT_NULL = 0, + TILT_ANALOG, + TILT_DPAD, + TILT_ACTION_BUTTON, + TILT_TRIGGER_BUTTONS, +}; diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 816211b738..a404370d44 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -8,6 +8,7 @@ #include "Common/Log.h" #include "Core/Config.h" +#include "Core/ConfigValues.h" #include "Core/HLE/sceCtrl.h" #include "Core/TiltEventProcessor.h" @@ -75,6 +76,10 @@ Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, transformedTilt.y_ *= -1.0f; } + // For the button mappings to work, we need a minimum deadzone. + // Analog stick though is better off with a zero one but any can work. + float actualDeadzone = g_Config.iTiltInputType == TILT_ANALOG ? deadzone : std::max(0.2f, deadzone); + // finally, dampen the tilt according to our curve. return dampTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); } @@ -99,7 +104,7 @@ void TranslateTiltToInput(const Tilt &tilt) { GenerateActionButtonEvent(tilt); break; - case TILT_TRIGGER_BUTTON: + case TILT_TRIGGER_BUTTONS: GenerateTriggerButtonEvent(tilt); break; } @@ -127,7 +132,7 @@ void GenerateDPadEvent(const Tilt &tilt) { } int ctrlMask = 0; - int direction = (int)(floorf((atan2f(tilt.y_, tilt.x_) / (2.0f * (float)M_PI) * 8.0f) + 0.5f)) & 7; + int direction = (int)(floorf((atan2f(-tilt.y_, tilt.x_) / (2.0f * (float)M_PI) * 8.0f) + 0.5f)) & 7; switch (direction) { case 0: ctrlMask |= CTRL_RIGHT; break; case 1: ctrlMask |= CTRL_RIGHT | CTRL_DOWN; break; @@ -161,7 +166,7 @@ void GenerateActionButtonEvent(const Tilt &tilt) { return; } - int direction = (int)(floorf((atan2f(tilt.y_, tilt.x_) / (2.0f * (float)M_PI) * 4.0f) + 0.5f)) & 3; + int direction = (int)(floorf((atan2f(-tilt.y_, tilt.x_) / (2.0f * (float)M_PI) * 4.0f) + 0.5f)) & 3; int downButtons = buttons[direction] & ~__CtrlPeekButtons(); __CtrlButtonDown(downButtons); tiltButtonsDown |= downButtons; diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index ef298384aa..9504dc90e5 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -2,14 +2,6 @@ namespace TiltEventProcessor { -enum TiltTypes { - TILT_NULL = 0, - TILT_ANALOG, - TILT_DPAD, - TILT_ACTION_BUTTON, - TILT_TRIGGER_BUTTON, -}; - // Represents a generic Tilt event struct Tilt { Tilt() : x_(0), y_(0) {} diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index a288be6fe1..e8262e5225 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -65,6 +65,10 @@ std::string GamepadView::DescribeText() const { } float GamepadView::GetButtonOpacity() { + if (forceVisible_) { + return 1.0f; + } + if (coreState != CORE_RUNNING) { return 0.0f; } diff --git a/UI/GamepadEmu.h b/UI/GamepadEmu.h index 96211f5a58..f7ec6943a8 100644 --- a/UI/GamepadEmu.h +++ b/UI/GamepadEmu.h @@ -36,12 +36,17 @@ public: void Update() override; std::string DescribeText() const override; + void SetForceVisible(bool visible) { + forceVisible_ = visible; + } + protected: virtual float GetButtonOpacity(); const char *key_; double lastFrameTime_; float secondsWithoutTouch_ = 0.0; + bool forceVisible_ = false; }; class MultiTouchButton : public GamepadView { diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index 2b2f794eea..c5827c4394 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -18,12 +18,14 @@ #include "Core/Config.h" #include "Core/System.h" #include "Core/TiltEventProcessor.h" +#include "Core/ConfigValues.h" #include "Common/Math/math_util.h" #include "Common/Log.h" #include "Common/Data/Text/I18n.h" #include "UI/JoystickHistoryView.h" +#include "UI/GamepadEmu.h" #include "UI/TiltAnalogSettingsScreen.h" void TiltAnalogSettingsScreen::CreateViews() { @@ -38,16 +40,57 @@ void TiltAnalogSettingsScreen::CreateViews() { ScrollView *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(600, FILL_PARENT)); root_->Add(menuRoot); - // AnchorLayout *rightSide = new AnchorLayout(new LinearLayoutParams(1.0)); - tilt_ = new JoystickHistoryView(StickHistoryViewType::OTHER, "", new LinearLayoutParams(1.0f)); - root_->Add(tilt_); + if (g_Config.iTiltInputType == TILT_ANALOG) { + tilt_ = new JoystickHistoryView(StickHistoryViewType::OTHER, "", new LinearLayoutParams(1.0f)); + root_->Add(tilt_); + } else { + AnchorLayout *rightSide = new AnchorLayout(new LinearLayoutParams(1.0)); + root_->Add(rightSide); + switch (g_Config.iTiltInputType) { + case TILT_DPAD: + { + PSPDpad *pad = rightSide->Add(new PSPDpad(ImageID("I_DIR_LINE"), "D-pad", ImageID("I_DIR_LINE"), ImageID("I_ARROW"), 1.5f, 1.3f, new AnchorLayoutParams(NONE, NONE, NONE, NONE, true))); + pad->SetForceVisible(true); + break; + } + case TILT_ACTION_BUTTON: + { + PSPButton *circle = new PSPButton(CTRL_CIRCLE, "Circle button", ImageID("I_ROUND_LINE"), ImageID("I_ROUND"), ImageID("I_CIRCLE"), 1.5f, new AnchorLayoutParams(NONE, NONE, 100.0f, NONE, true)); + PSPButton *cross= new PSPButton(CTRL_CROSS, "Cross button", ImageID("I_ROUND_LINE"), ImageID("I_ROUND"), ImageID("I_CROSS"), 1.5f, new AnchorLayoutParams(NONE, NONE, NONE, 100.0f, true)); + PSPButton *triangle = new PSPButton(CTRL_TRIANGLE, "Triangle button", ImageID("I_ROUND_LINE"), ImageID("I_ROUND"), ImageID("I_TRIANGLE"), 1.5f, new AnchorLayoutParams(NONE, 100.0f, NONE, NONE, true)); + PSPButton *square = new PSPButton(CTRL_SQUARE, "Square button", ImageID("I_ROUND_LINE"), ImageID("I_ROUND"), ImageID("I_SQUARE"), 1.5f, new AnchorLayoutParams(100.0f, NONE, NONE, NONE, true)); + circle->SetForceVisible(true); + cross->SetForceVisible(true); + triangle->SetForceVisible(true); + square->SetForceVisible(true); + rightSide->Add(circle); + rightSide->Add(cross); + rightSide->Add(triangle); + rightSide->Add(square); + break; + } + case TILT_TRIGGER_BUTTONS: + { + PSPButton *lTrigger = new PSPButton(CTRL_LTRIGGER, "Left shoulder button", ImageID("I_SHOULDER_LINE"), ImageID("I_SHOULDER"), ImageID("I_L"), 1.5f, new AnchorLayoutParams(100.0f, NONE, NONE, NONE, true)); + PSPButton *rTrigger = new PSPButton(CTRL_RTRIGGER, "Right shoulder button", ImageID("I_SHOULDER_LINE"), ImageID("I_SHOULDER"), ImageID("I_R"), 1.5f, new AnchorLayoutParams(NONE, NONE, 100.0f, NONE, true)); + rTrigger->FlipImageH(true); + lTrigger->SetForceVisible(true); + rTrigger->SetForceVisible(true); + rightSide->Add(lTrigger); + rightSide->Add(rTrigger); + break; + } + } + } LinearLayout *settings = new LinearLayoutList(ORIENT_VERTICAL); settings->SetSpacing(0); settings->Add(new ItemHeader(co->T("Calibration"))); - InfoItem *calibrationInfo = new InfoItem(co->T("To Calibrate", "Keep device on a flat surface and press calibrate."), ""); + TextView *calibrationInfo = new TextView(co->T("To Calibrate", "Hold device at your preferred angle and press Calibrate.")); + calibrationInfo->SetSmall(true); + calibrationInfo->SetPadding(5); settings->Add(calibrationInfo); Choice *calibrate = new Choice(co->T("Calibrate")); calibrate->OnClick.Handle(this, &TiltAnalogSettingsScreen::OnCalibrate); @@ -88,7 +131,9 @@ UI::EventReturn TiltAnalogSettingsScreen::OnCalibrate(UI::EventParams &e) { void TiltAnalogSettingsScreen::update() { UIDialogScreenWithGameBackground::update(); - tilt_->SetXY( - Clamp(TiltEventProcessor::rawTiltAnalogX, -1.0f, 1.0f), - Clamp(TiltEventProcessor::rawTiltAnalogY, -1.0f, 1.0f)); + if (tilt_) { + tilt_->SetXY( + Clamp(TiltEventProcessor::rawTiltAnalogX, -1.0f, 1.0f), + Clamp(TiltEventProcessor::rawTiltAnalogY, -1.0f, 1.0f)); + } } diff --git a/UI/TiltAnalogSettingsScreen.h b/UI/TiltAnalogSettingsScreen.h index bcbc5ae446..1c338e5e94 100644 --- a/UI/TiltAnalogSettingsScreen.h +++ b/UI/TiltAnalogSettingsScreen.h @@ -22,6 +22,7 @@ #include "MiscScreens.h" class JoystickHistoryView; +class GamepadView; class TiltAnalogSettingsScreen : public UIDialogScreenWithGameBackground { public: @@ -37,4 +38,5 @@ private: Lin::Vec3 down_{}; JoystickHistoryView *tilt_ = nullptr; + GamepadView *gpView_ = nullptr; }; diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 63a606ba18..baaff2697f 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -103,7 +103,7 @@ Thin borders = ‎حدود رفيعة Tilt Input Type = ‎نوع الإدخال المنطقة Tilt Sensitivity along X axis = ‎X حساسية المنطقة علي طول محور Tilt Sensitivity along Y axis = ‎Y حساسية المنطقة علي طول محور -To Calibrate = ‎لتقوم بالمعايرة, ضع الجهاز عل سطح مستوي وإضغط "معايرة". +To Calibrate = امسك الجهاز في الزاوية المفضلة لديك واضغط على "معايرة". Toggle mode = Toggle mode Touch Control Visibility = ‎شفافية تحكم اللمس Use custom right analog = Use custom right analog diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 4b7f6cf63d..1bf32d8cc4 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index ffced9f819..41c65e9b1e 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 90b77d8c2d..d385060fac 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -95,7 +95,7 @@ Thin borders = Vores fines Tilt Input Type = Tipus de control de l'acceleròmetre Tilt Sensitivity along X axis = Sensibilitat d'inclinació de l'eix X Tilt Sensitivity along Y axis = Sensibilitat d'inclinació de l'eix Y -To Calibrate = Poseu l'aparell en una superfície plana i premeu "Calibrar". +To Calibrate = Mantingueu el dispositiu a l'angle que preferiu i premeu "Calibrar". Toggle mode = Toggle mode Touch Control Visibility = Visibilitat del control tàctil Use custom right analog = Utilitzar stick dret personalitzat diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 3ca4742326..232d9058c7 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -95,7 +95,7 @@ Thin borders = Tenké okraje Tilt Input Type = Typ vstupu náklonu Tilt Sensitivity along X axis = Citlivost náklonu podle osy X Tilt Sensitivity along Y axis = Citlivost náklonu podle osy Y -To Calibrate = Mějte zařízení na rovném povrchu a stiskněte "Kalibrovat". +To Calibrate = Držte zařízení ve vašem preferovaném úhlu a stiskněte "Kalibrovat". Toggle mode = Toggle mode Touch Control Visibility = Viditelnost dotykového ovládání Use custom right analog = Use custom right analog diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index bc879541b8..65f9cc2389 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -95,7 +95,7 @@ Thin borders = Tynde rammer Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt følsomhed langs X aksen Tilt Sensitivity along Y axis = Tilt følsomhed langs Y aksen -To Calibrate = Hold enheden på flad overflade for at kalibrere og tryk på "Kalibrer". +To Calibrate = Hold enheden i din foretrukne vinkel, og tryk på "Kalibrer". Toggle mode = Toggle mode Touch Control Visibility = Touch kontrol synlighed Use custom right analog = Use custom right analog diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index bdf459d498..cc9bb2868d 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -95,7 +95,7 @@ Thin borders = Dünne Ränder Tilt Input Type = Eingabetyp für Neigen Tilt Sensitivity along X axis = Neigungsempfindlichkeit über X-Achse Tilt Sensitivity along Y axis = Neigungsempfindlichkeit über Y-Achse -To Calibrate = Legen Sie ihr Gerät auf eine flache Oberfläche und drücken "Kalibrieren". +To Calibrate = Halten Sie das Gerät in Ihrem bevorzugten Winkel und drücken Sie "Kalibrieren". Toggle mode = Toggle mode Touch Control Visibility = Sichtbarkeit der Touchsteuerung Use custom right analog = Use custom right analog diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index a94075c66a..af3d9caab0 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index ca734db5c0..f0edddece7 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -118,7 +118,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Repeat mode = Repeat mode Touch Control Visibility = Touch control visibility diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 7a9904ee04..afe3b280e9 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -95,7 +95,7 @@ Thin borders = Bordes finos Tilt Input Type = Tipo de control del acelerómetro Tilt Sensitivity along X axis = Sensibilidad de inclinación del eje X Tilt Sensitivity along Y axis = Sensibilidad de inclinación del eje Y -To Calibrate = Pon el aparato en una superficie plana y presiona "Calibrar". +To Calibrate = Sostenga el dispositivo en su ángulo preferido y presione "Calibrar". Toggle mode = Toggle mode Touch Control Visibility = Visibilidad del control táctil Use custom right analog = Usar stick derecho personalizado diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 46b110b1b3..240e0a0fb5 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -95,7 +95,7 @@ Thin borders = Bordes finos Tilt Input Type = Tipo de control del acelerómetro Tilt Sensitivity along X axis = Sensibilidad de inclinación del eje X Tilt Sensitivity along Y axis = Sensibilidad de inclinación del eje Y -To Calibrate = Pon el aparato en una superficie plana y presiona "Calibrar". +To Calibrate = Sostenga el dispositivo en su ángulo preferido y presione "Calibrar". Toggle mode = Modo de alternancia Touch Control Visibility = Visibilidad de pantalla táctil Use custom right analog = Usar Analog derecho personalizado diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 24c7bad3f6..764ce6b32f 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -95,7 +95,7 @@ Thin borders = ‎نوار نازک Tilt Input Type = ‎...استفاده از شتاب سنج به عنوان Tilt Sensitivity along X axis = ‎X حساسیت شتاب سنج در جهت Tilt Sensitivity along Y axis = ‎Y حساسیت شتاب سنج در جهت -To Calibrate = ‎برای کالیبره کردن، دستگاه را روی سطح صافی گذاشته و "کالیبره کردن" را بزنید +To Calibrate = دستگاه را در زاویه دلخواه نگه دارید و " ‎کالیبره کردن" را فشار دهید. Toggle mode = حالت تعویض Touch Control Visibility = ‎نشان دادن دکمه های تاچ Use custom right analog = استفاده شخصی سازی شده انالوگ سمت راست diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 6ab613a0f0..bf0571bde3 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 8282f860f7..904b75e67d 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -95,7 +95,7 @@ Thin borders = Bordures fines Tilt Input Type = Type inclinaison analogique Tilt Sensitivity along X axis = Sensibilité de l'inclinaison analogique sur l'axe X Tilt Sensitivity along Y axis = Sensibilité de l'inclinaison analogique sur l'axe Y -To Calibrate = Poser l'appareil sur une surface plane et presser "Étalonner". +To Calibrate = Tenez l'appareil à votre angle préféré et appuyez sur "Calibrer". Toggle mode = Toggle mode Touch Control Visibility = Visibilité des commandes tactiles Use custom right analog = Utiliser le stick droit personnalisé diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index a0d0d08fbf..ce6ffa67c4 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -95,7 +95,7 @@ Thin borders = Bordes finos Tilt Input Type = Tipo de control do acelerómetro Tilt Sensitivity along X axis = Sensibilidade de inclinación do eixe X Tilt Sensitivity along Y axis = Sensibilidade de inclinación do eixe Y -To Calibrate = Pon o aparello nunha superficie plana e presiona "Calibrar". +To Calibrate = Sostenga el dispositivo en su ángulo preferido y presione "Calibrar". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 6f8721e3e3..32e578b976 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -95,7 +95,7 @@ Thin borders = Λεπτά διαχωριστικά Tilt Input Type = Τύπο εισόδου κλίσης Tilt Sensitivity along X axis = Ευαισθησία οριζόντιου άξονα Tilt Sensitivity along Y axis = Ευαισθησία κάθετου άξονα -To Calibrate = Για τη βαθμονόμηση, αφήστε τη συσκευή σε μια επίπεδη επιφάνεια και πατήστε "Βαθμονόμηση". +To Calibrate = Κρατήστε τη συσκευή στη γωνία που προτιμάτε και πατήστε "Βαθμονόμηση". Toggle mode = Toggle mode Touch Control Visibility = Ορατότητα πλήκτρων αφής Use custom right analog = Use custom right analog diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index ed9450790e..5bac3ff1d0 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index b593b24fcb..e68f294de7 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 04d54edf64..e746a0be33 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -95,7 +95,7 @@ Thin borders = Tanki rubovi Tilt Input Type = Tip ulaza tilta Tilt Sensitivity along X axis = Tilt senzitivnost X osi Tilt Sensitivity along Y axis = Tilt senzitivnost Y osi -To Calibrate = Drži uređaj na ravnoj površini i pritisni "Kalibriraj". +To Calibrate = Držite uređaj pod željenim kutom i pritisnite "Kalibriraj". Toggle mode = Toggle mode Touch Control Visibility = Vidljivost dodirnih kontroli Use custom right analog = Use custom right analog diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index bb54e06831..de9663c72d 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -95,7 +95,7 @@ Thin borders = Vékony szélek Tilt Input Type = Döntési bevitel típusa Tilt Sensitivity along X axis = X tengely menti döntés érzékenysége Tilt Sensitivity along Y axis = X tengely menti döntés érzékenysége -To Calibrate = Hagyd az eszközt egy sima felületen, és nyomd meg a "Kalibrálás"-t. +To Calibrate = Tartsa a készüléket a kívánt szögben, és nyomja meg a "Kalibrálás" gombot. Toggle mode = Toggle mode Touch Control Visibility = Érintőképernyős irányítás láthatósága Use custom right analog = Személyre szabott jobb analog kar diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index f7b80d715b..1b9ec4ee4e 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -95,7 +95,7 @@ Thin borders = Garis batas tipis Tilt Input Type = Jenis masukan kemiringan Tilt Sensitivity along X axis = Sensitivitas kemiringan sepanjang sumbu X Tilt Sensitivity along Y axis = Sensitivitas kemiringan sepanjang sumbu Y -To Calibrate = Taruh perangkat di permukaan datar dan tekan "Kalibrasi". +To Calibrate = Pegang perangkat pada sudut pilihan Anda dan tekan "Kalibrasi". Toggle mode = Mode peralihan Touch Control Visibility = Visibilitas kontrol sentuh Use custom right analog = Gunakan analog kanan kustom diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index e6d4aeca51..8f7dd318b7 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -94,7 +94,7 @@ Thin borders = Bordi fini Tilt Input Type = Tipo di Input Inclinazione Tilt Sensitivity along X axis = Inverti Sensibilità sull'asse X Tilt Sensitivity along Y axis = Inverti Sensibilità sull'asse Y -To Calibrate = Mantenere il dispositivo su una superficie piatta e premere "Calibra". +To Calibrate = Tieni il dispositivo all'angolazione che preferisci e premi "Calibra". Toggle mode = Scambia modalità Repeat mode = Modalità ripeti Touch Control Visibility = Visibilità controlli Touch diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index b1967d4733..ceb63df9c5 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -95,7 +95,7 @@ Thin borders = 薄い枠線 Tilt Input Type = 傾き入力のタイプ Tilt Sensitivity along X axis = X軸の傾きの感度 Tilt Sensitivity along Y axis = Y軸の傾きの感度 -To Calibrate = デバイスを水平に置いて「キャリブレート」を押してください +To Calibrate = 好みの角度でデバイスを持ち、「キャリブレート」を押します。 Toggle mode = トグル(切り替え)ボタンとして使用する Touch Control Visibility = タッチコントロールの表示 Use custom right analog = カスタム右アナログを使用する diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 50ed265ce5..8043ef27ee 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -95,7 +95,7 @@ Thin borders = Watesan lancip Tilt Input Type = Ngiringake Tipe input Tilt Sensitivity along X axis = Ngiringake sensitivitas bebarengan X sumbu Tilt Sensitivity along Y axis = Ngiringake sensitivitas bebarengan Y sumbu -To Calibrate = Sijine piranti ing warata lan pencet "Kalibrasi". +To Calibrate = Pegang perangkat pada sudut pilihan Anda dan tekan "Kalibrasi". Toggle mode = Toggle mode Touch Control Visibility = Visibilitas kontrol sentuh Use custom right analog = Use custom right analog diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 2b7ad25e6f..22a20734ca 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -94,7 +94,7 @@ Thin borders = 얇은 테두리 Tilt Input Type = 기울기 입력 유형 Tilt Sensitivity along X axis = X 축 기울기 감도 Tilt Sensitivity along Y axis = Y 축 기울기 감도 -To Calibrate = 장치를 평평한 표면에 놓고 "보정"을 누르세요. +To Calibrate = 원하는 각도로 장치를 잡고 "보정"을 누르십시오. Toggle mode = 토글 모드 Repeat mode = 반복 모드 Touch Control Visibility = 터치 제어 가시성 diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index dd5ce1b1af..62cf023aa7 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -95,7 +95,7 @@ Thin borders = Ploni kraštai Tilt Input Type = Pakreipimo įvedimo įrenginio tipas Tilt Sensitivity along X axis = Pakreipimo sensitivacija palei X ašį Tilt Sensitivity along Y axis = Pakreipimo sensitivacija palei Y ašį -To Calibrate = Laikykite įrenginį ant tiesaus paviršiaus ir paspauskite "Kalibruoti". +To Calibrate = Laikykite įrenginį norimu kampu ir paspauskite "Kalibruoti". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 898e109a61..a82fd0f045 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -95,7 +95,7 @@ Thin borders = Tepian tipis Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold device at your preferred angle and press "Calibrate". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 2eb996ca98..3b689e9f52 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -95,7 +95,7 @@ Thin borders = Dunne randen Tilt Input Type = Invoertype voor kantelen Tilt Sensitivity along X axis = Kantelgevoeligheid op X-as Tilt Sensitivity along Y axis = Kantelgevoeligheid op Y-as -To Calibrate = Zet het apparaat op een vlakke ondergrond en druk op "Kalibreren". +To Calibrate = Houd het apparaat in de gewenste hoek en druk op "Kalibreren". Toggle mode = Toggle mode Touch Control Visibility = Zichtbaarheid touchbesturing Use custom right analog = Use custom right analog diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index afd0f81d30..0cc4605468 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -33,7 +33,7 @@ Button Binding = Button Binding Button Opacity = Knappgenomsiktighet Button style = Button style Calibrate Analog Stick = Calibrate Analog Stick -Calibrate = Calibrate +Calibrate = Kalibrer Calibrated = Calibrated Calibration = Calibration Circular stick input = Circular stick input @@ -95,7 +95,7 @@ Thin borders = Thin borders Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis -To Calibrate = Keep device on a flat surface and press "Calibrate". +To Calibrate = Hold enheten i ønsket vinkel og trykk "Kalibrer". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 0a788c74b3..ed797927cb 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -95,7 +95,7 @@ Thin borders = Cienkie krawędzie Tilt Input Type = Typ przechyłu Tilt Sensitivity along X axis = Czułość przechyłu wzdłuż osi X Tilt Sensitivity along Y axis = Czułość przechyłu wzdłuż osi Y -To Calibrate = Połóż urządzenie na płaskiej powierzchni i wciśnij "Kalibracja". +To Calibrate = Trzymaj urządzenie pod preferowanym kątem i naciśnij „Kalibracja”. Toggle mode = Zmień tryb Touch Control Visibility = Kontroler dotykowy (widoczny) Use custom right analog = Use custom right analog diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index dbdd9d02cb..3f8239f0d1 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -118,7 +118,7 @@ Thin borders = Bordas finas Tilt Input Type = Controle da entrada da inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y -To Calibrate = Mantenha o dispositivo numa superfície plana e pressione "Calibrar". +To Calibrate = Segure o dispositivo em seu ângulo preferido e pressione "Calibrar". Toggle mode = Alternar modo Repeat mode = Modo de repetição Touch Control Visibility = Visibilidade do controle de toque diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 03cb4bb3cf..1ea0793de9 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -118,7 +118,7 @@ Thin borders = Bordas Finas Tilt Input Type = Controlo da entrada de inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y -To Calibrate = Mantenha o dispositivo numa superfície plana e pressione "Calibrar". +To Calibrate = Segure o dispositivo em seu ângulo preferido e pressione "Calibrar". Toggle mode = Alternar modo Repeat mode = Modo de repetição Touch Control Visibility = Visibilidade do controlo de toque diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 0bddfd1a36..ebfce6e590 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -95,7 +95,7 @@ Thin borders = Margini subțiri Tilt Input Type = Tip intrare prin înclinare Tilt Sensitivity along X axis = Inversează sensitivitatea pe axa X Tilt Sensitivity along Y axis = Inversează sensitivitatea pe axa Y -To Calibrate = Tine aparatul pe o suprafață plată și apasă "Calibrate". +To Calibrate = Țineți dispozitivul în unghiul dorit și apăsați „Calibrați”. Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index c23bc92d70..ad9df9625b 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -95,7 +95,7 @@ Thin borders = Тонкие границы Tilt Input Type = Тип управления наклоном Tilt Sensitivity along X axis = Чувствительность наклона вдоль X Tilt Sensitivity along Y axis = Чувствительность наклона вдоль Y -To Calibrate = Положите устройство на ровную поверхность и нажмите "Калибровать" +To Calibrate = Держите устройство под нужным вам углом и нажмите «Калибровать». Toggle mode = Режим переключателя Touch Control Visibility = Видимость элементов управления Use custom right analog = Использовать настраиваемый правый аналоговый стик diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index c50da361b5..cac07b29d0 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -95,7 +95,7 @@ Thin borders = Tunna kanter Tilt Input Type = Lutningstyp Tilt Sensitivity along X axis = Lutningskänslighet X Tilt Sensitivity along Y axis = Lutningskänslighet Y -To Calibrate = Lägg enheten på en plan yta och tryck "Kalibrera" för kalibrering. +To Calibrate = Håll enheten i önskad vinkel och tryck på "Kalibrera". Toggle mode = Toggle mode Touch Control Visibility = Touch control visibility Use custom right analog = Use custom right analog diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 5491e7175b..0ba426b45f 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -95,7 +95,7 @@ Thin borders = แบบขอบบาง Tilt Input Type = รูปแบบนำเข้าการเอียง Tilt Sensitivity along X axis = ความไวต่อการตอบสนองเอียงตามแกน X Tilt Sensitivity along Y axis = ความไวต่อการตอบสนองเอียงตามแกน Y -To Calibrate = ให้วางอุปกรณ์ลงบนพื้นราบ และกด "สอบเทียบสมดุล" +To Calibrate = ถืออุปกรณ์ในมุมที่คุณต้องการแล้วกด "สอบเทียบสมดุล" Toggle mode = โหมดสลับปุ่มกด Touch Control Visibility = การแสดงผลปุ่มควบคุมแบบสัมผัส Use custom right analog = ใช้การปรับเปลี่ยนปุ่มอนาล็อกขวา diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index c4600b33a7..c8ba327a1e 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -95,7 +95,7 @@ Thin borders = İnce kenarlar Tilt Input Type = Eğim giriş türü Tilt Sensitivity along X axis = X ekseni boyunca eğim hassasiyeti Tilt Sensitivity along Y axis = Y ekseni boyunca eğim hassasiyeti -To Calibrate = Kalibre etmek için cihazı düz bir zemine yerleştirin ve "Kalibre et" tuşuna basın. +To Calibrate = Cihazı tercih ettiğiniz açıda tutun ve "Kalibre" ya basın. Toggle mode = Geçiş modu Touch Control Visibility = Dokunmatik kontrol görünürlüğü Use custom right analog = Özel sağ analog kullan diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 55570aa4d2..ffcb3a1146 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -95,7 +95,7 @@ Thin borders = Тонкі границі (збільшення) Tilt Input Type = Тип управління нахилом Tilt Sensitivity along X axis = Чутливість нахилу по осі X Tilt Sensitivity along Y axis = Чутливість нахилу по осі Y -To Calibrate = Для калібрування поставте пристрій на рівну поверхню і натисніть "Калібрувати". +To Calibrate = Тримайте пристрій під потрібним кутом і натисніть «Калібрувати». Toggle mode = Toggle mode Touch Control Visibility = Видимість елементів управління Use custom right analog = Використовуйте кастомний правий аналог diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index 7e8964304b..a0cb9af7bc 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -95,7 +95,7 @@ Thin borders = Viền mỏng Tilt Input Type = Đầu vào kiểu nghiêng Tilt Sensitivity along X axis = Độ nhạy nghiêng theo chiều x Tilt Sensitivity along Y axis = Độ nhạy nghiêng theo chiều y -To Calibrate = Giữ thiết bị cân bằng và bấm "chỉnh cân bằng". +To Calibrate = Giữ thiết bị ở góc ưa thích của bạn và nhấn "chỉnh cân bằng" Toggle mode = Toggle mode Touch Control Visibility = Hiển thị điều khiển cảm ứng Use custom right analog = Use custom right analog diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index dac0af37a2..00e944b777 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -95,7 +95,7 @@ Thin borders = 细边框 Tilt Input Type = 重力感应按键 Tilt Sensitivity along X axis = 沿X轴倾斜灵敏度 Tilt Sensitivity along Y axis = 沿Y轴倾斜灵敏度 -To Calibrate = 请放好设备在水平面上,然后按"校准" +To Calibrate = 以您喜欢的角度握住设备,然后按“校准”。 Toggle mode = 开关模式(只需按一次) Touch Control Visibility = 显示的按键 Use custom right analog = 自定义右摇杆用途 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 26efd6f82b..7a66b5dcde 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -94,7 +94,7 @@ Thin borders = 特細框線 Tilt Input Type = 傾斜輸入類型 Tilt Sensitivity along X axis = 沿 X 軸傾斜敏感度 Tilt Sensitivity along Y axis = 沿 Y 軸傾斜敏感度 -To Calibrate = 把裝置放置水平表面,然後按下「校正」。 +To Calibrate = 以您喜歡的角度握住設備,然後按“校準”。 Toggle mode = 切換模式 Repeat mode = 重複模式 Touch Control Visibility = 觸控控制可見性 From 6b7a51d73e09b477c3c9e6ac91a70d857b7135f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 10:29:16 +0100 Subject: [PATCH 013/424] Move tilt type selector into the customization dialog --- UI/GameSettingsScreen.cpp | 10 ---------- UI/TiltAnalogSettingsScreen.cpp | 25 ++++++++++++++++++++----- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 276ee7cda3..73ddad201d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -694,9 +694,6 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); - static const char *tiltTypes[] = { "None (Disabled)", "Analog Stick", "D-PAD", "PSP Action Buttons", "L/R Trigger Buttons" }; - controlsSettings->Add(new PopupMultiChoice(&g_Config.iTiltInputType, co->T("Tilt Input Type"), tiltTypes, 0, ARRAY_SIZE(tiltTypes), co->GetName(), screenManager()))->OnClick.Handle(this, &GameSettingsScreen::OnTiltTypeChange); - Choice *customizeTilt = controlsSettings->Add(new Choice(co->T("Customize tilt"))); customizeTilt->OnClick.Handle(this, &GameSettingsScreen::OnTiltCustomize); customizeTilt->SetEnabledFunc([] { @@ -1709,13 +1706,6 @@ UI::EventReturn GameSettingsScreen::OnTouchControlLayout(UI::EventParams &e) { return UI::EVENT_DONE; } -//when the tilt event type is modified, we need to reset all tilt settings. -//refer to the ResetTiltEvents() function for a detailed explanation. -UI::EventReturn GameSettingsScreen::OnTiltTypeChange(UI::EventParams &e) { - TiltEventProcessor::ResetTiltEvents(); - return UI::EVENT_DONE; -}; - UI::EventReturn GameSettingsScreen::OnTiltCustomize(UI::EventParams &e) { screenManager()->push(new TiltAnalogSettingsScreen(gamePath_)); return UI::EVENT_DONE; diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index c5827c4394..16246ae098 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -83,10 +83,24 @@ void TiltAnalogSettingsScreen::CreateViews() { } } + auto enabledFunc = [=]() -> bool { + return g_Config.iTiltInputType != 0; + }; + LinearLayout *settings = new LinearLayoutList(ORIENT_VERTICAL); settings->SetSpacing(0); + static const char *tiltTypes[] = { "None (Disabled)", "Analog Stick", "D-PAD", "PSP Action Buttons", "L/R Trigger Buttons" }; + settings->Add(new PopupMultiChoice(&g_Config.iTiltInputType, co->T("Tilt Input Type"), tiltTypes, 0, ARRAY_SIZE(tiltTypes), co->GetName(), screenManager()))->OnChoice.Add( + [=](UI::EventParams &p) { + //when the tilt event type is modified, we need to reset all tilt settings. + //refer to the ResetTiltEvents() function for a detailed explanation. + TiltEventProcessor::ResetTiltEvents(); + RecreateViews(); + return UI::EVENT_DONE; + }); + settings->Add(new ItemHeader(co->T("Calibration"))); TextView *calibrationInfo = new TextView(co->T("To Calibrate", "Hold device at your preferred angle and press Calibrate.")); calibrationInfo->SetSmall(true); @@ -94,16 +108,17 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(calibrationInfo); Choice *calibrate = new Choice(co->T("Calibrate")); calibrate->OnClick.Handle(this, &TiltAnalogSettingsScreen::OnCalibrate); + calibrate->SetEnabledFunc(enabledFunc); settings->Add(calibrate); settings->Add(new ItemHeader(co->T("Invert Axes"))); - settings->Add(new CheckBox(&g_Config.bInvertTiltX, co->T("Invert Tilt along X axis"))); - settings->Add(new CheckBox(&g_Config.bInvertTiltY, co->T("Invert Tilt along Y axis"))); + settings->Add(new CheckBox(&g_Config.bInvertTiltX, co->T("Invert Tilt along X axis")))->SetEnabledFunc(enabledFunc); + settings->Add(new CheckBox(&g_Config.bInvertTiltY, co->T("Invert Tilt along Y axis")))->SetEnabledFunc(enabledFunc); settings->Add(new ItemHeader(co->T("Sensitivity"))); - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(), "%")); - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%")); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0")); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); + settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); menuRoot->Add(settings); From cdca958781ef0653b8ddd283c5c35571165fbb91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 10:53:42 +0100 Subject: [PATCH 014/424] Change "Customize tilt..." to "Tilt control setup" --- Tools/langtool/src/main.rs | 40 +++++++++++++++++++++++++++++++++ Tools/langtool/src/section.rs | 22 ++++++++++++++++++ UI/GameSettingsScreen.cpp | 2 +- UI/TiltAnalogSettingsScreen.cpp | 3 ++- assets/lang/ar_AE.ini | 2 +- assets/lang/az_AZ.ini | 2 +- assets/lang/bg_BG.ini | 2 +- assets/lang/ca_ES.ini | 2 +- assets/lang/cz_CZ.ini | 2 +- assets/lang/da_DK.ini | 2 +- assets/lang/de_DE.ini | 2 +- assets/lang/dr_ID.ini | 2 +- assets/lang/en_US.ini | 2 +- assets/lang/es_ES.ini | 2 +- assets/lang/es_LA.ini | 2 +- assets/lang/fa_IR.ini | 2 +- assets/lang/fi_FI.ini | 2 +- assets/lang/fr_FR.ini | 2 +- assets/lang/gl_ES.ini | 2 +- assets/lang/gr_EL.ini | 2 +- assets/lang/he_IL.ini | 2 +- assets/lang/he_IL_invert.ini | 2 +- assets/lang/hr_HR.ini | 2 +- assets/lang/hu_HU.ini | 2 +- assets/lang/id_ID.ini | 2 +- assets/lang/it_IT.ini | 2 +- assets/lang/ja_JP.ini | 2 +- assets/lang/jv_ID.ini | 2 +- assets/lang/ko_KR.ini | 2 +- assets/lang/lo_LA.ini | 2 +- assets/lang/lt-LT.ini | 2 +- assets/lang/ms_MY.ini | 2 +- assets/lang/nl_NL.ini | 2 +- assets/lang/no_NO.ini | 2 +- assets/lang/pl_PL.ini | 2 +- assets/lang/pt_BR.ini | 2 +- assets/lang/pt_PT.ini | 2 +- assets/lang/ro_RO.ini | 2 +- assets/lang/ru_RU.ini | 2 +- assets/lang/sv_SE.ini | 2 +- assets/lang/tg_PH.ini | 2 +- assets/lang/th_TH.ini | 2 +- assets/lang/tr_TR.ini | 2 +- assets/lang/uk_UA.ini | 2 +- assets/lang/vi_VN.ini | 2 +- assets/lang/zh_CN.ini | 2 +- assets/lang/zh_TW.ini | 2 +- 47 files changed, 108 insertions(+), 45 deletions(-) diff --git a/Tools/langtool/src/main.rs b/Tools/langtool/src/main.rs index 99107fff3a..45b79e50f7 100644 --- a/Tools/langtool/src/main.rs +++ b/Tools/langtool/src/main.rs @@ -29,6 +29,14 @@ enum Command { new: String, key: String, }, + RenameKey { + section: String, + old: String, + new: String, + }, + SortSection { + section: String, + }, RemoveKey { section: String, key: String, @@ -108,6 +116,26 @@ fn add_new_key(target_ini: &mut IniFile, section: &str, key: &str) -> io::Result Ok(()) } +fn rename_key(target_ini: &mut IniFile, section: &str, old: &str, new: &str) -> io::Result<()> { + if let Some(section) = target_ini.get_section_mut(section) { + let _ = section.rename_key(old, new); + } else { + println!("No section {}", section); + } + Ok(()) +} + +fn sort_section(target_ini: &mut IniFile, section: &str) -> io::Result<()> { + if let Some(section) = target_ini.get_section_mut(section) { + section.sort(); + } else { + println!("No section {}", section); + } + Ok(()) +} + +// TODO: Look into using https://github.com/Byron/google-apis-rs/tree/main/gen/translate2 for initial translations. + fn main() { let opt = Opt::from_args(); @@ -158,6 +186,12 @@ fn main() { Command::RemoveUnknownLines {} => { deal_with_unknown_lines(&reference_ini, &mut target_ini, true).unwrap(); } + Command::SortSection { ref section } => sort_section(&mut target_ini, section).unwrap(), + Command::RenameKey { + ref section, + ref old, + ref new, + } => rename_key(&mut target_ini, section, old, new).unwrap(), Command::AddNewKey { ref section, ref key, @@ -192,6 +226,12 @@ fn main() { } => { add_new_key(&mut reference_ini, section, key).unwrap(); } + Command::SortSection { ref section } => sort_section(&mut reference_ini, section).unwrap(), + Command::RenameKey { + ref section, + ref old, + ref new, + } => rename_key(&mut reference_ini, section, old, new).unwrap(), Command::MoveKey { ref old, ref new, diff --git a/Tools/langtool/src/section.rs b/Tools/langtool/src/section.rs index f57c2e3563..0ccfad7a48 100644 --- a/Tools/langtool/src/section.rs +++ b/Tools/langtool/src/section.rs @@ -82,6 +82,28 @@ impl Section { true } + pub fn rename_key(&mut self, old: &str, new: &str) { + let prefix = old.to_owned() + " ="; + let mut found_index = None; + for (index, line) in self.lines.iter().enumerate() { + if line.starts_with(&prefix) { + found_index = Some(index); + } + } + if let Some(index) = found_index { + let line = self.lines.remove(index); + let line = new.to_owned() + " =" + line.strip_prefix(&prefix).unwrap(); + self.insert_line_if_missing(&line); + } else { + let name = &self.name; + println!("didn't find a line starting with {prefix} in section {name}"); + } + } + + pub fn sort(&mut self) { + self.lines.sort(); + } + pub fn comment_out_lines_if_not_in(&mut self, other: &Section) { // Brute force (O(n^2)). Bad but not a problem. diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 73ddad201d..35d624026d 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -694,7 +694,7 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); - Choice *customizeTilt = controlsSettings->Add(new Choice(co->T("Customize tilt"))); + Choice *customizeTilt = controlsSettings->Add(new Choice(co->T("Tilt control setup"))); customizeTilt->OnClick.Handle(this, &GameSettingsScreen::OnTiltCustomize); customizeTilt->SetEnabledFunc([] { return g_Config.iTiltInputType != 0; diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index 16246ae098..6dbbdcfab2 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -91,7 +91,9 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->SetSpacing(0); + static const char *tiltTypes[] = { "None (Disabled)", "Analog Stick", "D-PAD", "PSP Action Buttons", "L/R Trigger Buttons" }; + settings->Add(new ItemHeader(co->T("Tilt control setup"))); settings->Add(new PopupMultiChoice(&g_Config.iTiltInputType, co->T("Tilt Input Type"), tiltTypes, 0, ARRAY_SIZE(tiltTypes), co->GetName(), screenManager()))->OnChoice.Add( [=](UI::EventParams &p) { //when the tilt event type is modified, we need to reset all tilt settings. @@ -100,7 +102,6 @@ void TiltAnalogSettingsScreen::CreateViews() { RecreateViews(); return UI::EVENT_DONE; }); - settings->Add(new ItemHeader(co->T("Calibration"))); TextView *calibrationInfo = new TextView(co->T("To Calibrate", "Hold device at your preferred angle and press Calibrate.")); calibrationInfo->SetSmall(true); diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index baaff2697f..091a2856be 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -51,7 +51,6 @@ Control Mapping = ‎تخطيط التحكم Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = ‎تعديل نسق إعدادات اللمس... -Customize tilt = ‎إمالة مخصصة... D-PAD = D-Pad Deadzone radius = ‎مساحة المنطقة الميتة Disable D-Pad diagonals (4-way touch) = ‎(4طرق للمس)تعطيل أقطار D-Pad @@ -100,6 +99,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = ‎حدود رفيعة +Tilt control setup = ‎إمالة مخصصة... Tilt Input Type = ‎نوع الإدخال المنطقة Tilt Sensitivity along X axis = ‎X حساسية المنطقة علي طول محور Tilt Sensitivity along Y axis = ‎Y حساسية المنطقة علي طول محور diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 1bf32d8cc4..659165a6db 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -43,7 +43,6 @@ Control Mapping = Control mapping Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index 41c65e9b1e..b53040462f 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -43,7 +43,6 @@ Control Mapping = Избиране на контроли Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone радиус Disable D-Pad diagonals (4-way touch) = Изключи D-Pad диагонали (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index d385060fac..1fc5d21d19 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -43,7 +43,6 @@ Control Mapping = Assignar botons Custom Key Setting = Ajust de tecla personalitzada Customize = Personalitzar Customize Touch Controls = Editar pantalla tàctil -Customize tilt = Personalitzar acceleròmetre D-PAD = Creueta Deadzone radius = Ràdio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonals de creueta @@ -92,6 +91,7 @@ Swipe = Lliscar cap a Swipe sensitivity = Sensibilitat de lliscament Swipe smoothing = Fluïdesa del lliscat Thin borders = Vores fines +Tilt control setup = Personalitzar acceleròmetre Tilt Input Type = Tipus de control de l'acceleròmetre Tilt Sensitivity along X axis = Sensibilitat d'inclinació de l'eix X Tilt Sensitivity along Y axis = Sensibilitat d'inclinació de l'eix Y diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 232d9058c7..1c4bd4f103 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -43,7 +43,6 @@ Control Mapping = Mapování ovládání Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Upravit rozdělení dotykového ovládání... -Customize tilt = Přizpůsobit náklon... D-PAD = D-Pad Deadzone radius = Poloměr mrtvé zóny Disable D-Pad diagonals (4-way touch) = Zakázat diagonální D-Pad (čtyřsměrný dotek) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tenké okraje +Tilt control setup = Přizpůsobit náklon... Tilt Input Type = Typ vstupu náklonu Tilt Sensitivity along X axis = Citlivost náklonu podle osy X Tilt Sensitivity along Y axis = Citlivost náklonu podle osy Y diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 65f9cc2389..9c1da40995 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -43,7 +43,6 @@ Control Mapping = Ændre tasteplaceringen Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Tilpas layout... -Customize tilt = Tilpas tilt... D-PAD = D-Pad Deadzone radius = Dødzone radius Disable D-Pad diagonals (4-way touch) = Deaktiver D-Pad diagonaler (4-vejs touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tynde rammer +Tilt control setup = Tilpas tilt... Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt følsomhed langs X aksen Tilt Sensitivity along Y axis = Tilt følsomhed langs Y aksen diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index cc9bb2868d..6b91074989 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -43,7 +43,6 @@ Control Mapping = Tastenbelegung ändern Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Layout anpassen -Customize tilt = Neigung anpassen D-PAD = Steuerkreuz Deadzone radius = Radius für tote Zone Disable D-Pad diagonals (4-way touch) = Deaktiviere D-Pad Diagonalen (4-Wege-Touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Dünne Ränder +Tilt control setup = Neigung anpassen Tilt Input Type = Eingabetyp für Neigen Tilt Sensitivity along X axis = Neigungsempfindlichkeit über X-Achse Tilt Sensitivity along Y axis = Neigungsempfindlichkeit über Y-Achse diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index af3d9caab0..f6addd09f8 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -43,7 +43,6 @@ Control Mapping = Atoro'i tombolna Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index f0edddece7..362ffc0a03 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -67,7 +67,6 @@ Control Mapping = Control mapping Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -115,6 +114,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index afe3b280e9..67364fc79d 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -43,7 +43,6 @@ Control Mapping = Asignar botones Custom Key Setting = Ajuste de tecla personalizada Customize = Personalizar Customize Touch Controls = Editar pantalla táctil -Customize tilt = Personalizar acelerómetro D-PAD = Cruceta Deadzone radius = Radio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonales de cruceta @@ -92,6 +91,7 @@ Swipe = Deslizar hacia Swipe sensitivity = Sensibilidad del deslizado Swipe smoothing = Fluidez del deslizado Thin borders = Bordes finos +Tilt control setup = Personalizar acelerómetro Tilt Input Type = Tipo de control del acelerómetro Tilt Sensitivity along X axis = Sensibilidad de inclinación del eje X Tilt Sensitivity along Y axis = Sensibilidad de inclinación del eje Y diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 240e0a0fb5..9945e3c650 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -43,7 +43,6 @@ Control Mapping = Asignar botones Custom Key Setting = Configurar teclas personalizadas Customize = Personalizar Customize Touch Controls = Editar pantalla táctil -Customize tilt = Personalizar acelerómetro D-PAD = Cruceta Deadzone radius = Radio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonales de la cruceta @@ -92,6 +91,7 @@ Swipe = Deslizar hacia Swipe sensitivity = Sensibilidad del deslizado Swipe smoothing = Fluidez del deslizado Thin borders = Bordes finos +Tilt control setup = Personalizar acelerómetro Tilt Input Type = Tipo de control del acelerómetro Tilt Sensitivity along X axis = Sensibilidad de inclinación del eje X Tilt Sensitivity along Y axis = Sensibilidad de inclinación del eje Y diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 764ce6b32f..01ba71f2f5 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -43,7 +43,6 @@ Control Mapping = ‎تنظیمات کنترلر Custom Key Setting = شخصی سازی تنظیمات کلید Customize = شخصی سازی Customize Touch Controls = ‎...ویرایش چیدمان دکمه های تاچ -Customize tilt = ‎تنظیمات شتاب سنج D-PAD = D-Pad Deadzone radius = ‎شعاع ناحیه غیر فعال Disable D-Pad diagonals (4-way touch) = ‎غیر فعال کردن جهت های قطری (تاچ ۴ جهته) @@ -92,6 +91,7 @@ Swipe = حساسیت Swipe sensitivity = حساسیت کش رفتن Swipe smoothing = ضربه تند وشدید زدن Thin borders = ‎نوار نازک +Tilt control setup = ‎تنظیمات شتاب سنج Tilt Input Type = ‎...استفاده از شتاب سنج به عنوان Tilt Sensitivity along X axis = ‎X حساسیت شتاب سنج در جهت Tilt Sensitivity along Y axis = ‎Y حساسیت شتاب سنج در جهت diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index bf0571bde3..34810869a2 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -43,7 +43,6 @@ Control Mapping = Control mapping Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 904b75e67d..faf713b89f 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -43,7 +43,6 @@ Control Mapping = Réassignation des touches Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Disposition personnalisée... -Customize tilt = Personnaliser inclinaison analogique... D-PAD = Croix directionnelle Deadzone radius = Rayon de la zone morte Disable D-Pad diagonals (4-way touch) = Désactiver les diagonales de la croix directionnelle @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Bordures fines +Tilt control setup = Personnaliser inclinaison analogique... Tilt Input Type = Type inclinaison analogique Tilt Sensitivity along X axis = Sensibilité de l'inclinaison analogique sur l'axe X Tilt Sensitivity along Y axis = Sensibilité de l'inclinaison analogique sur l'axe Y diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index ce6ffa67c4..366d7a51e0 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -43,7 +43,6 @@ Control Mapping = Asignar botóns Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Deseño personalizado... -Customize tilt = Personalizar acelerómetro D-PAD = D-Pad Deadzone radius = Radio de zona inactiva Disable D-Pad diagonals (4-way touch) = Desactivar diagonais do D-Pad @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Bordes finos +Tilt control setup = Personalizar acelerómetro Tilt Input Type = Tipo de control do acelerómetro Tilt Sensitivity along X axis = Sensibilidade de inclinación do eixe X Tilt Sensitivity along Y axis = Sensibilidade de inclinación do eixe Y diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 32e578b976..05e6b30145 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -43,7 +43,6 @@ Control Mapping = Χαρτογράφηση κουμπιών Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Προσαρμοσμένη διάταξη... -Customize tilt = Προσαρμογή κλίσης... D-PAD = Ψηφιακό πληκτρολόγιο Deadzone radius = Ακτίνα ορίων Disable D-Pad diagonals (4-way touch) = Απενεργοποίηση διαγωνίων ψηφιακού πληκρολογίου @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Λεπτά διαχωριστικά +Tilt control setup = Προσαρμογή κλίσης... Tilt Input Type = Τύπο εισόδου κλίσης Tilt Sensitivity along X axis = Ευαισθησία οριζόντιου άξονα Tilt Sensitivity along Y axis = Ευαισθησία κάθετου άξονα diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index 5bac3ff1d0..32210508a9 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -43,7 +43,6 @@ Control Mapping = מיפוי מקשים Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index e68f294de7..b076e61772 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -43,7 +43,6 @@ Control Mapping = םישקמ יופימ Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index e746a0be33..87186065cf 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -43,7 +43,6 @@ Control Mapping = Namještanje kontrola Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Izmijeni raspored dodirnih kontrola... -Customize tilt = Izmijeni tilt... D-PAD = D-Pad Deadzone radius = Radijus mrtve zone Disable D-Pad diagonals (4-way touch) = Isključi D-Pad dijagonale (4-smjerni dodir) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tanki rubovi +Tilt control setup = Izmijeni tilt... Tilt Input Type = Tip ulaza tilta Tilt Sensitivity along X axis = Tilt senzitivnost X osi Tilt Sensitivity along Y axis = Tilt senzitivnost Y osi diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index de9663c72d..d9d9801e81 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -43,7 +43,6 @@ Control Mapping = Gombok beállítása Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Elrendezés testreszabása… -Customize tilt = Döntés testreszabása… D-PAD = D-Pad Deadzone radius = Holtzóna sugara Disable D-Pad diagonals (4-way touch) = D-Pad átlóinak letiltása (4-irányú érintés) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Vékony szélek +Tilt control setup = Döntés testreszabása… Tilt Input Type = Döntési bevitel típusa Tilt Sensitivity along X axis = X tengely menti döntés érzékenysége Tilt Sensitivity along Y axis = X tengely menti döntés érzékenysége diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 1b9ec4ee4e..0c5febe0a9 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -43,7 +43,6 @@ Control Mapping = Pemetaan kontrol Custom Key Setting = Pengaturan kunci kustom Customize = Sesuaikan Customize Touch Controls = Sesuaikan tata letak kontrol sentuh -Customize tilt = Sesuaikan kemiringan D-PAD = D-Pad Deadzone radius = Radius mati Disable D-Pad diagonals (4-way touch) = Matikan D-Pad diagonal (sentuhan 4 arah) @@ -92,6 +91,7 @@ Swipe = Geser Swipe sensitivity = Geser sensitivitas Swipe smoothing = Geser kehalusan Thin borders = Garis batas tipis +Tilt control setup = Sesuaikan kemiringan Tilt Input Type = Jenis masukan kemiringan Tilt Sensitivity along X axis = Sensitivitas kemiringan sepanjang sumbu X Tilt Sensitivity along Y axis = Sensitivitas kemiringan sepanjang sumbu Y diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 8f7dd318b7..56111fc258 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -43,7 +43,6 @@ Control Mapping = Mappatura dei Controlli Custom Key Setting = Impostazioni tasto personalizz. Customize = Personalizza Customize Touch Controls = Personalizza Controlli Touch -Customize tilt = Personalizza Inclinazione D-PAD = Croce direzionale Deadzone radius = Raggio della zona morta Disable D-Pad diagonals (4-way touch) = Disattiva Diagonali del D-Pad (Tocco a 4-Vie) @@ -91,6 +90,7 @@ Swipe = Scorrimento Swipe sensitivity = Sensibilità Scorrimento Swipe smoothing = Fluidità Scorrimento Thin borders = Bordi fini +Tilt control setup = Personalizza Inclinazione Tilt Input Type = Tipo di Input Inclinazione Tilt Sensitivity along X axis = Inverti Sensibilità sull'asse X Tilt Sensitivity along Y axis = Inverti Sensibilità sull'asse Y diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index ceb63df9c5..6f04fbb432 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -42,7 +42,6 @@ Confine Mouse = ウィンドウ/表示領域内でマウスをトラップする Control Mapping = キーマッピング(入力ボタン設定) Custom Key Setting = カスタムキーの設定 Customize = カスタマイズ -Customize tilt = 傾きをカスタマイズする Customize Touch Controls = 画面タッチ用コントローラーをカスタマイズする D-PAD = 十字キー Deadzone radius = デッドゾーンの半径 @@ -92,6 +91,7 @@ Swipe = スワイプ Swipe sensitivity = スワイプの感度 Swipe smoothing = スワイプの滑らかさ Thin borders = 薄い枠線 +Tilt control setup = 傾きをカスタマイズする Tilt Input Type = 傾き入力のタイプ Tilt Sensitivity along X axis = X軸の傾きの感度 Tilt Sensitivity along Y axis = Y軸の傾きの感度 diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 8043ef27ee..6d01a10515 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -43,7 +43,6 @@ Control Mapping = Pemetaan Kontrol Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit Sentuh Kontrol layout... -Customize tilt = Ngatur ngiringake ... D-PAD = D-Pad Deadzone radius = Radius deadzone Disable D-Pad diagonals (4-way touch) = Mateni D-Pad diagonals (4-cara tutul) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Watesan lancip +Tilt control setup = Ngatur ngiringake ... Tilt Input Type = Ngiringake Tipe input Tilt Sensitivity along X axis = Ngiringake sensitivitas bebarengan X sumbu Tilt Sensitivity along Y axis = Ngiringake sensitivitas bebarengan Y sumbu diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 22a20734ca..22587f1a45 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -43,7 +43,6 @@ Control Mapping = 제어 맵핑 Custom Key Setting = 커스텀 키 설정 Customize = 맞춤설정 Customize Touch Controls = 터치 제어 레이아웃 수정... -Customize tilt = 기울기 맞춤설정... D-PAD = 십자 패드 Deadzone radius = 데드존 반경 Disable D-Pad diagonals (4-way touch) = 십자 패드 대각선 비활성화 (4 방향 터치) @@ -91,6 +90,7 @@ Swipe = 스와이프 Swipe sensitivity = 스와이프 감도 Swipe smoothing = 스와이프 스무딩 Thin borders = 얇은 테두리 +Tilt control setup = 기울기 맞춤설정... Tilt Input Type = 기울기 입력 유형 Tilt Sensitivity along X axis = X 축 기울기 감도 Tilt Sensitivity along Y axis = Y 축 기울기 감도 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index e967b03ba1..86d1265ba1 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -43,7 +43,6 @@ Control Mapping = ປ່ຽນແປງຄ່າຄວບຄຸມ Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = ປັບປ່ຽນການຄວບຄຸມແບບສຳຜັດ... -Customize tilt = ປັບແຕ່ງການອຽງໂດຍໃຊ້ເຊັນເຊີ້ຄວບຄຸມ... D-PAD = D-Pad Deadzone radius = ຂອບເຂດ Deadzone Disable D-Pad diagonals (4-way touch) = ປິດການໃຊ້ງານປຸ່ມ D-Pad (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = ຂອບແບບບາງ +Tilt control setup = ປັບແຕ່ງການອຽງໂດຍໃຊ້ເຊັນເຊີ້ຄວບຄຸມ... Tilt Input Type = ນຳເຂົ້າຮູບແບບການອຽງ Tilt Sensitivity along X axis = ຄວາມໄວການອຽງຕາມແກນ X Tilt Sensitivity along Y axis = ຄວາມໄວການອຽງໄວຕາມແກນ Y diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 62cf023aa7..646ab7494e 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -43,7 +43,6 @@ Control Mapping = Valdymo mygtukų nustatymai Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Pakeisti liečiamo valdymo mygtukų pozicijas ir dydį... -Customize tilt = Pakeisti pakreipimo parametrus... D-PAD = Krypčių mygtukai Deadzone radius = "Mirties zonos" spindulys Disable D-Pad diagonals (4-way touch) = Išjungti krypčių mygtukų įstrižainę (4 paspaudimais vienu metu liečiamam ekranui) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Ploni kraštai +Tilt control setup = Pakeisti pakreipimo parametrus... Tilt Input Type = Pakreipimo įvedimo įrenginio tipas Tilt Sensitivity along X axis = Pakreipimo sensitivacija palei X ašį Tilt Sensitivity along Y axis = Pakreipimo sensitivacija palei Y ašį diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index a82fd0f045..2778e76e94 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -43,7 +43,6 @@ Control Mapping = Pemetaan kawalan Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit susunan kawalan... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Lumpuhkan PadD diagonal (4-jalan sentuh) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Tepian tipis +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 3b689e9f52..3ca5034f52 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -43,7 +43,6 @@ Control Mapping = Besturing toewijzen Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Indeling aanraakbesturing bewerken... -Customize tilt = Kantelen personaliseren... D-PAD = Richtingstoetsen Deadzone radius = Straal dode zone Disable D-Pad diagonals (4-way touch) = Diagonale pijltoetsen uitzetten (4 richtingen) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Dunne randen +Tilt control setup = Kantelen personaliseren... Tilt Input Type = Invoertype voor kantelen Tilt Sensitivity along X axis = Kantelgevoeligheid op X-as Tilt Sensitivity along Y axis = Kantelgevoeligheid op Y-as diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 0cc4605468..635c60bf81 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -43,7 +43,6 @@ Control Mapping = Control mapping Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Edit touch control layout... -Customize tilt = Customize tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Thin borders +Tilt control setup = Tilt control setup Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index ed797927cb..757c58c37c 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -43,7 +43,6 @@ Control Mapping = Mapowanie przycisków Custom Key Setting = Niestandardowe Ustawienia Klawiszy Customize = Ustawienia Niestandardowe Customize Touch Controls = Edycja układu przycisków ekranowych... -Customize tilt = Zmodyfikuj przechył... D-PAD = Krzyżak Deadzone radius = Promień martwej strefy Disable D-Pad diagonals (4-way touch) = Wył. przekątne krzyżaka (pozostaw 4 kierunki) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Cienkie krawędzie +Tilt control setup = Zmodyfikuj przechył... Tilt Input Type = Typ przechyłu Tilt Sensitivity along X axis = Czułość przechyłu wzdłuż osi X Tilt Sensitivity along Y axis = Czułość przechyłu wzdłuż osi Y diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 3f8239f0d1..145a306ee3 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -67,7 +67,6 @@ Control Mapping = Mapeamento dos controles Custom Key Setting = Configuração Personalizada das Teclas Customize = Personalizar Customize Touch Controls = Editar esquema do controle do toque... -Customize tilt = Personalizar inclinação... D-PAD = D-Pad Deadzone radius = Raio da zona morta Disable D-Pad diagonals (4-way touch) = Desativar diagonais do D-Pad (toque de 4 direções) @@ -115,6 +114,7 @@ Swipe = Deslizar Swipe sensitivity = Sensibilidade do deslizar Swipe smoothing = Suavidade do deslizar Thin borders = Bordas finas +Tilt control setup = Personalizar inclinação... Tilt Input Type = Controle da entrada da inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 1ea0793de9..072e9c6ff1 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -67,7 +67,6 @@ Control Mapping = Mapeamento dos Controlos Custom Key Setting = Configuração Personalizada das Teclas Customize = Personalizar Customize Touch Controls = Editar disposição do controlos de toque... -Customize tilt = Personalizar inclinação... D-PAD = D-Pad Deadzone radius = Raio da zona morta Disable D-Pad diagonals (4-way touch) = Desativar diagonais do D-Pad (toque de 4 direções) @@ -115,6 +114,7 @@ Swipe = Deslizar Swipe sensitivity = Sensibilidade do deslizar Swipe smoothing = Suavidade do deslizar Thin borders = Bordas Finas +Tilt control setup = Personalizar inclinação... Tilt Input Type = Controlo da entrada de inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index ebfce6e590..75025f5fe9 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -43,7 +43,6 @@ Control Mapping = Editare controale Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Aranjare controale touch... -Customize tilt = Personificare înclinare... D-PAD = D-Pad Deadzone radius = Raza zonei moarte Disable D-Pad diagonals (4-way touch) = Dezactivare diagonale D-Pad (touch in 4 direcții) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Margini subțiri +Tilt control setup = Personificare înclinare... Tilt Input Type = Tip intrare prin înclinare Tilt Sensitivity along X axis = Inversează sensitivitatea pe axa X Tilt Sensitivity along Y axis = Inversează sensitivitatea pe axa Y diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index ad9df9625b..05a99f929e 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -43,7 +43,6 @@ Control Mapping = Назначение кнопок Custom Key Setting = Настройка кастомных кнопок Customize = Настроить Customize Touch Controls = Изменить сенсорное управление... -Customize tilt = Настроить наклон... D-PAD = Крестовина Deadzone radius = Радиус мертвой зоны Disable D-Pad diagonals (4-way touch) = Отключить крестовину по диагонали @@ -92,6 +91,7 @@ Swipe = Свайпы Swipe sensitivity = Чувствительность свайпов Swipe smoothing = Сглаживание свайпов Thin borders = Тонкие границы +Tilt control setup = Настроить наклон... Tilt Input Type = Тип управления наклоном Tilt Sensitivity along X axis = Чувствительность наклона вдоль X Tilt Sensitivity along Y axis = Чувствительность наклона вдоль Y diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index cac07b29d0..02f9e5c157 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -43,7 +43,6 @@ Control Mapping = Kontrollmappning Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Anpassad layout... -Customize tilt = Anpassa tilt... D-PAD = D-Pad Deadzone radius = Deadzone-radie Disable D-Pad diagonals (4-way touch) = Slå av D-Pad-diagonaler (4-vägs touch) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe-känslighet Swipe smoothing = Swipe-utjämning Thin borders = Tunna kanter +Tilt control setup = Tilt kontrollinställningar Tilt Input Type = Lutningstyp Tilt Sensitivity along X axis = Lutningskänslighet X Tilt Sensitivity along Y axis = Lutningskänslighet Y diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index d53616f88d..7c8f3d374a 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -43,7 +43,6 @@ Control Mapping = Pagtakda ng Kontrol Custom Key Setting = Magtakda ng pagsadyang pag-aayos sa pindutan Customize = Pasadya Customize Touch Controls = Ayusin ang mga pindutan sa screen -Customize tilt = I-pasadya ang tilt... D-PAD = D-Pad Deadzone radius = Deadzone radius Disable D-Pad diagonals (4-way touch) = Disable D-Pad diagonals (4-way touch) @@ -92,6 +91,7 @@ Swipe = Mahagip Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Manipis na gilid +Tilt control setup = I-pasadya ang tilt... Tilt Input Type = Tilt input type Tilt Sensitivity along X axis = Tilt sensitivity along X axis Tilt Sensitivity along Y axis = Tilt sensitivity along Y axis diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 0ba426b45f..a0083d8ed8 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -42,7 +42,6 @@ Confine Mouse = จำกัดเมาส์ภายในหน้าต่ Control Mapping = เปลี่ยนแปลงค่าควบคุม Custom Key Setting = ติดตั้งปุ่มคอมโบปรับแต่ง Customize = ปรับแต่ง -Customize tilt = ปรับแต่งการเอียงโดยใช้เซ็นเซอร์ควบคุม... Customize Touch Controls = ปรับแต่งปุ่มควบคุมสัมผัสหน้าจอ D-PAD = ปุ่มลูกศร Deadzone radius = รัศมีของ Deadzone @@ -92,6 +91,7 @@ Swipe = ปัดหน้าจอ Swipe sensitivity = ความแรงที่ใช้ปัดหน้าจอ Swipe smoothing = ความลื่นไหลในการปัดหน้าจอ Thin borders = แบบขอบบาง +Tilt control setup = ปรับแต่งการเอียงโดยใช้เซ็นเซอร์ควบคุม... Tilt Input Type = รูปแบบนำเข้าการเอียง Tilt Sensitivity along X axis = ความไวต่อการตอบสนองเอียงตามแกน X Tilt Sensitivity along Y axis = ความไวต่อการตอบสนองเอียงตามแกน Y diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index c8ba327a1e..0948a6cd6b 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -43,7 +43,6 @@ Control Mapping = Kontrolleri Ayarla Custom Key Setting = Özel Tuş Ayarı Customize = Düzenle Customize Touch Controls = Dokunmatik kontrolleri düzenle... -Customize tilt = Eğimi düzenle... D-PAD = D-Pad Deadzone radius = Ölü bölge yarıçapı Disable D-Pad diagonals (4-way touch) = D-Pad'i devre dışı bırak (4'lü Yön Tuşları) @@ -92,6 +91,7 @@ Swipe = Kaydır Swipe sensitivity = Kaydırma hassasiyeti Swipe smoothing = Pürüzsüz kaydırma Thin borders = İnce kenarlar +Tilt control setup = Eğimi düzenle... Tilt Input Type = Eğim giriş türü Tilt Sensitivity along X axis = X ekseni boyunca eğim hassasiyeti Tilt Sensitivity along Y axis = Y ekseni boyunca eğim hassasiyeti diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index ffcb3a1146..b034407cf5 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -43,7 +43,6 @@ Control Mapping = Призначення кнопок Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Розташування кнопок... -Customize tilt = Налаштування нахилу... D-PAD = Хрестовина Deadzone radius = Радіус мертвої зони Disable D-Pad diagonals (4-way touch) = Вимкнути хрестовину по діагоналі @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Тонкі границі (збільшення) +Tilt control setup = Налаштування нахилу... Tilt Input Type = Тип управління нахилом Tilt Sensitivity along X axis = Чутливість нахилу по осі X Tilt Sensitivity along Y axis = Чутливість нахилу по осі Y diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index a0cb9af7bc..14ef9e8c3c 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -43,7 +43,6 @@ Control Mapping = Chỉnh nút Custom Key Setting = Custom Key Setting Customize = Customize Customize Touch Controls = Chỉnh vị trí nút... -Customize tilt = Chỉnh độ nghiêng... D-PAD = D-Pad Deadzone radius = Bán kính vùng chết Disable D-Pad diagonals (4-way touch) = Tắt D-Pad chéo (chạm 4 hướng) @@ -92,6 +91,7 @@ Swipe = Swipe Swipe sensitivity = Swipe sensitivity Swipe smoothing = Swipe smoothing Thin borders = Viền mỏng +Tilt control setup = Chỉnh độ nghiêng... Tilt Input Type = Đầu vào kiểu nghiêng Tilt Sensitivity along X axis = Độ nhạy nghiêng theo chiều x Tilt Sensitivity along Y axis = Độ nhạy nghiêng theo chiều y diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 00e944b777..ddbebadfd6 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -43,7 +43,6 @@ Control Mapping = 按键映射 Custom Key Setting = 自定义键位设置 Customize = 自定义… Customize Touch Controls = 编辑触屏布局… -Customize tilt = 自定义重力感应… D-PAD = 方向键 Deadzone radius = 死区半径 Disable D-Pad diagonals (4-way touch) = 禁用对角线输入(方向键) @@ -92,6 +91,7 @@ Swipe = 滑动 Swipe sensitivity = 滑动灵敏度 Swipe smoothing = 滑动平滑度 Thin borders = 细边框 +Tilt control setup = 自定义重力感应… Tilt Input Type = 重力感应按键 Tilt Sensitivity along X axis = 沿X轴倾斜灵敏度 Tilt Sensitivity along Y axis = 沿Y轴倾斜灵敏度 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 7a66b5dcde..27d1a20686 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -43,7 +43,6 @@ Control Mapping = 控制對應 Custom Key Setting = 自訂按鍵設定 Customize = 自訂 Customize Touch Controls = 編輯觸控控制版面配置… -Customize tilt = 自訂傾斜… D-PAD = 方向鍵 Deadzone radius = 死區半徑 Disable D-Pad diagonals (4-way touch) = 停用方向鍵對角線 (四向觸控) @@ -91,6 +90,7 @@ Swipe = 滑動 Swipe sensitivity = 滑動敏感度 Swipe smoothing = 滑動平滑度 Thin borders = 特細框線 +Tilt control setup = 自訂傾斜… Tilt Input Type = 傾斜輸入類型 Tilt Sensitivity along X axis = 沿 X 軸傾斜敏感度 Tilt Sensitivity along Y axis = 沿 Y 軸傾斜敏感度 From 1a035a726aba833a8a5bed35eb0da069f00ae4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 11:01:42 +0100 Subject: [PATCH 015/424] Set a reasonable default angle --- Core/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index b604d0232a..86cd15c61e 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -970,7 +970,7 @@ static const ConfigSetting controlSettings[] = { // ConfigSetting("KeyMapping", &g_Config.iMappingMap, 0), #ifdef MOBILE_DEVICE - ConfigSetting("TiltBaseAngleY", &g_Config.fTiltBaseAngleY, 0.0f, true, true), + ConfigSetting("TiltBaseAngleY", &g_Config.fTiltBaseAngleY, 0.9f, true, true), ConfigSetting("TiltInvertX", &g_Config.bInvertTiltX, false, true, true), ConfigSetting("TiltInvertY", &g_Config.bInvertTiltY, false, true, true), ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 70, true, true), From af8e4cd36b7dc7af2794813ad1706637e23805b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 11:59:56 +0100 Subject: [PATCH 016/424] Fixes for portrait mode. Move the haptic feedback setting where it belongs. --- Core/TiltEventProcessor.cpp | 2 ++ UI/GameSettingsScreen.cpp | 11 +++++------ UI/NativeApp.cpp | 6 +++--- UI/TiltAnalogSettingsScreen.cpp | 20 +++++++++++++------- ext/armips | 2 +- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index a404370d44..631aee0d68 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -56,6 +56,8 @@ inline float clamp(float f) { Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity) { if (landscape) { std::swap(x, y); + } else { + x *= -1.0f; } Lin::Vec3 down(x, y, z); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 35d624026d..ab756a0d2a 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -692,13 +692,8 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) #endif if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { - controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); - Choice *customizeTilt = controlsSettings->Add(new Choice(co->T("Tilt control setup"))); customizeTilt->OnClick.Handle(this, &GameSettingsScreen::OnTiltCustomize); - customizeTilt->SetEnabledFunc([] { - return g_Config.iTiltInputType != 0; - }); } else if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_VR) { controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); } @@ -715,10 +710,14 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls); - // Hide stick background, usefull when increasing the size + // Hide stick background, useful when increasing the size CheckBox *hideStickBackground = controlsSettings->Add(new CheckBox(&g_Config.bHideStickBackground, co->T("Hide touch analog stick background circle"))); hideStickBackground->SetEnabledPtr(&g_Config.bShowTouchControls); + if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { + controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); + } + // On non iOS systems, offer to let the user see this button. // Some Windows touch devices don't have a back button or other button to call up the menu. if (System_GetPropertyBool(SYSPROP_HAS_BACK_BUTTON)) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index e80f14d926..b66e64b93e 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1381,9 +1381,6 @@ void NativeAxis(const AxisInput &axis) { return; } - // create the base coordinate tilt system from the calibration data. - float tiltBaseAngleY = g_Config.fTiltBaseAngleY; - // figure out what the current tilt orientation is by checking the axis event // This is static, since we need to remember where we last were (in terms of orientation) static float tiltX; @@ -1397,6 +1394,9 @@ void NativeAxis(const AxisInput &axis) { default: break; } + // create the base coordinate tilt system from the calibration data. + float tiltBaseAngleY = g_Config.fTiltBaseAngleY; + // Figure out the sensitivity of the tilt. (sensitivity is originally 0 - 100) // We divide by 50, so that the rest of the 50 units can be used to overshoot the // target. If you want precise control, you'd keep the sensitivity ~50. diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index 6dbbdcfab2..a79317e85a 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -34,11 +34,21 @@ void TiltAnalogSettingsScreen::CreateViews() { auto co = GetI18NCategory("Controls"); auto di = GetI18NCategory("Dialog"); - root_ = new LinearLayout(ORIENT_HORIZONTAL); + bool vertical = UseVerticalLayout(); + + root_ = new LinearLayout(vertical ? ORIENT_VERTICAL : ORIENT_HORIZONTAL); root_->SetTag("TiltAnalogSettings"); - ScrollView *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(600, FILL_PARENT)); - root_->Add(menuRoot); + LinearLayout *settings = new LinearLayoutList(ORIENT_VERTICAL); + + if (vertical) { + // Don't need a scrollview, probably.. + root_->Add(settings); + } else { + ViewGroup *menuRoot = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(600, FILL_PARENT)); + root_->Add(menuRoot); + menuRoot->Add(settings); + } if (g_Config.iTiltInputType == TILT_ANALOG) { tilt_ = new JoystickHistoryView(StickHistoryViewType::OTHER, "", new LinearLayoutParams(1.0f)); @@ -87,8 +97,6 @@ void TiltAnalogSettingsScreen::CreateViews() { return g_Config.iTiltInputType != 0; }; - LinearLayout *settings = new LinearLayoutList(ORIENT_VERTICAL); - settings->SetSpacing(0); @@ -121,8 +129,6 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); - menuRoot->Add(settings); - settings->Add(new BorderView(BORDER_BOTTOM, BorderStyle::HEADER_FG, 2.0f, new LayoutParams(FILL_PARENT, 40.0f))); settings->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); } diff --git a/ext/armips b/ext/armips index 6719edebaa..7bd1ec93d4 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 6719edebaae03330ee5441d9b28280672edf00d5 +Subproject commit 7bd1ec93d4586985ba1ef420b43b5e620f68695e From c11f7e3a5fcbd6c28c2d29309d92f08051d3fe28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 16:12:28 +0100 Subject: [PATCH 017/424] Fix texture alpha when texturing from full-alpha textures. Fixes #16875 --- GPU/Common/ShaderUniforms.cpp | 6 +++++- GPU/GPUState.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 2d5211fc27..8cfa0c3c55 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -199,7 +199,11 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView } if (dirtyUniforms & DIRTY_TEX_ALPHA_MUL) { - ub->texNoAlpha = gstate.isTextureAlphaUsed() ? 0.0f : 1.0f; + bool doTextureAlpha = gstate.isTextureAlphaUsed(); + if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) { + doTextureAlpha = false; + } + ub->texNoAlpha = doTextureAlpha ? 0.0f : 1.0f; ub->texMul = gstate.isColorDoublingEnabled() ? 2.0f : 1.0f; } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 3c3002a337..839f52f181 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -549,7 +549,7 @@ struct GPUStateCache { void SetTextureFullAlpha(bool fullAlpha) { if (fullAlpha != textureFullAlpha) { textureFullAlpha = fullAlpha; - Dirty(DIRTY_FRAGMENTSHADER_STATE); + Dirty(DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEX_ALPHA_MUL); } } void SetNeedShaderTexclamp(bool need) { From 88ba003f467c97e224d6dd3262ad677693601627 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Jan 2023 07:55:07 -0800 Subject: [PATCH 018/424] ThreadManager: Add a simple priority field. Currently, not actually respected. --- Common/GPU/Vulkan/VulkanRenderManager.cpp | 4 ++++ Common/Thread/ParallelLoop.cpp | 27 ++++++++++++++--------- Common/Thread/ParallelLoop.h | 8 +++---- Common/Thread/Promise.h | 18 ++++++++++----- Common/Thread/ThreadManager.h | 9 ++++++++ Core/ELF/ElfReader.cpp | 4 ++-- Core/HLE/sceKernelMemory.cpp | 2 +- Core/TextureReplacer.cpp | 12 +++++++++- GPU/Debugger/Record.cpp | 2 +- GPU/Software/BinManager.cpp | 5 +++++ UI/GameInfoCache.cpp | 12 ++++++++++ UI/MemStickScreen.cpp | 2 +- unittest/TestThreadManager.cpp | 7 ++++-- 13 files changed, 83 insertions(+), 29 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 32e859936a..40ecd8514a 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -403,6 +403,10 @@ public: return TaskType::CPU_COMPUTE; } + TaskPriority Priority() const override { + return TaskPriority::HIGH; + } + void Run() override { for (auto &task : tasks_) { task.pipeline->Create(vulkan_, task.compatibleRenderPass, task.rpType, task.sampleCount, task.scheduleTime, task.countToCompile); diff --git a/Common/Thread/ParallelLoop.cpp b/Common/Thread/ParallelLoop.cpp index 2f00664618..18ec756e4e 100644 --- a/Common/Thread/ParallelLoop.cpp +++ b/Common/Thread/ParallelLoop.cpp @@ -6,13 +6,17 @@ class LoopRangeTask : public Task { public: - LoopRangeTask(WaitableCounter *counter, const std::function &loop, int lower, int upper) - : counter_(counter), loop_(loop), lower_(lower), upper_(upper) {} + LoopRangeTask(WaitableCounter *counter, const std::function &loop, int lower, int upper, TaskPriority p) + : counter_(counter), loop_(loop), lower_(lower), upper_(upper), priority_(p) {} TaskType Type() const override { return TaskType::CPU_COMPUTE; } + TaskPriority Priority() const override { + return priority_; + } + void Run() override { loop_(lower_, upper_); counter_->Count(); @@ -23,9 +27,10 @@ public: int lower_; int upper_; + const TaskPriority priority_; }; -WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize) { +WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize, TaskPriority priority) { if (minSize == -1) { minSize = 1; } @@ -38,7 +43,7 @@ WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std:: } else if (range <= minSize) { // Single background task. WaitableCounter *waitableCounter = new WaitableCounter(1); - threadMan->EnqueueTaskOnThread(0, new LoopRangeTask(waitableCounter, loop, lower, upper)); + threadMan->EnqueueTaskOnThread(0, new LoopRangeTask(waitableCounter, loop, lower, upper, priority)); return waitableCounter; } else { // Split the range between threads. Allow for some fractional bits. @@ -65,7 +70,7 @@ WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std:: // Let's do the stragglers on the current thread. break; } - threadMan->EnqueueTaskOnThread(i, new LoopRangeTask(waitableCounter, loop, start, end)); + threadMan->EnqueueTaskOnThread(i, new LoopRangeTask(waitableCounter, loop, start, end, priority)); counter += delta; if ((counter >> fractionalBits) >= upper) { break; @@ -83,7 +88,7 @@ WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std:: } } -void ParallelRangeLoop(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize) { +void ParallelRangeLoop(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize, TaskPriority priority) { if (cpu_info.num_cores == 1 || (minSize >= (upper - lower) && upper > lower)) { // "Optimization" for single-core devices, or minSize larger than the range. // No point in adding threading overhead, let's just do it inline (since this is the blocking variant). @@ -96,7 +101,7 @@ void ParallelRangeLoop(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize); +WaitableCounter *ParallelRangeLoopWaitable(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize, TaskPriority priority); // Note that upper bounds are non-inclusive: range is [lower, upper) -void ParallelRangeLoop(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize); +void ParallelRangeLoop(ThreadManager *threadMan, const std::function &loop, int lower, int upper, int minSize, TaskPriority priority = TaskPriority::NORMAL); // Common utilities for large (!) memory copies. // Will only fall back to threads if it seems to make sense. // NOTE: These support a max of 2GB. -void ParallelMemcpy(ThreadManager *threadMan, void *dst, const void *src, size_t bytes); -void ParallelMemset(ThreadManager *threadMan, void *dst, uint8_t value, size_t bytes); +void ParallelMemcpy(ThreadManager *threadMan, void *dst, const void *src, size_t bytes, TaskPriority priority = TaskPriority::NORMAL); +void ParallelMemset(ThreadManager *threadMan, void *dst, uint8_t value, size_t bytes, TaskPriority priority = TaskPriority::NORMAL); diff --git a/Common/Thread/Promise.h b/Common/Thread/Promise.h index e09e4c8174..f8dbaf9e6a 100644 --- a/Common/Thread/Promise.h +++ b/Common/Thread/Promise.h @@ -10,7 +10,8 @@ template class PromiseTask : public Task { public: - PromiseTask(std::function fun, Mailbox *tx, TaskType t) : fun_(fun), tx_(tx), type_(t) { + PromiseTask(std::function fun, Mailbox *tx, TaskType t, TaskPriority p) + : fun_(fun), tx_(tx), type_(t), priority_(p) { tx_->AddRef(); } ~PromiseTask() { @@ -21,6 +22,10 @@ public: return type_; } + TaskPriority Priority() const override { + return priority_; + } + void Run() override { T value = fun_(); tx_->Send(value); @@ -28,7 +33,8 @@ public: std::function fun_; Mailbox *tx_; - TaskType type_; + const TaskType type_; + const TaskPriority priority_; }; // Represents pending or actual data. @@ -39,13 +45,13 @@ public: template class Promise { public: - static Promise *Spawn(ThreadManager *threadman, std::function fun, TaskType taskType) { + static Promise *Spawn(ThreadManager *threadman, std::function fun, TaskType taskType, TaskPriority taskPriority = TaskPriority::NORMAL) { Mailbox *mailbox = new Mailbox(); Promise *promise = new Promise(); promise->rx_ = mailbox; - PromiseTask *task = new PromiseTask(fun, mailbox, taskType); + PromiseTask *task = new PromiseTask(fun, mailbox, taskType, taskPriority); threadman->EnqueueTask(task); return promise; } @@ -65,8 +71,8 @@ public: } // Allow an empty promise to spawn, too, in case we want to delay it. - void SpawnEmpty(ThreadManager *threadman, std::function fun, TaskType taskType) { - PromiseTask *task = new PromiseTask(fun, rx_, taskType); + void SpawnEmpty(ThreadManager *threadman, std::function fun, TaskType taskType, TaskPriority taskPriority = TaskPriority::NORMAL) { + PromiseTask *task = new PromiseTask(fun, rx_, taskType, taskPriority); threadman->EnqueueTask(task); } diff --git a/Common/Thread/ThreadManager.h b/Common/Thread/ThreadManager.h index 45d1974871..12ba50c3f2 100644 --- a/Common/Thread/ThreadManager.h +++ b/Common/Thread/ThreadManager.h @@ -11,11 +11,20 @@ enum class TaskType { DEDICATED_THREAD, // These can never get stuck in queue behind others, but are more expensive to launch. Cannot use I/O. }; +enum class TaskPriority { + HIGH = 0, + NORMAL = 1, + LOW = 2, + + COUNT, +}; + // Implement this to make something that you can run on the thread manager. class Task { public: virtual ~Task() {} virtual TaskType Type() const = 0; + virtual TaskPriority Priority() const = 0; virtual void Run() = 0; virtual bool Cancellable() { return false; } virtual void Cancel() {} diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 3008b17f61..b842f6798e 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -100,7 +100,7 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) { relocOps[r] = Memory::ReadUnchecked_Instruction(addr, true).encoding; } - }, 0, numRelocs, 128); + }, 0, numRelocs, 128, TaskPriority::HIGH); ParallelRangeLoop(&g_threadManager, [&](int l, int h) { for (int r = l; r < h; r++) { @@ -213,7 +213,7 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) { Memory::WriteUnchecked_U32(op, addr); NotifyMemInfo(MemBlockFlags::WRITE, addr, 4, "Relocation"); } - }, 0, numRelocs, 128); + }, 0, numRelocs, 128, TaskPriority::HIGH); if (numErrors) { WARN_LOG(LOADER, "%i bad relocations found!!!", numErrors.load()); diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index 23ff06c147..d4122b63b9 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -434,7 +434,7 @@ void __KernelMemoryInit() kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), false); userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), false); volatileMemory.Init(PSP_GetVolatileMemoryStart(), PSP_GetVolatileMemoryEnd() - PSP_GetVolatileMemoryStart(), false); - ParallelMemset(&g_threadManager, Memory::GetPointerWrite(PSP_GetKernelMemoryBase()), 0, PSP_GetUserMemoryEnd() - PSP_GetKernelMemoryBase()); + ParallelMemset(&g_threadManager, Memory::GetPointerWrite(PSP_GetKernelMemoryBase()), 0, PSP_GetUserMemoryEnd() - PSP_GetKernelMemoryBase(), TaskPriority::HIGH); NotifyMemInfo(MemBlockFlags::WRITE, PSP_GetKernelMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetKernelMemoryBase(), "MemInit"); INFO_LOG(SCEKERNEL, "Kernel and user memory pools initialized"); diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 810715226c..3fbfd935b2 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -708,7 +708,13 @@ public: TextureSaveTask(SimpleBuf _data) : data(std::move(_data)) {} - TaskType Type() const override { return TaskType::CPU_COMPUTE; } // Also I/O blocking but dominated by compute + // Also I/O blocking but dominated by compute. + TaskType Type() const override { return TaskType::CPU_COMPUTE; } + + TaskPriority Priority() const override { + return TaskPriority::LOW; + } + void Run() override { const Path filename = basePath / hashfile; const Path saveFilename = basePath / NEW_TEXTURE_DIR / hashfile; @@ -995,6 +1001,10 @@ public: return TaskType::IO_BLOCKING; } + TaskPriority Priority() const override { + return TaskPriority::NORMAL; + } + void Run() override { tex_.Prepare(); waitable_->Notify(); diff --git a/GPU/Debugger/Record.cpp b/GPU/Debugger/Record.cpp index 3fb3924376..d1a1bbf2ca 100644 --- a/GPU/Debugger/Record.cpp +++ b/GPU/Debugger/Record.cpp @@ -287,7 +287,7 @@ static const u8 *mymemmem(const u8 *haystack, size_t off, size_t hlen, const u8 p++; alignp(); } - }, 0, range, 128 * 1024); + }, 0, range, 128 * 1024, TaskPriority::LOW); return result; } diff --git a/GPU/Software/BinManager.cpp b/GPU/Software/BinManager.cpp index a7522e1d71..e8ce567fb2 100644 --- a/GPU/Software/BinManager.cpp +++ b/GPU/Software/BinManager.cpp @@ -105,6 +105,11 @@ public: return TaskType::CPU_COMPUTE; } + TaskPriority Priority() const override { + // Let priority emulation tasks win over this. + return TaskPriority::NORMAL; + } + void Run() override { ProcessItems(); status_ = false; diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 16efa42e90..c71e5e6fc4 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -345,6 +345,18 @@ public: return TaskType::IO_BLOCKING; } + TaskPriority Priority() const override { + switch (gamePath_.Type()) { + case PathType::NATIVE: + case PathType::CONTENT_URI: + return TaskPriority::NORMAL; + + default: + // Remote/network access. + return TaskPriority::LOW; + } + } + void Run() override { // An early-return will result in the destructor running, where we can set // flags like working and pending. diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 53030fd9d0..e640dd5399 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -755,7 +755,7 @@ UI::EventReturn ConfirmMemstickMoveScreen::OnConfirm(UI::EventParams ¶ms) { } return new MoveResult{ true, "", failedFiles }; - }, TaskType::IO_BLOCKING); + }, TaskType::IO_BLOCKING, TaskPriority::HIGH); RecreateViews(); } else { diff --git a/unittest/TestThreadManager.cpp b/unittest/TestThreadManager.cpp index ece88ca494..f6a11f2fa3 100644 --- a/unittest/TestThreadManager.cpp +++ b/unittest/TestThreadManager.cpp @@ -45,7 +45,7 @@ bool TestParallelLoop(ThreadManager *threadMan) { printf("tester thread ID: %d\n", GetCurrentThreadIdForDebug()); printf("waitable test\n"); - WaitableCounter *waitable = ParallelRangeLoopWaitable(threadMan, rangeFunc, 0, 7, 1); + WaitableCounter *waitable = ParallelRangeLoopWaitable(threadMan, rangeFunc, 0, 7, 1, TaskPriority::HIGH); // Can do stuff here if we like. waitable->WaitAndRelease(); // Now it's done. @@ -58,7 +58,7 @@ bool TestParallelLoop(ThreadManager *threadMan) { ParallelRangeLoop(threadMan, rangeFunc, 0, 100, 40); // Try a loop with minimum size larger than range. printf("waitable test [10-30)\n"); - WaitableCounter *waitable2 = ParallelRangeLoopWaitable(threadMan, rangeFunc, 10, 30, 40); + WaitableCounter *waitable2 = ParallelRangeLoopWaitable(threadMan, rangeFunc, 10, 30, 40, TaskPriority::LOW); waitable2->WaitAndRelease(); return true; } @@ -75,6 +75,9 @@ public: IncrementTask(TaskType type, LimitedWaitable *waitable) : type_(type), waitable_(waitable) {} ~IncrementTask() {} TaskType Type() const override { return type_; } + TaskPriority Priority() const override { + return TaskPriority::NORMAL; + } void Run() override { g_atomicCounter++; waitable_->Notify(); From 0971555e51a1174fc3bf7bafc9ad2af61c462c00 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Jan 2023 08:05:48 -0800 Subject: [PATCH 019/424] ThreadManager: Add simple priority queues. This allows basic differentiation of priorities. --- Common/Thread/ThreadManager.cpp | 82 +++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index 9e87c1cfd6..318207c645 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -22,12 +22,13 @@ const int MAX_CORES_TO_USE = 16; const int MIN_IO_BLOCKING_THREADS = 4; +static constexpr size_t TASK_PRIORITY_COUNT = (size_t)TaskPriority::COUNT; struct GlobalThreadContext { std::mutex mutex; // associated with each respective condition variable - std::deque compute_queue; + std::deque compute_queue[TASK_PRIORITY_COUNT]; std::atomic compute_queue_size; - std::deque io_queue; + std::deque io_queue[TASK_PRIORITY_COUNT]; std::atomic io_queue_size; std::vector threads_; @@ -42,7 +43,7 @@ struct ThreadContext { int index; TaskType type; std::atomic cancelled; - std::deque private_queue; + std::deque private_queue[TASK_PRIORITY_COUNT]; char name[16]; }; @@ -65,12 +66,14 @@ void ThreadManager::Teardown() { // Purge any cancellable tasks while the threads shut down. if (global_->compute_queue_size > 0 || global_->io_queue_size > 0) { - auto drainQueue = [&](std::deque &queue, std::atomic &size) { - for (auto it = queue.begin(); it != queue.end(); ++it) { - if (TeardownTask(*it, false)) { - queue.erase(it); - size--; - return false; + auto drainQueue = [&](std::deque queue[TASK_PRIORITY_COUNT], std::atomic &size) { + for (size_t i = 0; i < TASK_PRIORITY_COUNT; ++i) { + for (auto it = queue[i].begin(); it != queue[i].end(); ++it) { + if (TeardownTask(*it, false)) { + queue[i].erase(it); + size--; + return false; + } } } return true; @@ -86,8 +89,10 @@ void ThreadManager::Teardown() { for (ThreadContext *&threadCtx : global_->threads_) { threadCtx->thread.join(); // TODO: Is it better to just delete these? - for (Task *task : threadCtx->private_queue) { - TeardownTask(task, true); + for (size_t i = 0; i < TASK_PRIORITY_COUNT; ++i) { + for (Task *task : threadCtx->private_queue[i]) { + TeardownTask(task, true); + } } delete threadCtx; } @@ -109,11 +114,12 @@ bool ThreadManager::TeardownTask(Task *task, bool enqueue) { } if (enqueue) { + size_t queueIndex = (size_t)task->Priority(); if (task->Type() == TaskType::CPU_COMPUTE) { - global_->compute_queue.push_back(task); + global_->compute_queue[queueIndex].push_back(task); global_->compute_queue_size++; } else if (task->Type() == TaskType::IO_BLOCKING) { - global_->io_queue.push_back(task); + global_->io_queue[queueIndex].push_back(task); global_->io_queue_size++; } else { _assert_(false); @@ -147,33 +153,39 @@ static void WorkerThreadFunc(GlobalThreadContext *global, ThreadContext *thread) if (global_queue_size() > 0) { // Grab one from the global queue if there is any. std::unique_lock lock(global->mutex); - auto &queue = isCompute ? global->compute_queue : global->io_queue; + auto queue = isCompute ? global->compute_queue : global->io_queue; auto &queue_size = isCompute ? global->compute_queue_size : global->io_queue_size; - if (!queue.empty()) { - task = queue.front(); - queue.pop_front(); - queue_size--; + if (queue_size != 0) { + for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { + if (queue[p].empty()) + continue; - // We are processing one now, so mark that. - thread->queue_size++; + task = queue[p].front(); + queue[p].pop_front(); + queue_size--; + + // We are processing one now, so mark that. + thread->queue_size++; + break; + } } } if (!task) { std::unique_lock lock(thread->mutex); - // We must check both queue and single again, while locked. - bool wait = true; - if (!thread->private_queue.empty()) { - task = thread->private_queue.front(); - thread->private_queue.pop_front(); - wait = false; - } else if (thread->cancelled) { - wait = false; - } else { - wait = global_queue_size() == 0; + for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { + if (thread->private_queue[p].empty()) + continue; + + task = thread->private_queue[p].front(); + thread->private_queue[p].pop_front(); + break; } + // We must check both queue and single again, while locked. + bool wait = !thread->cancelled && !task && global_queue_size() == 0; + if (wait) thread->cond.wait(lock); } @@ -229,6 +241,7 @@ void ThreadManager::EnqueueTask(Task *task) { _assert_msg_(IsInitialized(), "ThreadManager not initialized"); + size_t queueIndex = (size_t)task->Priority(); int minThread; int maxThread; if (task->Type() == TaskType::CPU_COMPUTE) { @@ -247,7 +260,7 @@ void ThreadManager::EnqueueTask(Task *task) { ThreadContext *thread = global_->threads_[threadNum]; if (thread->queue_size.load() == 0) { std::unique_lock lock(thread->mutex); - thread->private_queue.push_back(task); + thread->private_queue[queueIndex].push_back(task); thread->queue_size++; thread->cond.notify_one(); // Found it - done. @@ -260,10 +273,10 @@ void ThreadManager::EnqueueTask(Task *task) { { std::unique_lock lock(global_->mutex); if (task->Type() == TaskType::CPU_COMPUTE) { - global_->compute_queue.push_back(task); + global_->compute_queue[queueIndex].push_back(task); global_->compute_queue_size++; } else if (task->Type() == TaskType::IO_BLOCKING) { - global_->io_queue.push_back(task); + global_->io_queue[queueIndex].push_back(task); global_->io_queue_size++; } else { _assert_(false); @@ -284,11 +297,12 @@ void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task) { _assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized"); ThreadContext *thread = global_->threads_[threadNum]; + size_t queueIndex = (size_t)task->Priority(); thread->queue_size++; std::unique_lock lock(thread->mutex); - thread->private_queue.push_back(task); + thread->private_queue[queueIndex].push_back(task); thread->cond.notify_one(); } From c690b12669813ebe87aee40030e918698eba1496 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Jan 2023 08:15:13 -0800 Subject: [PATCH 020/424] ThreadManager: Use priority across global/thread. --- Common/Thread/ThreadManager.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index 318207c645..0fc8574091 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -156,23 +156,27 @@ static void WorkerThreadFunc(GlobalThreadContext *global, ThreadContext *thread) auto queue = isCompute ? global->compute_queue : global->io_queue; auto &queue_size = isCompute ? global->compute_queue_size : global->io_queue_size; - if (queue_size != 0) { - for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { - if (queue[p].empty()) - continue; - + for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { + if (!queue[p].empty()) { task = queue[p].front(); queue[p].pop_front(); queue_size--; // We are processing one now, so mark that. thread->queue_size++; - break; + } else if (thread->queue_size != 0) { + // Check the thread, as we prefer a HIGH thread task to a global NORMAL task. + std::unique_lock lock(thread->mutex); + if (!thread->private_queue[p].empty()) { + task = thread->private_queue[p].front(); + thread->private_queue[p].pop_front(); + } } } } if (!task) { + // We didn't have any global, do we have anything on the thread? std::unique_lock lock(thread->mutex); for (size_t p = 0; p < TASK_PRIORITY_COUNT; ++p) { if (thread->private_queue[p].empty()) From d2d854b8eabf1d805f48a5addf0b798c8ee154db Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 15 Jan 2023 08:15:59 -0800 Subject: [PATCH 021/424] Replacement: Fix JNI attach for texture save. --- Core/TextureReplacer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 3fbfd935b2..ef6f20e27c 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -708,8 +708,8 @@ public: TextureSaveTask(SimpleBuf _data) : data(std::move(_data)) {} - // Also I/O blocking but dominated by compute. - TaskType Type() const override { return TaskType::CPU_COMPUTE; } + // This must be IO blocking because of Android storage, despite being CPU heavy. + TaskType Type() const override { return TaskType::IO_BLOCKING; } TaskPriority Priority() const override { return TaskPriority::LOW; From 2cada630873ada11f4fd26f609d97f1145dba0e8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 2 Feb 2023 17:07:31 -0800 Subject: [PATCH 022/424] UI: Buildfix on MSVC 2017. --- Core/TiltEventProcessor.cpp | 1 + UI/JoystickHistoryView.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 631aee0d68..8f1f3d4303 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -1,5 +1,6 @@ #define _USE_MATH_DEFINES +#include #include #include "Common/Math/math_util.h" diff --git a/UI/JoystickHistoryView.cpp b/UI/JoystickHistoryView.cpp index fc49622bb5..38dbcb54a5 100644 --- a/UI/JoystickHistoryView.cpp +++ b/UI/JoystickHistoryView.cpp @@ -1,3 +1,4 @@ +#include #include "UI/JoystickHistoryView.h" #include "Common/UI/Context.h" #include "Common/UI/UI.h" From 7635c4447c12ca2be80b3cda6156ab30d0b9f374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Feb 2023 08:51:35 +0100 Subject: [PATCH 023/424] Oops, apply the alpha fix for D3D9 and OpenGL too. See #16875 --- GPU/Directx9/ShaderManagerDX9.cpp | 6 +++++- GPU/GLES/ShaderManagerGLES.cpp | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 7f6039301a..e6dc013922 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -286,8 +286,12 @@ void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) { PSSetFloat(CONST_PS_STENCILREPLACE, (float)gstate.getStencilTestRef() * (1.0f / 255.0f)); } if (dirtyUniforms & DIRTY_TEX_ALPHA_MUL) { + bool doTextureAlpha = gstate.isTextureAlphaUsed(); + if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) { + doTextureAlpha = false; + } // NOTE: Reversed value, more efficient in shader. - PSSetFloat(CONST_PS_TEX_NO_ALPHA, gstate.isTextureAlphaUsed() ? 0.0f : 1.0f); + PSSetFloat(CONST_PS_TEX_NO_ALPHA, doTextureAlpha ? 0.0f : 1.0f); PSSetFloat(CONST_PS_TEX_MUL, gstate.isColorDoublingEnabled() ? 2.0f : 1.0f); } if (dirtyUniforms & DIRTY_SHADERBLEND) { diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 3659f8f2cb..9dabc96442 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -458,7 +458,11 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin SetColorUniform3(render_, &u_texenv, gstate.texenvcolor); } if (dirty & DIRTY_TEX_ALPHA_MUL) { - render_->SetUniformF1(&u_texNoAlpha, gstate.isTextureAlphaUsed() ? 0.0f : 1.0f); + bool doTextureAlpha = gstate.isTextureAlphaUsed(); + if (gstate_c.textureFullAlpha && gstate.getTextureFunction() != GE_TEXFUNC_REPLACE) { + doTextureAlpha = false; + } + render_->SetUniformF1(&u_texNoAlpha, doTextureAlpha ? 0.0f : 1.0f); render_->SetUniformF1(&u_texMul, gstate.isColorDoublingEnabled() ? 2.0f : 1.0f); } if (dirty & DIRTY_ALPHACOLORREF) { From 4fa7bbfc4042a11aa16f6bd7e4397d919f5a0b75 Mon Sep 17 00:00:00 2001 From: Lubos Date: Fri, 3 Feb 2023 10:00:15 +0100 Subject: [PATCH 024/424] OpenXR - Ignore should render parameter --- Common/VR/VRRenderer.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 7db2073244..8a3cc8ef90 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -250,9 +250,6 @@ bool VR_InitFrame( engine_t* engine ) { OXR(xrWaitFrame(engine->appState.Session, &waitFrameInfo, &frameState)); engine->predictedDisplayTime = frameState.predictedDisplayTime; - if (!frameState.shouldRender) { - return false; - } // Get the HMD pose, predicted for the middle of the time period during which // the new eye images will be displayed. The number of frames predicted ahead From df1700002ba9c35977592705c5e4835bb1e1a4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Feb 2023 18:58:26 +0100 Subject: [PATCH 025/424] Attempt at libretro buildfix --- Common/VR/VRFramebuffer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 34303c1ec6..6d8b94177a 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -2,8 +2,7 @@ #if XR_USE_GRAPHICS_API_OPENGL_ES -#include -#include +#include "Common/GPU/OpenGL/GLCommon.h" #endif From f2a6c744bc9f30dfd1282bae35204744eb4cb862 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Feb 2023 18:51:59 +0100 Subject: [PATCH 026/424] Add built-in stretch functionality to depth readback shader path --- GPU/Common/FramebufferManagerCommon.cpp | 39 +++++++++++++++++-------- GPU/Common/FramebufferManagerCommon.h | 2 +- GPU/Directx9/FramebufferManagerDX9.cpp | 7 ++++- GPU/Directx9/FramebufferManagerDX9.h | 2 +- GPU/GLES/DepthBufferGLES.cpp | 18 ++++++++---- GPU/GLES/FramebufferManagerGLES.h | 2 +- 6 files changed, 48 insertions(+), 22 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index de73d52e29..9c7a4de708 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2640,17 +2640,26 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 } bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; - if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { - buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, flipY); - } else { - buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY); - } - // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) - bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, "GetDepthBuffer"); - if (!retval) { - // Try ReadbackDepthbufferSync, in case GLES. + + bool retval; + if (true) { + // Always use ReadbackDepthbufferSync (while we debug it) buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); - retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w); + retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h); + } else { + // Old code + if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, flipY); + } else { + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY); + } + // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) + retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, "GetDepthBuffer"); + if (!retval) { + // Try ReadbackDepthbufferSync, in case GLES. + buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); + retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h); + } } // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. @@ -2748,7 +2757,7 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, if (channel == RASTER_DEPTH) { _assert_msg_(vfb && vfb->z_address != 0 && vfb->z_stride != 0, "Depth buffer invalid"); - ReadbackDepthbufferSync(vfb->fbo, x, y, w, h, (uint16_t *)destPtr, stride); + ReadbackDepthbufferSync(vfb->fbo, x, y, w, h, (uint16_t *)destPtr, stride, w, h); } else { draw_->CopyFramebufferToMemorySync(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, "ReadbackFramebufferSync"); } @@ -2760,8 +2769,14 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, gpuStats.numReadbacks++; } -bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride) { +bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { Draw::DataFormat destFormat = GEFormatToThin3D(GE_FORMAT_DEPTH16); + + if (w != destW || h != destH) { + // This path can't handle stretch blits. That's fine, this path is going away later. + return false; + } + // TODO: Apply depth scale factors if we don't have depth clamp. return draw_->CopyFramebufferToMemorySync(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, pixels, pixelsStride, "ReadbackDepthbufferSync"); } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 4f0212f8cd..2e91e4b2a8 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -453,7 +453,7 @@ public: protected: virtual void ReadbackFramebufferSync(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel); // Used for when a shader is required, such as GLES. - virtual bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride); + virtual bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH); virtual bool ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride); void SetViewport2D(int x, int y, int w, int h); Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index da53a7b802..a3a37eea4c 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -53,7 +53,12 @@ FramebufferManagerDX9::FramebufferManagerDX9(Draw::DrawContext *draw) FramebufferManagerDX9::~FramebufferManagerDX9() { } -bool FramebufferManagerDX9::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride) { +bool FramebufferManagerDX9::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { + // Don't yet support stretched readbacks here. + if (destW != w || destH != h) { + return false; + } + // We always read the depth buffer in 24_8 format. LPDIRECT3DTEXTURE9 tex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(fbo, Draw::FB_DEPTH_BIT, 0); if (!tex) diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index e189425b38..bcbe3f7941 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -38,5 +38,5 @@ public: ~FramebufferManagerDX9(); protected: - bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride) override; + bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) override; }; diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/GLES/DepthBufferGLES.cpp index 96072685ea..39b9fed283 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/GLES/DepthBufferGLES.cpp @@ -173,7 +173,7 @@ static Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const cha return pipeline; } -bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride) { +bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { using namespace Draw; if (!fbo) { @@ -186,16 +186,22 @@ bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int } // Pixel size always 4 here because we always request float or RGBA. - const u32 bufSize = w * h * 4; + const u32 bufSize = destW * destH * 4; if (!convBuf_ || convBufSize_ < bufSize) { delete[] convBuf_; convBuf_ = new u8[bufSize]; convBufSize_ = bufSize; } - const bool useColorPath = gl_extensions.IsGLES; + float scaleX = (float)destW / w; + float scaleY = (float)destH / h; + + bool useColorPath = gl_extensions.IsGLES || scaleX != 1.0f || scaleY != 1.0f; bool format16Bit = false; + // For testing. DO NOT merge. + useColorPath = true; + if (useColorPath) { if (!depthReadbackPipeline_) { depthReadbackPipeline_ = CreateReadbackPipeline(draw_, "depth_dl", &depthUBDesc, depth_dl_fs, "depth_dl_fs", depth_vs, "depth_vs"); @@ -205,14 +211,14 @@ bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int shaderManager_->DirtyLastShader(); auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width(), fbo->Height()); draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackDepthbufferSync"); - Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f }; + Draw::Viewport viewport = { 0.0f, 0.0f, (float)destW, (float)destH, 0.0f, 1.0f }; draw_->SetViewports(1, &viewport); draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_DEPTH_BIT, 0); draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &depthReadbackSampler_); // We must bind the program after starting the render pass. - draw_->SetScissorRect(0, 0, w, h); + draw_->SetScissorRect(0, 0, destW, destH); draw_->BindPipeline(depthReadbackPipeline_); DepthUB ub{}; @@ -241,7 +247,7 @@ bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int }; draw_->DrawUP(positions, 3); - draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, "ReadbackDepthbufferSync"); + draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x * scaleX, y * scaleY, w * scaleX, h * scaleY, DataFormat::R8G8B8A8_UNORM, convBuf_, w, "ReadbackDepthbufferSync"); textureCache_->ForgetLastTexture(); // TODO: Use 4444 so we can copy lines directly (instead of 32 -> 16 on CPU)? diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index c910014375..528fc0a79a 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -37,7 +37,7 @@ public: protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; - bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride) override; + bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) override; bool ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) override; private: From 4402530ca77d77bf9e0b8d94d1e7f2195753d9d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Feb 2023 20:32:16 +0100 Subject: [PATCH 027/424] Use ShaderWriter to generate the depth readback shader --- GPU/GLES/DepthBufferGLES.cpp | 95 +++++++++++++++++------------------- 1 file changed, 46 insertions(+), 49 deletions(-) diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/GLES/DepthBufferGLES.cpp index 39b9fed283..b2e0ea1eef 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/GLES/DepthBufferGLES.cpp @@ -25,53 +25,13 @@ #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/ShaderManagerGLES.h" #include "GPU/GLES/TextureCacheGLES.h" +#include "Common/GPU/ShaderWriter.h" -static const char *depth_dl_fs = R"( -#ifdef GL_ES -#ifdef GL_FRAGMENT_PRECISION_HIGH -precision highp float; -#else -precision mediump float; -#endif -#endif -#if __VERSION__ >= 130 -#define varying in -#define texture2D texture -#define gl_FragColor fragColor0 -out vec4 fragColor0; -#endif -varying vec2 v_texcoord; -uniform vec4 u_depthFactor; -uniform vec4 u_depthShift; -uniform vec4 u_depthTo8; -uniform sampler2D tex; -void main() { - float depth = texture2D(tex, v_texcoord).r; - // At this point, clamped maps [0, 1] to [0, 65535]. - float clamped = clamp((depth + u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0); - vec4 enc = u_depthShift * clamped; - enc = floor(mod(enc, 256.0)) * u_depthTo8; - // Let's ignore the bits outside 16 bit precision. - gl_FragColor = enc.yzww; -} -)"; - -static const char *depth_vs = R"( -#ifdef GL_ES -precision highp float; -#endif -#if __VERSION__ >= 130 -#define attribute in -#define varying out -#endif -attribute vec2 a_position; -varying vec2 v_texcoord; -void main() { - v_texcoord = a_position * 2.0; - gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0); -} -)"; +static const InputDef inputs[2] = { + { "vec2", "a_position", Draw::SEM_POSITION }, + { "vec2", "a_texcoord0", Draw::SEM_TEXCOORD0 }, +}; struct DepthUB { float u_depthFactor[4]; @@ -79,12 +39,45 @@ struct DepthUB { float u_depthTo8[4]; }; +const UniformDef depthUniforms[3] = { + { "vec4", "u_depthFactor", 0 }, + { "vec4", "u_depthShift", 1}, + { "vec4", "u_depthTo8", 2}, +}; + const UniformBufferDesc depthUBDesc{ sizeof(DepthUB), { { "u_depthFactor", -1, -1, UniformType::FLOAT4, 0 }, { "u_depthShift", -1, -1, UniformType::FLOAT4, 16 }, { "u_depthTo8", -1, -1, UniformType::FLOAT4, 32 }, } }; +static const SamplerDef samplers[1] = { + { 0, "tex", SamplerFlags::ARRAY_ON_VULKAN }, +}; + +static const VaryingDef varyings[1] = { + { "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" }, +}; + +void GenerateDepthDownloadFs(ShaderWriter &writer) { + writer.DeclareSamplers(samplers); + writer.BeginFSMain(depthUniforms, varyings); + writer.C(" float depth = texture2D(tex, v_texcoord).r;\n"); + // At this point, clamped maps [0, 1] to [0, 65535]. + writer.C(" float clamped = clamp((depth + u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);\n"); + writer.C(" vec4 enc = u_depthShift * clamped;\n"); + writer.C(" enc = floor(mod(enc, 256.0)) * u_depthTo8;\n"); + writer.C(" vec4 outColor = enc.yzww;\n"); // Let's ignore the bits outside 16 bit precision. + writer.EndFSMain("outColor"); +} + +void GenerateDepthDownloadVs(ShaderWriter &writer) { + writer.BeginVSMain(inputs, Slice::empty(), varyings); + writer.C("v_texcoord = a_position * 2.0;\n"); + writer.C("gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);"); + writer.EndVSMain(varyings); +} + static const char *stencil_dl_fs = R"( #ifdef GL_ES #ifdef GL_FRAGMENT_PRECISION_HIGH @@ -199,12 +192,16 @@ bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int bool useColorPath = gl_extensions.IsGLES || scaleX != 1.0f || scaleY != 1.0f; bool format16Bit = false; - // For testing. DO NOT merge. - useColorPath = true; - if (useColorPath) { if (!depthReadbackPipeline_) { - depthReadbackPipeline_ = CreateReadbackPipeline(draw_, "depth_dl", &depthUBDesc, depth_dl_fs, "depth_dl_fs", depth_vs, "depth_vs"); + const ShaderLanguageDesc &shaderLanguageDesc = draw_->GetShaderLanguageDesc(); + char depth_dl_fs[1024]; + char depth_dl_vs[1024]; + ShaderWriter fsWriter(depth_dl_fs, shaderLanguageDesc, ShaderStage::Fragment); + ShaderWriter vsWriter(depth_dl_vs, shaderLanguageDesc, ShaderStage::Vertex); + GenerateDepthDownloadFs(fsWriter); + GenerateDepthDownloadVs(vsWriter); + depthReadbackPipeline_ = CreateReadbackPipeline(draw_, "depth_dl", &depthUBDesc, depth_dl_fs, "depth_dl_fs", depth_dl_vs, "depth_dl_vs"); depthReadbackSampler_ = draw_->CreateSamplerState({}); } From 23c8a79473a96765d507b5649b14d498e33ea266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Feb 2023 20:53:49 +0100 Subject: [PATCH 028/424] Make depth readback through the "color path" work on all backends except D3D9 --- GPU/Common/FramebufferManagerCommon.cpp | 13 +------------ GPU/Common/FramebufferManagerCommon.h | 4 ++++ GPU/Directx9/FramebufferManagerDX9.h | 5 +---- GPU/GLES/DepthBufferGLES.cpp | 17 ++++++++--------- GPU/GLES/FramebufferManagerGLES.cpp | 4 ---- GPU/GLES/FramebufferManagerGLES.h | 6 ------ 6 files changed, 14 insertions(+), 35 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9c7a4de708..e94728c0bd 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -80,6 +80,7 @@ FramebufferManagerCommon::~FramebufferManagerCommon() { bvfbs_.clear(); delete presentation_; + delete[] convBuf_; } void FramebufferManagerCommon::Init(int msaaLevel) { @@ -2769,18 +2770,6 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, gpuStats.numReadbacks++; } -bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { - Draw::DataFormat destFormat = GEFormatToThin3D(GE_FORMAT_DEPTH16); - - if (w != destW || h != destH) { - // This path can't handle stretch blits. That's fine, this path is going away later. - return false; - } - - // TODO: Apply depth scale factors if we don't have depth clamp. - return draw_->CopyFramebufferToMemorySync(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, pixels, pixelsStride, "ReadbackDepthbufferSync"); -} - bool FramebufferManagerCommon::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) { return draw_->CopyFramebufferToMemorySync(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, "ReadbackStencilbufferSync"); } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 2e91e4b2a8..e66812c22e 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -601,4 +601,8 @@ protected: Draw2D draw2D_; // The fragment shaders are "owned" by the pipelines since they're 1:1. + + // Depth readback helper state + u8 *convBuf_ = nullptr; + u32 convBufSize_ = 0; }; diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index bcbe3f7941..5ac924e4e1 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -21,10 +21,6 @@ #include -// Keeps track of allocated FBOs. -// Also provides facilities for drawing and later converting raw -// pixel data. - #include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" @@ -38,5 +34,6 @@ public: ~FramebufferManagerDX9(); protected: + // TODO: The non-color path of FramebufferManagerCommon::ReadbackDepthbufferSync seems to work just as well. bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) override; }; diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/GLES/DepthBufferGLES.cpp index b2e0ea1eef..b249331b1c 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/GLES/DepthBufferGLES.cpp @@ -28,9 +28,8 @@ #include "Common/GPU/ShaderWriter.h" -static const InputDef inputs[2] = { +static const InputDef vs_inputs[] = { { "vec2", "a_position", Draw::SEM_POSITION }, - { "vec2", "a_texcoord0", Draw::SEM_TEXCOORD0 }, }; struct DepthUB { @@ -39,7 +38,7 @@ struct DepthUB { float u_depthTo8[4]; }; -const UniformDef depthUniforms[3] = { +const UniformDef depthUniforms[] = { { "vec4", "u_depthFactor", 0 }, { "vec4", "u_depthShift", 1}, { "vec4", "u_depthTo8", 2}, @@ -51,18 +50,18 @@ const UniformBufferDesc depthUBDesc{ sizeof(DepthUB), { { "u_depthTo8", -1, -1, UniformType::FLOAT4, 32 }, } }; -static const SamplerDef samplers[1] = { - { 0, "tex", SamplerFlags::ARRAY_ON_VULKAN }, +static const SamplerDef samplers[] = { + { 0, "tex" }, }; -static const VaryingDef varyings[1] = { +static const VaryingDef varyings[] = { { "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" }, }; void GenerateDepthDownloadFs(ShaderWriter &writer) { writer.DeclareSamplers(samplers); writer.BeginFSMain(depthUniforms, varyings); - writer.C(" float depth = texture2D(tex, v_texcoord).r;\n"); + writer.C(" float depth = ").SampleTexture2D("tex", "v_texcoord").C(".r; \n"); // At this point, clamped maps [0, 1] to [0, 65535]. writer.C(" float clamped = clamp((depth + u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);\n"); writer.C(" vec4 enc = u_depthShift * clamped;\n"); @@ -72,7 +71,7 @@ void GenerateDepthDownloadFs(ShaderWriter &writer) { } void GenerateDepthDownloadVs(ShaderWriter &writer) { - writer.BeginVSMain(inputs, Slice::empty(), varyings); + writer.BeginVSMain(vs_inputs, Slice::empty(), varyings); writer.C("v_texcoord = a_position * 2.0;\n"); writer.C("gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0);"); writer.EndVSMain(varyings); @@ -166,7 +165,7 @@ static Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const cha return pipeline; } -bool FramebufferManagerGLES::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { +bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { using namespace Draw; if (!fbo) { diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index e5a2308fb4..4c0b7480f9 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -45,10 +45,6 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : presentation_->SetLanguage(draw_->GetShaderLanguageDesc().shaderLanguage); } -FramebufferManagerGLES::~FramebufferManagerGLES() { - delete[] convBuf_; -} - void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) { _assert_msg_(nvfb->fbo, "Expecting a valid nvfb in UpdateDownloadTempBuffer"); diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 528fc0a79a..15c123a1e5 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -29,7 +29,6 @@ class GLRProgram; class FramebufferManagerGLES : public FramebufferManagerCommon { public: FramebufferManagerGLES(Draw::DrawContext *draw); - ~FramebufferManagerGLES(); void NotifyDisplayResized() override; @@ -37,10 +36,5 @@ public: protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; - bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) override; bool ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) override; - -private: - u8 *convBuf_ = nullptr; - u32 convBufSize_ = 0; }; From fb8aff5a8c710f4159b9dfec124d1c7b4869f6e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 3 Feb 2023 21:06:43 +0100 Subject: [PATCH 029/424] Split out the depth stuff from the file, move to GPU/Common --- CMakeLists.txt | 3 +- .../DepthBufferCommon.cpp} | 83 +-------- GPU/GLES/StencilBufferGLES.cpp | 170 ++++++++++++++++++ GPU/GPU.vcxproj | 8 +- GPU/GPU.vcxproj.filters | 9 +- UWP/GPU_UWP/GPU_UWP.vcxproj | 3 +- UWP/GPU_UWP/GPU_UWP.vcxproj.filters | 3 +- android/jni/Android.mk | 3 +- libretro/Makefile.common | 3 +- 9 files changed, 193 insertions(+), 92 deletions(-) rename GPU/{GLES/DepthBufferGLES.cpp => Common/DepthBufferCommon.cpp} (75%) create mode 100644 GPU/GLES/StencilBufferGLES.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 105200b0ea..7403596347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1499,7 +1499,7 @@ if(NOT MOBILE_DEVICE) endif() set(GPU_GLES - GPU/GLES/DepthBufferGLES.cpp + GPU/GLES/StencilBufferGLES.cpp GPU/GLES/GPU_GLES.cpp GPU/GLES/GPU_GLES.h GPU/GLES/FragmentTestCacheGLES.cpp @@ -1580,6 +1580,7 @@ set(GPU_SOURCES ${GPU_NEON} GPU/Common/Draw2D.cpp GPU/Common/Draw2D.h + GPU/Common/DepthBufferCommon.cpp GPU/Common/TextureShaderCommon.cpp GPU/Common/TextureShaderCommon.h GPU/Common/DepalettizeShaderCommon.cpp diff --git a/GPU/GLES/DepthBufferGLES.cpp b/GPU/Common/DepthBufferCommon.cpp similarity index 75% rename from GPU/GLES/DepthBufferGLES.cpp rename to GPU/Common/DepthBufferCommon.cpp index b249331b1c..620131a0bd 100644 --- a/GPU/GLES/DepthBufferGLES.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -21,10 +21,9 @@ #include "Common/LogReporting.h" #include "Core/ConfigValues.h" #include "GPU/Common/GPUStateUtils.h" -#include "GPU/GLES/DrawEngineGLES.h" -#include "GPU/GLES/FramebufferManagerGLES.h" -#include "GPU/GLES/ShaderManagerGLES.h" -#include "GPU/GLES/TextureCacheGLES.h" +#include "GPU/Common/DrawEngineCommon.h" +#include "GPU/Common/FramebufferManagerCommon.h" +#include "GPU/Common/TextureCacheCommon.h" #include "Common/GPU/ShaderWriter.h" @@ -123,7 +122,7 @@ static bool SupportsDepthTexturing() { return gl_extensions.ARB_texture_float; } -static Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag) { +Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag) { using namespace Draw; const ShaderLanguageDesc &shaderLanguageDesc = draw->GetShaderLanguageDesc(); @@ -268,7 +267,7 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i // TODO: Apply this in the shader? May have precision issues if it becomes important to match. // We downloaded float values directly in this case. uint16_t *dest = pixels; - const GLfloat *packedf = (GLfloat *)convBuf_; + const float *packedf = (float *)convBuf_; DepthScaleFactors depthScale = GetDepthScaleFactors(); for (int yp = 0; yp < h; ++yp) { for (int xp = 0; xp < w; ++xp) { @@ -289,75 +288,3 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); return true; } - -// Well, this is not depth, but it's depth/stencil related. -bool FramebufferManagerGLES::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) { - using namespace Draw; - - if (!fbo) { - ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "ReadbackStencilbufferSync: bad fbo"); - return false; - } - - const bool useColorPath = gl_extensions.IsGLES; - if (!useColorPath) { - return draw_->CopyFramebufferToMemorySync(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, "ReadbackStencilbufferSync"); - } - - // Unsupported below GLES 3.1 or without ARB_stencil_texturing. - // OES_texture_stencil8 is related, but used to specify texture data. - if ((gl_extensions.IsGLES && !gl_extensions.VersionGEThan(3, 1)) && !gl_extensions.ARB_stencil_texturing) - return false; - - // Pixel size always 4 here because we always request RGBA back. - const u32 bufSize = w * h * 4; - if (!convBuf_ || convBufSize_ < bufSize) { - delete[] convBuf_; - convBuf_ = new u8[bufSize]; - convBufSize_ = bufSize; - } - - if (!stencilReadbackPipeline_) { - stencilReadbackPipeline_ = CreateReadbackPipeline(draw_, "stencil_dl", &depthUBDesc, stencil_dl_fs, "stencil_dl_fs", stencil_vs, "stencil_vs"); - stencilReadbackSampler_ = draw_->CreateSamplerState({}); - } - - shaderManager_->DirtyLastShader(); - auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width(), fbo->Height()); - draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackStencilbufferSync"); - Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f }; - draw_->SetViewports(1, &viewport); - - draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_STENCIL_BIT, 0); - draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &stencilReadbackSampler_); - - // We must bind the program after starting the render pass. - draw_->SetScissorRect(0, 0, w, h); - draw_->BindPipeline(stencilReadbackPipeline_); - - // Fullscreen triangle coordinates. - static const float positions[6] = { - 0.0, 0.0, - 1.0, 0.0, - 0.0, 1.0, - }; - draw_->DrawUP(positions, 3); - - draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, "ReadbackStencilbufferSync"); - - textureCache_->ForgetLastTexture(); - - // TODO: Use 1/4 width to write all values directly and skip CPU conversion? - uint8_t *dest = pixels; - const u32_le *packed32 = (u32_le *)convBuf_; - for (int yp = 0; yp < h; ++yp) { - for (int xp = 0; xp < w; ++xp) { - dest[xp] = packed32[xp] & 0xFF; - } - dest += pixelsStride; - packed32 += w; - } - - gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); - return true; -} diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp new file mode 100644 index 0000000000..32cd92497d --- /dev/null +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -0,0 +1,170 @@ +// Copyright (c) 2012- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include + +#include "Common/GPU/OpenGL/GLFeatures.h" +#include "Common/LogReporting.h" +#include "Core/ConfigValues.h" +#include "GPU/Common/GPUStateUtils.h" +#include "GPU/Common/DrawEngineCommon.h" +#include "GPU/Common/TextureCacheCommon.h" +#include "GPU/GLES/FramebufferManagerGLES.h" +#include "Common/GPU/ShaderWriter.h" + +static const InputDef vs_inputs[] = { + { "vec2", "a_position", Draw::SEM_POSITION }, +}; + +struct DepthUB { + float u_depthFactor[4]; + float u_depthShift[4]; + float u_depthTo8[4]; +}; + +const UniformDef depthUniforms[] = { + { "vec4", "u_depthFactor", 0 }, + { "vec4", "u_depthShift", 1}, + { "vec4", "u_depthTo8", 2}, +}; + +const UniformBufferDesc depthUBDesc{ sizeof(DepthUB), { + { "u_depthFactor", -1, -1, UniformType::FLOAT4, 0 }, + { "u_depthShift", -1, -1, UniformType::FLOAT4, 16 }, + { "u_depthTo8", -1, -1, UniformType::FLOAT4, 32 }, +} }; + +static const SamplerDef samplers[] = { + { 0, "tex" }, +}; + +static const VaryingDef varyings[] = { + { "vec2", "v_texcoord", Draw::SEM_TEXCOORD0, 0, "highp" }, +}; + +static const char *stencil_dl_fs = R"( +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#endif +#if __VERSION__ >= 130 +#define varying in +#define texture2D texture +#define gl_FragColor fragColor0 +out vec4 fragColor0; +#endif +varying vec2 v_texcoord; +lowp uniform usampler2D tex; +void main() { + uint stencil = texture2D(tex, v_texcoord).r; + float scaled = float(stencil) / 255.0; + gl_FragColor = vec4(scaled, scaled, scaled, scaled); +} +)"; + +static const char *stencil_vs = R"( +#ifdef GL_ES +precision highp float; +#endif +#if __VERSION__ >= 130 +#define attribute in +#define varying out +#endif +attribute vec2 a_position; +varying vec2 v_texcoord; +void main() { + v_texcoord = a_position * 2.0; + gl_Position = vec4(v_texcoord * 2.0 - vec2(1.0, 1.0), 0.0, 1.0); +} +)"; + +Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag); + +// Well, this is not depth, but it's depth/stencil related. +bool FramebufferManagerGLES::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) { + using namespace Draw; + + if (!fbo) { + ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "ReadbackStencilbufferSync: bad fbo"); + return false; + } + + const bool useColorPath = gl_extensions.IsGLES; + if (!useColorPath) { + return draw_->CopyFramebufferToMemorySync(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, "ReadbackStencilbufferSync"); + } + + // Unsupported below GLES 3.1 or without ARB_stencil_texturing. + // OES_texture_stencil8 is related, but used to specify texture data. + if ((gl_extensions.IsGLES && !gl_extensions.VersionGEThan(3, 1)) && !gl_extensions.ARB_stencil_texturing) + return false; + + // Pixel size always 4 here because we always request RGBA back. + const u32 bufSize = w * h * 4; + if (!convBuf_ || convBufSize_ < bufSize) { + delete[] convBuf_; + convBuf_ = new u8[bufSize]; + convBufSize_ = bufSize; + } + + if (!stencilReadbackPipeline_) { + stencilReadbackPipeline_ = CreateReadbackPipeline(draw_, "stencil_dl", &depthUBDesc, stencil_dl_fs, "stencil_dl_fs", stencil_vs, "stencil_vs"); + stencilReadbackSampler_ = draw_->CreateSamplerState({}); + } + + shaderManager_->DirtyLastShader(); + auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width(), fbo->Height()); + draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackStencilbufferSync"); + Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f }; + draw_->SetViewports(1, &viewport); + + draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_STENCIL_BIT, 0); + draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &stencilReadbackSampler_); + + // We must bind the program after starting the render pass. + draw_->SetScissorRect(0, 0, w, h); + draw_->BindPipeline(stencilReadbackPipeline_); + + // Fullscreen triangle coordinates. + static const float positions[6] = { + 0.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + }; + draw_->DrawUP(positions, 3); + + draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, "ReadbackStencilbufferSync"); + + textureCache_->ForgetLastTexture(); + + // TODO: Use 1/4 width to write all values directly and skip CPU conversion? + uint8_t *dest = pixels; + const u32_le *packed32 = (u32_le *)convBuf_; + for (int yp = 0; yp < h; ++yp) { + for (int xp = 0; xp < w; ++xp) { + dest[xp] = packed32[xp] & 0xFF; + } + dest += pixelsStride; + packed32 += w; + } + + gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); + return true; +} diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 860dbc38f3..0f8711b03b 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -454,6 +454,7 @@ + @@ -525,12 +526,6 @@ - - true - true - true - true - true true @@ -561,6 +556,7 @@ true true + true true diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index b8a990374a..828e4c5265 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -461,9 +461,6 @@ Debugger - - GLES - Debugger @@ -518,6 +515,12 @@ Common + + Common + + + GLES + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 05b7839736..369a75da72 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -441,6 +441,7 @@ + @@ -531,4 +532,4 @@ - + \ No newline at end of file diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index 2296b16a16..2481c765c9 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -60,6 +60,7 @@ + @@ -123,4 +124,4 @@ - + \ No newline at end of file diff --git a/android/jni/Android.mk b/android/jni/Android.mk index eae8a9c672..6932d49ecf 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -372,6 +372,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/Common/GPUStateUtils.cpp.arm \ $(SRC)/GPU/Common/SoftwareTransformCommon.cpp.arm \ $(SRC)/GPU/Common/ReinterpretFramebuffer.cpp \ + $(SRC)/GPU/Common/DepthBufferCommon.cpp \ $(SRC)/GPU/Common/VertexDecoderCommon.cpp.arm \ $(SRC)/GPU/Common/TextureCacheCommon.cpp.arm \ $(SRC)/GPU/Common/TextureScalerCommon.cpp.arm \ @@ -392,7 +393,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/Debugger/Record.cpp \ $(SRC)/GPU/Debugger/Stepping.cpp \ $(SRC)/GPU/GLES/FramebufferManagerGLES.cpp \ - $(SRC)/GPU/GLES/DepthBufferGLES.cpp \ + $(SRC)/GPU/GLES/StencilBufferGLES.cpp \ $(SRC)/GPU/GLES/GPU_GLES.cpp.arm \ $(SRC)/GPU/GLES/TextureCacheGLES.cpp.arm \ $(SRC)/GPU/GLES/DrawEngineGLES.cpp.arm \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 4095102bba..2b62ff352d 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -391,6 +391,7 @@ SOURCES_CXX += \ $(GPUDIR)/Common/TextureCacheCommon.cpp \ $(GPUDIR)/Common/TextureScalerCommon.cpp \ $(GPUDIR)/Common/SoftwareTransformCommon.cpp \ + $(GPUDIR)/Common/DepthBufferCommon.cpp \ $(GPUDIR)/Common/StencilCommon.cpp \ $(GPUDIR)/Software/TransformUnit.cpp \ $(GPUDIR)/Software/SoftGpu.cpp \ @@ -409,7 +410,7 @@ SOURCES_CXX += \ $(GPUDIR)/Software/Rasterizer.cpp \ $(GPUDIR)/Software/RasterizerRectangle.cpp \ $(GPUDIR)/Software/RasterizerRegCache.cpp \ - $(GPUDIR)/GLES/DepthBufferGLES.cpp \ + $(GPUDIR)/GLES/StencilBufferGLES.cpp \ $(GPUDIR)/GLES/DrawEngineGLES.cpp \ $(GPUDIR)/GLES/GPU_GLES.cpp \ $(GPUDIR)/GLES/FragmentTestCacheGLES.cpp \ From 6ab6d8500737c564229a0a5f85b2a720337f26cf Mon Sep 17 00:00:00 2001 From: DDinghoya Date: Sat, 4 Feb 2023 11:43:02 +0900 Subject: [PATCH 030/424] Update ko_KR.ini --- assets/lang/ko_KR.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 22587f1a45..4215f116af 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -90,7 +90,7 @@ Swipe = 스와이프 Swipe sensitivity = 스와이프 감도 Swipe smoothing = 스와이프 스무딩 Thin borders = 얇은 테두리 -Tilt control setup = 기울기 맞춤설정... +Tilt control setup = 기울기 제어 설정... Tilt Input Type = 기울기 입력 유형 Tilt Sensitivity along X axis = X 축 기울기 감도 Tilt Sensitivity along Y axis = Y 축 기울기 감도 From c7234aa3b575afbe35ec2b5b3af98d8cb8b8a87f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Feb 2023 11:36:48 +0100 Subject: [PATCH 031/424] Handle scaling internally in ReadFramebufferSync --- GPU/Common/FramebufferManagerCommon.cpp | 34 +++++++++++-------------- GPU/Common/FramebufferManagerCommon.h | 2 ++ 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index e94728c0bd..0f7c5fe2cf 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2720,8 +2720,7 @@ bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { return retval; } -// This function takes an already correctly-sized framebuffer and reads it into emulated PSP VRAM. -// Does not need to account for scaling. +// This reads a channel of a framebuffer into emulated PSP VRAM, taking care of scaling down as needed. // // Color conversion is currently done on CPU but should theoretically be done on GPU. // (Except using the GPU might cause problems because of various implementations' @@ -2733,6 +2732,16 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, return; } + if (vfb->renderWidth == vfb->width && vfb->renderHeight == vfb->height) { + // No need to stretch-blit + } else { + VirtualFramebuffer *nvfb = FindDownloadTempBuffer(vfb, channel); + if (nvfb) { + BlitFramebuffer(nvfb, x, y, vfb, x, y, w, h, 0, channel, "Blit_ReadFramebufferToMemory"); + vfb = nvfb; + } + } + const u32 fb_address = channel == RASTER_COLOR ? vfb->fb_address : vfb->z_address; Draw::DataFormat destFormat = channel == RASTER_COLOR ? GEFormatToThin3D(vfb->fb_format) : GEFormatToThin3D(GE_FORMAT_DEPTH16); @@ -2780,7 +2789,6 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, w = vfb->bufferWidth - x; } if (vfb && vfb->fbo) { - // We'll pseudo-blit framebuffers here to get a resized version of vfb. if (gameUsesSequentialCopies_) { // Ignore the x/y/etc., read the entire thing. See below. x = 0; @@ -2811,16 +2819,8 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, } } - if (vfb->renderWidth == vfb->width && vfb->renderHeight == vfb->height) { - // No need to stretch-blit - ReadbackFramebufferSync(vfb, x, y, w, h, channel); - } else { - VirtualFramebuffer *nvfb = FindDownloadTempBuffer(vfb, channel); - if (nvfb) { - BlitFramebuffer(nvfb, x, y, vfb, x, y, w, h, 0, channel, "Blit_ReadFramebufferToMemory"); - ReadbackFramebufferSync(nvfb, x, y, w, h, channel); - } - } + // This handles any required stretching internally. + ReadbackFramebufferSync(vfb, x, y, w, h, channel); draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); textureCache_->ForgetLastTexture(); @@ -2871,12 +2871,8 @@ void FramebufferManagerCommon::DownloadFramebufferForClut(u32 fb_address, u32 lo } vfb->clutUpdatedBytes = loadBytes; - // We'll pseudo-blit framebuffers here to get a resized version of vfb. - VirtualFramebuffer *nvfb = FindDownloadTempBuffer(vfb, RASTER_COLOR); - if (nvfb) { - BlitFramebuffer(nvfb, x, y, vfb, x, y, w, h, 0, RASTER_COLOR, "Blit_DownloadFramebufferForClut"); - ReadbackFramebufferSync(nvfb, x, y, w, h, RASTER_COLOR); - } + // This function now handles scaling down internally. + ReadbackFramebufferSync(vfb, x, y, w, h, RASTER_COLOR); textureCache_->ForgetLastTexture(); RebindFramebuffer("RebindFramebuffer - DownloadFramebufferForClut"); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index e66812c22e..2046300edf 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -123,6 +123,8 @@ struct VirtualFramebuffer { // Tracking for downloads-to-CLUT. u16 clutUpdatedBytes; + + // Means that the whole image has already been read back to memory - used when combining small readbacks (gameUsesSequentialCopies_). bool memoryUpdated; // TODO: Fold into usageFlags? From 62484f01edf2968544168022ca5bbc1a7bf45b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Feb 2023 12:05:50 +0100 Subject: [PATCH 032/424] Make ReadbackFramebufferSync able to use the stretch ability of ReadbackDepthbufferSync --- GPU/Common/FramebufferManagerCommon.cpp | 34 +++++++++++++++---------- GPU/Common/FramebufferManagerCommon.h | 4 +++ GPU/Common/TextureCacheCommon.cpp | 4 +-- GPU/GPU.cpp | 4 +++ GPU/GPU.h | 2 ++ 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 0f7c5fe2cf..fc6b9bf86c 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2072,7 +2072,8 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd return vfb; } -// 1:1 pixel sides buffers, we resize buffers to these before we read them back. +// 1:1 pixel size buffers, we resize buffers to these before we read them back. +// TODO: We shouldn't keep whole VirtualFramebuffer structs for these - the fbo and last_frame_render is enough. VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFramebuffer *vfb, RasterChannel channel) { // For now we'll keep these on the same struct as the ones that can get displayed // (and blatantly copy work already done above while at it). @@ -2080,10 +2081,14 @@ VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFram // We maintain a separate vector of framebuffer objects for blitting. for (VirtualFramebuffer *v : bvfbs_) { - if (v->fb_address == vfb->fb_address && v->fb_format == vfb->fb_format) { + if (v->Address(channel) == vfb->Address(channel) && v->Format(channel) == vfb->Format(channel)) { if (v->bufferWidth == vfb->bufferWidth && v->bufferHeight == vfb->bufferHeight) { nvfb = v; - v->fb_stride = vfb->fb_stride; + if (channel == RASTER_COLOR) { + v->fb_stride = vfb->fb_stride; + } else { + v->z_stride = vfb->z_stride; + } v->width = vfb->width; v->height = vfb->height; break; @@ -2095,10 +2100,10 @@ VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFram if (!nvfb) { nvfb = new VirtualFramebuffer{}; nvfb->fbo = nullptr; - nvfb->fb_address = vfb->fb_address; - nvfb->fb_stride = vfb->fb_stride; - nvfb->z_address = vfb->z_address; - nvfb->z_stride = vfb->z_stride; + nvfb->fb_address = channel == RASTER_COLOR ? vfb->fb_address : 0; + nvfb->fb_stride = channel == RASTER_COLOR ? vfb->fb_stride : 0; + nvfb->z_address = channel == RASTER_DEPTH ? vfb->z_address : 0; + nvfb->z_stride = channel == RASTER_DEPTH ? vfb->z_stride : 0; nvfb->width = vfb->width; nvfb->height = vfb->height; nvfb->renderWidth = vfb->bufferWidth; @@ -2111,10 +2116,10 @@ VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFram nvfb->drawnHeight = vfb->drawnHeight; char name[64]; - snprintf(name, sizeof(name), "download_temp"); - // TODO: We don't have a way to create a depth-only framebuffer yet. - // Also, at least on Vulkan we always create both depth and color, need to rework how we handle renderpasses. - nvfb->fbo = draw_->CreateFramebuffer({ nvfb->bufferWidth, nvfb->bufferHeight, 1, 1, 0, channel == RASTER_DEPTH ? true : false, name }); + snprintf(name, sizeof(name), "download_temp_%08x_%s", vfb->Address(channel), RasterChannelToString(channel)); + + // We always create a color-only framebuffer here - readbacks of depth convert to color while translating the values. + nvfb->fbo = draw_->CreateFramebuffer({ nvfb->bufferWidth, nvfb->bufferHeight, 1, 1, 0, false, name }); if (!nvfb->fbo) { ERROR_LOG(FRAMEBUF, "Error creating FBO! %d x %d", nvfb->renderWidth, nvfb->renderHeight); delete nvfb; @@ -2732,7 +2737,8 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, return; } - if (vfb->renderWidth == vfb->width && vfb->renderHeight == vfb->height) { + // Note that ReadbackDepthBufferSync can stretch on its own while converting data format, so we don't need to downscale in that case. + if (vfb->renderScaleFactor == 1 || channel == RASTER_DEPTH) { // No need to stretch-blit } else { VirtualFramebuffer *nvfb = FindDownloadTempBuffer(vfb, channel); @@ -2767,7 +2773,9 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, if (channel == RASTER_DEPTH) { _assert_msg_(vfb && vfb->z_address != 0 && vfb->z_stride != 0, "Depth buffer invalid"); - ReadbackDepthbufferSync(vfb->fbo, x, y, w, h, (uint16_t *)destPtr, stride, w, h); + ReadbackDepthbufferSync(vfb->fbo, + x * vfb->renderScaleFactor, y * vfb->renderScaleFactor, + w * vfb->renderScaleFactor, h * vfb->renderScaleFactor, (uint16_t *)destPtr, stride, w, h); } else { draw_->CopyFramebufferToMemorySync(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, "ReadbackFramebufferSync"); } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 2046300edf..da63f69de0 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -154,6 +154,10 @@ struct VirtualFramebuffer { inline int BufferWidthInBytes() const { return bufferWidth * BufferFormatBytesPerPixel(fb_format); } inline int FbStrideInBytes() const { return fb_stride * BufferFormatBytesPerPixel(fb_format); } inline int ZStrideInBytes() const { return z_stride * 2; } + + inline int Stride(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_stride : z_stride; } + inline u32 Address(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_address : z_address; } + inline int Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; } }; struct FramebufferHeuristicParams { diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index dcbd5e4c3f..0d276ed39a 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1032,7 +1032,7 @@ bool TextureCacheCommon::MatchFramebuffer( // 3rd Birthday (and a bunch of other games) render to a 16 bit clut texture. if (matchingClutFormat) { if (!noOffset) { - WARN_LOG_ONCE(subareaClut, G3D, "Matching framebuffer (%s) using %s with offset at %08x +%dx%d", channel == RASTER_DEPTH ? "DEPTH" : "COLOR", GeTextureFormatToString(entry.format), fb_address, matchInfo->xOffset, matchInfo->yOffset); + WARN_LOG_ONCE(subareaClut, G3D, "Matching framebuffer (%s) using %s with offset at %08x +%dx%d", RasterChannelToString(channel), GeTextureFormatToString(entry.format), fb_address, matchInfo->xOffset, matchInfo->yOffset); } return true; } else if (IsClutFormat((GETextureFormat)(entry.format)) || IsDXTFormat((GETextureFormat)(entry.format))) { @@ -2596,7 +2596,7 @@ void TextureCacheCommon::ClearNextFrame() { std::string AttachCandidate::ToString() const { return StringFromFormat("[%s seq:%d rel:%d C:%08x/%d(%s) Z:%08x/%d X:%d Y:%d reint: %s]", - this->channel == RASTER_COLOR ? "COLOR" : "DEPTH", + RasterChannelToString(this->channel), this->channel == RASTER_COLOR ? this->fb->colorBindSeq : this->fb->depthBindSeq, this->relevancy, this->fb->fb_address, this->fb->fb_stride, GeBufferFormatToString(this->fb->fb_format), diff --git a/GPU/GPU.cpp b/GPU/GPU.cpp index abfe5a5a0b..2a7d477204 100644 --- a/GPU/GPU.cpp +++ b/GPU/GPU.cpp @@ -136,3 +136,7 @@ void GPU_Shutdown() { delete gpu; gpu = nullptr; } + +const char *RasterChannelToString(RasterChannel channel) { + return channel == RASTER_COLOR ? "COLOR" : "DEPTH"; +} diff --git a/GPU/GPU.h b/GPU/GPU.h index d9bbed5cee..4411733728 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -147,3 +147,5 @@ bool GPU_Init(GraphicsContext *ctx, Draw::DrawContext *draw); bool GPU_IsReady(); bool GPU_IsStarted(); void GPU_Shutdown(); + +const char *RasterChannelToString(RasterChannel channel); From 236611ac165a0ce65366d42bb09ce1cce33b4175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Feb 2023 13:28:59 +0100 Subject: [PATCH 033/424] Initial implementation of depth readback for Syphon Filter. Fixes the lens flares. --- Core/Compatibility.cpp | 1 + Core/Compatibility.h | 1 + GPU/Common/DepthBufferCommon.cpp | 21 ++++----- GPU/Common/FramebufferManagerCommon.cpp | 57 ++++++++++++++++--------- GPU/Common/FramebufferManagerCommon.h | 3 +- assets/compat.ini | 22 +++++++++- 6 files changed, 72 insertions(+), 33 deletions(-) diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 0a79f79810..35d3b7cd9a 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -125,6 +125,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "ForceCircleButtonConfirm", &flags_.ForceCircleButtonConfirm); CheckSetting(iniFile, gameID, "DisallowFramebufferAtOffset", &flags_.DisallowFramebufferAtOffset); CheckSetting(iniFile, gameID, "RockmanDash2SoundFix", &flags_.RockmanDash2SoundFix); + CheckSetting(iniFile, gameID, "ReadbackDepth", &flags_.ReadbackDepth); } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index 99b16ce525..dbc62c256c 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -96,6 +96,7 @@ struct CompatFlags { bool ForceCircleButtonConfirm; bool DisallowFramebufferAtOffset; bool RockmanDash2SoundFix; + bool ReadbackDepth; }; struct VRCompat { diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 620131a0bd..5d63385e26 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -204,16 +204,16 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i } shaderManager_->DirtyLastShader(); - auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width(), fbo->Height()); + auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width() * scaleX, fbo->Height() * scaleY); draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackDepthbufferSync"); Draw::Viewport viewport = { 0.0f, 0.0f, (float)destW, (float)destH, 0.0f, 1.0f }; draw_->SetViewports(1, &viewport); + draw_->SetScissorRect(0, 0, fbo->Width() * scaleX, fbo->Height() * scaleY); draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_DEPTH_BIT, 0); draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &depthReadbackSampler_); // We must bind the program after starting the render pass. - draw_->SetScissorRect(0, 0, destW, destH); draw_->BindPipeline(depthReadbackPipeline_); DepthUB ub{}; @@ -242,10 +242,10 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i }; draw_->DrawUP(positions, 3); - draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x * scaleX, y * scaleY, w * scaleX, h * scaleY, DataFormat::R8G8B8A8_UNORM, convBuf_, w, "ReadbackDepthbufferSync"); + draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x * scaleX, y * scaleY, w * scaleX, h * scaleY, DataFormat::R8G8B8A8_UNORM, convBuf_, destW, "ReadbackDepthbufferSync"); textureCache_->ForgetLastTexture(); - // TODO: Use 4444 so we can copy lines directly (instead of 32 -> 16 on CPU)? + // TODO: Use 4444 (or better, R16_UNORM) so we can copy lines directly (instead of 32 -> 16 on CPU)? format16Bit = true; } else { draw_->CopyFramebufferToMemorySync(fbo, FB_DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, "ReadbackDepthbufferSync"); @@ -254,14 +254,15 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i if (format16Bit) { // In this case, we used the shader to apply depth scale factors. + // This can be SSE'd or NEON'd very efficiently, though ideally we would avoid this conversion by using R16_UNORM for readback. uint16_t *dest = pixels; const u32_le *packed32 = (u32_le *)convBuf_; - for (int yp = 0; yp < h; ++yp) { - for (int xp = 0; xp < w; ++xp) { + for (int yp = 0; yp < destH; ++yp) { + for (int xp = 0; xp < destW; ++xp) { dest[xp] = packed32[xp] & 0xFFFF; } dest += pixelsStride; - packed32 += w; + packed32 += destW; } } else { // TODO: Apply this in the shader? May have precision issues if it becomes important to match. @@ -269,8 +270,8 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i uint16_t *dest = pixels; const float *packedf = (float *)convBuf_; DepthScaleFactors depthScale = GetDepthScaleFactors(); - for (int yp = 0; yp < h; ++yp) { - for (int xp = 0; xp < w; ++xp) { + for (int yp = 0; yp < destH; ++yp) { + for (int xp = 0; xp < destW; ++xp) { float scaled = depthScale.Apply(packedf[xp]); if (scaled <= 0.0f) { dest[xp] = 0; @@ -281,7 +282,7 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i } } dest += pixelsStride; - packedf += w; + packedf += destW; } } diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index fc6b9bf86c..dc810fe632 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -206,11 +206,6 @@ u32 FramebufferManagerCommon::ColorBufferByteSize(const VirtualFramebuffer *vfb) return vfb->fb_stride * vfb->height * (vfb->fb_format == GE_FORMAT_8888 ? 4 : 2); } -bool FramebufferManagerCommon::ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const { - // Dangan Ronpa hack - return PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000; -} - // Heuristics to figure out the size of FBO to create. // TODO: Possibly differentiate on whether through mode is used (since in through mode, viewport is meaningless?) void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, int fb_stride, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int &drawing_width, int &drawing_height) { @@ -1015,14 +1010,48 @@ void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer } } +void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb) { + if (vfb && vfb->safeWidth > 0 && vfb->safeHeight > 0 && !(vfb->usageFlags & FB_USAGE_FIRST_FRAME_SAVED) && !vfb->memoryUpdated) { + // Some games will draw to some memory once, and use it as a render-to-texture later. + // To support this, we save the first frame to memory when we have a safe w/h. + // Saving each frame would be slow. + + // TODO: This type of download could be made async, for less stutter on framebuffer creation. + if (!g_Config.bSkipGPUReadbacks && !PSP_CoreParameter().compat.flags().DisableFirstFrameReadback) { + ReadFramebufferToMemory(vfb, 0, 0, vfb->safeWidth, vfb->safeHeight, RASTER_COLOR); + vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; + vfb->safeWidth = 0; + vfb->safeHeight = 0; + } + } +} + +bool FramebufferManagerCommon::ShouldDownloadFramebufferColor(const VirtualFramebuffer *vfb) const { + // Dangan Ronpa hack + return PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000; +} + +bool FramebufferManagerCommon::ShouldDownloadFramebufferDepth(const VirtualFramebuffer *vfb) const { + // Download depth buffer for Syphon Filter lens flares + if (!PSP_CoreParameter().compat.flags().ReadbackDepth || g_Config.bSkipGPUReadbacks) { + return false; + } + return (vfb->usageFlags & FB_USAGE_RENDER_DEPTH) != 0 && vfb->width >= 480 && vfb->height >= 272; +} + void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { - if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { + // TODO: Isn't this wrong? Shouldn't we download the prevVfb if anything? + if (ShouldDownloadFramebufferColor(vfb) && !vfb->memoryUpdated) { ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR); vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } else { DownloadFramebufferOnSwitch(prevVfb); } + if (prevVfb && ShouldDownloadFramebufferDepth(prevVfb)) { + ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH); + } + textureCache_->ForgetLastTexture(); shaderManager_->DirtyLastShader(); @@ -1387,20 +1416,6 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int currentRenderVfb_ = nullptr; } -void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb) { - if (vfb && vfb->safeWidth > 0 && vfb->safeHeight > 0 && !(vfb->usageFlags & FB_USAGE_FIRST_FRAME_SAVED) && !vfb->memoryUpdated) { - // Some games will draw to some memory once, and use it as a render-to-texture later. - // To support this, we save the first frame to memory when we have a safe w/h. - // Saving each frame would be slow. - if (!g_Config.bSkipGPUReadbacks && !PSP_CoreParameter().compat.flags().DisableFirstFrameReadback) { - ReadFramebufferToMemory(vfb, 0, 0, vfb->safeWidth, vfb->safeHeight, RASTER_COLOR); - vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; - vfb->safeWidth = 0; - vfb->safeHeight = 0; - } - } -} - void FramebufferManagerCommon::SetViewport2D(int x, int y, int w, int h) { Draw::Viewport vp{ (float)x, (float)y, (float)w, (float)h, 0.0f, 1.0f }; draw_->SetViewports(1, &vp); @@ -1570,7 +1585,7 @@ void FramebufferManagerCommon::DecimateFBOs() { VirtualFramebuffer *vfb = vfbs_[i]; int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used); - if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) { + if (ShouldDownloadFramebufferColor(vfb) && age == 0 && !vfb->memoryUpdated) { ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR); vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index da63f69de0..df4a67bb27 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -490,7 +490,8 @@ protected: void ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, int h, bool force = false, bool skipCopy = false); void ShowScreenResolution(); - bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const; + bool ShouldDownloadFramebufferColor(const VirtualFramebuffer *vfb) const; + bool ShouldDownloadFramebufferDepth(const VirtualFramebuffer *vfb) const; void DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb); bool FindTransferFramebuffer(u32 basePtr, int stride, int x, int y, int w, int h, int bpp, bool destination, BlockTransferRect *rect); diff --git a/assets/compat.ini b/assets/compat.ini index 357993bab1..58f88da370 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -1437,4 +1437,24 @@ UCAS40262 = true # Rockman Dash 2, see #11442 ULJM05037 = true ULJM05216 = true -NPJH50181 = true \ No newline at end of file +NPJH50181 = true + +[ReadbackDepth] +# Syphon Filter - Dark Mirror +UCES00310 = true +UCUS98641 = true +UCUS98656 = true +UCUS98656 = true # Demo + +# Syphon Filter - Logan's Shadow +UCUS98606 = true +UCES00710 = true +NPUG80173 = true +NPUA80013 = true # Demo +UCUS98704 = true # Demo +NPEG90002 = true # Demo +SYPH04036 = true # Prototype? + +# Syphon Filter - Combat Ops (weird multiplayer-only variant) +NPUG80114 = true +NPEG00004 = true From 281b0d6aabd060f4aaafab6631057c9abb743ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Feb 2023 18:01:53 +0100 Subject: [PATCH 034/424] Quick fix for the lens flare in Burnout We have to assume that ForceLowerResolutionForEffects has been set for good reason - in this case, the effect probably can't safely function without it. Fixes #11100 once again. --- GPU/Common/FramebufferManagerCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index dc810fe632..b47a856c51 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1659,7 +1659,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, break; } - if (vfb->usageFlags & FB_USAGE_COLOR_MIXED_DEPTH) { + if ((vfb->usageFlags & FB_USAGE_COLOR_MIXED_DEPTH) && !PSP_CoreParameter().compat.flags().ForceLowerResolutionForEffectsOn) { force1x = false; } if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) { From 4427cb4fc3c8ef10b6b3fdfb7104896fc9261b91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Feb 2023 23:40:36 +0100 Subject: [PATCH 035/424] Add parameter to thin3d::CopyFramebufferToMemory to specify blocking mode. Not yet implemented. --- Common/GPU/D3D11/thin3d_d3d11.cpp | 4 ++-- Common/GPU/D3D9/thin3d_d3d9.cpp | 4 ++-- Common/GPU/OpenGL/thin3d_gl.cpp | 4 ++-- Common/GPU/Vulkan/thin3d_vulkan.cpp | 4 ++-- Common/GPU/thin3d.h | 9 ++++++++- GPU/Common/DepthBufferCommon.cpp | 7 +++++-- GPU/Common/FramebufferManagerCommon.cpp | 12 ++++++------ GPU/Common/TextureCacheCommon.cpp | 5 +++-- GPU/GLES/FramebufferManagerGLES.cpp | 2 +- GPU/GLES/StencilBufferGLES.cpp | 4 ++-- 10 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 29bea57c32..c0fcb9afbb 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -91,7 +91,7 @@ public: void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; - bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override; + bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override; // These functions should be self explanatory. void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override; @@ -1525,7 +1525,7 @@ bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, return false; } -bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, const char *tag) { +bool D3D11DrawContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) { D3D11Framebuffer *fb = (D3D11Framebuffer *)src; if (fb) { diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index b7e920d604..b0116c875a 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -530,7 +530,7 @@ public: // Not implemented } bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; - bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override; + bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override; // These functions should be self explanatory. void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override; @@ -1426,7 +1426,7 @@ bool D3D9Context::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int return SUCCEEDED(device_->StretchRect(srcSurf, &srcRect, dstSurf, &dstRect, (filter == FB_BLIT_LINEAR && channelBits == FB_COLOR_BIT) ? D3DTEXF_LINEAR : D3DTEXF_POINT)); } -bool D3D9Context::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, const char *tag) { +bool D3D9Context::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int bx, int by, int bw, int bh, Draw::DataFormat destFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) { D3D9Framebuffer *fb = (D3D9Framebuffer *)src; if (fb) { diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 480f0cc3bb..77297a4452 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -365,7 +365,7 @@ public: void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; - bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override; + bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override; // These functions should be self explanatory. void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp, const char *tag) override; @@ -988,7 +988,7 @@ static void LogReadPixelsError(GLenum error) { } #endif -bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride, const char *tag) { +bool OpenGLContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat dataFormat, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) { if (gl_extensions.IsGLES && (channelBits & FB_COLOR_BIT) == 0) { // Can't readback depth or stencil on GLES. return false; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 7046121f20..f65bb1ed2f 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -414,7 +414,7 @@ public: void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) override; - bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) override; + bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) override; DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) override; // These functions should be self explanatory. @@ -1632,7 +1632,7 @@ bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int sr return true; } -bool VKContext::CopyFramebufferToMemorySync(Framebuffer *srcfb, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) { +bool VKContext::CopyFramebufferToMemory(Framebuffer *srcfb, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) { VKFramebuffer *src = (VKFramebuffer *)srcfb; int aspectMask = 0; diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index bf10cb3801..3db2d7b8db 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -292,6 +292,11 @@ enum class Event { PRESENTED, }; +enum class ReadbackMode { + BLOCK, + OLD_DATA_OK, // Lets the backend return old results that won't need any waiting to get. +}; + constexpr uint32_t MAX_TEXTURE_SLOTS = 3; struct FramebufferDesc { @@ -693,7 +698,9 @@ public: virtual void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits, const char *tag) = 0; virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter, const char *tag) = 0; - virtual bool CopyFramebufferToMemorySync(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, const char *tag) { + + // If the backend doesn't support old data, it's "OK" to block. + virtual bool CopyFramebufferToMemory(Framebuffer *src, int channelBits, int x, int y, int w, int h, Draw::DataFormat format, void *pixels, int pixelStride, ReadbackMode mode, const char *tag) { return false; } virtual DataFormat PreferredFramebufferReadbackFormat(Framebuffer *src) { diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 5d63385e26..c628b61ee6 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -242,16 +242,19 @@ bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, i }; draw_->DrawUP(positions, 3); - draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x * scaleX, y * scaleY, w * scaleX, h * scaleY, DataFormat::R8G8B8A8_UNORM, convBuf_, destW, "ReadbackDepthbufferSync"); + draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, + x * scaleX, y * scaleY, w * scaleX, h * scaleY, + DataFormat::R8G8B8A8_UNORM, convBuf_, destW, ReadbackMode::BLOCK, "ReadbackDepthbufferSync"); textureCache_->ForgetLastTexture(); // TODO: Use 4444 (or better, R16_UNORM) so we can copy lines directly (instead of 32 -> 16 on CPU)? format16Bit = true; } else { - draw_->CopyFramebufferToMemorySync(fbo, FB_DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, "ReadbackDepthbufferSync"); + draw_->CopyFramebufferToMemory(fbo, FB_DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, ReadbackMode::BLOCK, "ReadbackDepthbufferSync"); format16Bit = false; } + // TODO: Move this conversion into the backends. if (format16Bit) { // In this case, we used the shader to apply depth scale factors. // This can be SSE'd or NEON'd very efficiently, though ideally we would avoid this conversion by using R16_UNORM for readback. diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index b47a856c51..91d3f3c69b 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2629,7 +2629,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB // TODO: Maybe should handle flipY inside CopyFramebufferToMemorySync somehow? bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; buffer.Allocate(w, h, GE_FORMAT_8888, flipY); - bool retval = draw_->CopyFramebufferToMemorySync(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w, "GetFramebuffer"); + bool retval = draw_->CopyFramebufferToMemory(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetFramebuffer"); gpuStats.numReadbacks++; // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); @@ -2675,7 +2675,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY); } // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) - retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, "GetDepthBuffer"); + retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetDepthBuffer"); if (!retval) { // Try ReadbackDepthbufferSync, in case GLES. buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); @@ -2716,7 +2716,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; // No need to free on failure, the caller/destructor will do that. Usually this is a reused buffer, anyway. buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT, flipY); - bool retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w, "GetStencilbuffer"); + bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetStencilbuffer"); if (!retval) { // Try ReadbackStencilbufferSync, in case GLES. retval = ReadbackStencilbufferSync(vfb->fbo, 0, 0, w, h, buffer.GetData(), w); @@ -2734,7 +2734,7 @@ bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { if (fmt != Draw::DataFormat::B8G8R8A8_UNORM) fmt = Draw::DataFormat::R8G8B8A8_UNORM; buffer.Allocate(w, h, fmt == Draw::DataFormat::R8G8B8A8_UNORM ? GPU_DBG_FORMAT_8888 : GPU_DBG_FORMAT_8888_BGRA, false); - bool retval = draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, fmt, buffer.GetData(), w, "GetOutputFramebuffer"); + bool retval = draw_->CopyFramebufferToMemory(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, fmt, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer"); // That may have unbound the framebuffer, rebind to avoid crashes when debugging. RebindFramebuffer("RebindFramebuffer - GetOutputFramebuffer"); return retval; @@ -2792,7 +2792,7 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, x * vfb->renderScaleFactor, y * vfb->renderScaleFactor, w * vfb->renderScaleFactor, h * vfb->renderScaleFactor, (uint16_t *)destPtr, stride, w, h); } else { - draw_->CopyFramebufferToMemorySync(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, "ReadbackFramebufferSync"); + draw_->CopyFramebufferToMemory(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, Draw::ReadbackMode::BLOCK, "ReadbackFramebufferSync"); } char tag[128]; @@ -2803,7 +2803,7 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, } bool FramebufferManagerCommon::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) { - return draw_->CopyFramebufferToMemorySync(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, "ReadbackStencilbufferSync"); + return draw_->CopyFramebufferToMemory(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, Draw::ReadbackMode::BLOCK, "ReadbackStencilbufferSync"); } void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel) { diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 0d276ed39a..40824ecd49 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -28,6 +28,7 @@ #include "Common/StringUtils.h" #include "Common/TimeUtil.h" #include "Common/Math/math_util.h" +#include "Common/GPU/thin3d.h" #include "Core/Config.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/System.h" @@ -1183,12 +1184,12 @@ bool TextureCacheCommon::GetCurrentFramebufferTextureDebug(GPUDebugBuffer &buffe buffer.Allocate(desiredW, desiredH, GPU_DBG_FORMAT_FLOAT, false); if (w < desiredW || h < desiredH) buffer.ZeroBytes(); - retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::D32F, buffer.GetData(), desiredW, "GetCurrentTextureDebug"); + retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::D32F, buffer.GetData(), desiredW, Draw::ReadbackMode::BLOCK, "GetCurrentTextureDebug"); } else { buffer.Allocate(desiredW, desiredH, GPU_DBG_FORMAT_8888, false); if (w < desiredW || h < desiredH) buffer.ZeroBytes(); - retval = draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), desiredW, "GetCurrentTextureDebug"); + retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), desiredW, Draw::ReadbackMode::BLOCK, "GetCurrentTextureDebug"); } // Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf. diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 4c0b7480f9..d88800873e 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -68,6 +68,6 @@ bool FramebufferManagerGLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { int w, h; draw_->GetFramebufferDimensions(nullptr, &w, &h); buffer.Allocate(w, h, GPU_DBG_FORMAT_888_RGB, true); - draw_->CopyFramebufferToMemorySync(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w, "GetOutputFramebuffer"); + draw_->CopyFramebufferToMemory(nullptr, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetOutputFramebuffer"); return true; } diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 32cd92497d..0097e34c59 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -108,7 +108,7 @@ bool FramebufferManagerGLES::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, i const bool useColorPath = gl_extensions.IsGLES; if (!useColorPath) { - return draw_->CopyFramebufferToMemorySync(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, "ReadbackStencilbufferSync"); + return draw_->CopyFramebufferToMemory(fbo, FB_STENCIL_BIT, x, y, w, h, DataFormat::S8, pixels, pixelsStride, ReadbackMode::BLOCK, "ReadbackStencilbufferSync"); } // Unsupported below GLES 3.1 or without ARB_stencil_texturing. @@ -150,7 +150,7 @@ bool FramebufferManagerGLES::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, i }; draw_->DrawUP(positions, 3); - draw_->CopyFramebufferToMemorySync(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, "ReadbackStencilbufferSync"); + draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, ReadbackMode::BLOCK, "ReadbackStencilbufferSync"); textureCache_->ForgetLastTexture(); From 7b5def9ff6d50b2044ba387981490046c3c13557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Feb 2023 23:52:38 +0100 Subject: [PATCH 036/424] Use VMA to manage readback memory --- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 65 ++++++------------------- Common/GPU/Vulkan/VulkanQueueRunner.h | 2 +- 2 files changed, 15 insertions(+), 52 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 137703bb0d..32d4713633 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -71,11 +71,8 @@ void VulkanQueueRunner::ResizeReadbackBuffer(VkDeviceSize requiredSize) { if (readbackBuffer_ && requiredSize <= readbackBufferSize_) { return; } - if (readbackMemory_) { - vulkan_->Delete().QueueDeleteDeviceMemory(readbackMemory_); - } if (readbackBuffer_) { - vulkan_->Delete().QueueDeleteBuffer(readbackBuffer_); + vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); } readbackBufferSize_ = requiredSize; @@ -86,51 +83,21 @@ void VulkanQueueRunner::ResizeReadbackBuffer(VkDeviceSize requiredSize) { buf.size = readbackBufferSize_; buf.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - VkResult res = vkCreateBuffer(device, &buf, nullptr, &readbackBuffer_); + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; + VmaAllocationInfo allocInfo{}; + + VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &buf, &allocCreateInfo, &readbackBuffer_, &readbackAllocation_, &allocInfo); _assert_(res == VK_SUCCESS); - VkMemoryRequirements reqs{}; - vkGetBufferMemoryRequirements(device, readbackBuffer_, &reqs); - - VkMemoryAllocateInfo allocInfo{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; - allocInfo.allocationSize = reqs.size; - - // For speedy readbacks, we want the CPU cache to be enabled. However on most hardware we then have to - // sacrifice coherency, which means manual flushing. But try to find such memory first! If no cached - // memory type is available we fall back to just coherent. - const VkFlags desiredTypes[] = { - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - }; - VkFlags successTypeReqs = 0; - for (VkFlags typeReqs : desiredTypes) { - if (vulkan_->MemoryTypeFromProperties(reqs.memoryTypeBits, typeReqs, &allocInfo.memoryTypeIndex)) { - successTypeReqs = typeReqs; - break; - } - } - _assert_(successTypeReqs != 0); - readbackBufferIsCoherent_ = (successTypeReqs & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; - - res = vkAllocateMemory(device, &allocInfo, nullptr, &readbackMemory_); - if (res != VK_SUCCESS) { - readbackMemory_ = VK_NULL_HANDLE; - vkDestroyBuffer(device, readbackBuffer_, nullptr); - readbackBuffer_ = VK_NULL_HANDLE; - return; - } - uint32_t offset = 0; - vkBindBufferMemory(device, readbackBuffer_, readbackMemory_, offset); + const VkMemoryType &memoryType = vulkan_->GetMemoryProperties().memoryTypes[allocInfo.memoryType]; + readbackBufferIsCoherent_ = (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; } void VulkanQueueRunner::DestroyDeviceObjects() { INFO_LOG(G3D, "VulkanQueueRunner::DestroyDeviceObjects"); - if (readbackMemory_) { - vulkan_->Delete().QueueDeleteDeviceMemory(readbackMemory_); - } if (readbackBuffer_) { - vulkan_->Delete().QueueDeleteBuffer(readbackBuffer_); + vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); } readbackBufferSize_ = 0; @@ -2104,20 +2071,15 @@ void VulkanQueueRunner::PerformReadbackImage(const VKRStep &step, VkCommandBuffe } void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { - if (!readbackMemory_) + if (!readbackBuffer_) return; // Something has gone really wrong. // Read back to the requested address in ram from buffer. void *mappedData; const size_t srcPixelSize = DataFormatSizeInBytes(srcFormat); - - VkResult res = vkMapMemory(vulkan_->GetDevice(), readbackMemory_, 0, width * height * srcPixelSize, 0, &mappedData); + VkResult res = vmaMapMemory(vulkan_->Allocator(), readbackAllocation_, &mappedData); if (!readbackBufferIsCoherent_) { - VkMappedMemoryRange range{}; - range.memory = readbackMemory_; - range.offset = 0; - range.size = width * height * srcPixelSize; - vkInvalidateMappedMemoryRanges(vulkan_->GetDevice(), 1, &range); + vmaInvalidateAllocation(vulkan_->Allocator(), readbackAllocation_, 0, width * height * srcPixelSize); } if (res != VK_SUCCESS) { @@ -2148,5 +2110,6 @@ void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataForm ERROR_LOG(G3D, "CopyReadbackBuffer: Unknown format"); _assert_msg_(false, "CopyReadbackBuffer: Unknown src format %d", (int)srcFormat); } - vkUnmapMemory(vulkan_->GetDevice(), readbackMemory_); + + vmaUnmapMemory(vulkan_->Allocator(), readbackAllocation_); } diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index da46a07b0a..235802c982 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -323,7 +323,7 @@ private: // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. - VkDeviceMemory readbackMemory_ = VK_NULL_HANDLE; + VmaAllocation readbackAllocation_ = VK_NULL_HANDLE; VkBuffer readbackBuffer_ = VK_NULL_HANDLE; VkDeviceSize readbackBufferSize_ = 0; bool readbackBufferIsCoherent_ = false; From 31df6bf0fe7957313d4d5856cfe457d361f93e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 00:35:30 +0100 Subject: [PATCH 037/424] Move some code around, get rid of some unnecessary fences --- Common/GPU/Vulkan/VulkanFrameData.cpp | 17 +++---- Common/GPU/Vulkan/VulkanFrameData.h | 4 +- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 66 +++++++++++++------------ Common/GPU/Vulkan/VulkanQueueRunner.h | 1 + 4 files changed, 47 insertions(+), 41 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanFrameData.cpp b/Common/GPU/Vulkan/VulkanFrameData.cpp index fcb91c3cc1..192fe1f28a 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.cpp +++ b/Common/GPU/Vulkan/VulkanFrameData.cpp @@ -36,11 +36,6 @@ void FrameData::Init(VulkanContext *vulkan, int index) { vulkan->SetDebugName(fence, VK_OBJECT_TYPE_FENCE, StringFromFormat("fence%d", index).c_str()); readyForFence = true; - // This fence is used for synchronizing readbacks. Does not need preinitialization. - // TODO: Put this in frameDataShared, only one is needed. - readbackFence = vulkan->CreateFence(false); - vulkan->SetDebugName(fence, VK_OBJECT_TYPE_FENCE, "readbackFence"); - VkQueryPoolCreateInfo query_ci{ VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO }; query_ci.queryCount = MAX_TIMESTAMP_QUERIES; query_ci.queryType = VK_QUERY_TYPE_TIMESTAMP; @@ -52,7 +47,6 @@ void FrameData::Destroy(VulkanContext *vulkan) { vkDestroyCommandPool(device, cmdPoolInit, nullptr); vkDestroyCommandPool(device, cmdPoolMain, nullptr); vkDestroyFence(device, fence, nullptr); - vkDestroyFence(device, readbackFence, nullptr); vkDestroyQueryPool(device, profile.queryPool, nullptr); } @@ -144,7 +138,7 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame } if ((hasMainCommands || hasPresentCommands) && type == FrameSubmitType::Sync) { - fenceToTrigger = readbackFence; + fenceToTrigger = sharedData.readbackFence; } if (hasMainCommands) { @@ -206,8 +200,8 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame if (type == FrameSubmitType::Sync) { // Hard stall of the GPU, not ideal, but necessary so the CPU has the contents of the readback. - vkWaitForFences(vulkan->GetDevice(), 1, &readbackFence, true, UINT64_MAX); - vkResetFences(vulkan->GetDevice(), 1, &readbackFence); + vkWaitForFences(vulkan->GetDevice(), 1, &sharedData.readbackFence, true, UINT64_MAX); + vkResetFences(vulkan->GetDevice(), 1, &sharedData.readbackFence); syncDone = true; } } @@ -219,10 +213,15 @@ void FrameDataShared::Init(VulkanContext *vulkan) { _dbg_assert_(res == VK_SUCCESS); res = vkCreateSemaphore(vulkan->GetDevice(), &semaphoreCreateInfo, nullptr, &renderingCompleteSemaphore); _dbg_assert_(res == VK_SUCCESS); + + // This fence is used for synchronizing readbacks. Does not need preinitialization. + readbackFence = vulkan->CreateFence(false); + vulkan->SetDebugName(readbackFence, VK_OBJECT_TYPE_FENCE, "readbackFence"); } void FrameDataShared::Destroy(VulkanContext *vulkan) { VkDevice device = vulkan->GetDevice(); vkDestroySemaphore(device, acquireSemaphore, nullptr); vkDestroySemaphore(device, renderingCompleteSemaphore, nullptr); + vkDestroyFence(device, readbackFence, nullptr); } diff --git a/Common/GPU/Vulkan/VulkanFrameData.h b/Common/GPU/Vulkan/VulkanFrameData.h index 88d4c185d2..148dc66338 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.h +++ b/Common/GPU/Vulkan/VulkanFrameData.h @@ -30,6 +30,9 @@ struct FrameDataShared { VkSemaphore acquireSemaphore = VK_NULL_HANDLE; VkSemaphore renderingCompleteSemaphore = VK_NULL_HANDLE; + // For synchronous readbacks. + VkFence readbackFence = VK_NULL_HANDLE; + void Init(VulkanContext *vulkan); void Destroy(VulkanContext *vulkan); }; @@ -49,7 +52,6 @@ struct FrameData { bool readyForFence = true; VkFence fence = VK_NULL_HANDLE; - VkFence readbackFence = VK_NULL_HANDLE; // Strictly speaking we might only need one global of these. // These are on different threads so need separate pools. VkCommandPool cmdPoolInit = VK_NULL_HANDLE; // Written to from main thread diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 32d4713633..3f1d047f85 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -67,39 +67,9 @@ void VulkanQueueRunner::CreateDeviceObjects() { #endif } -void VulkanQueueRunner::ResizeReadbackBuffer(VkDeviceSize requiredSize) { - if (readbackBuffer_ && requiredSize <= readbackBufferSize_) { - return; - } - if (readbackBuffer_) { - vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); - } - - readbackBufferSize_ = requiredSize; - - VkDevice device = vulkan_->GetDevice(); - - VkBufferCreateInfo buf{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - buf.size = readbackBufferSize_; - buf.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - - VmaAllocationCreateInfo allocCreateInfo{}; - allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; - VmaAllocationInfo allocInfo{}; - - VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &buf, &allocCreateInfo, &readbackBuffer_, &readbackAllocation_, &allocInfo); - _assert_(res == VK_SUCCESS); - - const VkMemoryType &memoryType = vulkan_->GetMemoryProperties().memoryTypes[allocInfo.memoryType]; - readbackBufferIsCoherent_ = (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; -} - void VulkanQueueRunner::DestroyDeviceObjects() { INFO_LOG(G3D, "VulkanQueueRunner::DestroyDeviceObjects"); - if (readbackBuffer_) { - vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); - } - readbackBufferSize_ = 0; + DestroyReadbackBuffer(); renderPasses_.IterateMut([&](const RPKey &rpkey, VKRRenderPass *rp) { _assert_(rp); @@ -1974,6 +1944,40 @@ void VulkanQueueRunner::SetupTransferDstWriteAfterWrite(VKRImage &img, VkImageAs ); } +void VulkanQueueRunner::ResizeReadbackBuffer(VkDeviceSize requiredSize) { + if (readbackBuffer_ && requiredSize <= readbackBufferSize_) { + return; + } + if (readbackBuffer_) { + vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); + } + + readbackBufferSize_ = requiredSize; + + VkDevice device = vulkan_->GetDevice(); + + VkBufferCreateInfo buf{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + buf.size = readbackBufferSize_; + buf.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; + + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; + VmaAllocationInfo allocInfo{}; + + VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &buf, &allocCreateInfo, &readbackBuffer_, &readbackAllocation_, &allocInfo); + _assert_(res == VK_SUCCESS); + + const VkMemoryType &memoryType = vulkan_->GetMemoryProperties().memoryTypes[allocInfo.memoryType]; + readbackBufferIsCoherent_ = (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; +} + +void VulkanQueueRunner::DestroyReadbackBuffer() { + if (readbackBuffer_) { + vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); + } + readbackBufferSize_ = 0; +} + void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd) { ResizeReadbackBuffer(sizeof(uint32_t) * step.readback.srcRect.extent.width * step.readback.srcRect.extent.height); diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index 235802c982..bdfe9aad95 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -298,6 +298,7 @@ private: void LogReadbackImage(const VKRStep &pass); void ResizeReadbackBuffer(VkDeviceSize requiredSize); + void DestroyReadbackBuffer(); void ApplyMGSHack(std::vector &steps); void ApplySonicHack(std::vector &steps); From c6ef38e573b63080d498a21f4e87004548b7aeeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=BA=E5=B7=A5=E7=9F=A5=E8=83=BD?= <42119227+Kaitul@users.noreply.github.com> Date: Sun, 5 Feb 2023 14:56:47 +0800 Subject: [PATCH 038/424] Update zh_TW.ini --- assets/lang/zh_TW.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 27d1a20686..7919506b93 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -90,11 +90,11 @@ Swipe = 滑動 Swipe sensitivity = 滑動敏感度 Swipe smoothing = 滑動平滑度 Thin borders = 特細框線 -Tilt control setup = 自訂傾斜… +Tilt control setup = 傾斜控制設定… Tilt Input Type = 傾斜輸入類型 Tilt Sensitivity along X axis = 沿 X 軸傾斜敏感度 Tilt Sensitivity along Y axis = 沿 Y 軸傾斜敏感度 -To Calibrate = 以您喜歡的角度握住設備,然後按“校準”。 +To Calibrate = 將裝置保持在您偏好的角度,然後按下「校準」。 Toggle mode = 切換模式 Repeat mode = 重複模式 Touch Control Visibility = 觸控控制可見性 From bff0d735e229dd36f9279d2e389b7b560875182c Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 5 Feb 2023 08:38:43 +0100 Subject: [PATCH 039/424] OpenXR - Fix HUD in Monster Hunter 3rd --- GPU/GLES/ShaderManagerGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 9dabc96442..c7d4d1a7f6 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -358,7 +358,7 @@ static inline bool GuessVRDrawingHUD(bool is2D, bool flatScreen) { //HUD texture cannot be in CLUT32 format else if (gstate.getTextureFormat() == GETextureFormat::GE_TFMT_CLUT32) hud = false; //HUD cannot have full texture alpha - else if (gstate_c.textureFullAlpha) hud = false; + else if (gstate_c.textureFullAlpha && gstate.getTextureFormat() != GETextureFormat::GE_TFMT_CLUT4) hud = false; //HUD must have full vertex alpha else if (!gstate_c.vertexFullAlpha && gstate.getDepthTestFunction() == GE_COMP_NEVER) hud = false; //HUD cannot render FB screenshot From 92f4de7b749abd87788224d83bc1467c8479368d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 10:16:54 +0100 Subject: [PATCH 040/424] Small cleanup. Let's reduce the number of readback paths. --- GPU/Common/FramebufferManagerCommon.cpp | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 91d3f3c69b..560c97aab4 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2662,26 +2662,8 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; - bool retval; - if (true) { - // Always use ReadbackDepthbufferSync (while we debug it) - buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); - retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h); - } else { - // Old code - if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { - buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, flipY); - } else { - buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY); - } - // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) - retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetDepthBuffer"); - if (!retval) { - // Try ReadbackDepthbufferSync, in case GLES. - buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); - retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h); - } - } + buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); + bool retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h); // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); From 937975000b54a2e7ff5b211ecc6836ed59d1d04d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 10:52:52 +0100 Subject: [PATCH 041/424] Add a ReadbackMode parameter to more functions in the FramebufferManager --- Common/GPU/OpenGL/GLQueueRunner.cpp | 2 +- Common/GPU/OpenGL/GLQueueRunner.h | 2 +- Common/GPU/OpenGL/GLRenderManager.cpp | 6 ++-- Common/GPU/OpenGL/GLRenderManager.h | 2 +- Common/GPU/OpenGL/thin3d_gl.cpp | 2 +- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 9 +++--- Common/GPU/Vulkan/VulkanQueueRunner.h | 3 +- Common/GPU/Vulkan/VulkanRenderManager.cpp | 7 +++-- Common/GPU/Vulkan/VulkanRenderManager.h | 2 +- Common/GPU/Vulkan/thin3d_vulkan.cpp | 2 +- GPU/Common/DepthBufferCommon.cpp | 2 +- GPU/Common/FramebufferManagerCommon.cpp | 36 +++++++++++------------ GPU/Common/FramebufferManagerCommon.h | 8 ++--- GPU/Directx9/FramebufferManagerDX9.cpp | 5 +--- GPU/Directx9/FramebufferManagerDX9.h | 3 +- GPU/GLES/FramebufferManagerGLES.h | 2 +- GPU/GLES/StencilBufferGLES.cpp | 4 +-- 17 files changed, 48 insertions(+), 49 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 63f75af330..519939a2d8 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -1615,7 +1615,7 @@ void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) { CHECK_GL_ERROR_IF_DEBUG(); } -void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { +void GLQueueRunner::CopyFromReadbackBuffer(GLRFramebuffer *framebuffer, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { // TODO: Maybe move data format conversion here, and always read back 8888. Drivers // don't usually provide very optimized conversion implementations, though some do. // Just need to be careful about dithering, which may break Danganronpa. diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index b91648a1fa..b79ff6b6ae 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -373,7 +373,7 @@ public: return (int)depth * 3 + (int)color; } - void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); + void CopyFromReadbackBuffer(GLRFramebuffer *framebuffer, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); void Resize(int width, int height) { targetWidth_ = width; diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index f0a1cce354..1c45abd7e3 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -360,7 +360,7 @@ void GLRenderManager::BlitFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLR steps_.push_back(step); } -bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag) { +bool GLRenderManager::CopyFramebufferToMemory(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag) { _assert_(pixels); GLRStep *step = new GLRStep{ GLRStepType::READBACK }; @@ -387,7 +387,7 @@ bool GLRenderManager::CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspec } else { return false; } - queueRunner_.CopyReadbackBuffer(w, h, srcFormat, destFormat, pixelStride, pixels); + queueRunner_.CopyFromReadbackBuffer(src, w, h, srcFormat, destFormat, pixelStride, pixels); return true; } @@ -404,7 +404,7 @@ void GLRenderManager::CopyImageToMemorySync(GLRTexture *texture, int mipLevel, i curRenderStep_ = nullptr; FlushSync(); - queueRunner_.CopyReadbackBuffer(w, h, Draw::DataFormat::R8G8B8A8_UNORM, destFormat, pixelStride, pixels); + queueRunner_.CopyFromReadbackBuffer(nullptr, w, h, Draw::DataFormat::R8G8B8A8_UNORM, destFormat, pixelStride, pixels); } void GLRenderManager::BeginFrame() { diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index 2d213be8b8..fe0b42aafd 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -570,7 +570,7 @@ public: // Binds a framebuffer as a texture, for the following draws. void BindFramebufferAsTexture(GLRFramebuffer *fb, int binding, int aspectBit); - bool CopyFramebufferToMemorySync(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag); + bool CopyFramebufferToMemory(GLRFramebuffer *src, int aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag); void CopyImageToMemorySync(GLRTexture *texture, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag); void CopyFramebuffer(GLRFramebuffer *src, GLRect2D srcRect, GLRFramebuffer *dst, GLOffset2D dstPos, int aspectMask, const char *tag); diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 77297a4452..95f43d9217 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -1001,7 +1001,7 @@ bool OpenGLContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits, i aspect |= GL_DEPTH_BUFFER_BIT; if (channelBits & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; - renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag); + renderManager_.CopyFramebufferToMemory(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, mode, tag); return true; } diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index 3f1d047f85..a28f54ba0a 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -2074,7 +2074,7 @@ void VulkanQueueRunner::PerformReadbackImage(const VKRStep &step, VkCommandBuffe // Doing that will also act like a heavyweight barrier ensuring that device writes are visible on the host. } -void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { +void VulkanQueueRunner::CopyReadbackBuffer(VKRFramebuffer *src, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { if (!readbackBuffer_) return; // Something has gone really wrong. @@ -2082,15 +2082,16 @@ void VulkanQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataForm void *mappedData; const size_t srcPixelSize = DataFormatSizeInBytes(srcFormat); VkResult res = vmaMapMemory(vulkan_->Allocator(), readbackAllocation_, &mappedData); - if (!readbackBufferIsCoherent_) { - vmaInvalidateAllocation(vulkan_->Allocator(), readbackAllocation_, 0, width * height * srcPixelSize); - } if (res != VK_SUCCESS) { ERROR_LOG(G3D, "CopyReadbackBuffer: vkMapMemory failed! result=%d", (int)res); return; } + if (!readbackBufferIsCoherent_) { + vmaInvalidateAllocation(vulkan_->Allocator(), readbackAllocation_, 0, width * height * srcPixelSize); + } + // TODO: Perform these conversions in a compute shader on the GPU. if (srcFormat == Draw::DataFormat::R8G8B8A8_UNORM) { ConvertFromRGBA8888(pixels, (const uint8_t *)mappedData, pixelStride, width, width, height, destFormat); diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index bdfe9aad95..9567a8f243 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -252,7 +252,8 @@ public: return (int)depth * 3 + (int)color; } - void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); + // src == 0 means to copy from the sync readback buffer. + void CopyReadbackBuffer(VKRFramebuffer *src, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); VKRRenderPass *GetRenderPass(const RPKey &key); diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 32e859936a..ee3215876c 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -908,8 +908,9 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR } } -bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag) { +bool VulkanRenderManager::CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag) { _dbg_assert_(insideFrame_); + for (int i = (int)steps_.size() - 1; i >= 0; i--) { if (steps_[i]->stepType == VKRStepType::RENDER && steps_[i]->render.framebuffer == src) { steps_[i]->render.numReads++; @@ -967,7 +968,7 @@ bool VulkanRenderManager::CopyFramebufferToMemorySync(VKRFramebuffer *src, VkIma } // Need to call this after FlushSync so the pixels are guaranteed to be ready in CPU-accessible VRAM. - queueRunner_.CopyReadbackBuffer(w, h, srcFormat, destFormat, pixelStride, pixels); + queueRunner_.CopyReadbackBuffer(src, w, h, srcFormat, destFormat, pixelStride, pixels); return true; } @@ -987,7 +988,7 @@ void VulkanRenderManager::CopyImageToMemorySync(VkImage image, int mipLevel, int FlushSync(); // Need to call this after FlushSync so the pixels are guaranteed to be ready in CPU-accessible VRAM. - queueRunner_.CopyReadbackBuffer(w, h, destFormat, destFormat, pixelStride, pixels); + queueRunner_.CopyReadbackBuffer(nullptr, w, h, destFormat, destFormat, pixelStride, pixels); } static void RemoveDrawCommands(std::vector *cmds) { diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index 4536fcf932..812128b906 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -217,7 +217,7 @@ public: void BindCurrentFramebufferAsInputAttachment0(VkImageAspectFlags aspectBits); - bool CopyFramebufferToMemorySync(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag); + bool CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAspectFlags aspectBits, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, Draw::ReadbackMode mode, const char *tag); void CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag); void CopyFramebuffer(VKRFramebuffer *src, VkRect2D srcRect, VKRFramebuffer *dst, VkOffset2D dstPos, VkImageAspectFlags aspectMask, const char *tag); diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index f65bb1ed2f..14c1c0e502 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -1640,7 +1640,7 @@ bool VKContext::CopyFramebufferToMemory(Framebuffer *srcfb, int channelBits, int if (channelBits & FBChannel::FB_DEPTH_BIT) aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT; if (channelBits & FBChannel::FB_STENCIL_BIT) aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT; - return renderManager_.CopyFramebufferToMemorySync(src ? src->GetFB() : nullptr, aspectMask, x, y, w, h, format, (uint8_t *)pixels, pixelStride, tag); + return renderManager_.CopyFramebufferToMemory(src ? src->GetFB() : nullptr, aspectMask, x, y, w, h, format, (uint8_t *)pixels, pixelStride, mode, tag); } DataFormat VKContext::PreferredFramebufferReadbackFormat(Framebuffer *src) { diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index c628b61ee6..fe4f96bc69 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -164,7 +164,7 @@ Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, return pipeline; } -bool FramebufferManagerCommon::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { +bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH, Draw::ReadbackMode mode) { using namespace Draw; if (!fbo) { diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 560c97aab4..abf4da62c6 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1018,7 +1018,7 @@ void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *v // TODO: This type of download could be made async, for less stutter on framebuffer creation. if (!g_Config.bSkipGPUReadbacks && !PSP_CoreParameter().compat.flags().DisableFirstFrameReadback) { - ReadFramebufferToMemory(vfb, 0, 0, vfb->safeWidth, vfb->safeHeight, RASTER_COLOR); + ReadFramebufferToMemory(vfb, 0, 0, vfb->safeWidth, vfb->safeHeight, RASTER_COLOR, Draw::ReadbackMode::BLOCK); vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; vfb->safeWidth = 0; vfb->safeHeight = 0; @@ -1042,14 +1042,15 @@ bool FramebufferManagerCommon::ShouldDownloadFramebufferDepth(const VirtualFrame void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { // TODO: Isn't this wrong? Shouldn't we download the prevVfb if anything? if (ShouldDownloadFramebufferColor(vfb) && !vfb->memoryUpdated) { - ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR); + ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR, Draw::ReadbackMode::BLOCK); vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } else { DownloadFramebufferOnSwitch(prevVfb); } if (prevVfb && ShouldDownloadFramebufferDepth(prevVfb)) { - ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH); + // Allow old data here to avoid blocking, if possible - no uses cases for this depend on data being super fresh. + ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH, Draw::ReadbackMode::OLD_DATA_OK); } textureCache_->ForgetLastTexture(); @@ -1586,7 +1587,7 @@ void FramebufferManagerCommon::DecimateFBOs() { int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used); if (ShouldDownloadFramebufferColor(vfb) && age == 0 && !vfb->memoryUpdated) { - ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR); + ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR, Draw::ReadbackMode::BLOCK); vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } @@ -1895,7 +1896,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, if (srcH == 0 || srcY + srcH > srcBuffer->bufferHeight) { WARN_LOG_ONCE(btdcpyheight, G3D, "Memcpy fbo download %08x -> %08x skipped, %d+%d is taller than %d", src, dst, srcY, srcH, srcBuffer->bufferHeight); } else if (!g_Config.bSkipGPUReadbacks && (!srcBuffer->memoryUpdated || channel == RASTER_DEPTH)) { - ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH, channel); + ReadFramebufferToMemory(srcBuffer, 0, srcY, srcBuffer->width, srcH, channel, Draw::ReadbackMode::BLOCK); srcBuffer->usageFlags = (srcBuffer->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; } return false; @@ -2365,7 +2366,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst if (tooTall) { WARN_LOG_ONCE(btdheight, G3D, "Block transfer download %08x -> %08x dangerous, %d+%d is taller than %d", srcBasePtr, dstBasePtr, srcRect.y, srcRect.h, srcRect.vfb->bufferHeight); } - ReadFramebufferToMemory(srcRect.vfb, static_cast(srcX * srcXFactor), srcY, static_cast(srcRect.w_bytes * srcXFactor), srcRect.h, RASTER_COLOR); + ReadFramebufferToMemory(srcRect.vfb, static_cast(srcX * srcXFactor), srcY, static_cast(srcRect.w_bytes * srcXFactor), srcRect.h, RASTER_COLOR, Draw::ReadbackMode::BLOCK); srcRect.vfb->usageFlags = (srcRect.vfb->usageFlags | FB_USAGE_DOWNLOAD) & ~FB_USAGE_DOWNLOAD_CLEAR; } } @@ -2663,7 +2664,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); - bool retval = ReadbackDepthbufferSync(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h); + bool retval = ReadbackDepthbuffer(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h, Draw::ReadbackMode::BLOCK); // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); @@ -2700,8 +2701,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G buffer.Allocate(w, h, GPU_DBG_FORMAT_8BIT, flipY); bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_STENCIL_BIT, 0, 0, w,h, Draw::DataFormat::S8, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetStencilbuffer"); if (!retval) { - // Try ReadbackStencilbufferSync, in case GLES. - retval = ReadbackStencilbufferSync(vfb->fbo, 0, 0, w, h, buffer.GetData(), w); + retval = ReadbackStencilbuffer(vfb->fbo, 0, 0, w, h, buffer.GetData(), w, Draw::ReadbackMode::BLOCK); } // That may have unbound the framebuffer, rebind to avoid crashes when debugging. RebindFramebuffer("RebindFramebuffer - GetStencilbuffer"); @@ -2728,7 +2728,7 @@ bool FramebufferManagerCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { // (Except using the GPU might cause problems because of various implementations' // dithering behavior and games that expect exact colors like Danganronpa, so we // can't entirely be rid of the CPU path.) -- unknown -void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel) { +void FramebufferManagerCommon::ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode) { if (w <= 0 || h <= 0) { ERROR_LOG(G3D, "Bad inputs to ReadbackFramebufferSync: %d %d %d %d", x, y, w, h); return; @@ -2770,11 +2770,11 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, if (channel == RASTER_DEPTH) { _assert_msg_(vfb && vfb->z_address != 0 && vfb->z_stride != 0, "Depth buffer invalid"); - ReadbackDepthbufferSync(vfb->fbo, + ReadbackDepthbuffer(vfb->fbo, x * vfb->renderScaleFactor, y * vfb->renderScaleFactor, - w * vfb->renderScaleFactor, h * vfb->renderScaleFactor, (uint16_t *)destPtr, stride, w, h); + w * vfb->renderScaleFactor, h * vfb->renderScaleFactor, (uint16_t *)destPtr, stride, w, h, mode); } else { - draw_->CopyFramebufferToMemory(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, Draw::ReadbackMode::BLOCK, "ReadbackFramebufferSync"); + draw_->CopyFramebufferToMemory(vfb->fbo, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, x, y, w, h, destFormat, destPtr, stride, mode, "ReadbackFramebufferSync"); } char tag[128]; @@ -2784,11 +2784,11 @@ void FramebufferManagerCommon::ReadbackFramebufferSync(VirtualFramebuffer *vfb, gpuStats.numReadbacks++; } -bool FramebufferManagerCommon::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) { - return draw_->CopyFramebufferToMemory(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, Draw::ReadbackMode::BLOCK, "ReadbackStencilbufferSync"); +bool FramebufferManagerCommon::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) { + return draw_->CopyFramebufferToMemory(fbo, Draw::FB_DEPTH_BIT, x, y, w, h, Draw::DataFormat::S8, pixels, pixelsStride, mode, "ReadbackStencilbufferSync"); } -void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel) { +void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode) { // Clamp to bufferWidth. Sometimes block transfers can cause this to hit. if (x + w >= vfb->bufferWidth) { w = vfb->bufferWidth - x; @@ -2825,7 +2825,7 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, } // This handles any required stretching internally. - ReadbackFramebufferSync(vfb, x, y, w, h, channel); + ReadbackFramebuffer(vfb, x, y, w, h, channel, mode); draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); textureCache_->ForgetLastTexture(); @@ -2877,7 +2877,7 @@ void FramebufferManagerCommon::DownloadFramebufferForClut(u32 fb_address, u32 lo vfb->clutUpdatedBytes = loadBytes; // This function now handles scaling down internally. - ReadbackFramebufferSync(vfb, x, y, w, h, RASTER_COLOR); + ReadbackFramebuffer(vfb, x, y, w, h, RASTER_COLOR, Draw::ReadbackMode::BLOCK); textureCache_->ForgetLastTexture(); RebindFramebuffer("RebindFramebuffer - DownloadFramebufferForClut"); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index df4a67bb27..37650a57ba 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -328,7 +328,7 @@ public: void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason); bool BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags, int layer); - void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel); + void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode); void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes); void DrawFramebufferToOutput(const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat); @@ -457,10 +457,10 @@ public: } protected: - virtual void ReadbackFramebufferSync(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel); + virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode); // Used for when a shader is required, such as GLES. - virtual bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH); - virtual bool ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride); + virtual bool ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH, Draw::ReadbackMode mode); + virtual bool ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode); void SetViewport2D(int x, int y, int w, int h); Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height); void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags); diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index a3a37eea4c..364bafbdf8 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -50,10 +50,7 @@ FramebufferManagerDX9::FramebufferManagerDX9(Draw::DrawContext *draw) preferredPixelsFormat_ = Draw::DataFormat::B8G8R8A8_UNORM; } -FramebufferManagerDX9::~FramebufferManagerDX9() { -} - -bool FramebufferManagerDX9::ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) { +bool FramebufferManagerDX9::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH, Draw::ReadbackMode mode) { // Don't yet support stretched readbacks here. if (destW != w || destH != h) { return false; diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index 5ac924e4e1..37458526fd 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -31,9 +31,8 @@ class ShaderManagerDX9; class FramebufferManagerDX9 : public FramebufferManagerCommon { public: FramebufferManagerDX9(Draw::DrawContext *draw); - ~FramebufferManagerDX9(); protected: // TODO: The non-color path of FramebufferManagerCommon::ReadbackDepthbufferSync seems to work just as well. - bool ReadbackDepthbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH) override; + bool ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH, Draw::ReadbackMode mode) override; }; diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 15c123a1e5..bdfaa27e8d 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -36,5 +36,5 @@ public: protected: void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; - bool ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) override; + bool ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) override; }; diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 0097e34c59..110d2d94f7 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -98,7 +98,7 @@ void main() { Draw::Pipeline *CreateReadbackPipeline(Draw::DrawContext *draw, const char *tag, const UniformBufferDesc *ubDesc, const char *fs, const char *fsTag, const char *vs, const char *vsTag); // Well, this is not depth, but it's depth/stencil related. -bool FramebufferManagerGLES::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride) { +bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) { using namespace Draw; if (!fbo) { @@ -150,7 +150,7 @@ bool FramebufferManagerGLES::ReadbackStencilbufferSync(Draw::Framebuffer *fbo, i }; draw_->DrawUP(positions, 3); - draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, ReadbackMode::BLOCK, "ReadbackStencilbufferSync"); + draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x, y, w, h, DataFormat::R8G8B8A8_UNORM, convBuf_, w, mode, "ReadbackStencilbufferSync"); textureCache_->ForgetLastTexture(); From 63c43b90f8270dcc69b3f18101d1e800de0461a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 13:59:16 +0100 Subject: [PATCH 042/424] Remove a level of indentation in LoadCLUT --- GPU/Common/TextureCacheCommon.cpp | 279 +++++++++++++++--------------- 1 file changed, 142 insertions(+), 137 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 40824ecd49..e6c29e8264 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1238,158 +1238,163 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) { clutTotalBytes_ = loadBytes; clutRenderAddress_ = 0xFFFFFFFF; - if (Memory::IsValidAddress(clutAddr)) { - if (Memory::IsVRAMAddress(clutAddr)) { - // Clear the uncached and mirror bits, etc. to match framebuffers. - const u32 clutLoadAddr = clutAddr & 0x041FFFFF; - const u32 clutLoadEnd = clutLoadAddr + loadBytes; - static const u32 MAX_CLUT_OFFSET = 4096; + if (!Memory::IsValidAddress(clutAddr)) { + memset(clutBufRaw_, 0x00, loadBytes); + // Reload the clut next time (should we really do it in this case?) + clutLastFormat_ = 0xFFFFFFFF; + clutMaxBytes_ = std::max(clutMaxBytes_, loadBytes); + return; + } - clutRenderOffset_ = MAX_CLUT_OFFSET; - const std::vector &framebuffers = framebufferManager_->Framebuffers(); + if (Memory::IsVRAMAddress(clutAddr)) { + // Clear the uncached and mirror bits, etc. to match framebuffers. + const u32 clutLoadAddr = clutAddr & 0x041FFFFF; + const u32 clutLoadEnd = clutLoadAddr + loadBytes; + static const u32 MAX_CLUT_OFFSET = 4096; - u32 bestClutAddress = 0xFFFFFFFF; + clutRenderOffset_ = MAX_CLUT_OFFSET; + const std::vector &framebuffers = framebufferManager_->Framebuffers(); - VirtualFramebuffer *chosenFramebuffer = nullptr; - for (VirtualFramebuffer *framebuffer : framebuffers) { - // Let's not deal with divide by zero. - if (framebuffer->fb_stride == 0) - continue; + u32 bestClutAddress = 0xFFFFFFFF; - const u32 fb_address = framebuffer->fb_address; - const u32 fb_bpp = BufferFormatBytesPerPixel(framebuffer->fb_format); - int offset = clutLoadAddr - fb_address; + VirtualFramebuffer *chosenFramebuffer = nullptr; + for (VirtualFramebuffer *framebuffer : framebuffers) { + // Let's not deal with divide by zero. + if (framebuffer->fb_stride == 0) + continue; - // Is this inside the framebuffer at all? Note that we only check the first line here, this should - // be changed. - bool matchRange = offset >= 0 && offset < (int)(framebuffer->fb_stride * fb_bpp); - if (matchRange) { - // And is it inside the rendered area? Sometimes games pack data in the margin between width and stride. - // If the framebuffer width was detected as 512, we're gonna assume it's really 480. - int fbMatchWidth = framebuffer->width; - if (fbMatchWidth == 512) { - fbMatchWidth = 480; - } - bool inMargin = ((offset / fb_bpp) % framebuffer->fb_stride) == fbMatchWidth; + const u32 fb_address = framebuffer->fb_address; + const u32 fb_bpp = BufferFormatBytesPerPixel(framebuffer->fb_format); + int offset = clutLoadAddr - fb_address; - // The offset check here means, in the context of the loop, that we'll pick - // the framebuffer with the smallest offset. This is yet another framebuffer matching - // loop with its own rules, eventually we'll probably want to do something - // more systematic. - if (matchRange && !inMargin && offset < (int)clutRenderOffset_) { - WARN_LOG_N_TIMES(clutfb, 5, G3D, "Detected LoadCLUT(%d bytes) from framebuffer %08x (%s), byte offset %d", loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), offset); - framebuffer->last_frame_clut = gpuStats.numFlips; - // Also mark used so it's not decimated. - framebuffer->last_frame_used = gpuStats.numFlips; - framebuffer->usageFlags |= FB_USAGE_CLUT; - bestClutAddress = framebuffer->fb_address; - clutRenderOffset_ = (u32)offset; - chosenFramebuffer = framebuffer; - if (offset == 0) { - // Not gonna find a better match according to the smallest-offset rule, so we'll go with this one. - break; - } + // Is this inside the framebuffer at all? Note that we only check the first line here, this should + // be changed. + bool matchRange = offset >= 0 && offset < (int)(framebuffer->fb_stride * fb_bpp); + if (matchRange) { + // And is it inside the rendered area? Sometimes games pack data in the margin between width and stride. + // If the framebuffer width was detected as 512, we're gonna assume it's really 480. + int fbMatchWidth = framebuffer->width; + if (fbMatchWidth == 512) { + fbMatchWidth = 480; + } + bool inMargin = ((offset / fb_bpp) % framebuffer->fb_stride) == fbMatchWidth; + + // The offset check here means, in the context of the loop, that we'll pick + // the framebuffer with the smallest offset. This is yet another framebuffer matching + // loop with its own rules, eventually we'll probably want to do something + // more systematic. + if (matchRange && !inMargin && offset < (int)clutRenderOffset_) { + WARN_LOG_N_TIMES(clutfb, 5, G3D, "Detected LoadCLUT(%d bytes) from framebuffer %08x (%s), byte offset %d", loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), offset); + framebuffer->last_frame_clut = gpuStats.numFlips; + // Also mark used so it's not decimated. + framebuffer->last_frame_used = gpuStats.numFlips; + framebuffer->usageFlags |= FB_USAGE_CLUT; + bestClutAddress = framebuffer->fb_address; + clutRenderOffset_ = (u32)offset; + chosenFramebuffer = framebuffer; + if (offset == 0) { + // Not gonna find a better match according to the smallest-offset rule, so we'll go with this one. + break; } } } - - // To turn off dynamic CLUT (for demonstration or testing purposes), add "false &&" to this check. - if (chosenFramebuffer && chosenFramebuffer->fbo) { - clutRenderAddress_ = bestClutAddress; - - if (!dynamicClutTemp_) { - Draw::FramebufferDesc desc{}; - desc.width = 512; - desc.height = 1; - desc.depth = 1; - desc.z_stencil = false; - desc.numLayers = 1; - desc.multiSampleLevel = 0; - desc.tag = "dynamic_clut"; - dynamicClutFbo_ = draw_->CreateFramebuffer(desc); - desc.tag = "dynamic_clut_temp"; - dynamicClutTemp_ = draw_->CreateFramebuffer(desc); - } - - // We'll need to copy from the offset. - const u32 fb_bpp = BufferFormatBytesPerPixel(chosenFramebuffer->fb_format); - const int totalPixelsOffset = clutRenderOffset_ / fb_bpp; - const int clutYOffset = totalPixelsOffset / chosenFramebuffer->fb_stride; - const int clutXOffset = totalPixelsOffset % chosenFramebuffer->fb_stride; - const int scale = chosenFramebuffer->renderScaleFactor; - - // Copy the pixels to our temp clut, scaling down if needed and wrapping. - framebufferManager_->BlitUsingRaster( - chosenFramebuffer->fbo, clutXOffset * scale, clutYOffset * scale, (clutXOffset + 512.0f) * scale, (clutYOffset + 1.0f) * scale, - dynamicClutTemp_, 0.0f, 0.0f, 512.0f, 1.0f, - false, scale, framebufferManager_->Get2DPipeline(DRAW2D_COPY_COLOR_RECT2LIN), "copy_clut_to_temp"); - - framebufferManager_->RebindFramebuffer("after_copy_clut_to_temp"); - clutRenderFormat_ = chosenFramebuffer->fb_format; - } - NotifyMemInfo(MemBlockFlags::ALLOC, clutAddr, loadBytes, "CLUT"); } - // It's possible for a game to load CLUT outside valid memory without crashing, should result in zeroes. - u32 bytes = Memory::ValidSize(clutAddr, loadBytes); - _assert_(bytes <= 2048); - bool performDownload = PSP_CoreParameter().compat.flags().AllowDownloadCLUT; - if (GPURecord::IsActive()) - performDownload = true; - if (clutRenderAddress_ != 0xFFFFFFFF && performDownload) { - framebufferManager_->DownloadFramebufferForClut(clutRenderAddress_, clutRenderOffset_ + bytes); - Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); - if (bytes < loadBytes) { - memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); + // To turn off dynamic CLUT (for demonstration or testing purposes), add "false &&" to this check. + if (chosenFramebuffer && chosenFramebuffer->fbo) { + clutRenderAddress_ = bestClutAddress; + + if (!dynamicClutTemp_) { + Draw::FramebufferDesc desc{}; + desc.width = 512; + desc.height = 1; + desc.depth = 1; + desc.z_stencil = false; + desc.numLayers = 1; + desc.multiSampleLevel = 0; + desc.tag = "dynamic_clut"; + dynamicClutFbo_ = draw_->CreateFramebuffer(desc); + desc.tag = "dynamic_clut_temp"; + dynamicClutTemp_ = draw_->CreateFramebuffer(desc); } - } else { - // Here we could check for clutRenderAddress_ != 0xFFFFFFFF and zero the CLUT or something, - // but choosing not to for now. Though the results of loading the CLUT from RAM here is - // almost certainly going to be bogus. -#ifdef _M_SSE - if (bytes == loadBytes) { - const __m128i *source = (const __m128i *)Memory::GetPointerUnchecked(clutAddr); - __m128i *dest = (__m128i *)clutBufRaw_; - int numBlocks = bytes / 32; - for (int i = 0; i < numBlocks; i++, source += 2, dest += 2) { - __m128i data1 = _mm_loadu_si128(source); - __m128i data2 = _mm_loadu_si128(source + 1); - _mm_store_si128(dest, data1); - _mm_store_si128(dest + 1, data2); - } - } else { - Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); - if (bytes < loadBytes) { - memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); - } - } -#elif PPSSPP_ARCH(ARM_NEON) - if (bytes == loadBytes) { - const uint32_t *source = (const uint32_t *)Memory::GetPointerUnchecked(clutAddr); - uint32_t *dest = (uint32_t *)clutBufRaw_; - int numBlocks = bytes / 32; - for (int i = 0; i < numBlocks; i++, source += 8, dest += 8) { - uint32x4_t data1 = vld1q_u32(source); - uint32x4_t data2 = vld1q_u32(source + 4); - vst1q_u32(dest, data1); - vst1q_u32(dest + 4, data2); - } - } else { - Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); - if (bytes < loadBytes) { - memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); - } - } -#else - Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); - if (bytes < loadBytes) { - memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); - } -#endif + + // We'll need to copy from the offset. + const u32 fb_bpp = BufferFormatBytesPerPixel(chosenFramebuffer->fb_format); + const int totalPixelsOffset = clutRenderOffset_ / fb_bpp; + const int clutYOffset = totalPixelsOffset / chosenFramebuffer->fb_stride; + const int clutXOffset = totalPixelsOffset % chosenFramebuffer->fb_stride; + const int scale = chosenFramebuffer->renderScaleFactor; + + // Copy the pixels to our temp clut, scaling down if needed and wrapping. + framebufferManager_->BlitUsingRaster( + chosenFramebuffer->fbo, clutXOffset * scale, clutYOffset * scale, (clutXOffset + 512.0f) * scale, (clutYOffset + 1.0f) * scale, + dynamicClutTemp_, 0.0f, 0.0f, 512.0f, 1.0f, + false, scale, framebufferManager_->Get2DPipeline(DRAW2D_COPY_COLOR_RECT2LIN), "copy_clut_to_temp"); + + framebufferManager_->RebindFramebuffer("after_copy_clut_to_temp"); + clutRenderFormat_ = chosenFramebuffer->fb_format; + } + NotifyMemInfo(MemBlockFlags::ALLOC, clutAddr, loadBytes, "CLUT"); + } + + // It's possible for a game to load CLUT outside valid memory without crashing, should result in zeroes. + u32 bytes = Memory::ValidSize(clutAddr, loadBytes); + _assert_(bytes <= 2048); + bool performDownload = PSP_CoreParameter().compat.flags().AllowDownloadCLUT; + if (GPURecord::IsActive()) + performDownload = true; + if (clutRenderAddress_ != 0xFFFFFFFF && performDownload) { + framebufferManager_->DownloadFramebufferForClut(clutRenderAddress_, clutRenderOffset_ + bytes); + Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); + if (bytes < loadBytes) { + memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); } } else { - memset(clutBufRaw_, 0x00, loadBytes); + // Here we could check for clutRenderAddress_ != 0xFFFFFFFF and zero the CLUT or something, + // but choosing not to for now. Though the results of loading the CLUT from RAM here is + // almost certainly going to be bogus. +#ifdef _M_SSE + if (bytes == loadBytes) { + const __m128i *source = (const __m128i *)Memory::GetPointerUnchecked(clutAddr); + __m128i *dest = (__m128i *)clutBufRaw_; + int numBlocks = bytes / 32; + for (int i = 0; i < numBlocks; i++, source += 2, dest += 2) { + __m128i data1 = _mm_loadu_si128(source); + __m128i data2 = _mm_loadu_si128(source + 1); + _mm_store_si128(dest, data1); + _mm_store_si128(dest + 1, data2); + } + } else { + Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); + if (bytes < loadBytes) { + memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); + } + } +#elif PPSSPP_ARCH(ARM_NEON) + if (bytes == loadBytes) { + const uint32_t *source = (const uint32_t *)Memory::GetPointerUnchecked(clutAddr); + uint32_t *dest = (uint32_t *)clutBufRaw_; + int numBlocks = bytes / 32; + for (int i = 0; i < numBlocks; i++, source += 8, dest += 8) { + uint32x4_t data1 = vld1q_u32(source); + uint32x4_t data2 = vld1q_u32(source + 4); + vst1q_u32(dest, data1); + vst1q_u32(dest + 4, data2); + } + } else { + Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); + if (bytes < loadBytes) { + memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); + } + } +#else + Memory::MemcpyUnchecked(clutBufRaw_, clutAddr, bytes); + if (bytes < loadBytes) { + memset((u8 *)clutBufRaw_ + bytes, 0x00, loadBytes - bytes); + } +#endif } + // Reload the clut next time. clutLastFormat_ = 0xFFFFFFFF; clutMaxBytes_ = std::max(clutMaxBytes_, loadBytes); From 5ac9b88e815d850475ae4f21ddda9db306da288b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 16:41:12 +0100 Subject: [PATCH 043/424] Plumbing miss --- GPU/Common/DepthBufferCommon.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index fe4f96bc69..96ec6c95bd 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -244,13 +244,13 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x draw_->CopyFramebufferToMemory(blitFBO, FB_COLOR_BIT, x * scaleX, y * scaleY, w * scaleX, h * scaleY, - DataFormat::R8G8B8A8_UNORM, convBuf_, destW, ReadbackMode::BLOCK, "ReadbackDepthbufferSync"); + DataFormat::R8G8B8A8_UNORM, convBuf_, destW, mode, "ReadbackDepthbufferSync"); textureCache_->ForgetLastTexture(); // TODO: Use 4444 (or better, R16_UNORM) so we can copy lines directly (instead of 32 -> 16 on CPU)? format16Bit = true; } else { - draw_->CopyFramebufferToMemory(fbo, FB_DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, ReadbackMode::BLOCK, "ReadbackDepthbufferSync"); + draw_->CopyFramebufferToMemory(fbo, FB_DEPTH_BIT, x, y, w, h, DataFormat::D32F, convBuf_, w, mode, "ReadbackDepthbufferSync"); format16Bit = false; } From 23049533b991b5fe13ad83021fea6674842c1d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 22:57:33 +0100 Subject: [PATCH 044/424] Restore GetDepthBuffer precision - the stretchy-color-readback path is not suitable for this. --- GPU/Common/FramebufferManagerCommon.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index abf4da62c6..e04cf5d98a 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2663,8 +2663,19 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32 bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; - buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); - bool retval = ReadbackDepthbuffer(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h, Draw::ReadbackMode::BLOCK); + // Old code + if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT_DIV_256, flipY); + } else { + buffer.Allocate(w, h, GPU_DBG_FORMAT_FLOAT, flipY); + } + // No need to free on failure, that's the caller's job (it likely will reuse a buffer.) + bool retval = draw_->CopyFramebufferToMemory(vfb->fbo, Draw::FB_DEPTH_BIT, 0, 0, w, h, Draw::DataFormat::D32F, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetDepthBuffer"); + if (!retval) { + // Try ReadbackDepthbufferSync, in case GLES. + buffer.Allocate(w, h, GPU_DBG_FORMAT_16BIT, flipY); + retval = ReadbackDepthbuffer(vfb->fbo, 0, 0, w, h, (uint16_t *)buffer.GetData(), w, w, h, Draw::ReadbackMode::BLOCK); + } // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); From 3fcdf0e4dfd12905b45b47d2b54a9948f678b374 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 5 Feb 2023 23:52:28 -0800 Subject: [PATCH 045/424] libretro: Add cpu_features flags to Android.mk. --- libretro/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libretro/jni/Android.mk b/libretro/jni/Android.mk index b6f1126e3d..0d5b95d7fd 100644 --- a/libretro/jni/Android.mk +++ b/libretro/jni/Android.mk @@ -5,7 +5,7 @@ ifneq ($(GIT_VERSION)," unknown") COREFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" endif -COREFLAGS := +COREFLAGS := -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DHAVE_DLFCN_H CORE_DIR := ../.. FFMPEGDIR := $(CORE_DIR)/ffmpeg FFMPEGLIBS += libavformat libavcodec libavutil libswresample libswscale From 6f9d6c6c5fa333059d4cfed1f68e7121db8e7e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 13:45:29 +0100 Subject: [PATCH 046/424] New version of WM_USER_GET_BASE_POINTER --- Windows/MainWindow.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 7bb751f0fb..6c30fa9d71 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -781,10 +781,10 @@ namespace MainWindow case WM_USER_GET_BASE_POINTER: Reporting::NotifyDebugger(); switch (lParam) { - case 0: - return (u32)(u64)Memory::base; - case 1: - return (u32)((u64)Memory::base >> 32); + case 0: return (u32)(u64)Memory::base; + case 1: return (u32)((u64)Memory::base >> 32); + case 2: return (u32)(u64)(&Memory::base); + case 3: return (u32)((u64)(&Memory::base) >> 32); default: return 0; } From 655797a8467d07c2e1ec8a6108ca66a12d76e531 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 6 Feb 2023 21:07:32 -0800 Subject: [PATCH 047/424] iOS: Disable jit in DefaultCpuCore(). This means loading game-specific inis should properly auto-disable. --- Core/Config.cpp | 8 +++++--- Core/Config.h | 2 -- UI/NativeApp.cpp | 7 ------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 86cd15c61e..836e7244ec 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -60,7 +60,7 @@ http::Downloader g_DownloadManager; Config g_Config; -bool jitForcedOff; +static bool jitForcedOff; // Not in Config.h because it's #included a lot. struct ConfigPrivate { @@ -477,9 +477,11 @@ std::string CreateRandMAC() { static int DefaultCpuCore() { #if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - return (int)CPUCore::JIT; + if (System_GetPropertyBool(SYSPROP_CAN_JIT)) + return (int)CPUCore::JIT; + return (int)CPUCore::IR_JIT; #else - return (int)CPUCore::INTERPRETER; + return (int)CPUCore::IR_JIT; #endif } diff --git a/Core/Config.h b/Core/Config.h index dc2f1a8ca7..1d53f24724 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -29,8 +29,6 @@ extern const char *PPSSPP_GIT_VERSION; -extern bool jitForcedOff; - enum ChatPositions { BOTTOM_LEFT = 0, BOTTOM_CENTER = 1, diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index b66e64b93e..2de45b8861 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -758,13 +758,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } } - if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) { - // Just gonna force it to the IR interpreter on startup. - // We don't hide the option, but we make sure it's off on bootup. In case someone wants - // to experiment in future iOS versions or something... - jitForcedOff = true; - } - auto des = GetI18NCategory("DesktopUI"); // Note to translators: do not translate this/add this to PPSSPP-lang's files. // It's intended to be custom for every user. From ec54095b68b18bf1936e01ca3417d44c85cab470 Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Mon, 6 Feb 2023 23:36:55 -0500 Subject: [PATCH 048/424] Build for iOS as a libretro core --- .gitlab-ci.yml | 13 +++++++++++++ CMakeLists.txt | 6 ++++-- Common/GPU/OpenGL/GLQueueRunner.cpp | 2 +- libretro/libretro.cpp | 11 +++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d7bb40f1ee..e97fab6fee 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,6 +49,10 @@ include: - project: 'libretro-infrastructure/ci-templates' file: '/android-cmake.yml' + # iOS + - project: 'libretro-infrastructure/ci-templates' + file: '/ios-cmake.yml' + ################################## CONSOLES ################################ #################################### MISC ################################## @@ -133,3 +137,12 @@ libretro-build-android-x86: extends: - .libretro-android-cmake-x86 - .core-defs + +# iOS arm64 +libretro-build-ios-arm64: + extends: + - .libretro-ios-cmake-arm64 + - .core-defs + - .cmake-defs + variables: + CORE_ARGS: -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ios.cmake -DLIBRETRO=ON diff --git a/CMakeLists.txt b/CMakeLists.txt index 7403596347..8b8ecd9255 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1130,7 +1130,7 @@ if(ANDROID) set(nativeExtraLibs ${nativeExtraLibs} openxr) endif() # No target -elseif(IOS) +elseif(IOS AND NOT LIBRETRO) set(nativeExtra ${nativeExtra} ios/main.mm ios/AppDelegate.mm @@ -1177,6 +1177,8 @@ elseif(IOS) set_source_files_properties(UI/DarwinFileSystemServices.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) set_source_files_properties(Common/Battery/AppleBatteryClient.m PROPERTIES COMPILE_FLAGS -fobjc-arc) set(TargetBin PPSSPP) +elseif(IOS AND LIBRETRO) + set(nativeExtraLibs ${nativeExtraLibs} "-framework GLKit") elseif(USING_QT_UI) set(CMAKE_AUTOMOC ON) find_package(Qt5 COMPONENTS OpenGL Gui Core Multimedia) @@ -2493,7 +2495,7 @@ if(NOT ANDROID) file(INSTALL assets/flash0 DESTINATION assets) endif() # packaging and code signing -if(IOS) +if(IOS AND NOT LIBRETRO) set(DEPLOYMENT_TARGET 11.0) file(GLOB IOSAssets ios/assets/*.png) list(REMOVE_ITEM IOSAssets ${CMAKE_CURRENT_SOURCE_DIR}/ios/assets/Default-568h@2x.png) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 519939a2d8..44f072c6f7 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -1758,7 +1758,7 @@ void GLQueueRunner::fbo_unbind() { glBindFramebuffer(GL_FRAMEBUFFER, g_defaultFBO); #endif -#if PPSSPP_PLATFORM(IOS) +#if PPSSPP_PLATFORM(IOS) && !defined(__LIBRETRO__) bindDefaultFBO(); #endif diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 889a58b017..8d9811dfdc 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -644,6 +644,13 @@ static void check_variables(CoreParameter &coreParam) g_Config.iCpuCore = (int)CPUCore::INTERPRETER; } + if (System_GetPropertyBool(SYSPROP_CAN_JIT) == false && g_Config.iCpuCore == (int)CPUCore::JIT) { + // Just gonna force it to the IR interpreter on startup. + // We don't hide the option, but we make sure it's off on bootup. In case someone wants + // to experiment in future iOS versions or something... + g_Config.iCpuCore = (int)CPUCore::IR_JIT; + } + var.key = "ppsspp_fast_memory"; if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { @@ -1844,7 +1851,11 @@ bool System_GetPropertyBool(SystemProperty prop) switch (prop) { case SYSPROP_CAN_JIT: +#if PPSSPP_PLATFORM(IOS) + return false; +#else return true; +#endif default: return false; } From 2865310bca308c6d4a55f76e39f0c0faafe75d91 Mon Sep 17 00:00:00 2001 From: ZiHan Huang Date: Mon, 6 Feb 2023 20:48:21 +0800 Subject: [PATCH 049/424] vulkan: Add the function realization of arm device to kms vulkan Signed-off-by: ZiHan Huang --- Common/GPU/Vulkan/VulkanContext.cpp | 181 ++++++++++++++++++++++++++++ Common/GPU/Vulkan/VulkanLoader.cpp | 10 ++ Common/GPU/Vulkan/VulkanLoader.h | 5 + SDL/SDLMain.cpp | 2 +- SDL/SDLVulkanGraphicsContext.cpp | 9 ++ 5 files changed, 206 insertions(+), 1 deletion(-) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index aa34ad3b0d..6768602852 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -886,6 +886,187 @@ VkResult VulkanContext::ReinitSurface() { case WINDOWSYSTEM_DISPLAY: { VkDisplaySurfaceCreateInfoKHR display{ VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR }; +#if !defined(__LIBRETRO__) + /* + And when not to use libretro need VkDisplaySurfaceCreateInfoKHR this extension, + then you need to use dlopen to read vulkan loader in VulkanLoader.cpp. + huangzihan China + */ + + if(!vkGetPhysicalDeviceDisplayPropertiesKHR || + !vkGetPhysicalDeviceDisplayPlanePropertiesKHR || + !vkGetDisplayModePropertiesKHR || + !vkGetDisplayPlaneSupportedDisplaysKHR || + !vkGetDisplayPlaneCapabilitiesKHR ) { + _assert_msg_(false, "DISPLAY Vulkan cannot find any vulkan function symbols."); + return VK_ERROR_INITIALIZATION_FAILED; + } + + //The following code is for reference: + // https://github.com/vanfanel/ppsspp + // When using the VK_KHR_display extension and not using LIBRETRO, a complete + // VkDisplaySurfaceCreateInfoKHR is needed. + + uint32_t display_count; + uint32_t plane_count; + + VkDisplayPropertiesKHR *display_props = NULL; + VkDisplayPlanePropertiesKHR *plane_props = NULL; + VkDisplayModePropertiesKHR* mode_props = NULL; + + VkExtent2D image_size; + // This is the chosen physical_device, it has been chosen elsewhere. + VkPhysicalDevice phys_device = physical_devices_[physical_device_]; + VkDisplayModeKHR display_mode = VK_NULL_HANDLE; + VkDisplayPlaneAlphaFlagBitsKHR alpha_mode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR; + uint32_t plane = UINT32_MAX; + + // For now, use the first available (connected) display. + int display_index = 0; + + VkResult result; + bool ret = false; + bool mode_found = false; + + int i, j; + + // 1 physical device can have N displays connected. + // Vulkan only counts the connected displays. + + // Get a list of displays on the physical device. + display_count = 0; + vkGetPhysicalDeviceDisplayPropertiesKHR(phys_device, &display_count, NULL); + if (display_count == 0) { + _assert_msg_(false, "DISPLAY Vulkan couldn't find any displays."); + return VK_ERROR_INITIALIZATION_FAILED; + } + display_props = new VkDisplayPropertiesKHR[display_count]; + vkGetPhysicalDeviceDisplayPropertiesKHR(phys_device, &display_count, display_props); + + // Get a list of display planes on the physical device. + plane_count = 0; + vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phys_device, &plane_count, NULL); + if (plane_count == 0) { + _assert_msg_(false, "DISPLAY Vulkan couldn't find any planes on the physical device"); + return VK_ERROR_INITIALIZATION_FAILED; + + } + plane_props = new VkDisplayPlanePropertiesKHR[plane_count]; + vkGetPhysicalDeviceDisplayPlanePropertiesKHR(phys_device, &plane_count, plane_props); + + // Get the Vulkan display we are going to use. + VkDisplayKHR myDisplay = display_props[display_index].display; + + // Get the list of display modes of the display + uint32_t mode_count = 0; + vkGetDisplayModePropertiesKHR(phys_device, myDisplay, &mode_count, NULL); + if (mode_count == 0) { + _assert_msg_(false, "DISPLAY Vulkan couldn't find any video modes on the display"); + return VK_ERROR_INITIALIZATION_FAILED; + } + mode_props = new VkDisplayModePropertiesKHR[mode_count]; + vkGetDisplayModePropertiesKHR(phys_device, myDisplay, &mode_count, mode_props); + + // See if there's an appropiate mode available on the display + display_mode = VK_NULL_HANDLE; + for (i = 0; i < mode_count; ++i) + { + const VkDisplayModePropertiesKHR* mode = &mode_props[i]; + + if (mode->parameters.visibleRegion.width == pixel_xres && + mode->parameters.visibleRegion.height == pixel_yres) + { + display_mode = mode->displayMode; + mode_found = true; + break; + } + } + + // Free the mode list now. + delete [] mode_props; + + // If there are no useable modes found on the display, error out + if (display_mode == VK_NULL_HANDLE) + { + _assert_msg_(false, "DISPLAY Vulkan couldn't find any video modes on the display"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + /* Iterate on the list of planes of the physical device + to find a plane that matches these criteria: + -It must be compatible with the chosen display + mode. + -It isn't currently bound to another display. + -It supports per-pixel alpha, if possible. */ + for (i = 0; i < plane_count; i++) { + uint32_t supported_displays_count = 0; + VkDisplayKHR* supported_displays; + VkDisplayPlaneCapabilitiesKHR plane_caps; + + /* See if the plane is compatible with the current display. */ + vkGetDisplayPlaneSupportedDisplaysKHR(phys_device, i, &supported_displays_count, NULL); + if (supported_displays_count == 0) { + /* This plane doesn't support any displays. Continue to the next plane. */ + continue; + } + + /* Get the list of displays supported by this plane. */ + supported_displays = new VkDisplayKHR[supported_displays_count]; + vkGetDisplayPlaneSupportedDisplaysKHR(phys_device, i, + &supported_displays_count, supported_displays); + + /* The plane must be bound to the chosen display, or not in use. + If none of these is true, iterate to another plane. */ + if ( !( (plane_props[i].currentDisplay == myDisplay) || + (plane_props[i].currentDisplay == VK_NULL_HANDLE))) + continue; + + /* Iterate the list of displays supported by this plane + in order to find out if the chosen display is among them. */ + bool plane_supports_display = false; + for (j = 0; j < supported_displays_count; j++) { + if (supported_displays[j] == myDisplay) { + plane_supports_display = true; + break; + } + } + + /* Free the list of displays supported by this plane. */ + delete [] supported_displays; + + /* If the display is not supported by this plane, iterate to the next plane. */ + if (!plane_supports_display) + continue; + + /* Want a plane that supports the alpha mode we have chosen. */ + vkGetDisplayPlaneCapabilitiesKHR(phys_device, display_mode, i, &plane_caps); + if (plane_caps.supportedAlpha & alpha_mode) { + /* Yep, this plane is alright. */ + plane = i; + break; + } + } + + /* If we couldn't find an appropiate plane, error out. */ + if (plane == UINT32_MAX) { + _assert_msg_(false, "DISPLAY Vulkan couldn't find an appropiate plane"); + return VK_ERROR_INITIALIZATION_FAILED; + } + + // Finally, create the vulkan surface. + image_size.width = pixel_xres; + image_size.height = pixel_yres; + + display.displayMode = display_mode; + display.imageExtent = image_size; + display.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + display.alphaMode = alpha_mode; + display.globalAlpha = 1.0f; + display.planeIndex = plane; + display.planeStackIndex = plane_props[plane].currentStackIndex; + display.pNext = nullptr; + delete [] display_props; + delete [] plane_props; +#endif display.flags = 0; retval = vkCreateDisplayPlaneSurfaceKHR(instance_, &display, nullptr, &surface_); break; diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 94092b2166..2a00ed9622 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -195,6 +195,11 @@ PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; #endif #if defined(VK_USE_PLATFORM_DISPLAY_KHR) PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; +PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; +PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; +PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; +PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; #endif PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; @@ -564,6 +569,11 @@ void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanExtensions &en #endif #if defined(VK_USE_PLATFORM_DISPLAY_KHR) LOAD_INSTANCE_FUNC(instance, vkCreateDisplayPlaneSurfaceKHR); + LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceDisplayPropertiesKHR); + LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceDisplayPlanePropertiesKHR); + LOAD_INSTANCE_FUNC(instance, vkGetDisplayModePropertiesKHR); + LOAD_INSTANCE_FUNC(instance, vkGetDisplayPlaneSupportedDisplaysKHR); + LOAD_INSTANCE_FUNC(instance, vkGetDisplayPlaneCapabilitiesKHR); #endif LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR); diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index caaef0d597..85b4bb5510 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -194,6 +194,11 @@ extern PFN_vkCreateWaylandSurfaceKHR vkCreateWaylandSurfaceKHR; #endif #if defined(VK_USE_PLATFORM_DISPLAY_KHR) extern PFN_vkCreateDisplayPlaneSurfaceKHR vkCreateDisplayPlaneSurfaceKHR; +extern PFN_vkGetPhysicalDeviceDisplayPropertiesKHR vkGetPhysicalDeviceDisplayPropertiesKHR; +extern PFN_vkGetPhysicalDeviceDisplayPlanePropertiesKHR vkGetPhysicalDeviceDisplayPlanePropertiesKHR; +extern PFN_vkGetDisplayModePropertiesKHR vkGetDisplayModePropertiesKHR; +extern PFN_vkGetDisplayPlaneSupportedDisplaysKHR vkGetDisplayPlaneSupportedDisplaysKHR; +extern PFN_vkGetDisplayPlaneCapabilitiesKHR vkGetDisplayPlaneCapabilitiesKHR; #endif extern PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index dea43f64f0..406f303a73 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -768,7 +768,7 @@ int main(int argc, char *argv[]) { #if !PPSSPP_PLATFORM(SWITCH) } else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext(); - if (!ctx->Init(window, x, y, mode, &error_message)) { + if (!ctx->Init(window, x, y, mode | SDL_WINDOW_VULKAN, &error_message)) { printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str()); g_Config.iGPUBackend = (int)GPUBackend::OPENGL; SetGPUBackend((GPUBackend)g_Config.iGPUBackend); diff --git a/SDL/SDLVulkanGraphicsContext.cpp b/SDL/SDLVulkanGraphicsContext.cpp index 624d3b497f..b01571b626 100644 --- a/SDL/SDLVulkanGraphicsContext.cpp +++ b/SDL/SDLVulkanGraphicsContext.cpp @@ -110,6 +110,15 @@ bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, vulkan_->InitSurface(WINDOWSYSTEM_METAL_EXT, makeWindowMetalCompatible(sys_info.info.uikit.window), nullptr); break; #endif +#endif +#if defined(VK_USE_PLATFORM_DISPLAY_KHR) + case WINDOWSYSTEM_DISPLAY: + /* + There is no problem passing null for the next two arguments, and reinit will be called later + huangzihan china + */ + vulkan_->InitSurface(WINDOWSYSTEM_DISPLAY, nullptr, nullptr); + break; #endif default: fprintf(stderr, "Vulkan subsystem %d not supported\n", sys_info.subsystem); From d502198aa35d548eb539e359f617ccd75c831d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Feb 2023 10:46:52 +0100 Subject: [PATCH 050/424] Move GLFrameData out of GLRenderManager. Small refactor to prepare for adding delayed readback support to the OpenGL backend. --- CMakeLists.txt | 2 + Common/Common.vcxproj | 2 + Common/Common.vcxproj.filters | 6 +++ Common/GPU/OpenGL/GLFrameData.cpp | 75 ++++++++++++++++++++++++++ Common/GPU/OpenGL/GLFrameData.h | 52 ++++++++++++++++++ Common/GPU/OpenGL/GLQueueRunner.h | 1 + Common/GPU/OpenGL/GLRenderManager.cpp | 77 ++------------------------- Common/GPU/OpenGL/GLRenderManager.h | 42 ++------------- android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 10 files changed, 147 insertions(+), 112 deletions(-) create mode 100644 Common/GPU/OpenGL/GLFrameData.cpp create mode 100644 Common/GPU/OpenGL/GLFrameData.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b8ecd9255..32213160a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -632,6 +632,8 @@ add_library(Common STATIC Common/GPU/OpenGL/gl3stub.h Common/GPU/OpenGL/GLFeatures.cpp Common/GPU/OpenGL/GLFeatures.h + Common/GPU/OpenGL/GLFrameData.cpp + Common/GPU/OpenGL/GLFrameData.h Common/GPU/OpenGL/thin3d_gl.cpp Common/GPU/OpenGL/GLRenderManager.cpp Common/GPU/OpenGL/GLRenderManager.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index c3c1ebebaf..451e8dd426 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -436,6 +436,7 @@ + @@ -871,6 +872,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 6dfa552f1b..3c0a310aff 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -464,6 +464,9 @@ UI + + GPU\OpenGL + @@ -878,6 +881,9 @@ UI + + GPU\OpenGL + diff --git a/Common/GPU/OpenGL/GLFrameData.cpp b/Common/GPU/OpenGL/GLFrameData.cpp new file mode 100644 index 0000000000..fa5a051d30 --- /dev/null +++ b/Common/GPU/OpenGL/GLFrameData.cpp @@ -0,0 +1,75 @@ +#include "Common/GPU/OpenGL/GLCommon.h" +#include "Common/GPU/OpenGL/GLFrameData.h" +#include "Common/GPU/OpenGL/GLRenderManager.h" +#include "Common/Log.h" + +void GLDeleter::Take(GLDeleter &other) { + _assert_msg_(IsEmpty(), "Deleter already has stuff"); + shaders = std::move(other.shaders); + programs = std::move(other.programs); + buffers = std::move(other.buffers); + textures = std::move(other.textures); + inputLayouts = std::move(other.inputLayouts); + framebuffers = std::move(other.framebuffers); + pushBuffers = std::move(other.pushBuffers); + other.shaders.clear(); + other.programs.clear(); + other.buffers.clear(); + other.textures.clear(); + other.inputLayouts.clear(); + other.framebuffers.clear(); + other.pushBuffers.clear(); +} + +// Runs on the GPU thread. +void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) { + for (auto pushBuffer : pushBuffers) { + renderManager->UnregisterPushBuffer(pushBuffer); + if (skipGLCalls) { + pushBuffer->Destroy(false); + } + delete pushBuffer; + } + pushBuffers.clear(); + for (auto shader : shaders) { + if (skipGLCalls) + shader->shader = 0; // prevent the glDeleteShader + delete shader; + } + shaders.clear(); + for (auto program : programs) { + if (skipGLCalls) + program->program = 0; // prevent the glDeleteProgram + delete program; + } + programs.clear(); + for (auto buffer : buffers) { + if (skipGLCalls) + buffer->buffer_ = 0; + delete buffer; + } + buffers.clear(); + for (auto texture : textures) { + if (skipGLCalls) + texture->texture = 0; + delete texture; + } + textures.clear(); + for (auto inputLayout : inputLayouts) { + // No GL objects in an inputLayout yet + delete inputLayout; + } + inputLayouts.clear(); + for (auto framebuffer : framebuffers) { + if (skipGLCalls) { + framebuffer->handle = 0; + framebuffer->color_texture.texture = 0; + framebuffer->z_stencil_buffer = 0; + framebuffer->z_stencil_texture.texture = 0; + framebuffer->z_buffer = 0; + framebuffer->stencil_buffer = 0; + } + delete framebuffer; + } + framebuffers.clear(); +} diff --git a/Common/GPU/OpenGL/GLFrameData.h b/Common/GPU/OpenGL/GLFrameData.h new file mode 100644 index 0000000000..a50fbe7d55 --- /dev/null +++ b/Common/GPU/OpenGL/GLFrameData.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include +#include +#include + +#include "Common/GPU/OpenGL/GLCommon.h" + +class GLRShader; +class GLRBuffer; +class GLRTexture; +class GLRInputLayout; +class GLRFramebuffer; +class GLPushBuffer; +class GLRProgram; +class GLRenderManager; + +class GLDeleter { +public: + void Perform(GLRenderManager *renderManager, bool skipGLCalls); + + bool IsEmpty() const { + return shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty() && pushBuffers.empty(); + } + + void Take(GLDeleter &other); + + std::vector shaders; + std::vector programs; + std::vector buffers; + std::vector textures; + std::vector inputLayouts; + std::vector framebuffers; + std::vector pushBuffers; +}; + +// Per-frame data, round-robin so we can overlap submission with execution of the previous frame. +struct GLFrameData { + bool skipSwap = false; + + std::mutex fenceMutex; + std::condition_variable fenceCondVar; + bool readyForFence = true; + + // Swapchain. + bool hasBegun = false; + + GLDeleter deleter; + GLDeleter deleter_prev; + std::set activePushBuffers; +}; diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index b79ff6b6ae..0db0575eae 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -6,6 +6,7 @@ #include #include "Common/GPU/OpenGL/GLCommon.h" +#include "Common/GPU/OpenGL/GLFrameData.h" #include "Common/GPU/DataFormat.h" #include "Common/GPU/Shader.h" #include "Common/GPU/thin3d.h" diff --git a/Common/GPU/OpenGL/GLRenderManager.cpp b/Common/GPU/OpenGL/GLRenderManager.cpp index 1c45abd7e3..b10caa2541 100644 --- a/Common/GPU/OpenGL/GLRenderManager.cpp +++ b/Common/GPU/OpenGL/GLRenderManager.cpp @@ -41,77 +41,6 @@ GLRTexture::~GLRTexture() { } } -void GLDeleter::Take(GLDeleter &other) { - _assert_msg_(IsEmpty(), "Deleter already has stuff"); - shaders = std::move(other.shaders); - programs = std::move(other.programs); - buffers = std::move(other.buffers); - textures = std::move(other.textures); - inputLayouts = std::move(other.inputLayouts); - framebuffers = std::move(other.framebuffers); - pushBuffers = std::move(other.pushBuffers); - other.shaders.clear(); - other.programs.clear(); - other.buffers.clear(); - other.textures.clear(); - other.inputLayouts.clear(); - other.framebuffers.clear(); - other.pushBuffers.clear(); -} - -// Runs on the GPU thread. -void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) { - for (auto pushBuffer : pushBuffers) { - renderManager->UnregisterPushBuffer(pushBuffer); - if (skipGLCalls) { - pushBuffer->Destroy(false); - } - delete pushBuffer; - } - pushBuffers.clear(); - for (auto shader : shaders) { - if (skipGLCalls) - shader->shader = 0; // prevent the glDeleteShader - delete shader; - } - shaders.clear(); - for (auto program : programs) { - if (skipGLCalls) - program->program = 0; // prevent the glDeleteProgram - delete program; - } - programs.clear(); - for (auto buffer : buffers) { - if (skipGLCalls) - buffer->buffer_ = 0; - delete buffer; - } - buffers.clear(); - for (auto texture : textures) { - if (skipGLCalls) - texture->texture = 0; - delete texture; - } - textures.clear(); - for (auto inputLayout : inputLayouts) { - // No GL objects in an inputLayout yet - delete inputLayout; - } - inputLayouts.clear(); - for (auto framebuffer : framebuffers) { - if (skipGLCalls) { - framebuffer->handle = 0; - framebuffer->color_texture.texture = 0; - framebuffer->z_stencil_buffer = 0; - framebuffer->z_stencil_texture.texture = 0; - framebuffer->z_buffer = 0; - framebuffer->stencil_buffer = 0; - } - delete framebuffer; - } - framebuffers.clear(); -} - GLRenderManager::~GLRenderManager() { _dbg_assert_(!run_); @@ -414,7 +343,7 @@ void GLRenderManager::BeginFrame() { int curFrame = GetCurFrame(); - FrameData &frameData = frameData_[curFrame]; + GLFrameData &frameData = frameData_[curFrame]; { VLOG("PUSH: BeginFrame (curFrame = %d, readyForFence = %d, time=%0.3f)", curFrame, (int)frameData.readyForFence, time_now_d()); std::unique_lock lock(frameData.fenceMutex); @@ -435,7 +364,7 @@ void GLRenderManager::Finish() { curRenderStep_ = nullptr; // EndCurRenderStep is this simple here. int curFrame = GetCurFrame(); - FrameData &frameData = frameData_[curFrame]; + GLFrameData &frameData = frameData_[curFrame]; frameData_[curFrame].deleter.Take(deleter_); @@ -463,7 +392,7 @@ void GLRenderManager::Finish() { // Render thread. Returns true if the caller should handle a swap. bool GLRenderManager::Run(GLRRenderThreadTask &task) { - FrameData &frameData = frameData_[task.frame]; + GLFrameData &frameData = frameData_[task.frame]; if (!frameData.hasBegun) { frameData.hasBegun = true; diff --git a/Common/GPU/OpenGL/GLRenderManager.h b/Common/GPU/OpenGL/GLRenderManager.h index fe0b42aafd..281a42353f 100644 --- a/Common/GPU/OpenGL/GLRenderManager.h +++ b/Common/GPU/OpenGL/GLRenderManager.h @@ -10,11 +10,12 @@ #include #include -#include "Common/GPU/OpenGL/GLCommon.h" #include "Common/GPU/MiscTypes.h" #include "Common/Data/Convert/SmallDataConvert.h" #include "Common/Log.h" -#include "GLQueueRunner.h" +#include "Common/GPU/OpenGL/GLQueueRunner.h" +#include "Common/GPU/OpenGL/GLFrameData.h" +#include "Common/GPU/OpenGL/GLCommon.h" class GLRInputLayout; class GLPushBuffer; @@ -373,25 +374,6 @@ enum class GLRRunType { class GLRenderManager; class GLPushBuffer; -class GLDeleter { -public: - void Perform(GLRenderManager *renderManager, bool skipGLCalls); - - bool IsEmpty() const { - return shaders.empty() && programs.empty() && buffers.empty() && textures.empty() && inputLayouts.empty() && framebuffers.empty() && pushBuffers.empty(); - } - - void Take(GLDeleter &other); - - std::vector shaders; - std::vector programs; - std::vector buffers; - std::vector textures; - std::vector inputLayouts; - std::vector framebuffers; - std::vector pushBuffers; -}; - // These are enqueued from the main thread, // and the render thread pops them off struct GLRRenderThreadTask { @@ -1035,23 +1017,7 @@ private: frameData_[frame].activePushBuffers.insert(buffer); } - // Per-frame data, round-robin so we can overlap submission with execution of the previous frame. - struct FrameData { - bool skipSwap = false; - - std::mutex fenceMutex; - std::condition_variable fenceCondVar; - bool readyForFence = true; - - // Swapchain. - bool hasBegun = false; - - GLDeleter deleter; - GLDeleter deleter_prev; - std::set activePushBuffers; - }; - - FrameData frameData_[MAX_INFLIGHT_FRAMES]; + GLFrameData frameData_[MAX_INFLIGHT_FRAMES]; // Submission time state bool insideFrame_ = false; diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6932d49ecf..218ce2f8ec 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -42,6 +42,7 @@ NATIVE_FILES :=\ $(SRC)/Common/GPU/OpenGL/GLDebugLog.cpp \ $(SRC)/Common/GPU/OpenGL/GLSLProgram.cpp \ $(SRC)/Common/GPU/OpenGL/GLFeatures.cpp \ + $(SRC)/Common/GPU/OpenGL/GLFrameData.cpp \ $(SRC)/Common/GPU/OpenGL/GLRenderManager.cpp \ $(SRC)/Common/GPU/OpenGL/GLQueueRunner.cpp \ $(SRC)/Common/GPU/OpenGL/DataFormatGL.cpp diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 2b62ff352d..ed11027f32 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -279,6 +279,7 @@ SOURCES_CXX += \ $(COMMONDIR)/GPU/OpenGL/GLDebugLog.cpp \ $(COMMONDIR)/GPU/OpenGL/GLSLProgram.cpp \ $(COMMONDIR)/GPU/OpenGL/GLFeatures.cpp \ + $(COMMONDIR)/GPU/OpenGL/GLFrameData.cpp \ $(COMMONDIR)/GPU/OpenGL/GLRenderManager.cpp \ $(COMMONDIR)/GPU/OpenGL/GLQueueRunner.cpp \ $(COMMONDIR)/GPU/OpenGL/DataFormatGL.cpp \ From b4aa12029875f191c8b58fc017f83a639b918d01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Feb 2023 11:25:41 +0100 Subject: [PATCH 051/424] OpenGL readback: Move any format convert to when the data is read. Eliminates a copy, and will fit better with delayed readbacks. --- Common/GPU/OpenGL/GLQueueRunner.cpp | 44 ++++++++++++++--------------- Common/GPU/OpenGL/GLQueueRunner.h | 4 +-- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 44f072c6f7..568da74e03 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -88,9 +88,6 @@ void GLQueueRunner::DestroyDeviceObjects() { delete[] readbackBuffer_; readbackBuffer_ = nullptr; readbackBufferSize_ = 0; - delete[] tempBuffer_; - tempBuffer_ = nullptr; - tempBufferSize_ = 0; CHECK_GL_ERROR_IF_DEBUG(); } @@ -1481,26 +1478,24 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { CHECK_GL_ERROR_IF_DEBUG(); // Always read back in 8888 format for the color aspect. - GLuint internalFormat = GL_RGBA; GLuint format = GL_RGBA; GLuint type = GL_UNSIGNED_BYTE; int srcAlignment = 4; - int dstAlignment = (int)DataFormatSizeInBytes(pass.readback.dstFormat); #ifndef USING_GLES2 if (pass.readback.aspectMask & GL_DEPTH_BUFFER_BIT) { - internalFormat = GL_DEPTH_COMPONENT; format = GL_DEPTH_COMPONENT; type = GL_FLOAT; srcAlignment = 4; } else if (pass.readback.aspectMask & GL_STENCIL_BUFFER_BIT) { - internalFormat = GL_STENCIL_INDEX; format = GL_STENCIL_INDEX; type = GL_UNSIGNED_BYTE; srcAlignment = 1; } #endif + readbackAspectMask_ = pass.readback.aspectMask; + int pixelStride = pass.readback.srcRect.w; // Apply the correct alignment. glPixelStorei(GL_PACK_ALIGNMENT, srcAlignment); @@ -1511,31 +1506,20 @@ void GLQueueRunner::PerformReadback(const GLRStep &pass) { GLRect2D rect = pass.readback.srcRect; - bool convert = internalFormat == GL_RGBA && pass.readback.dstFormat != DataFormat::R8G8B8A8_UNORM; - - int tempSize = srcAlignment * rect.w * rect.h; - int readbackSize = dstAlignment * rect.w * rect.h; - if (convert && tempSize > tempBufferSize_) { - delete[] tempBuffer_; - tempBuffer_ = new uint8_t[tempSize]; - tempBufferSize_ = tempSize; - } + int readbackSize = srcAlignment * rect.w * rect.h; if (readbackSize > readbackBufferSize_) { delete[] readbackBuffer_; readbackBuffer_ = new uint8_t[readbackSize]; readbackBufferSize_ = readbackSize; } - glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, convert ? tempBuffer_ : readbackBuffer_); + glReadPixels(rect.x, rect.y, rect.w, rect.h, format, type, readbackBuffer_); #ifdef DEBUG_READ_PIXELS LogReadPixelsError(glGetError()); #endif if (!gl_extensions.IsGLES || gl_extensions.GLES3) { glPixelStorei(GL_PACK_ROW_LENGTH, 0); } - if (convert && tempBuffer_ && readbackBuffer_) { - ConvertFromRGBA8888(readbackBuffer_, tempBuffer_, pixelStride, pixelStride, rect.w, rect.h, pass.readback.dstFormat); - } CHECK_GL_ERROR_IF_DEBUG(); } @@ -1624,8 +1608,24 @@ void GLQueueRunner::CopyFromReadbackBuffer(GLRFramebuffer *framebuffer, int widt // Something went wrong during the read and no readback buffer was allocated, probably. return; } - for (int y = 0; y < height; y++) { - memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, width * bpp); + + // Always read back in 8888 format for the color aspect. + GLuint internalFormat = GL_RGBA; +#ifndef USING_GLES2 + if (readbackAspectMask_ & GL_DEPTH_BUFFER_BIT) { + internalFormat = GL_DEPTH_COMPONENT; + } else if (readbackAspectMask_ & GL_STENCIL_BUFFER_BIT) { + internalFormat = GL_STENCIL_INDEX; + } +#endif + + bool convert = internalFormat == GL_RGBA && destFormat != Draw::DataFormat::R8G8B8A8_UNORM; + if (convert) { + ConvertFromRGBA8888(pixels, readbackBuffer_, pixelStride, pixelStride, width, height, destFormat); + } else { + for (int y = 0; y < height; y++) { + memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, width * bpp); + } } } diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index 0db0575eae..9ef6614bfc 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -420,9 +420,7 @@ private: // We size it generously. uint8_t *readbackBuffer_ = nullptr; int readbackBufferSize_ = 0; - // Temp buffer for color conversion - uint8_t *tempBuffer_ = nullptr; - int tempBufferSize_ = 0; + uint32_t readbackAspectMask_ = 0; float maxAnisotropyLevel_ = 0.0f; From 742e123b2b455b30f8406525fde45da7f3b28b1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Feb 2023 17:07:19 +0100 Subject: [PATCH 052/424] Address feedback --- Common/GPU/OpenGL/GLQueueRunner.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 568da74e03..4908fcd12d 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -1621,7 +1621,8 @@ void GLQueueRunner::CopyFromReadbackBuffer(GLRFramebuffer *framebuffer, int widt bool convert = internalFormat == GL_RGBA && destFormat != Draw::DataFormat::R8G8B8A8_UNORM; if (convert) { - ConvertFromRGBA8888(pixels, readbackBuffer_, pixelStride, pixelStride, width, height, destFormat); + // srcStride is width because we read back "packed" (with no gaps) from GL. + ConvertFromRGBA8888(pixels, readbackBuffer_, pixelStride, width, width, height, destFormat); } else { for (int y = 0; y < height; y++) { memcpy(pixels + y * pixelStride * bpp, readbackBuffer_ + y * width * bpp, width * bpp); From 9e736ca50ca4cc8b33e5e87c3c175ef91bcdd1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Feb 2023 17:43:12 +0100 Subject: [PATCH 053/424] Workaround for sin/cos issue in GTA on Mac (and maybe others) --- Core/MIPS/MIPSVFPUUtils.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Core/MIPS/MIPSVFPUUtils.cpp b/Core/MIPS/MIPSVFPUUtils.cpp index 1019cbf494..b60cd7c97c 100644 --- a/Core/MIPS/MIPSVFPUUtils.cpp +++ b/Core/MIPS/MIPSVFPUUtils.cpp @@ -29,6 +29,13 @@ #define V(i) (currentMIPS->v[voffset[i]]) #define VI(i) (currentMIPS->vi[voffset[i]]) +// Flushes the angle to 0 if exponent smaller than this in vfpu_sin/vfpu_cos/vfpu_sincos. +// Was measured to be around 0x68, but GTA on Mac is somehow super sensitive +// to the shape of the sine curve which seem to be very slightly different. +// +// So setting a lower value. +#define PRECISION_EXP_THRESHOLD 0x65 + union float2int { uint32_t i; float f; @@ -899,7 +906,7 @@ float vfpu_sin(float a) { return val.f; } - if (k < 0x68) { + if (k < PRECISION_EXP_THRESHOLD) { val.i &= 0x80000000; return val.f; } @@ -945,7 +952,7 @@ float vfpu_cos(float a) { return val.f; } - if (k < 0x68) + if (k < PRECISION_EXP_THRESHOLD) return 1.0f; // Okay, now modulus by 4 to begin with (identical wave every 4.) @@ -993,7 +1000,7 @@ void vfpu_sincos(float a, float &s, float &c) { return; } - if (k < 0x68) { + if (k < PRECISION_EXP_THRESHOLD) { val.i &= 0x80000000; s = val.f; c = 1.0f; From 40e92ce7530f56b64f4bc5fbf64c42280e5140bf Mon Sep 17 00:00:00 2001 From: Eric Warmenhoven Date: Tue, 7 Feb 2023 12:11:35 -0500 Subject: [PATCH 054/424] Build for tvOS as a libretro core --- .gitlab-ci.yml | 13 +++++++++++++ cmake/Toolchains/ios.cmake | 19 +++++++++++++++---- libretro/libretro_vulkan.cpp | 1 - 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e97fab6fee..ec27838610 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -53,6 +53,10 @@ include: - project: 'libretro-infrastructure/ci-templates' file: '/ios-cmake.yml' + # tvOS + - project: 'libretro-infrastructure/ci-templates' + file: '/tvos-cmake.yml' + ################################## CONSOLES ################################ #################################### MISC ################################## @@ -146,3 +150,12 @@ libretro-build-ios-arm64: - .cmake-defs variables: CORE_ARGS: -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ios.cmake -DLIBRETRO=ON + +# tvOS arm64 +libretro-build-tvos-arm64: + extends: + - .libretro-tvos-cmake-arm64 + - .core-defs + - .cmake-defs + variables: + CORE_ARGS: -DIOS_PLATFORM=TVOS -DUSE_FFMPEG=NO -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/ios.cmake -DLIBRETRO=ON diff --git a/cmake/Toolchains/ios.cmake b/cmake/Toolchains/ios.cmake index a8041ec376..2e5dca4ca2 100644 --- a/cmake/Toolchains/ios.cmake +++ b/cmake/Toolchains/ios.cmake @@ -19,9 +19,14 @@ add_definitions( ) set(OPENGL_LIBRARIES "-framework OpenGLES") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}") +if(IOS_PLATFORM STREQUAL "TVOS") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mappletvos-version-min=${IPHONEOS_DEPLOYMENT_TARGET}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mappletvos-version-min=${IPHONEOS_DEPLOYMENT_TARGET}") +else() + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}") +endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mios-version-min=${IPHONEOS_DEPLOYMENT_TARGET}") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") # Standard settings @@ -31,7 +36,11 @@ set(CMAKE_SYSTEM_PROCESSOR aarch64) set(IOS ON) set(CMAKE_CROSSCOMPILING ON) set(CMAKE_MACOSX_BUNDLE YES) -set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${IPHONEOS_DEPLOYMENT_TARGET}) +if(IOS_PLATFORM STREQUAL "TVOS") + #set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${IPHONEOS_DEPLOYMENT_TARGET}) +else() + set(CMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${IPHONEOS_DEPLOYMENT_TARGET}) +endif() # Setup iOS platform unless specified manually with IOS_PLATFORM if(NOT DEFINED IOS_PLATFORM) @@ -44,6 +53,8 @@ if(IOS_PLATFORM STREQUAL "OS") set(IOS_SDK_NAME "iphoneos") elseif(IOS_PLATFORM STREQUAL "SIMULATOR") set(IOS_SDK_NAME "iphonesimulator") +elseif(IOS_PLATFORM STREQUAL "TVOS") + set(IOS_SDK_NAME "appletvos") else() message (FATAL_ERROR "Unsupported IOS_PLATFORM value selected '${IOS_PLATFORM}'. Please choose OS or leave default") endif() @@ -63,7 +74,7 @@ set(CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selecte set(CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support") # set the architecture for iOS -if(IOS_PLATFORM STREQUAL "OS") +if(IOS_PLATFORM STREQUAL "OS" OR IOS_PLATFORM STREQUAL "TVOS") set(IOS_ARCH "arm64") else() set(IOS_ARCH "i386;x86_64") diff --git a/libretro/libretro_vulkan.cpp b/libretro/libretro_vulkan.cpp index 8fc3faabd3..45269649b4 100644 --- a/libretro/libretro_vulkan.cpp +++ b/libretro/libretro_vulkan.cpp @@ -98,7 +98,6 @@ static VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice_libretro(VkPhysicalDevice p for (unsigned i = 0; i < vk_init_info.num_required_device_extensions; i++) add_name_unique(EnabledExtensionNames, vk_init_info.required_device_extensions[i]); - add_name_unique(EnabledExtensionNames, VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME); for (unsigned i = 0; i < sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); i++) { if (((VkBool32 *)vk_init_info.required_features)[i]) ((VkBool32 *)&EnabledFeatures)[i] = VK_TRUE; From 6e91ca9e54a0294b7112b975d25833d0cf322833 Mon Sep 17 00:00:00 2001 From: Lubos Date: Tue, 7 Feb 2023 19:48:16 +0100 Subject: [PATCH 055/424] OpenXR - Option to disable automatic switch between 2D and VR --- Common/VR/PPSSPPVR.cpp | 18 +++++++++++++++--- Core/Config.cpp | 3 ++- Core/Config.h | 1 + UI/GameSettingsScreen.cpp | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index f3ede39317..d30511ad20 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -42,6 +42,7 @@ static std::map pspKeys; static int vr3DGeometryCount = 0; static long vrCompat[VR_COMPAT_MAX]; +static bool vrFlatForced = false; static bool vrFlatGame = false; static float vrMatrix[VR_MATRIX_COUNT][16]; static bool vrMirroring[VR_MIRRORING_COUNT]; @@ -317,7 +318,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { if (g_Config.iHeadRotation) { float pitch = -VR_GetHMDAngles().x; float yaw = -VR_GetHMDAngles().y; - bool disable = pspKeys[CTRL_SCREEN] || appMode == VR_MENU_MODE; + bool disable = vrFlatForced || appMode == VR_MENU_MODE; bool isVR = !IsFlatVRScene(); // calculate delta angles of the rotation @@ -482,6 +483,7 @@ bool UpdateVRAxis(const AxisInput &axis) { bool UpdateVRKeys(const KeyInput &key) { //store key value std::vector nativeKeys; + bool wasScreenKeyOn = pspKeys[CTRL_SCREEN]; bool wasCameraAdjustOn = pspKeys[VIRTKEY_VR_CAMERA_ADJUST]; if (KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &nativeKeys)) { for (int& nativeKey : nativeKeys) { @@ -503,6 +505,15 @@ bool UpdateVRKeys(const KeyInput &key) { } } + // Update force flat 2D mode + if (g_Config.bManualForceVR) { + if (!wasScreenKeyOn && pspKeys[CTRL_SCREEN]) { + vrFlatForced = !vrFlatForced; + } + } else { + vrFlatForced = pspKeys[CTRL_SCREEN]; + } + // Release keys on enabling camera adjust if (!wasCameraAdjustOn && pspKeys[VIRTKEY_VR_CAMERA_ADJUST]) { KeyInput keyUp; @@ -748,9 +759,10 @@ bool StartVRRender() { // Decide if the scene is 3D or not bool stereo = hasUnitScale && g_Config.bEnableStereo; - bool forceFlat = PSP_CoreParameter().compat.vrCompat().ForceFlatScreen; + bool vrIncompatibleGame = PSP_CoreParameter().compat.vrCompat().ForceFlatScreen; + bool vrScene = !vrFlatForced && (g_Config.bManualForceVR || (vr3DGeometryCount > 15)); VR_SetConfigFloat(VR_CONFIG_CANVAS_ASPECT, 480.0f / 272.0f); - if (g_Config.bEnableVR && !pspKeys[CTRL_SCREEN] && !forceFlat && (appMode == VR_GAME_MODE) && (vr3DGeometryCount > 15)) { + if (g_Config.bEnableVR && !vrIncompatibleGame && (appMode == VR_GAME_MODE) && vrScene) { VR_SetConfig(VR_CONFIG_MODE, stereo ? VR_MODE_STEREO_6DOF : VR_MODE_MONO_6DOF); vrFlatGame = false; } else { diff --git a/Core/Config.cpp b/Core/Config.cpp index 86cd15c61e..8cc8eeaea1 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1140,7 +1140,8 @@ static const ConfigSetting vrSettings[] = { ConfigSetting("VREnable6DoF", &g_Config.bEnable6DoF, true), ConfigSetting("VREnableStereo", &g_Config.bEnableStereo, false), ConfigSetting("VREnableMotions", &g_Config.bEnableMotions, true), - ConfigSetting("VRbForce72Hz", &g_Config.bForce72Hz, true), + ConfigSetting("VRForce72Hz", &g_Config.bForce72Hz, true), + ConfigSetting("VRManualForceVR", &g_Config.bManualForceVR, false), ConfigSetting("VRCameraDistance", &g_Config.fCameraDistance, 0.0f), ConfigSetting("VRCameraHeight", &g_Config.fCameraHeight, 0.0f), ConfigSetting("VRCameraSide", &g_Config.fCameraSide, 0.0f), diff --git a/Core/Config.h b/Core/Config.h index dc2f1a8ca7..f3a93d4dc7 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -465,6 +465,7 @@ public: bool bEnableStereo; bool bEnableMotions; bool bForce72Hz; + bool bManualForceVR; float fCameraDistance; float fCameraHeight; float fCameraSide; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index ab756a0d2a..2f71c2ec55 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1137,6 +1137,7 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, vr->T("Heads-up display scale"), 0.1f, screenManager(), "")); vrSettings->Add(new ItemHeader(vr->T("Experts only"))); + vrSettings->Add(new CheckBox(&g_Config.bManualForceVR, vr->T("Manual switching between flat screen and VR using SCREEN key"))); static const char *vrHeadRotations[] = { vr->T("Disabled"), vr->T("Horizontal only"), vr->T("Horizontal and vertical") }; vrSettings->Add(new PopupMultiChoice(&g_Config.iHeadRotation, vr->T("Map HMD rotations on keys instead of VR camera"), vrHeadRotations, 0, ARRAY_SIZE(vrHeadRotations), vr->GetName(), screenManager())); PopupSliderChoiceFloat *vrHeadRotationScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadRotationScale, 0.1f, 10.0f, vr->T("Game camera rotation step per frame"), 0.1f, screenManager(), "°")); From b3e6b81e43b9eceaf65a7a17f591d470fc345faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Feb 2023 16:59:23 +0100 Subject: [PATCH 056/424] Implement delayed depth readbacks for Vulkan only --- Common/GPU/Vulkan/VulkanFrameData.cpp | 13 +++ Common/GPU/Vulkan/VulkanFrameData.h | 25 ++++- Common/GPU/Vulkan/VulkanQueueRunner.cpp | 115 ++++++++++++++-------- Common/GPU/Vulkan/VulkanQueueRunner.h | 13 +-- Common/GPU/Vulkan/VulkanRenderManager.cpp | 10 +- GPU/Common/FramebufferManagerCommon.cpp | 10 +- GPU/GPU.h | 2 + GPU/GPUCommon.cpp | 3 +- 8 files changed, 136 insertions(+), 55 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanFrameData.cpp b/Common/GPU/Vulkan/VulkanFrameData.cpp index 192fe1f28a..90d2c43483 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.cpp +++ b/Common/GPU/Vulkan/VulkanFrameData.cpp @@ -4,6 +4,13 @@ #include "Common/Log.h" #include "Common/StringUtils.h" +void CachedReadback::Destroy(VulkanContext *vulkan) { + if (buffer) { + vulkan->Delete().QueueDeleteBufferAllocation(buffer, allocation); + } + bufferSize = 0; +} + void FrameData::Init(VulkanContext *vulkan, int index) { this->index = index; VkDevice device = vulkan->GetDevice(); @@ -48,6 +55,12 @@ void FrameData::Destroy(VulkanContext *vulkan) { vkDestroyCommandPool(device, cmdPoolMain, nullptr); vkDestroyFence(device, fence, nullptr); vkDestroyQueryPool(device, profile.queryPool, nullptr); + + readbacks_.IterateMut([=](const ReadbackKey &key, CachedReadback *value) { + value->Destroy(vulkan); + delete value; + }); + readbacks_.Clear(); } void FrameData::AcquireNextImage(VulkanContext *vulkan, FrameDataShared &shared) { diff --git a/Common/GPU/Vulkan/VulkanFrameData.h b/Common/GPU/Vulkan/VulkanFrameData.h index 148dc66338..0e1344f24e 100644 --- a/Common/GPU/Vulkan/VulkanFrameData.h +++ b/Common/GPU/Vulkan/VulkanFrameData.h @@ -6,6 +6,7 @@ #include #include "Common/GPU/Vulkan/VulkanContext.h" +#include "Common/Data/Collections/Hashmaps.h" enum { MAX_TIMESTAMP_QUERIES = 128, @@ -25,6 +26,23 @@ struct QueueProfileContext { double cpuEndTime; }; +class VKRFramebuffer; + +struct ReadbackKey { + const VKRFramebuffer *framebuf; + int width; + int height; +}; + +struct CachedReadback { + VkBuffer buffer; + VmaAllocation allocation; + VkDeviceSize bufferSize; + bool isCoherent; + + void Destroy(VulkanContext *vulkan); +}; + struct FrameDataShared { // Permanent objects VkSemaphore acquireSemaphore = VK_NULL_HANDLE; @@ -77,6 +95,11 @@ struct FrameData { QueueProfileContext profile; bool profilingEnabled_ = false; + // Async readback cache. + DenseHashMap readbacks_; + + FrameData() : readbacks_(8) {} + void Init(VulkanContext *vulkan, int index); void Destroy(VulkanContext *vulkan); @@ -91,5 +114,5 @@ struct FrameData { private: // Metadata for logging etc - int index; + int index = -1; }; diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.cpp b/Common/GPU/Vulkan/VulkanQueueRunner.cpp index a28f54ba0a..3b2bbdd9be 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.cpp +++ b/Common/GPU/Vulkan/VulkanQueueRunner.cpp @@ -69,7 +69,8 @@ void VulkanQueueRunner::CreateDeviceObjects() { void VulkanQueueRunner::DestroyDeviceObjects() { INFO_LOG(G3D, "VulkanQueueRunner::DestroyDeviceObjects"); - DestroyReadbackBuffer(); + + syncReadback_.Destroy(vulkan_); renderPasses_.IterateMut([&](const RPKey &rpkey, VKRRenderPass *rp) { _assert_(rp); @@ -419,7 +420,7 @@ void VulkanQueueRunner::RunSteps(std::vector &steps, FrameData &frame PerformBlit(step, cmd); break; case VKRStepType::READBACK: - PerformReadback(step, cmd); + PerformReadback(step, cmd, frameData); break; case VKRStepType::READBACK_IMAGE: PerformReadbackImage(step, cmd); @@ -1944,52 +1945,35 @@ void VulkanQueueRunner::SetupTransferDstWriteAfterWrite(VKRImage &img, VkImageAs ); } -void VulkanQueueRunner::ResizeReadbackBuffer(VkDeviceSize requiredSize) { - if (readbackBuffer_ && requiredSize <= readbackBufferSize_) { +void VulkanQueueRunner::ResizeReadbackBuffer(CachedReadback *readback, VkDeviceSize requiredSize) { + if (readback->buffer && requiredSize <= readback->bufferSize) { return; } - if (readbackBuffer_) { - vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); + + if (readback->buffer) { + vulkan_->Delete().QueueDeleteBufferAllocation(readback->buffer, readback->allocation); } - readbackBufferSize_ = requiredSize; + readback->bufferSize = requiredSize; VkDevice device = vulkan_->GetDevice(); VkBufferCreateInfo buf{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; - buf.size = readbackBufferSize_; + buf.size = readback->bufferSize; buf.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; VmaAllocationCreateInfo allocCreateInfo{}; allocCreateInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; VmaAllocationInfo allocInfo{}; - VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &buf, &allocCreateInfo, &readbackBuffer_, &readbackAllocation_, &allocInfo); + VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &buf, &allocCreateInfo, &readback->buffer, &readback->allocation, &allocInfo); _assert_(res == VK_SUCCESS); const VkMemoryType &memoryType = vulkan_->GetMemoryProperties().memoryTypes[allocInfo.memoryType]; - readbackBufferIsCoherent_ = (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; + readback->isCoherent = (memoryType.propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) != 0; } -void VulkanQueueRunner::DestroyReadbackBuffer() { - if (readbackBuffer_) { - vulkan_->Delete().QueueDeleteBufferAllocation(readbackBuffer_, readbackAllocation_); - } - readbackBufferSize_ = 0; -} - -void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd) { - ResizeReadbackBuffer(sizeof(uint32_t) * step.readback.srcRect.extent.width * step.readback.srcRect.extent.height); - - VkBufferImageCopy region{}; - region.imageOffset = { step.readback.srcRect.offset.x, step.readback.srcRect.offset.y, 0 }; - region.imageExtent = { step.readback.srcRect.extent.width, step.readback.srcRect.extent.height, 1 }; - region.imageSubresource.aspectMask = step.readback.aspectMask; - region.imageSubresource.layerCount = 1; - region.bufferOffset = 0; - region.bufferRowLength = step.readback.srcRect.extent.width; - region.bufferImageHeight = step.readback.srcRect.extent.height; - +void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd, FrameData &frameData) { VkImage image; VkImageLayout copyLayout; // Special case for backbuffer readbacks. @@ -2023,7 +2007,40 @@ void VulkanQueueRunner::PerformReadback(const VKRStep &step, VkCommandBuffer cmd copyLayout = srcImage->layout; } - vkCmdCopyImageToBuffer(cmd, image, copyLayout, readbackBuffer_, 1, ®ion); + // TODO: Handle different readback formats! + u32 readbackSizeInBytes = sizeof(uint32_t) * step.readback.srcRect.extent.width * step.readback.srcRect.extent.height; + + CachedReadback *cached = nullptr; + + if (step.readback.delayed) { + ReadbackKey key; + key.framebuf = step.readback.src; + key.width = step.readback.srcRect.extent.width; + key.height = step.readback.srcRect.extent.height; + + // See if there's already a buffer we can reuse + cached = frameData.readbacks_.Get(key); + if (!cached) { + cached = new CachedReadback(); + cached->bufferSize = 0; + frameData.readbacks_.Insert(key, cached); + } + } else { + cached = &syncReadback_; + } + + ResizeReadbackBuffer(cached, readbackSizeInBytes); + + VkBufferImageCopy region{}; + region.imageOffset = { step.readback.srcRect.offset.x, step.readback.srcRect.offset.y, 0 }; + region.imageExtent = { step.readback.srcRect.extent.width, step.readback.srcRect.extent.height, 1 }; + region.imageSubresource.aspectMask = step.readback.aspectMask; + region.imageSubresource.layerCount = 1; + region.bufferOffset = 0; + region.bufferRowLength = step.readback.srcRect.extent.width; + region.bufferImageHeight = step.readback.srcRect.extent.height; + + vkCmdCopyImageToBuffer(cmd, image, copyLayout, cached->buffer, 1, ®ion); // NOTE: Can't read the buffer using the CPU here - need to sync first. @@ -2050,7 +2067,7 @@ void VulkanQueueRunner::PerformReadbackImage(const VKRStep &step, VkCommandBuffe SetupTransitionToTransferSrc(srcImage, VK_IMAGE_ASPECT_COLOR_BIT, &recordBarrier_); recordBarrier_.Flush(cmd); - ResizeReadbackBuffer(sizeof(uint32_t) * step.readback_image.srcRect.extent.width * step.readback_image.srcRect.extent.height); + ResizeReadbackBuffer(&syncReadback_, sizeof(uint32_t) * step.readback_image.srcRect.extent.width * step.readback_image.srcRect.extent.height); VkBufferImageCopy region{}; region.imageOffset = { step.readback_image.srcRect.offset.x, step.readback_image.srcRect.offset.y, 0 }; @@ -2061,7 +2078,7 @@ void VulkanQueueRunner::PerformReadbackImage(const VKRStep &step, VkCommandBuffe region.bufferOffset = 0; region.bufferRowLength = step.readback_image.srcRect.extent.width; region.bufferImageHeight = step.readback_image.srcRect.extent.height; - vkCmdCopyImageToBuffer(cmd, step.readback_image.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, readbackBuffer_, 1, ®ion); + vkCmdCopyImageToBuffer(cmd, step.readback_image.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, syncReadback_.buffer, 1, ®ion); // Now transfer it back to a texture. TransitionImageLayout2(cmd, step.readback_image.image, 0, 1, 1, // I don't think we have any multilayer cases for regular textures. Above in PerformReadback, though.. @@ -2074,22 +2091,39 @@ void VulkanQueueRunner::PerformReadbackImage(const VKRStep &step, VkCommandBuffe // Doing that will also act like a heavyweight barrier ensuring that device writes are visible on the host. } -void VulkanQueueRunner::CopyReadbackBuffer(VKRFramebuffer *src, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { - if (!readbackBuffer_) - return; // Something has gone really wrong. +bool VulkanQueueRunner::CopyReadbackBuffer(FrameData &frameData, VKRFramebuffer *src, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) { + CachedReadback *readback = &syncReadback_; + + // Look up in readback cache. + if (src) { + ReadbackKey key; + key.framebuf = src; + key.width = width; + key.height = height; + CachedReadback *cached = frameData.readbacks_.Get(key); + if (cached) { + readback = cached; + } else { + // Didn't have a cached image ready yet + return false; + } + } + + if (!readback->buffer) + return false; // Didn't find anything in cache, or something has gone really wrong. // Read back to the requested address in ram from buffer. void *mappedData; const size_t srcPixelSize = DataFormatSizeInBytes(srcFormat); - VkResult res = vmaMapMemory(vulkan_->Allocator(), readbackAllocation_, &mappedData); + VkResult res = vmaMapMemory(vulkan_->Allocator(), readback->allocation, &mappedData); if (res != VK_SUCCESS) { ERROR_LOG(G3D, "CopyReadbackBuffer: vkMapMemory failed! result=%d", (int)res); - return; + return false; } - if (!readbackBufferIsCoherent_) { - vmaInvalidateAllocation(vulkan_->Allocator(), readbackAllocation_, 0, width * height * srcPixelSize); + if (!readback->isCoherent) { + vmaInvalidateAllocation(vulkan_->Allocator(), readback->allocation, 0, width * height * srcPixelSize); } // TODO: Perform these conversions in a compute shader on the GPU. @@ -2116,5 +2150,6 @@ void VulkanQueueRunner::CopyReadbackBuffer(VKRFramebuffer *src, int width, int h _assert_msg_(false, "CopyReadbackBuffer: Unknown src format %d", (int)srcFormat); } - vmaUnmapMemory(vulkan_->Allocator(), readbackAllocation_); + vmaUnmapMemory(vulkan_->Allocator(), readback->allocation); + return true; } diff --git a/Common/GPU/Vulkan/VulkanQueueRunner.h b/Common/GPU/Vulkan/VulkanQueueRunner.h index 9567a8f243..6df7dfc681 100644 --- a/Common/GPU/Vulkan/VulkanQueueRunner.h +++ b/Common/GPU/Vulkan/VulkanQueueRunner.h @@ -199,6 +199,7 @@ struct VKRStep { int aspectMask; VKRFramebuffer *src; VkRect2D srcRect; + bool delayed; } readback; struct { VkImage image; @@ -253,7 +254,7 @@ public: } // src == 0 means to copy from the sync readback buffer. - void CopyReadbackBuffer(VKRFramebuffer *src, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); + bool CopyReadbackBuffer(FrameData &frameData, VKRFramebuffer *src, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); VKRRenderPass *GetRenderPass(const RPKey &key); @@ -289,7 +290,7 @@ private: void PerformRenderPass(const VKRStep &pass, VkCommandBuffer cmd); void PerformCopy(const VKRStep &pass, VkCommandBuffer cmd); void PerformBlit(const VKRStep &pass, VkCommandBuffer cmd); - void PerformReadback(const VKRStep &pass, VkCommandBuffer cmd); + void PerformReadback(const VKRStep &pass, VkCommandBuffer cmd, FrameData &frameData); void PerformReadbackImage(const VKRStep &pass, VkCommandBuffer cmd); void LogRenderPass(const VKRStep &pass, bool verbose); @@ -298,8 +299,7 @@ private: void LogReadback(const VKRStep &pass); void LogReadbackImage(const VKRStep &pass); - void ResizeReadbackBuffer(VkDeviceSize requiredSize); - void DestroyReadbackBuffer(); + void ResizeReadbackBuffer(CachedReadback *readback, VkDeviceSize requiredSize); void ApplyMGSHack(std::vector &steps); void ApplySonicHack(std::vector &steps); @@ -325,10 +325,7 @@ private: // Readback buffer. Currently we only support synchronous readback, so we only really need one. // We size it generously. - VmaAllocation readbackAllocation_ = VK_NULL_HANDLE; - VkBuffer readbackBuffer_ = VK_NULL_HANDLE; - VkDeviceSize readbackBufferSize_ = 0; - bool readbackBufferIsCoherent_ = false; + CachedReadback syncReadback_{}; // TODO: Enable based on compat.ini. uint32_t hacksEnabled_ = 0; diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index fbe6b72c7d..620e857ff1 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -929,11 +929,14 @@ bool VulkanRenderManager::CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAs step->readback.src = src; step->readback.srcRect.offset = { x, y }; step->readback.srcRect.extent = { (uint32_t)w, (uint32_t)h }; + step->readback.delayed = mode == Draw::ReadbackMode::OLD_DATA_OK; step->dependencies.insert(src); step->tag = tag; steps_.push_back(step); - FlushSync(); + if (mode == Draw::ReadbackMode::BLOCK) { + FlushSync(); + } Draw::DataFormat srcFormat = Draw::DataFormat::UNDEFINED; if (aspectBits & VK_IMAGE_ASPECT_COLOR_BIT) { @@ -972,7 +975,8 @@ bool VulkanRenderManager::CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAs } // Need to call this after FlushSync so the pixels are guaranteed to be ready in CPU-accessible VRAM. - queueRunner_.CopyReadbackBuffer(src, w, h, srcFormat, destFormat, pixelStride, pixels); + queueRunner_.CopyReadbackBuffer(frameData_[vulkan_->GetCurFrame()], + mode == Draw::ReadbackMode::OLD_DATA_OK ? src : nullptr, w, h, srcFormat, destFormat, pixelStride, pixels); return true; } @@ -992,7 +996,7 @@ void VulkanRenderManager::CopyImageToMemorySync(VkImage image, int mipLevel, int FlushSync(); // Need to call this after FlushSync so the pixels are guaranteed to be ready in CPU-accessible VRAM. - queueRunner_.CopyReadbackBuffer(nullptr, w, h, destFormat, destFormat, pixelStride, pixels); + queueRunner_.CopyReadbackBuffer(frameData_[vulkan_->GetCurFrame()], nullptr, w, h, destFormat, destFormat, pixelStride, pixels); } static void RemoveDrawCommands(std::vector *cmds) { diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index e04cf5d98a..e36d838afa 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2631,7 +2631,9 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB bool flipY = (GetGPUBackend() == GPUBackend::OPENGL && !useBufferedRendering_) ? true : false; buffer.Allocate(w, h, GE_FORMAT_8888, flipY); bool retval = draw_->CopyFramebufferToMemory(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w, Draw::ReadbackMode::BLOCK, "GetFramebuffer"); - gpuStats.numReadbacks++; + + // Don't need to increment gpu stats for readback count here, this is a debugger-only function. + // After a readback we'll have flushed and started over, need to dirty a bunch of things to be safe. gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); // We may have blitted to a temp FBO. @@ -2792,7 +2794,11 @@ void FramebufferManagerCommon::ReadbackFramebuffer(VirtualFramebuffer *vfb, int size_t len = snprintf(tag, sizeof(tag), "FramebufferPack/%08x_%08x_%dx%d_%s", vfb->fb_address, vfb->z_address, w, h, GeBufferFormatToString(vfb->fb_format)); NotifyMemInfo(MemBlockFlags::WRITE, fb_address + dstByteOffset, dstSize, tag, len); - gpuStats.numReadbacks++; + if (mode == Draw::ReadbackMode::BLOCK) { + gpuStats.numBlockingReadbacks++; + } else { + gpuStats.numReadbacks++; + } } bool FramebufferManagerCommon::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode) { diff --git a/GPU/GPU.h b/GPU/GPU.h index 4411733728..3c3481c43b 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -88,6 +88,7 @@ struct GPUStatistics { numFlushes = 0; numTexturesDecoded = 0; numFramebufferEvaluations = 0; + numBlockingReadbacks = 0; numReadbacks = 0; numUploads = 0; numDepal = 0; @@ -118,6 +119,7 @@ struct GPUStatistics { int numShaderSwitches; int numTexturesDecoded; int numFramebufferEvaluations; + int numBlockingReadbacks; int numReadbacks; int numUploads; int numDepal; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index fa26a53a1c..19a8fece4b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3467,7 +3467,7 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { "Vertices: %d cached: %d uncached: %d\n" "FBOs active: %d (evaluations: %d)\n" "Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n" - "readbacks %d, uploads %d, depal %d\n" + "readbacks %d (%d non-block), uploads %d, depal %d\n" "Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n" "GPU cycles executed: %d (%f per vertex)\n", gpuStats.msProcessingDisplayLists * 1000.0f, @@ -3485,6 +3485,7 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, gpuStats.numTextureDataBytesHashed / 1024, + gpuStats.numBlockingReadbacks, gpuStats.numReadbacks, gpuStats.numUploads, gpuStats.numDepal, From 5f13bc061a998e1dc1da937a0b6528c0b075f28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Feb 2023 19:28:16 +0100 Subject: [PATCH 057/424] Color readback: Read the previous framebuffer instead of the one being switched to --- GPU/Common/FramebufferManagerCommon.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index e36d838afa..401f79f0f1 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1040,17 +1040,19 @@ bool FramebufferManagerCommon::ShouldDownloadFramebufferDepth(const VirtualFrame } void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { - // TODO: Isn't this wrong? Shouldn't we download the prevVfb if anything? - if (ShouldDownloadFramebufferColor(vfb) && !vfb->memoryUpdated) { - ReadFramebufferToMemory(vfb, 0, 0, vfb->width, vfb->height, RASTER_COLOR, Draw::ReadbackMode::BLOCK); - vfb->usageFlags = (vfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; - } else { - DownloadFramebufferOnSwitch(prevVfb); - } + if (prevVfb) { + // TODO: Isn't this wrong? Shouldn't we download the prevVfb if anything? + if (ShouldDownloadFramebufferColor(prevVfb) && !prevVfb->memoryUpdated) { + ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RASTER_COLOR, Draw::ReadbackMode::BLOCK); + prevVfb->usageFlags = (prevVfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; + } else { + DownloadFramebufferOnSwitch(prevVfb); + } - if (prevVfb && ShouldDownloadFramebufferDepth(prevVfb)) { - // Allow old data here to avoid blocking, if possible - no uses cases for this depend on data being super fresh. - ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH, Draw::ReadbackMode::OLD_DATA_OK); + if (ShouldDownloadFramebufferDepth(prevVfb)) { + // Allow old data here to avoid blocking, if possible - no uses cases for this depend on data being super fresh. + ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH, Draw::ReadbackMode::OLD_DATA_OK); + } } textureCache_->ForgetLastTexture(); From 94f51d5d26d58b88e9aff8841d4629869aac1364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Feb 2023 19:32:44 +0100 Subject: [PATCH 058/424] Make the Dangan Ronpa readback async --- GPU/Common/FramebufferManagerCommon.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 401f79f0f1..2f4604f9e7 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1043,15 +1043,14 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe if (prevVfb) { // TODO: Isn't this wrong? Shouldn't we download the prevVfb if anything? if (ShouldDownloadFramebufferColor(prevVfb) && !prevVfb->memoryUpdated) { - ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RASTER_COLOR, Draw::ReadbackMode::BLOCK); + ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RASTER_COLOR, Draw::ReadbackMode::OLD_DATA_OK); prevVfb->usageFlags = (prevVfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; } else { DownloadFramebufferOnSwitch(prevVfb); } if (ShouldDownloadFramebufferDepth(prevVfb)) { - // Allow old data here to avoid blocking, if possible - no uses cases for this depend on data being super fresh. - ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH, Draw::ReadbackMode::OLD_DATA_OK); + ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RasterChannel::RASTER_DEPTH, Draw::ReadbackMode::BLOCK); } } From 9827dd536cb4680e85b4cf346338c698baa7722d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Feb 2023 22:59:46 +0100 Subject: [PATCH 059/424] Count listsyncs and drawsyncs in gpu stats. Eat some cycles in listSync Chose a conservative number (same as sceGeContinue) --- Core/HLE/sceGe.cpp | 1 + GPU/GPU.h | 4 ++++ GPU/GPUCommon.cpp | 8 +++++++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index c4feedd6c6..639791f687 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -383,6 +383,7 @@ static int sceGeListUpdateStallAddr(u32 displayListID, u32 stallAddress) { // 0 : wait for completion. 1:check and return int sceGeListSync(u32 displayListID, u32 mode) { DEBUG_LOG(SCEGE, "sceGeListSync(dlid=%08x, mode=%08x)", displayListID, mode); + hleEatCycles(220); // Fudged without measuring, copying sceGeContinue. return gpu->ListSync(LIST_ID_MAGIC ^ displayListID, mode); } diff --git a/GPU/GPU.h b/GPU/GPU.h index 4411733728..c31056764f 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -74,6 +74,8 @@ struct GPUStatistics { void ResetFrame() { numDrawCalls = 0; + numDrawSyncs = 0; + numListSyncs = 0; numCachedDrawCalls = 0; numVertsSubmitted = 0; numCachedVertsDrawn = 0; @@ -104,6 +106,8 @@ struct GPUStatistics { // Per frame statistics int numDrawCalls; + int numDrawSyncs; + int numListSyncs; int numCachedDrawCalls; int numFlushes; int numVertsSubmitted; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index fa26a53a1c..00c500269c 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -675,6 +675,8 @@ void GPUCommon::DumpNextFrame() { } u32 GPUCommon::DrawSync(int mode) { + gpuStats.numDrawSyncs++; + if (mode < 0 || mode > 1) return SCE_KERNEL_ERROR_INVALID_MODE; @@ -723,6 +725,8 @@ void GPUCommon::CheckDrawSync() { } int GPUCommon::ListSync(int listid, int mode) { + gpuStats.numListSyncs++; + if (listid < 0 || listid >= DisplayListMaxCount) return SCE_KERNEL_ERROR_INVALID_ID; @@ -3461,7 +3465,7 @@ void GPUCommon::UpdateUVScaleOffset() { size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; return snprintf(buffer, size, - "DL processing time: %0.2f ms\n" + "DL processing time: %0.2f ms, %d drawsync, %d listsync\n" "Draw calls: %d, flushes %d, clears %d (cached: %d)\n" "Num Tracked Vertex Arrays: %d\n" "Vertices: %d cached: %d uncached: %d\n" @@ -3471,6 +3475,8 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { "Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n" "GPU cycles executed: %d (%f per vertex)\n", gpuStats.msProcessingDisplayLists * 1000.0f, + gpuStats.numDrawSyncs, + gpuStats.numListSyncs, gpuStats.numDrawCalls, gpuStats.numFlushes, gpuStats.numClears, From 735cd26db62a77625d4edf782c5a32a6a98c47f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Feb 2023 23:13:12 +0100 Subject: [PATCH 060/424] Document Syphon Filter hack, but don't enable it --- GPU/Common/DepthBufferCommon.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 96ec6c95bd..2e69260410 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -218,14 +218,18 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x DepthUB ub{}; + // Setting this to 0.95f eliminates flickering lights with delayed readback in Syphon Filter. + // That's pretty ugly though! But we'll need to do that if we're gonna enable delayed readback in those games. + const float fudgeFactor = 1.0f; + if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { // Don't scale anything, since we're not using factors outside accurate mode. ub.u_depthFactor[0] = 0.0f; - ub.u_depthFactor[1] = 1.0f; + ub.u_depthFactor[1] = fudgeFactor; } else { const float factor = DepthSliceFactor(); ub.u_depthFactor[0] = -0.5f * (factor - 1.0f) * (1.0f / factor); - ub.u_depthFactor[1] = factor; + ub.u_depthFactor[1] = factor * fudgeFactor; } static constexpr float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f }; memcpy(ub.u_depthShift, shifts, sizeof(shifts)); From ecf82a90515960c47b483c4a3c03cf7f9759ff46 Mon Sep 17 00:00:00 2001 From: xujibbs <79200793+xujibbs@users.noreply.github.com> Date: Wed, 8 Feb 2023 09:02:06 +0800 Subject: [PATCH 061/424] Update zh_CN.ini --- assets/lang/zh_CN.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index ddbebadfd6..cb3aef28c6 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -91,8 +91,8 @@ Swipe = 滑动 Swipe sensitivity = 滑动灵敏度 Swipe smoothing = 滑动平滑度 Thin borders = 细边框 -Tilt control setup = 自定义重力感应… -Tilt Input Type = 重力感应按键 +Tilt control setup = 倾斜控制设置… +Tilt Input Type = 倾斜输入类型 Tilt Sensitivity along X axis = 沿X轴倾斜灵敏度 Tilt Sensitivity along Y axis = 沿Y轴倾斜灵敏度 To Calibrate = 以您喜欢的角度握住设备,然后按“校准”。 From 5ad111cfc4043ebc51de298074c3d1fc1941d60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Feb 2023 08:59:47 +0100 Subject: [PATCH 062/424] Return value fix --- Common/GPU/OpenGL/thin3d_gl.cpp | 3 +-- Common/GPU/Vulkan/VulkanRenderManager.cpp | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 95f43d9217..ca539f1f17 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -1001,8 +1001,7 @@ bool OpenGLContext::CopyFramebufferToMemory(Framebuffer *src, int channelBits, i aspect |= GL_DEPTH_BUFFER_BIT; if (channelBits & FB_STENCIL_BIT) aspect |= GL_STENCIL_BUFFER_BIT; - renderManager_.CopyFramebufferToMemory(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, mode, tag); - return true; + return renderManager_.CopyFramebufferToMemory(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, mode, tag); } diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 620e857ff1..55298b3be4 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -975,9 +975,8 @@ bool VulkanRenderManager::CopyFramebufferToMemory(VKRFramebuffer *src, VkImageAs } // Need to call this after FlushSync so the pixels are guaranteed to be ready in CPU-accessible VRAM. - queueRunner_.CopyReadbackBuffer(frameData_[vulkan_->GetCurFrame()], + return queueRunner_.CopyReadbackBuffer(frameData_[vulkan_->GetCurFrame()], mode == Draw::ReadbackMode::OLD_DATA_OK ? src : nullptr, w, h, srcFormat, destFormat, pixelStride, pixels); - return true; } void VulkanRenderManager::CopyImageToMemorySync(VkImage image, int mipLevel, int x, int y, int w, int h, Draw::DataFormat destFormat, uint8_t *pixels, int pixelStride, const char *tag) { From ab63689cca04aa334f392dc3cd4ec8c86f0bb347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Feb 2023 15:37:06 +0100 Subject: [PATCH 063/424] Remove bad comment --- GPU/Common/FramebufferManagerCommon.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 2f4604f9e7..68bb901968 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1041,7 +1041,6 @@ bool FramebufferManagerCommon::ShouldDownloadFramebufferDepth(const VirtualFrame void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { if (prevVfb) { - // TODO: Isn't this wrong? Shouldn't we download the prevVfb if anything? if (ShouldDownloadFramebufferColor(prevVfb) && !prevVfb->memoryUpdated) { ReadFramebufferToMemory(prevVfb, 0, 0, prevVfb->width, prevVfb->height, RASTER_COLOR, Draw::ReadbackMode::OLD_DATA_OK); prevVfb->usageFlags = (prevVfb->usageFlags | FB_USAGE_DOWNLOAD | FB_USAGE_FIRST_FRAME_SAVED) & ~FB_USAGE_DOWNLOAD_CLEAR; From abf76bd2121b8c0e22888ffac67dd4877ab4f26f Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 8 Feb 2023 17:26:36 +0100 Subject: [PATCH 064/424] OpenXR - One APK for both Pico and Quest --- CMakeLists.txt | 12 +---- android/PicoManifest.xml | 19 -------- android/{QuestManifest.xml => VRManifest.xml} | 1 + android/build.gradle | 43 ++++-------------- android/jni/Android.mk | 8 ---- .../src/org/ppsspp/ppsspp/NativeActivity.java | 2 +- .../src/org/ppsspp/ppsspp/PpssppActivity.java | 9 ++++ ext/openxr/README.md | 2 + .../arm64-v8a/libopenxr_meta.so} | Bin .../arm64-v8a/libopenxr_pico.so} | Bin ext/openxr/stub/arm64-v8a/libopenxr_loader.so | Bin 0 -> 12242344 bytes 11 files changed, 25 insertions(+), 71 deletions(-) delete mode 100644 android/PicoManifest.xml rename android/{QuestManifest.xml => VRManifest.xml} (92%) rename ext/openxr/{libs/quest/arm64-v8a/libopenxr_loader.so => android/arm64-v8a/libopenxr_meta.so} (100%) rename ext/openxr/{libs/pico/arm64-v8a/libopenxr_loader.so => android/arm64-v8a/libopenxr_pico.so} (100%) create mode 100644 ext/openxr/stub/arm64-v8a/libopenxr_loader.so diff --git a/CMakeLists.txt b/CMakeLists.txt index 32213160a6..a344e03c74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,16 +119,8 @@ add_definitions(-DASSETS_DIR="${CMAKE_INSTALL_FULL_DATADIR}/ppsspp/assets/") if(OPENXR) add_definitions(-DOPENXR) add_library(openxr SHARED IMPORTED) - if(OPENXR_PLATFORM_PICO) - add_definitions(-DOPENXR_PLATFORM_PICO) - set_property(TARGET openxr PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/ext/openxr/libs/pico/arm64-v8a/libopenxr_loader.so") - message("OpenXR for Pico enabled") - endif() - if(OPENXR_PLATFORM_QUEST) - add_definitions(-DOPENXR_PLATFORM_QUEST) - set_property(TARGET openxr PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/ext/openxr/libs/quest/arm64-v8a/libopenxr_loader.so") - message("OpenXR for Quest enabled") - endif() + set_property(TARGET openxr PROPERTY IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/ext/openxr/stub/arm64-v8a/libopenxr_loader.so") + message("OpenXR enabled") endif() if(GOLD) diff --git a/android/PicoManifest.xml b/android/PicoManifest.xml deleted file mode 100644 index 081b497ec9..0000000000 --- a/android/PicoManifest.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - diff --git a/android/QuestManifest.xml b/android/VRManifest.xml similarity index 92% rename from android/QuestManifest.xml rename to android/VRManifest.xml index 8958156f22..e607741e3b 100644 --- a/android/QuestManifest.xml +++ b/android/VRManifest.xml @@ -16,5 +16,6 @@ + diff --git a/android/build.gradle b/android/build.gradle index 94dfd3bf80..e910255ab4 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -91,6 +91,9 @@ android { path '../CMakeLists.txt' } } + packagingOptions { + exclude 'lib/arm64-v8a/libopenxr_loader.so' + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' @@ -105,11 +108,9 @@ android { gold { res.srcDirs = ['gold/res'] } - vr_pico { - manifest.srcFile 'PicoManifest.xml' - } - vr_quest { - manifest.srcFile 'QuestManifest.xml' + vr { + jniLibs.srcDirs = ['../ext/openxr/android'] + manifest.srcFile 'VRManifest.xml' } } productFlavors { @@ -150,7 +151,7 @@ android { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } - vr_pico { + vr { applicationId 'org.ppsspp.ppssppvr' dimension "variant" externalNativeBuild { @@ -162,27 +163,6 @@ android { '-DANDROID_CPP_FEATURES=', '-DANDROID_STL=c++_static', '-DANDROID_ARM_NEON=TRUE', - '-DOPENXR_PLATFORM_PICO=TRUE', - '-DOPENXR=TRUE' - } - } - ndk { - abiFilters 'arm64-v8a' - } - } - vr_quest { - applicationId 'org.ppsspp.ppssppvr' - dimension "variant" - externalNativeBuild { - cmake { - // Available arguments listed at https://developer.android.com/ndk/guides/cmake.html - arguments '-DANDROID=true', - '-DANDROID_PLATFORM=android-16', - '-DANDROID_TOOLCHAIN=clang', - '-DANDROID_CPP_FEATURES=', - '-DANDROID_STL=c++_static', - '-DANDROID_ARM_NEON=TRUE', - '-DOPENXR_PLATFORM_QUEST=TRUE', '-DOPENXR=TRUE' } } @@ -197,12 +177,9 @@ android { 'normalOptimized', // for testing 'normalRelease', // for Google Play releases 'goldRelease', // for Google Play releases - 'vr_picoDebug', // for VR debugging on Pico - 'vr_picoOptimized', // for VR testing on Pico - 'vr_picoRelease', // for VR releases on Pico - 'vr_questDebug', // for VR debugging on Quest - 'vr_questOptimized',// for VR testing on Quest - 'vr_questRelease', // for VR releases on Quest + 'vrDebug', // for VR debugging on Pico + 'vrOptimized', // for VR testing on Pico + 'vrRelease', // for VR releases on Pico ] variant.setIgnore(!needed) } diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 218ce2f8ec..9c7912881b 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -766,14 +766,6 @@ ifeq ($(OPENXR),1) LOCAL_CFLAGS += -DOPENXR endif -ifeq ($(OPENXR_PLATFORM_QUEST),1) - LOCAL_CFLAGS += -DOPENXR_PLATFORM_QUEST -endif - -ifeq ($(OPENXR_PLATFORM_PICO),1) - LOCAL_CFLAGS += -DOPENXR_PLATFORM_PICO -endif - ifeq ($(UNITTEST),1) include $(CLEAR_VARS) include $(LOCAL_PATH)/Locals.mk diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 869403abde..2a40786d35 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -1555,6 +1555,6 @@ public abstract class NativeActivity extends Activity { } public static boolean isVRDevice() { - return BuildConfig.FLAVOR.startsWith("vr_"); + return BuildConfig.FLAVOR.startsWith("vr"); } } diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index a025926d67..f544174d02 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -20,6 +20,7 @@ import androidx.documentfile.provider.DocumentFile; import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Locale; import java.util.UUID; import java.io.File; @@ -58,6 +59,14 @@ public class PpssppActivity extends NativeActivity { } static { + if (isVRDevice()) { + String manufacturer = Build.MANUFACTURER.toLowerCase(Locale.ROOT); + if (manufacturer.contains("oculus")) // rename oculus to meta as this will probably happen in the future anyway + manufacturer = "meta"; + + //Load manufacturer specific loader + System.loadLibrary("openxr_" + manufacturer); + } CheckABIAndLoadLibrary(); } diff --git a/ext/openxr/README.md b/ext/openxr/README.md index 13db1d3ade..2decd1f15d 100644 --- a/ext/openxr/README.md +++ b/ext/openxr/README.md @@ -7,6 +7,8 @@ OpenXR is an interface defined by Khronos Group. Implementation of the interface The used interface (headers in C language) is an older version because Pico doesn't support the latest one yet. The Implementations are taken from the vendor specific SDKs. +`libopenxr_loader.so` in `stub` is there only to satisfy linker, it doesn't matter which variant is it. + ### Links - Khronos OpenXR SDK: https://github.com/KhronosGroup/OpenXR-SDK/ diff --git a/ext/openxr/libs/quest/arm64-v8a/libopenxr_loader.so b/ext/openxr/android/arm64-v8a/libopenxr_meta.so similarity index 100% rename from ext/openxr/libs/quest/arm64-v8a/libopenxr_loader.so rename to ext/openxr/android/arm64-v8a/libopenxr_meta.so diff --git a/ext/openxr/libs/pico/arm64-v8a/libopenxr_loader.so b/ext/openxr/android/arm64-v8a/libopenxr_pico.so similarity index 100% rename from ext/openxr/libs/pico/arm64-v8a/libopenxr_loader.so rename to ext/openxr/android/arm64-v8a/libopenxr_pico.so diff --git a/ext/openxr/stub/arm64-v8a/libopenxr_loader.so b/ext/openxr/stub/arm64-v8a/libopenxr_loader.so new file mode 100644 index 0000000000000000000000000000000000000000..c93b4e444d7681f2dac6b53af4048a76b65c601f GIT binary patch literal 12242344 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

KCYxeUC!uQTB(d84=rYHMljl> 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

Qo~w(TfQ-buSbJ|L(t_Q>)ZMX_xNRzG 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 z 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�=`YnI7$ENYf5z!!zi{H4LD|PJ5#h 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

xvy8dRC!Te& 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≷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%0A;#Yrfa%MNj*63?y!5+Jn1Gi?*s5m_e#r( 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

-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%0D6fD!irUgBjAa<%`UD6gi3Uj)CK65rlW9ceHBpyV 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%0DP4+fVj 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

?e)eZi2JN} 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

C_1&_|O|ij>F5_zT8V7*5@hSjoWX@!nuG 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

xGys=4>8=5VVm1JapqLsYkBN_g~K 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

8JA#g!?zD(z#VU}V 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 Qt_fM3nS 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

T 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 ZdlYA%7iq0rm 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%0AAGCl`#FwClobn8Esz+|WB1T*I$ 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 &4)J5Ws{#;$;>A(}TW< zTLyV;o zRNe>I$l;Eg5N6}U2wv+77F~1qQN$|rWM2cgiJ^vc2P&W$TwrBhiZ6f?KgJ8A7h@}# zYQa1tKU~eYg}u+Vz$fE@)aUF9|Jfe;B_gmJ%L^$NQhb^n%Ky#t3ZSjGXm>_# zwcp095{53yYto-H`% zplaX6?~1ctsL86n&CZLnR;sSKaTi|H_nrPW%O@D$S$!AR1do{%P)1<~%5LcyY&_}e z#C<~X#Sk15&vp;ZoPpn=*?y7P&UJT2O$MT0a{tB1=eq8QR~NAN%G}Fm$?kw`whpHe zYd}hE_Y!oXqq~ER&4$X&E0-8QX5AI5vvP94rxJE+UoAK>?H1O&6AB| z6B1*XSh07Olwu2DFLx^ z-S@xdzF&gIxT;AXV@8iNfSVwXJ&T$QDE6dc01>QXa#ZGCgC;Wdx2f-vJaHF5XexTS z*%M`!FeIm0UL{zI0<_cvCoeI``F^|@%vN+aAMJG1Y?6mynxGL-81?`oPw8FQ=+XtC zi)mINEuC}){)wKUK4drP&==80_bf93ss9V;z+!b6R&a)tjB%^WeXIA8#p!Wqlz%_^ zab6iYi^a4+i4cv)bzCe|UrcfR(pllSID!GY@BA=ey>*UbJ0yae4+B-#IImfioEK9LHCm@FhSVCP?7G+_ZE9D;$5p;Q+(oNa64kmFKHZ z_)__wq~dUdvJOm)gP})&p~wxYg&y3_p6(!3&sU%DCBTCOs6@_)B?R`+>p2gfSLPle zaC!CZYx*?Xs$S%wtBFitAfjw+E$O4hjEIwL&N6<41r@o6{ep7Eo-&^d1M*1BCOk@d z^Vk@qgFld4ae#?$K*t5=rjT2Oi{ew!uW~(DBQ^#Ji}4hlSTZ^|i{+l}*%1YogaNxBg%{RZgKF+9)fN!XbI!IE)gnp_T)8(gLLv~~K-lU% zAra_JelIH|_ez_fFO#{!0IR*cm2CUGR24)E#p=5+M{|fy1=Vilyzzpi2oungs|Tox zx8P+cdXlSXal(4@=)lx_tf$w)+NiB>)G|Nz?^#eQ#3m-j%0Aw*FGi!ufyh;?1H?#b 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

CHv;1A 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 z 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�Cg+$YsaXYKyMhPt`E9t zq`E%j4#DcKgKUL^f`QyxVblgw3Jw%@Rk{w+&Z<(lOe%~CuLx-SUvjPYxdQhVHknPdLeEdqBSy;)DL(2=M^>L?I%DW z=FH16$x#rETOrLe(t9i!iVq9bWR1uZ*-|3bi@AO;>9`pLrJkq~gTj_%x3D@22#aiXc);1UqD#IH6m`9srF{el`HF3;V_-Xk_zpl~5Zbbbl2VvBfPjdB=UPXr7v(xj_C2UQBK<3^h6CkFaRg zLvw;|KD12Mle;-ESXHhksAg^=c2#P1e+w z^K-fy7i~PR(ZKESA)Vf5>(xGba7-sRqa~)vjg=GhU0o;hMfPQsEsGYS!>d#E7E*3- zFXsVu?i}D_{OJkg%pRl~l6k%a^_N689C$!s`bsopVtGZmk@e+~2S@;#Z z0F?HcofX>e0`zb-M&DQ`de#NxKIkL>#+f(6<8JVMYdfOzE*yxscGj~@QMj@9n+J05 zHD`2v04gKS5S6>j6jP1^hW z(2GuS42lH5!)3Zcw`9@p`vT%V@1l$!!|mD+ed@xYtuNHPHajm&>+cpwAya90aDD^z zui@3$HDTG=JR%`UbRsUWpu=-lzu8(3&yBO&^nSX5nn<^y3`ID{n8RQ+MH?wJQ8ypW z+p8ACn7b#K=|x)CfeFexYM$i8ad81hL|E!?N8w(=1+zPsf>*Hxr7`Ob2zT%26IeCLaNP(^}#{3;SOFFh1&ATRUKXHGV8yS2|}UI5jn%V4Xfn=_m> z-CxLs)qIK$I#E{FfvQik!UR9yZugcli~*NRPxG@$88ZttPB71*lH z;qGD;$DzaN4WEEY44y6DU+)si93Y_|*6O!(gIa&t*m$ur_9&T|MNFl5$ZiT?3uCrv zDY?=6wn;MuKR+I&u(T)=w0LDZ#awE)_6e92^?R8*I zmb6Do>cWbR8Id6^(PWrtmN;t8fb4;w8HM~AF-9o$N^~AzT<)pp48OvA(HVY~N2Buq z^}QUwr=cpmA)TjE$3xP2klbqm{b`FkP!n8^BV}t6D=CJ8zDMy0WVRsYm}aIz*6pyi zWuudzZ=NsS`f6WE1#9+pD*&P8dUX2Agpxv=A0$@;(o~iHoTM8nQ8kHTTqbI2s(WPk1nngIb=7=y3tlb#ij3!#TtlNjHf-Ntd6ZI)~@&<9r zA*QM)9M(xUEKUc**CRF^`Jx=B)qasG70i+wzzmyjR*%r|dH<1up#|WYfXG#?1lb&v z2bs|A=j(rwUuQKk^%k7J>LFZsO^M+A0$qMhhwsT`u}*+|hCB@Q4Sv*LG9bbgn12UP z997RDar7?ROKztN9Gu8xU0QH2MwcTT0)(9XWCOs{#bP-aUEW-d01v`zH1a0J5noq( z3kMe;FLCN$egq&JFB+%>FPP`~G$=hdFx>*Ce5f`=G0zE2at{c0p5<9W$t4ETVuo@R zIaQFiZo!MkYK4iOet)Wu(l}Arb^=-P$7HX|kC!(@g{_Y=eUeeWJjp1Vrx*oYaGzqB zOREp+mYD4EN#=6W;5w# z5)3zGvgc_{(m2zMrJ9k%k}oad{mc${l*8EaAm3olxR$r}+U zQo!6phY}K1hS7sl(79K)&NW)uCQ|Kyx@QipW9xocD!T08D9W2XZ^ekXJ79Ay*v3MS zy*uyh{CVqPcxOzuLOm@~s&a6G>@yfxB0}dO3awSvl}Y~(XlDlJ9pt~+5o{h>S~Q)} zvzN3ik|6pz_alUlz3T+=FA+uk=>m~Q?k}X8`jjaQK?F;7Fm;*BhghZaJIjICM*)Kv zpF-SuDX=T|KyYo=VlLF*T)fI~l@?jVFXI8%`}J=Fe$iro8_q0Y$If>29j>7d+Snt!$O3cTQc@oje+EAme7ypahf?F4H*_x_>P8VG>3 z;?%Asd-)Fbj-r>Ubtv1DQq-Dkr5j!tP$9sZz2`Hy?(%;C~Q^dY*WCJWu6ucnu-6 zMo}O78j6gorWZ>ZyV=icYH7IWu11KanF#R?x^>0DVk5u$U_E5>ns%I4kx>`H0bRn@ z4;yRJ7Pg(WX&0W-sN>4aJ>=^tCga^lEfR+p$au()s%xr7y%ZIx?vs|fW#R3lF*Z6$ zz1*pjLXTNkyyHV=sQ+rU+*n=@9hnp^QnU9r_Df*BgNOK{m& zIc^6~f+5&EzU;-TV~DvfOk0BK7Orn@PY`JKqE33+`J~^fts2yvD172Wz)!!<;btG{ z+1Bst9o-5e##fvx&NnYL>r#+hgZrg>PlN6C62=}0rH8I_JSTI0aj6oPZnhy-+ZE@ZOlwbE5S((vIhcy@qW{Gh(QO~( zTo~K9RGa@>k8uaERpir6f_iSjn!-e9tg8J{UWV?Qg6XaHJyEhbN=$h}qJ-Sk-cYv} z2Q-Z@VMi=}$+yVEGAro3foSh)fZm!*vQwbDE&K+t?zThJ4tKX5K-zkR%I=G9w}sv| z!0jE+Qdh9~@JaU=cW5k2ama^@zs-YML4z$!gwRg5E&|UR3fV@BTJJ!SLf)F7Dh+Cw zapZy%T-!DjT$#nFp&o zhsYc6m3-js?G#6cwV9(l@3eG6x~W>#L~0-RU~vDyR?VcSz2Lz#Td#+>O@VrkA0**C&Q=@TY{}m|AQc0x1jUDW;*$}f6g{HWe4V1N>|E<|F1qqqP0otOYxE?UmYn@+ z3j*{Ul2XbTp5|b7HH?o?nFtZCiRVDcD}oM|3s4G8FgL4|t|g>v&HA_v3-?@R)BqB9 zi;gq#=~4bEeZtMMh8GVw_Tc*2RX`TF@B^0{VUpts=bTMnanEXN4b}5JsJR^0*xoM{ z3a=;~9Sk7;ynKnaT&dluuQfpDx^H9ET7$L3X-?K{Y|VY-O=Yv?6gTK5AE*ge9t!xB zJtpbuj`uQUTGEcD4XzfRuBxS$__W2DBcS>*M=&?ghgkV3zeCs7@>k5*D#M-Lyc#BW z=JIV(I8%y^xzf>hrB@n6AH~*qwz#_F@IdEU+_d@YeL5A=_>x!4zf-ZmC5z=<=BqPs z2CboAEL{DFudn`+&=Mm>w?JmgOKH`NZg7Y+os8#>6O`103+cM@8oTs-#u`dYbRnc?`|II1K zq&}o86vt4kLYE53!zBAW9EC1U*++rQD4i!a8S%*j6rpUKY!+ybNY_OdFJEJc^D9&) z`4uVaSzk#_%e>rt8LJ z<%}KlFlniY1@nt75{)VcjRn$>&}5T|Pq7H0SIy_Qh<|A`>DjSsT9^5I+izYg;>k9h zaZ?Q9S} zo>O&GI9F%q7c|=kfFAX>-cYsGeEayxk6F68$NiW95zL}$hEGZpg>&1MuTz-cR+uuzmHwpdDA0{ilJN;XH`SPUya{u5@9Gv2b|h>$F{kDDPymH<@9Kk}oARpfK;^*rhPcW4A2@S0?R!4>LWu8Qa|5D6CLzfu2e_-BSKjbr+j%_lmaFkx)gGfLP9$Bp`sI=>& z5-B=4l}x03xoP=PQz51#R>g`1DhVpVkt#57z*WjD7w!cgtNRI6z^hZ$(vV)H<1vhf zHSC1I`440+uK9TGsb{THd8I^~sb>8KDu9bBZ7D>Dtjh(nUz@8JF6@D$D3X!5KrbFN z>ky$%X>hn?WqJTL_)E=KLR8_J9YQ>`HopaKu2SO0QO>FIoH%;}#glc^k z0%*RZ;c6&Cg&HTHSM+bEb30%x!P8KMcfmPQs6NETBB=zlB@u+(85U0^kixP`OPOnW zP8RE`DIXr38w;_LiFm-*5@;nLs}4*bg@kZ7eG=rxF#VQr(~zS1?k#yP(KE%o(69D6 zE4QuMH5R*@G9S95b5gqy91br9!c6S~@$}G`nZuh#Lp3VIr!);_NxTOJukeQCnBGTK}TYL4S= z`GDOpn_XEwGiisac%qguLxC*)Y_g_7Tb=3~_y*8IA<yBQd#3G93P$7WNoxwoYf_gxJeBDz9;| zNm=m7RoB-TavQV%{;44uXTCbPyIwc8!KqJDkb*XQJsHPz-1}t(lPG@xx?1S)ngF_1&Hh^KzPg z;PXA>MD2@ZqbB1ykxj(Bhl1*gY~fOQI-u5zIZ_+W&|AJXnID>{&9Wvt)$x#c4{G*m zuto&G#(NxM#!?krN~faI3GH)}j3m4s+8NNdET%QGm=#!SX+@QxCbff>qct;UL#bZ3 zm@Up&j}s@~A|&+cDWoRL5&=Mh%KZd=j`x!>f4{PA9&rI0QL4CY26#Mg7D4LIQd7Gr z%c%yRSVNWa1+s=MzA(kKHM8LITVv`z5yIND+={R3lft{;t$DuVnwy(HNSH3OtG#FJ z^SjPIfPL;cSN?1*xLPHf_9e3Bpq!^n!WHT(dwOX5*7WmWFIeGyLnmtmj#jI##wE^q zpW~!|k|dM)@_vH~*vaO@EZa;*!*Rfu!V=p`nG^Cn23DVJA#(b96!(Ofs;aGNU$KT~+sgiwcZBASL_HD`% zO+4fe^B`qzRy8hMVg3J97o7Pmbj@3u5z?9bh#GQL+OpGL*Pd+|A$>wk_RjA!?J+QnKY5I@&yp;JA~5 zz6EQ#B|EjYCxPU0J?~o?ed_ohqWR$*64v#|g=SEn2AcI#*Ebg$w3MkrUOH#$C<-_C zPmp(l%(5NVU3l8v_EQ@toGb`cQ6b0&@>%*lQ6_Ns3hbDk=V5Tf3KOPmEoit-Pz`^fc##v0hjoVNt8 zo2+%BS~xuk0eK?_$SA;sr~?xxl~AGpR4mzaNv4e$=4XclP3vNG5CkZBC;;S(Nxe`L zxH>gyr)t0;-$iXTrIG~;w`lq*2|N!+g(re=b46%?1W-IvSR)KwD7U97r-%IaldiYv2nKR;~Uv3x>5 zAg(|y>ceZMT!j<}ccg~;u1}A!CTvIH<4;*GrmnC!Gb6gVdW-Fhui! z=eEayEGJgvv$hZ_0h}RK5XR)?uASRbL7fVd!Sy{E9z-QkE$^YlPOZ)GO5_dg|Hzjc zktaM?Lb6oUZVAxTKrU||Dm7W!;8bv}B|uBH$fA~8PAwd@w`gdaeHmp-go;bI4c3&j z+dekBZ0k*7nE3`d-H0gz%;v*t@mcu9SQ>b9yE*@xbA8QcbUhv0^Duc&pNP~KN|@(d zh-6ZrTfrQ@_T#l=lG+3`Nmfa|61yyvkr7x-J~~QQ3!><~ZJWvbtbNzN&;v-?;$CK0R@13+e81z^UMbsn_F4qqB3#VrF$9l0%qcq1BqA zRS;S-1Ve0A9a;j-B0-LD3k@{)V|l3(OZ_Yxqo(dz3c^{bpx4eMTM2z@qE!YV$11O) zE(ly+NZoe|sT(n}twcyp?wBA`V6WA}i#<|RE>%JztVT^|xlrJqvv#Uv8s6-OZ5LAc z%l57Cr!QH?yOhmW!c}=~MY?RudfC(gX{OA05of(5P<<63k<=gpUz>JcDAB@;OpWvz z?|YoaMxyEK%AoNRsGNMEJQ_bNn_UB`G+v@{$I(DGO|8*tCDa6le!`rZ&|I3N)p%#& z-GgCgMXds{5-HhaI7brHO|J1y6z3G%Mm6)IIR%OYVzm64&=OifGcCo&I}et1+sU#C zU|7D_t=+49S7m~~)NQ3KN~`?LkDV!~)#xhY#!JJ}@mKKVD^A$uUNRs^f!+mY(CIWwQ(&?}F0- zS1(aXv%Q)n>3GL2WivPbp-cc<0x)Rwm$8rT;)qvhSIs|9T6GsHqsV5-RL7d64hJEx90KJ{T@yR}L4sXu_5nB+|zDF8ZY18g?f zQX_Z4YweYN>bHGr)rH+6+EP7~u8?$3`6(lq)SN5YcUGh9iIhcIJ!jVkbAQUGd4aOK zaGs(j(yR!jDcH<(n6eRlq9!2N=y-=5uSfza8?2!|9neRtncK19t;}66uciAqyN_s8 zHzBBuQnn>6o4D4_32F>n&ah5eP-Ec22hc7vsBADcZ^J6C>mw^o4l3DQHj@SI4{PCS z2&92wX;h~OmD7XvvlW?XAKj~$B@`xG?L?uo={imXN8DMi z1m#Sw!)qmOGq^Lo-GRdB@|jaZB9>g9!$}aSX?P8Zh)tqOR5eIBP%_Bi{sTgLTFMbcjaq} z(MA@zeq;0nrB8Fr_!E&bFK))hcbbV!Poilwzt8W|2ek-?Hig_?TJsU+ZA|K=P6;B{ z9!^J^$K@3nPIyUJ6LL~ygQp4&+KgzLYHnqQl?@Vw&gLz_;&k)r?agN7m`71?HSSq< zhESrFn-)b_|FW35Gc-U{p|x

Ob}N}dR7)C}^wmTS3#C_dsWKEB`ePbhFq?!};&oGf zbUR3P7K;)p3p?0fBowD4+xgqNQUS*RDa%HsmXUGQUamTVjxYo`VjCrTOXXD!DA&!!DSqN9%BR4Se4zwA z;od0GqbYhNfVr#9N1_X1OGs-QY3l}Xks@t2r4%(M9H)l?h4O7|T`mkl#5&!a;saXKZ15_$e&w>y`Qj0?!= zK2#dlc&i--nr6t$Lyj=L0VsA3{B3?OOiDjc7owQjE>y17z&rol( z2{zY6OOft}okb^(Kq<_A`5d_mMH^!EA}L{YKvkm4*`Uxqz% z8DNN1yQ6>fUpc_+$&6JP!Y1=6mCO7%=WKe_{6g1>qUc=T>`2wWcFJaJ2G_R_yaH!5J@!n9}c50X=-dmMKSi7&?XwNRogK>77-cL8! zfppvCknc`~rUYrTpZHr_DS;zz1T}z`iuO>o*D3Db5IrjzcjGh$H^t??+y%E;y18Fv z>)v=Vx}V{a4&)Y0r?>{}bTOk}*S(wUZZbbxjNqdi(?9EbzMl5>e%jkCK4o)yvj;VO zm5Sfr;abJsWIoy8ro?M{;Qgl_ZrixYR{RaXFXk9zHcNYSd*^iWuS`CM5niuW>0@tn zzrr278~(g^laBd^Yuv}%8)qZvDP#F>BEnJ(4=?;cxb~J)TqeSES*9E8V|*h1J`9yv$mo9r%I@y(6B;T1>E@Hbc!6vRt-GP_78tKKTx z(AB0it==?UZ_X$4>}r#)HdOXEBgDr)AtsmJWj%;|z6xU9!?Y3Uz`~7tqpQv1H2WKF zh8cj!V-V+E_IU~*K#aSxZaY={EDXAQc)H)e^cj^P+6_?KN}$!rOt&Tt>|axnpk z;5lHzGne7#Pg%B17C=5pmK*$q{g1ytET*(plQsUDFK7uq(~lTENiaVCrpw?GEKoX{ zY#!-%;)GrLdOoIqZs;M*0q?`eNp4q|u>Sm*;En04WlF3^zunJf1d2UQ`1b?wrSDgh zg~Xb4W_*MsgC+R^m862~qzHiLX3Jcx{!euqs50$jjg*Mw%a`7_-+rh6fgr(#O{d>| zTrcLMS{9yv#yU)JGcZOs?SYk5`-wIhSE@D18{fFSl0g3MP3b`sc zC*YEpr<(z>ylf5i>NcIOas82@OcT8Pa%+(>#asF1O9@maQt`*%TQBn%=7C-ZK{Ea% ze!9=U@?CE6#dkFuM4|EnCRcuuGN)4ch(lh4I|w3vSfq2jE%G!wKxqyH^T)l-z=0RQ zOZp;_sXv>yKy#LpGI?R_ z3ha=R07fd-veczq8#<|526FJ+k$pWKjB{!}-H6K#tsi*iWYEi#52TzJj18sa9DyQo9Fgg zic^72pIohw83-bwMQ8Mou%H$Lu4hIi0S#_)IfCxr`hiIoa9c+ni)(9dun8%VvMs^l zV5+kVt+j04b zXj4mhU^c`7qO4SC0pNMDwY8lFU@#pK3}3G^2z#h#35@fZaM2hiQjDR!W7%xXJRX@3 zcfZ+TmDJQAJ4GY(eGw7{bo)Ra5E9x0vM!9%3glPQ)f|%~ZnT6BB7M8H&=5f5KMMF5 z5+TCI8}xS-&;=%roPJ&2dkrL^ zYUN05e_MS2@+F&9+dm1u?x5?~XHr)oH((wU*0-X zO+O1mHNp}-imYt$ClT*NOT}>IG<+_0tcfBK@VQXjM}Vl_p7}aS90UJ?{Mi~UF{ zk;yz!s2Gn@x6EfqLUoSvvaA9iGjLGEA$^Gj&xlRqq=RPJM5QSQjX~*K>p7RuO-6Xm z6K2oiJamEasz!m0({vAI;vhXO3uUnvZ?zmWIuI-x{;vMU8xAi ziZnj8BjW(K)QDW0i4Qw6+EQK7t++Ty7my>Pe6*4p8@fVdt2G)EAk8^Nt0GfG=xi9J z;xcdFP&ftR5UON8tQ(phrESeB@**7|@85A@#-Z01K_87IYZ=a;NO+I7Mv~)^+7nwq z{BX3z#WZZWs8aJp1*WB`7!~|sHd}5UE$>7ePMLfeaOy~GNh9G#-s^j)0NDz@3UFkE z54mDVnf!6tLW3O{?E|XI+78wl=-5b872uYT&Oy)br&AR9Z6+hqlC`p&1Nw&3VzdvB z>BCDD#q@Xsi=w99C#rYgzu!^89Q`_+kFziQ)7$K^H(TGKykziYlr70{VqcDErmQ|Y z`1}DofqXv?z~prw|KG#^_wm7UwU{k7&{Ss2SL4O~%@hgWWRS?eDFxijPo=AwQR$hj zCL>XAG#-FYH)zW^_!j`u4~9)p@;r+Ew4{NO2bq3q{YxG+s}f2c{8)GBY262{oVqZT zzSMLo2TIc6dJ9h2f)fZ&7h~euL~7kwk16 zMwAfV1c zzp7Oa$^gp>LQ#h3gwg@I1zw>t(CSG^(%PG)GP9D;h5p_}y7};Wb;q3mi23wf_yds~ zTx=iBACk9Fu-->6yD^n&z=5&H?x0rhzRh1&QoeHB0&B{XHAG7L6zO`4Ym*9bEhEDpMK)eQR^8unI-2B6~b3T#%p~RHC<42oAHd{^74N+7m?}pQ*ExL3A1(zVE=&p4) z&lw8(1l``Ldv&@DK>cqLbAYJu0}}{qFQh8On_lDLT^%t#b)RbT{Z@*bYNsXVWfZ2jkziHjhCWogzm(s z8e!(t1w@}jsg2m40}qk>4h@xD5x&LgW-C_!zp|PNHl~^Gm26LfBOGPa@~q=Yrocql z$47WcS5W3n3EPgBIk?r(3i z)qrlyqr}?vayr@MAJVNkls02I^@EXef>Ag23x9RPz;bKocA!y2(havlxhMP&%^G0& zqP7{9oCtUqVuoq_M_;NMWSg6W#kcuwth4*@l8pTBZU`8sO4dab5dnfNt zueLW}eR#p3bu5s@0=0)|N0|%h*nyHZ&=`nvnb*4^uu z>OfM>w-g0G4PFfT1stv&CS2}%?E-k0-CAP7U1hujWX;1B6)qCz$q^?ocHBjA5RMBL z&N*#E#bB_I!>_~a{Z^ylQ;H5fE?+<$(bLLAfxqL7=rW1m2xP*A)5@a}vBmgqVpxac zrdHx!eE3g9-N5X^qsOGJw4Q|O8|6?d^(S`R2EHV@qvUBwMH!w=$Ip}WbRUbyChcO8 zHgt?}T*8%)DhI={==2OM`gPVH2j<@_0^`YV+{|GJ+(0 zv1c2D-G>J=ozMBUa&iZ6CU^IX`!)Z_m#Pd<8isCG;!nrHXy>cJaC@`e(W5c;XPCx1y%7eT}Os_0DIK{vPMyHc(Ph;arhyp#yI@wpQCLUgKaLU`7KTzGlo`K zvKk^Nwxi-GSSz+;vi*`bC^(Kcs8#t3=@Pl*I84TdLpw)xhZSsAb{v=5ih07SF-3-S%fbYj^7&r#g*Eo26;Qdo?zRFE%lLON?C&5AaCh_BzPzx_1v}>!Dd>GdO^6yku~d*S`7O#9wi=1-mwLMU1QvU7G(cSr;Cwo^+W?%(AO%f zY=9&Vg_@>PB4(?jbq5X$dC}sI;H@M+ZsHT_ zIK{>YxSD6TWz^hZvKAd~oUl6RI+dSxd@+BcoH?v<1RbW~S8TZ}T|*6|j>zBvqdEo7 zCBquFdb>g2+YRO0f$?XDBiXMjih8-TC5u{MDxsC4Tlkh*j8L!SxdCGo**>*OIE4$M z(-evkb>-hq&kszYY5lX{ZX4^mgH;wnhp==mps78geOXN17c0x5L#S34M2Ft2EQt=j zSXmSudb6@DI{0E`VRY!t>eA@Yo5+x9P#mpus?xVwNQfextZhAvR8~RV08Uj6bpuf4Rn!dtd9yQH>{`p<>crvx z49_-5DOao+8EOG4klxnoQby+W_6F zF=CLUY7A6d2dal7PNdXK?ZS^Gh0#udUJE9u0DtvEXO7h!s$B@7il)16Aq5Cw&+Z#i z#tekxvXcZW&6sSlwk>L~8|;WZ#2w12u)C9%?DeWT>;?$4E4R85y9vY^wb)I-)vw0x z3^fYxYlYNZH>CzD3TnhVS`l@=(YtL=6J!kG(IN@=0F~KCZ7Z__Y$HSLaK1MTv0Ejs zP2k&M<8+YAgG%Ikx=wH4xI|4COgva_Ui;P=#}gQm2_Gz?nM8VI>p^hh|sLOy9s37 zlNE^vbdYfvRda7e!cl`52gQIVxFbiEb=m9&S}&b;wfs)7H8)#i$X3C(W!A<*+Hr(+ z1YEc1yUDf<`5rr=+NSWk3DSP}v3UfVk+1kWCbLk+oPUgPHkX@C)px| zGh#rB(4rK3x&`2RrQ$CVMBMVATc_bjHmEx6l49|ILg32{GK#Rv%f*{Og%nVTRuzml zfs2JyaP5-u$RgwW-fx%pDE^;igVk!W>iu@UxSNdfpHI2r>}K6trju1(to}LIS}9ZonZ}DLE}gi1i^UQ=Ht6LavKXv* z7K~s$c0lnY?w2dUL7Em&P^tYXqoH}oO@0qZe-D|flTotfEixRvyXu3lMjz0Cce6?- zoAq!+?9|s;9G_54E`6$rXz-(XQ~NvAnGdhdutU(NR}S7A&T$p|nouuL>+j)CcS4Q7 zd=C5&2cdauxA@>zF2?;GQVb5>PSDG`rz2@ipr1#Y$!}*=NcJRg*$9qDogh2c)r6E1kV(B3ytU)*-%*8=Km7j2?`cFBFI{M)edO?@j z*6Vc2`CkK>nZP@w$@^*i`c4d6Xp zV9#YZ?x-aUnkRs3o416q_G+Q9`8SWLAmHl8moJlKoP>pBwz)&_AVfF$xQ@v!8l=t@RNuZb-B4i8J(s72Y-h=vT!xsh#{k2J!T{qL z6Ns;Up5$wqE|GWeCCK?1#(R)96s(qunpzgI6dSp(sAn zExh%L9D<*e+*Eue87V5opA`USU1)~`PMBK;bq%@SDg0Aaw8m;(!D6WlHyP#>dO5?pQ|V- zJ2_v&PxKQX2GXl$BM^a;t?m4K;>|J!%ekvq1CVx_kwLQt$EBHRsc8;lZ3)b0lwxmw zti5V~QAk5SYn$edFtlOx?C}4dLw#4=?NQ&s>b$X)eW8vayW^H2SGPc(Kf`|>8sqC( zJ-_cKgm)~~A=>1zg=PqR9fVWJYo}#p4^Ifu?j|)ssK@>^oZpD0pmT1-YMWyY4>hi7 zG*`Hpx*@d-gL|5Ruyv3qE(x+@*(LG9OFAg6^aM!`4tG3U6w0f%z>y+x%ZSh_(xX7 z2bv1bn^3p zVwt|~r1f~c^116tA{kOvSm!tW8QwXNP%z{q&&Mda{>4u0v~z;QD^S=C=hAa(C%)sC zLn`f8GSZoSQGRAW|FS)epe;WRYA@B*fXMmo>W$iSU;h!(WpdAQ>^whDKIMs4e|b&? z?-laiJ_QBgg0Z_QPaBEmT}t<3`6^7GUFow6K&|+?fJX7lb%mH$Lr=5xw)|P;i?IDQ zp8U^ocAMT$H+kg5w3j(i)BI>V8LK$M0uF6+^e01zT zGx8jazez`*KBp_>rV&*^R6SQDO&5!Evb#zw!8~PTFyA1v1eV5!ll z#DnYAejmvvC=Pj;fS8Y>GEw0(K_S9WdwlSq@=#z%pV6N@BSpP}+%GW&Lwq|+tPxME zG4bs)B7$0Hk>@cG*Nf!=sbn$Fl5|7&`wZXY)}ia5DjwP@VsKI}@7Eug3dtI|WXY21 zUKp(hsweV(zh#t87dfe}ao_Pe9c@r6;%_5$q$mxZ;PN1o{9!)U^lR|$8|7Z%jo-$- z5+2I*nP{Vx?hMZUh6t3n6uYj3`lfbM#>E>}n6@sjz4Ia}wuuVkWLypq0W{@O&3Hy>7u&w4Kr zW=FM2ot6l@zLp5Py4lGs5qb{Xf}cEyUQumJF56xVzKpUZ*YdD1a1-G5=?T+)e zGa>$1CXfW2^?cuyAoN}bYz=J8^SpnuLS;g_HisO2MAsAhW5K?N*UrbE`rPsj?Krp* ziRJKGulC44#r?8afgvv$d!?>5A6EZFK7;NU=+Z*{Gla_}cZU^jD^#}OrVQ#UmRtSQ ze!|wU1x6n|4!AD(kV@;|vquHE0v|nv!8Ew`XOsC5=umhbdMN(%@QIOb#V_!N6Ke!E zgG%v&*ZrC*$DAe38!F*J^G2}9SFvSnL?zBi;dEzPO*qm8*(e1Qwc{uI$*04RYQ1@X=2w z1@FE4saz+e=ZX!YFVfE&aJTEQ?y_G<{dM*WQt{CmlJ~E$l$pa{zWif4U(6q8i~BVq z1SBMO(#_7d-+rh6$-cm}n5Wb4KCTz@(Q^468l_F|#~J_r-2)|^eEZ?$(cbaP{Xdx- z(4B9;&jbH;F&$^CXPvo*M-|d)<2@_Fa`*eNMYSb~Eme~`{Ck>q;h`#-%L&hFYtXrw zjgV3;1VJ_yqF`_XnQ`&)f=)u;_w>Hn8q-avA4!Y8a)TS*-7J!?6BJ8d_mgXy6Ut6| zi={A>UxhNVv<+g#%}U$;1cGA5$5ojG(uv5->6QUzzdkjQ{_DSfe^hdNxB2W8+f0G5 zXFc!df~}8-^UHL8mklSA!Qf`hoP@HhfFU}VC(D(*3v{W-b!7%;Z+vR9VYT@nUaIBeL zx{N^-6x@yU+I4a}T|niY-zD5O2!;6S44UMj&-`px8$L#DmVT0Ioha+Lr|9sn@%rk}s<=|o@jU~^w#;Qfe(^;GYGP#DAI#z=%&Q{qR ztvRtvM0<+&WX#Z)y0Epw1kz3URjs>4(Mt$@*2O-J4K5{ z@9z%RLy}FabUGOKieHo<6zaE9&;Y?Q>CvT1go=we#|$Jp>7r3AD)NAmilPU?s-t+<`P!VkEdMG6SdK;D{7w{ z2}gFvVPuFP(=qhq6NBPG&FBz{yU?YnnG7S*WI^kERXC2EuXI0<^JO7lTMJbs+PNPz z3-kz3b8n9xh94k7PyI2J1a+u+h{JZa%8VFtz+Htqm9&%)0x3<9by~PsBs9qd=>o%H zX^Dr>N6h8&&O}1+%v^q@5QH^)@is6+KG1~~PC??&tGuT>TL!ckXhsgZ938NwISxxR z7;68s_y(2Mm5-R-k$DCby_1L4BzVHXj#5k{Qvat6sp9RqvjxzpW+1ce@&nS;9!H5oSR_~x8wG4|R zhl#yi4J?QPuF*l{ zMb4IJy}!=J$i|(lI7KYx3Y|}O(KZ#9F-|Nj2o9{^Y8Vz(Vd|Gs7LIU>vYKZv+?`Kx z0OSLUL7^REUjn<(D!OCol8UWV+n!_b>6J}h+!* zAqOO-d2zo#GbKp&esxZ_7q~Tmcx!R1^%~RZT`aOlAsZkM@{)p(>P2&-G_ zXv?6<0pc*N21h|*^1SFrroC0;oJfuW(S-vmS!b0bnjn_?RHM!R)~Pc`f|+9|p` zf6gLrR^mBxS36*Q7o5{1W!9hS7s^s4M_+4`%zei!9hTlV#D!(jMLP#IO+vMpK9}@Z2dk^X&tI!LY z=3+N>C=E(-p{gy;%GhRm%&c+Hka^mp?@2GCrgw=9iE25HGuZZ^$4_stDe1x2&Twdn zIjf8!O`^u2$^lMVDsA`DV1t)bGQA)$8UmBmfaO_AAx9g|-u^WEG8rx4%U^y#g5H#E zKitWqrX= zK$@A(7QkjNQ~1fSOZK4e2gEJH=sqs@E7t5YfmCOED8_Muoy0IbPK`6|?0AC_Z|K`LC8Tvce?5#y+mkNja&PJkslBB0{x8eo2F?FzTU7Fh zDXN+&s@A@5_OhepBG%X8;I&dCDoHBaU`QDd#>Ev;oPHs?Glo&bZ6QN1l-@F=g*1Bm$)Jx^AeZtpCAh*>D6}XW17SQSa z)hHBCp!CpmrOu;hKvvWX%APmW8!g-_s_^tMX<39hkGC38V6P{>nMd6^^xSDgTuLVn zhPy`D#t`Y@oL@m*kyYagaVw|@chMy?NEJ8UFr}RR;wyDcg|%Z;oCf86<%1ey&hdD= z5sN?$s99e2z&&Hi;xS0$vEnfu92&N#xSm-C3A=__g8bVnw^{gszscJ{f|; zoGCz5@ZUHSrJ*9gr^OYKT}q+BffLx4IRx95I!^M!0kJ2WO_IG$XLNm;TzLd==vgbc zMBhjpWGIE2%$N5Y<^I-7p(xNGm;pbLNI8^p64d6df%HWGa6GxqOGFaBy|fqHbmr{r zec4P1S{jeW0bSuL5u`4Ra&AvGwr@W4?{;#!C4ZcbA5tpzp>4H&rhK@h+7lmVA%yMW zEFD#_?^lg1QSj(yGM=n5(Ta1bc3HAX@1SBx{B4H)UHkA1&8enjCKiy)#`n$A2eq7A zMaBoEV$f}d+yX&)&z}9TDYA2@x`E~eWoeu(kuQ|ZH!LuDuOYd(DF4Y@n9IvwMQ`4} zU*q_qP{G||F-}&HmI-R}a*?ZV3>oFGeK58sKh?nrRgVtV>WI6y>`4>dqH#3(I@peF zRl?xiD>3g!qcV0|V+mw_x8&LOnhThTT1s*TfG@$SPz7BtbL}l9(c>JhPy#VZ11&w# zcO=GKmp@yJ63hyUFm*lCn+Wbn{ZXU_UAHdftZf#~>sA_@KRf^H+i9ki7hKb)CbCHW z%2WMMed}LtXK_6}RnC(2t0igVhH`zqo=i*Hx!#;j%EdgSGsVfo#AmwUL#HI4k8kbt z>E}eqvBSRV99zCkoR$K5$r|lr=4004Acl<<*5!h>1oUEO4X4b-P$7_?^!zjkQnsff z6G%_lgeF)fwJFy=EJpjz>E?Kkm4;a?xRwP<%1{_QHnnwl>iMz;^@Nxq?y1%NBj?Y; zk`8$%tJ4f`D4QGN;wEnf@(vBd;2jW!Ji1IPP;}g>wb7|^UkGG=NG>HdZCaCHJ|9b) zn-oh4dT(zsrM%&$Zu=A~>4>ql;bP%iWM*sHL07mQ7mCg@{iD2iFu}bg>Y_t`{sOiV z*hpT7$k!X-BXUdIFv{{hY?WSLY6;scpevG1FkI=9Rd{#nTzqJG^lK;==;}`SUT=UJ z$W!C`!L#KxX#wv*x#1i9Le

n4`(4Z_a1Xjw(hc<3SQPA08j+y-=75rE{D%bx9!L7XfwE2;< zZ%7h_JKZJ6OA^9RmF^z;Gy_?>*xBh>k#6P00OAzuiJCR5h)!(~T2i~a4{@PvDg>pr zRWl^nQK(crR%oVQOP3jwtpXmONEGv}hloy*&IJb#bzXw(a@wzzDbrhB;cC^|XS|Us z<|#-fkMhP^=F=ooN4K`l$dTk$f=gg>0^IP&3N^DD1@WWWL&G2Q69d%2%=pbW<~FOE-nu* zhaF9mgXY$(BgL!7#BQk=(+c3pW^aLc`t~J^vs2F{r)2zKxAMghu3t6)zm(zO9xZVW zn9FA#Tk&S)iVOr0iq3SwUUn4dp%y>7nJiNRylO&?xV_o$*O-4`Rcq^YWovpET2n9d z(iIK)-1WKmSJFF{#hvV)2+TyTqlflbDR~cv;#=q7@{Vr_N!8a8$Cedx>;O+)bQE=*5BM%3~+{qwYZ!z|%OUysoGGmk zjTXzt;$~BESvl$X`9u(9KSV zKY5G>*0TB(HG7?y3t^2_sCdCcI~;;+aKMRS{n87x7uVkvBEmYP{FI<0ij2a)oWK9! z^*J>4`#qo&!s2d2ta{1YzD;(zmXT^MBuI_ z|H{Ni{L^GDJN5U_ViLDU0icMr<+o1cSGe^ioAY$NVcZzPbj@T0PuU~CJj-S`*=h|~gZWsLKcS&KdRneFJv1PtI6^OZSZ-GTf%#|Y>~AXy2lmzr zX3gxI~q5s$^36| zUm}3N^*}%V5hP!%9{Y!4r4*)UIBk7mV*A7Wgsxj61ty34LdQD)+6T7$jT5ZcWSnBg z?DArwa|BEv?;B+Dg{h-R;<(9cw%(_?gh%Q3*V*PQyG`$>o3(*l+V7?Nz4Q>gFr2?$ z-Suv=yUF|=vHvH8%U~Yk(v!^|{uSjoDw!a(V@Gv=$9cxz>~O2F zo__Hces=EuTCYamp<0hc3ts>R4Vp;90%nyh*S!zf7tk+Xp7R6xb8 zF+=;?-fusGEvzB?yTyll`@-)1@7F(_n`1rXwGPfVibe*UT^~-^;J%N&5c(%B{&?U0 z(EGNJev-sGp8eg=wCrNb>+-HweBK*fW)rJhB8-seQ$=!#|Pw5I9 zk&09KE6958sj9t&MPP;)+slAE{J0|Y^@jq9?&4Iz3k=xr^STasb-+&AZ=p8?x&AiUe8}G- zHtCKjk6b_vjD95e2$=d8^8~d4axU`6z@vNnJY+7De#np|6XbjMp#aeRJss%lTS!n| z&iC^xoJAyeOundkIxtNCOZ0yXz`}0VrxL5q<(2)rtG1-1HiMxw@7|v!GV{g{oFML=9=-L9AacGZb(7UagQ6W$#884`qYd zqM`KJEeVCPF+HNdLvCFlltHU04az_?-TP&*syBG)+uPXFBOLal1-d(2J;D=vbM`ea7%;f8`E z2&b*|2m-7nLX_ebblzV093p5No?r2Sq*UZ#3VrNtL}>O6GJHu%?wr)c!VWGELJ}x@ zB{?inAmQeD3C{u)_re=A7>uU4PYV~6TlsauiK#zoMm>TABX_QoL+Bm3XujT%irt3r zlh*M2SJUE~oxXG};3QHD?@b`_a*%HhB06(;J6WwAmWmBID#}Nq(8=BgF>p3OM@5>$ zDF_I2_Q(j16zxu+z)ow(Bv!V*S!3?o5@DuDuMh#WBX-7(m5t$@&B-#*-Paq7T(94_0|B79&RGe|2V&}I3mbH>^!UyA47&T?XXO8 zcVo{K{SrLe+G-C|E%~vje+%g7aHrRiBM1=+r?m5U_>{*xR4c`2u-NJQ4-^2qUf_s^ z=`om!IFtNc8U5$|y?f+c%FhS0OWZ20f1;l3TM#)-#yi#|_>OkLrUh;Mk%Zg6;Skq? zDtju#_YScm``w%Jm#xRSvxh+ZMNXvu?|!jidx}U!SABXuSCcy5+x2|?j^3Ny_}+Y{ zUd`S0G9iMIke`{?Cl)?-#5fCgUjDH0S>JHAnqPTLemtNlBwZp=N?uOaT2D0INFqq%Z=&C63=ca;v429Svukn?!sHK z1?A;w$eoXRRu}}Ct_R?1<&GK6K#zKJqA11j;_lvdv_q^@3Zk`1=Fwzic%bp#dr! zUTblkaDNX@c@%H*AdiEaJPn6zPnBHziVntac5W7nDIIl(ll45E|D5Vbh*}JUv}L6H z2x%7Y#CYepuxm;^$<*?hStgu^z=~@|C!a&%Wb<8a1eAkT*V}O85(m zLCnBK@ZeJjCmnmV(>nn1kWuuItq`~cwh)zU_*wZ@<^=zdtrqLy{Q5(NT#uR){75r2 zUaU7mGTZXbwHiy{+7(J85PfUq=UUfV${$qUV%5M!)+_i>d%jqt*@TEkggd*QO-9r4 z=60DJAgLsSbAo=^&3_XD#w0r(Hbigd?$H0t%e=+fA!7^qD0Y$>-J^_QLwAyrX{cYB z?14bHosLkq8U{kh?fEV?WoQOotS+4I9gP>+`t|(r6i-~D=`$L`4c4P{nd>gIUif>( zH0LkUCG`&bYlh5}g4AyPrbn6)^J=9IylFo66g+2)%k*>9F#xX^qknk6xjngFoG#D| zjVg!+mtYo9yk~t*uc&>0l+GU$+`)=RWyVG+S+PR1!Tx_Fs8y%yg~Scj0*1v#f1IYX zn{m36Zg#rll)UVp?7!UK`x8mIS{Py`v%$N!gd;q5A2b5(ZWdVO{?QLe@A%j&elZ9V z!xaPRc8NP3{l#!amZ9HcTAFn2W*NHf#~r&AA?ShhBcNQi`84tZyq|}Kar6UM0GXkg zo*l&LeO}y8#}_cVHY%Lco26gYl*c!cT&g9BAo+naA~-*SLf}0LPOG#LnH$01Q2Iok zdZ@*a^|+H3cEYjgMx8jluZLjO8X1bq4gZrpj(X$y5>vUQ$@OkU!kx%=SoL&8_5yER z4ld4LpALQ+yt__L|N8p!_38EC5@!j#l0Q6dFv)Z}x}PFHZfvJj!TOyo=HJ~;a0Afe zdXvqPd!&S{If*Ly$N3RFC!^2fi_y>h<7K*DCySepDDg~)bp07MG{Cn8+sY~lR`FYv zo>MX+9kECR@9$+uZbM!cDoRJ6&=}+O-XY8seDlEVLa?00*W%3o;~)O?fAP@&GkxDt zu@Y=N$8w>aVX~NKNxDg}vL5`%U*JCYbeQ6V*GZJDrwf#IrpSbGX&HL74BP&ZO1PJq zqoh8m57`KH3|dzm=k5@EY+-F*D4G!)=!jA+(8YB^Yi}nfZvzq1TY|U{gC9erWVlC? zu8_nsBd2hPHb#BS!NRlvV=8p|24Ol|&Mi`ba>DZ0_LZxO(Bj)2e9u~we;2e_7ih&| zUG!BsG*(4lk-ftoAxf?u*FTdO8Llt0I|!Z?eMoAR((-HZgw9BeL@x*&GH7q#{Pv97 z^CC?-{=f<}4ZEigOL_f+FGy}*#~!tSOoJZjgAUiPZ`O>3{IT_IWWxIp(1#!tPAn8o)A?df z_t-{Sd>;1uX# z@ShJSDa@{PNsG~2;@EwNj_>1MiJ)&zCEA^`^WFuNctOoUS_KwKwlNl4L*TH zI;#K3<4OTAN5c9N4~0SLPccUOK>bLd-ajyLKlx>Kwwhq2IhIW|FI0kr5$>{${Ec>b zeK`9_oE-msbtzV4Fabkqzc+(Lf%}WqV)S}EUJWizQ0pUV1+|Zx0X(D)3ja5p=BL@zr~L=q41nUm1}kwu$Q__6F4bn4Z(cAnEElRa%mE(fUmWLO z>@8>g!wVSQ>0LI2TVOc9UDzz5W?B1X!sv_;V*Zl9IY{g+*8N=~>ks$y@ig;{%j_tJ zbsncVKtilhgUO!eu+_2eJGJ*6&4J04L+nwgL)m+;{z&l;I0dawIlYg4g@vl(x^jJ^ z+k=Z06!B(~3xQd`z@E4gi3Q~bK;0?ZoMBNp_IPxQU9sdomN*J>gV<}5Fl8)!3@Q}@ zj((z%>c8JVAkibXMFB_qpl9uw0(}3N_?@PBhGM^Eia?T*8VU!`LxxC@i{g2%zekmM zrzF*cn9+YNMMIZOvwVj_cgdzCal|PGbrZi1MGTL)@PMjL`v>N?%HTI0Q+^d zjx%o7;vX=|Zvf0*^Pc>{c-kKEL_RfqQw%GwGJyVneVJ|US0drDV3z}!xzphnEX)0A*(rX=R(lAmju*%rlpiM_ zz=_c5$^DJnab{PWejkNscih{6j^{-EMzEPBd8eFnTVZW5$N#nGI}7&g!+moxT5?2EzQH8Um?yx$^Z>I)~Yk zpRVR-K{#aa9GK76C4}!)O;04%p@L~V-B&0Is>N$K{4pV!lH*8FODEIU9`wv4tn(T# zl5$~bGD5gp9}+4xL29JQ**nBxKEnDC!Uiplapz>MP247Ey!iD#TRjfhh`!2J4|Kf& zrPTD3Bk>^|AD%~$0y9DX5UCol*rtyT$h{m~B_Y$)a|f(`@WvD*x4!4{36b$l>a)FX za|Au3c~$8AafG?fU;iaRX2I~6;q`wf?*@NMu3ulh1vmJ=P_qn-U&Ip;EJa44Bub6P zOP9Om@$uB-S%*l&;roe{&MZk1`;-%T`6a8ZQ#%Ivtm)7W?2O|HN=km5rgv-X9rp`PRPlxKvXL;>AgbYQVIY^gkECTZO?!>&cOR&alHflnddZht zeAy8gf!<9tcSa?=z1Mvg|XD?rB!iaP=4n2AgSelxy zbNT0`EIdQX7|;F%X6sLb>(|NI>+9D&`t1t2fP=H-eE7rV>&yR6ejJ_;u6n2M-(3%I zThZ{{>G{uRgXHx6*`WCFFYn%84xomg{(OmJUM;4_Qil<3*hT8u(55{d?okNd4UgeA zsD0geAyom-qZqVUYQ9K$4AcW zo08m1Qkz0`fub}sLwIqqB-YS9MZ(nrvFdnQC{=a(3e52GrEnXS?;FcvYs_K3>FRs2 zF~H(@7oHe{oBaGN`$P+Gq1xx_{r9?dT);QvKodNP`z+5|*}+uPF&XmBZPy8@x&5{~ zknnaIq|-du5$Gpf-)J-x+AMFP3{&dc)Ha@#VY4Owu|ZK(>EW)o`TY{H0jggOYfH_T z5>a^tcFXDziz{PNvDw7%6&KGYPL?ljjB|0)50x|1)iQ8^6|dX1tt*U?PilOY`~kZI%+YM=M}XwE+5I+YQn_-Vf> zokJWWme=qNUC^(+(zKs`U;Db z$MlUPhl?+?eBv7#hK>ehF|dVPe8QcmkiqdA^B_IVrbeBtQ1&mthAGk{<=ZNDP2XZ` zsXR&p8E%yj&-RpdS(`Hrp|&b;w*mv<`%E^^5$ zCa4~)TEr9F_JhQxJO4UXQ?l~?Dg^d$nGkM8SY?UCB>9}Bp9YsV9>${L5bxtP*1YjR z#0eE--Xl3`B9C(eX=e@47cbPAK=Z-sOrZ(=>tNXwUSt~AL9rPj>AWaTh#K&5=Hdn= z^t`A+{^D7E5Izu8pI9-v3GGOHIJ_AE0=H08tZIEF9?TCfIT4&p1dmThbh!Cth9ELu zY$COa$@(wT#Z5Yu8GQ2TJm*TFE$XldNb#}sXzJ!x_A3!YJgtAu_X~JFca_*2KIx{c z$OuhK=`=df{s|TGaBm^xLTAv+SmAX)q$%kyy1HrU1NQ5V-h7Sf`voQY_HZXvwh<@| z=ga#|kF^>OcM}w~a+MYJpW$CQkqN1sI>Cxgapq`QL!Sr7lzo_?(B+alv{XLzmLF5t z7_f>_XBTf-J@Y@;-z_p`2N$2q(8D@?5!tjQ@Q%kB3CKsl>g5w(tX_Sl`nv>)pIxbE z&!vBm-+L`P8eDuH^mo-~$mRM>^&s-{J9)pH;onkEuTpf=lDHyk`sK?6mg44{9ff}I z(dH8~2v12hIq}sp)nhKTCfKkdF{c@T{bQsjQkM|i`9=mb3TJS4n|0UUVovg)4S3{w zLqmq9OZR=zEQuRAusDIS?(N3VhLnv4f&R@YIL!z}Gf~7YpFsy&)fj=$Z#lyL3smaX zTJEh(Fvjr3?3HwpJvWR^t-h7}*={cv>~F+of*wH`ex{F%>S)Myd}at-T!cy2zb#ug zuiwJB*vCfSZP5VNpp!mPNh-?*7P8wAj^WlOQdI7+^aMSu2Ks8#mC@fMthl-rjar)b zv9APFgF-GRHRw*?by2C`K>d#Ou}4#jeH2JdNufttBsFuRrt;lee(twpVZEeh)?V7T2Bo2LD+9VGXc(^}9C!ipt zdFmf~9wdIVg)kXYI18x-h2hDm{r(}} zNZ>+glo-P1T;**Ub6(6Fd$u9a0qnUB6gnO$6x*&aaxlAKpeOKaBBL&Y9-*BFt~zed zBbL?GW(^Ku*dp(i_gI_vas94k7xrs!kiB%%{^dgi2RTa9a_!OOcJ!(JytQin7AxQ1 z7ncE}u8^*(7F6g0XN~@u9pK30sJ*Z}AhVF11g*K@2sezwJuqkw0qLCVz#ViD`U=Ku z77a>-8C?i}PMaO7%_tg_){A^V#R0TF9U<7xsQN-jU;s+AUzGwxYt@2#YjvW-p#agI z5IKNOl+a+bB}IRqSR&ybx9EG-i6%Cz_QbIvb)u3FSZi|aF}bMYSZ8XPpgIuC1k{aI zF09t1I@UOAzUWRb54;XU^FZrHxd6b{|F{tN)>p(mgSU1}F;SuQyt;{ko zkI-a1kpFPJil#Y}d9vxA+P)xp+uSNJo?Ar|6f^zRgYzqku zcyLXw>0}yywn8y&fjgU^Eg*|aT7fCNO2rK}k_%j4O1vQ`NoymcmH9v&naS(mYK3tD zsUu29$|dA@tqd=xc72dWe6hteBdgV9+TdWXPL$2=_ph~@Q$$c9$7VacyiU$mpn~qi zR?rUpuEkcc{BFipph7OkR=~pU$9CXw(Na31E&!ItzZJA2WXn)@H(Ryn2Fz4^TEW6C zu4^=!0cH_^?V(qy#?5RI`MX!P&_7x#Qhpmp5>!5A>nb~8(< zJCx}HZnY`_KX@xxt|PV+n6BrMaN>diVg};ag;j%ilN*A%=R?dBNQ}I zxGEO$40ysD+L1#fMA!0bwE;A65k#eg7Ue)7xhs|fDW5p%7I7^;G<7_6)LxHKXt z+r8^V5BVB{IPM#7I$kS+X^^^3uuokKWQh~HPegH4iHI#r2;R9}kt`y>k-^b+kAs|( zC(vqP^IWBPl+%)*qL5C57lU>=xH!bKQ<&mW(S}S~KooNN0LP%K4L1^j&Ag|G^fdv; zBd-fL3Uy7ek%;R_jfzNN5A=9s4gilrYY*&51b6ePBGTIh9*^99*ioqMf{sIMl^Dh( zj)AIzs2Pu4k8&Gk93iiuf&(JYd@B&+oNRjuqP!33YLd=3>nNer{t3zuDVmy~t6m~P zwQ=-Sl$CP>EA-Kc5gouyZd{=l2RRd3N9(A6L>2TKP;arq-<*69gC_|t84?=Y7?kXz zWSY>WOZ8%6D=M)yuu+gjhXtmsqH5R0I?!g1#1p3wt(A?@2UJ=rrYS*_={wnL)iBG&+vy4w}yFm!S=AJ^d=AdPKI718ue5 zK^w4W(NK@un3+ny@odq?k6YUoYF6N>w`K=iy)Bl_u375aSLR;r(CKeOYhu&@V^Z!}5WUl1 z=W*@+VpW~~Oo~|tre4-+J{a!%XFV6I{U695r~RKFPz|yLxvWzcz-9~HwF_Xk(Td{= z>YCM25*L4=slKkK4Vw?vsS9Ao;kG_GnNQQO3!u55wz@%$qS+w3`#J=gNR~GWthr9X zMuD5UjRL&`HE0y*f4?Z{HZop3ebD^x7uC;&J>Y9-+>TTEby(3K%l6%_WS-q-rBE+ig#-RD9i=h$zK~ppiZ*(`?5B&4X3LD z#5OPMr9f@o*NS#py$&}?YWvk|Q>}TwK>rp{aBBAp^uv({SDk)=0SKZ=%*IIrs7(_y zv$f5dsN{iKo&NmuP%vut3#l@E_DJNpoL%UUgXoMyCrYRk*Y;@G>6cw-V#A7uRVOOhXb~{e zr(B_jgQybeV3KNc{pgX5hzp1pNXl9#JPSW-1q=@Mze`seXaw;}%C* zMZdt!AnzBrky|o2c3$vQ{h*}a#b#EHrRo^>{>N6(0=~#ru>5|>R-i&Y%2vR_{>paX>NOaw$+4=zU<`q- zfJHcC&|jcNgTb1!Y}H_}CTxYMnQYW9X4t5~U`+&TH5jZ5%YV^MD@K-1^o}Q+1f#jt zTA`!-@*VMs1*cAf!J4ba4F+RuZ~%$~W_wz$Y&=()SY4BN2E6hN_J$B$o3a(-N(AHR z_7a+HoVG%(RfEBXRNNjXX$=NraDB}NgEglghy=D;CLLBs>E{nHw!%sS)e$M_a)~Dr z>NOawxs(QaktB@l2q?Ubk?0po!sHDGV{9r(yX{E<*=?@616keWmhJYK9pkLG1R3i{ z(cneUNZ zTA>m-*412>@iwu&xxrf6k;5M7{joU!ycb@3VE4rEdH`0B{H_DPn@x*uliNHS(| zAEauC#^UkNsoaIxkGY|tLIQej`I|uO#ZVX~Bp8geDmx??jD(C+6O)wY>HZj3q0$80|j0*P<7*56AZ=z^(GkX z!yOz>19<4b3PV10kU^iMCK!z6a~SlYMEi099?W7N&;tpLN-!A9&iDj_kq}h|KW*(D z-ddTkP#9u8f$PNuNwOH7U@($@Z3zZ@Q7K6Y1|tdYm|*a5=;UVZmSFHLao1BMb@b_2 zY4=8V2PGJcZE#Xn!?r|xu}CqR(i03G4E%SI9)G*SsCyEg?g<7X*_xDK&<^O2KX2od zY|5ZQ5`??F=lM%99q<vwmbcX>WMGg;@51lg`&;o#X~-M z%@)OCwRz1}n`yBb{J1HQt??g=j0!w0@o4^9BK`O7bzNlTVm-IBXnBErd$ij;6-ek} zfwrIx)=2&OJlH)Vo&4ruOY7#))VJr2HY2Ol7*`$QnUQf24@N(pxVaN-jT8yyLqA|d zT05jWM9$0c&EgCMlD7d_FvYX?XHNb@o7hMJZEJHRn6@@Yf^ph>RcrGVxB2wTvb_F; zULnCy7iJ?HZ$8duw= z$)wmqbhBAr&Yx)D{qJ9>aX6v$3|Yi)S|$uO#cW8wP6qSUB%j|Ev%$lBbuT`B{)}ja{$;6f*tA~Sg$K)3bfBR(ggeH#@bN0X!`meELtt@9|!n*g=}WW?ZiluYx8=XzqK8}%Id<3eI28-+-N`G+r;7sJ*m z?;ERJT8vSrba-HL9WfxCI{s0}<;Cc8$_IuVSLkb~87O_64Wdbua{~?c&2IYcU6w7U zUx)ABS;M$*;r2C3iL*nLE5qhINi!cr*gNyprP!?rA@R@34~rBtJv zmNKFeoAw5S%54_zBnfo0IMyynkhu=(wK4g78zpMf6cwn-gV|fPZ9L!p9Ih+S8W0TZ z=ReMI4+mN4m)VyIeTHdYKBz%_b4_7%T!!s<{S5`^Ca-&#_*hV3{e&MF`XB;p7waiX zUWoVqnO_&n9EMj`&c^?|xrY}_{3g&`Q&{L%ob`U0&#!n{^r?J6fu>P3^qFJBnmIO5 z;HY(`eQ-ugALI?*VVOv3+&K!IGEQMwV7Wu^Y@dcTFOUQ{<_tYjdH(5hIIT6mWm`wJ zLi8ceq_yRbr%cUy@stT#Dh95aq2hs4Gfq5ZY9@)NOw9!Gl&P5=o-%#)u`%1GU`bJn zkfb&&nOw^X^V=>>T1j?RXr&9vol-ulpkB(S9P6cgbAG*)Z=SE0^3Cq`Qoh-|UdlIv z*Gs{@Q!%%uk?ZA2L8aB`MHC|_3*t!;Mjsy5phCok7o_n%?cn>Fw7HnfQkA2r8CcLC zWC63iLP5%e{_{A$EMRp*xS2$uG25V;MshPepc_Q#6I&vtkXca7*97wr^{) zp|m4NH;m}YH6%67IqAUBOFr3IDp32(eg1Z%xL+66fC^O@4b-a>Ye0ocj0W1Q8*9*o zYK(>+(vdZ|LPbWy_3O$SRG})Pq55=Y4W>|;(J;fhvj$nH&S=Pf9a@7bRA@BRfG(|p z?MszL6BgDqZ?Xg%#$~9%CUjnisfO7=P|*qfma+{sc|X z@R&$dWoZ*KSQP275JaKoW`*n;Rc?yq!|oBgzWTGj+<)ZD>AXO>&k6}csdh1qW;}*? z#V>rkdK`s#^*9Rf>Jc~aRoofPA6>esK*f`K`yWR>t~`z`t~fjsZ#6Fj3+gkK!Ha!} z7yQDXfaKoc+aUS8}Qc_H39yfEiggA3ab7x;yb3)>(UwjnNT z9WGQ`baKd0fhI0&ynN%KvT0{yv=@TY_@o-n=O=qZB`lG zKMV1JU-f29zwq&38sq_D zu>6zg)Zqal4(*AL3N-Ox>gB<-kq6?f!vkfq7GjR(9gYD-&6oLH&7$^TX)<0THy|X7 z>E1odPU#8sM`S&58QKSEG5@~}Y#}Ib!V%jB`E>avylEEKKDh6*g!+KnWJ~o0Uk|!S zdB>{A9ZGN>&_gFMca%Jo(m*E-r3BE)Ln#4v>QG7m-F+w}A!*Y5L6JTipL1F7gpEg!Nge@(qX~(OgD|b|WT7MC&VilkzsL zT~X&3nd*IW*W2ZsE_D4I#KN25>9p7(T>Gcz#cj@uf9w0;Oa7ey#|o!2=H1Wm zEL4T`pPUAI!jAms?zSIkXBi%|2h7kRk973LeYp2M-1;7tzK1Wqhcn;9sqbNM0>VC^ zYqW4YxMj46cyLdnf?yNo2QS!4_e8wDqwoc>k2O-laPp4@Y8t0E@W32QPMFpY8w{$K zdl6)XFA9ve7<&Y%zrAnSM;3g`zN6q<_NoNmvhyMMmY3wgx4c*lzOBy2G&cOsj1y@o zX~mQT%BtWv-P?h3qIU@U!9i{{3^+D{bAijJHIVcZMfXg{ku=QTC6X@Ov6ZgV!fLe` zBZT5TEsDL7p1Qh-Yi#WjXn@G$7qu=iF(8_?_TFhgP%7d{2(aMyvQxj|?Rcvboi=jR znx~Vby==t9>V6uYVMW5$iQI~zAlaPuoM=nNc%k?!j2dIM)^nUWh0BMJBhSOV@8Q<> zu=G8A@jaaR9!`A^gL05C$9WnR1e-9&dBJL}XEi2h2%9jxrxnctLBoa%P2o7)6*qMF za&Z5;D{!>=%XYUJEMb=Zu$)3IFY_Ip-(*d&d78k&9;{)}XJok#U_EByR5Y1!Fc_B~ z`MBhEu#$hpbMbTlXfV+KbGa!dtA}OzFPs?_@5yF{9@!55@|W-Q&vrBUZjqPE?f`BT%g#zyL=zw)A_1L|RR`6IRLW!FN9M6P9&pzhq z2V<|0*I+y|nc|D6rRK54aY|;5>3bEr#Junh30_A*s)#N_plJUPB#T5{LepZ;KC`)p|{bN5q;$A6L;uTSk|H%?oia6(+?%@_eXHT`!bc zH5h#Mzo34Qr9kLZQaYI;{A9Jg_$#twAe4jFpLMp|3i=A#;!QO(1OJ_M@@2)BgV!lR zCVG4SWW6x-@pw5~x%ya-d3qTXyE>exAwboJpNh?MIVpU|L#oiNXCZ?LQa%?q<^3k# zynZNQfZ*7BIr+4D+Dr=i-URjhhxHnT*_B8XS&&slp*0$WTFrGtrwcJG=5YhYgl+O} zG#U=)tJT-1HA|CcB-w-TJ(&dW-pSed-8(rwzk9b{ynAQ#2`@1YB`q|vgF-oEFXwYe zDt?Zu$ktpXUeIo2dsPnx1{OrNX*p~Z5tB5pcqr9o_SE@pKKYtI6ysg7&~nB4Rtc4_ zR%I&1*D+;+$!o>pN@!fIp=yyDC9QaBjBBlNCUN{dUxIg=im=(!e9rk^wE2$@5i0;P zivB`I5l>RH)rL*bf&6fy``xvky!~7iy7=_EMaR0jQ*~{<;MpQyOAW<#FQ&c2ZP1r=GaLM7Jtf8=_vT=MueBOskTE-)c`Jx(oNk5I2;A@vD6%-T=M*KoMH6 zc`RXp0@SL$h(32(rX2fp0gy|BeD`Tr{E9s*mnSlay7nAGj?%Q2#H*`%cc|W|p;Nlh zON#KV;T3M15`59!R--_3N*5V)7rDoL`^eI^UEr8cw%(MBf_EbH@Im_Wf4}+o*B@@O z>=!I>Pt1b6sS+rOM4VGtecKVV*4F|V?Qs5nSxnzkxFSprT1P!>;AS$1DxJN5%;&Rg zz1l(*z&e^rDZ0M|;~{p_TQcT3>b#xGK)2H#ChHe`oKj(b4FE-iz3Tv$K9Tr{&U~F@t5u?w?8M3(H2bsWz8IplnmF%^U zXnP|CM}PSC2)b{(t0)7VN8i*aEurL*o36?L;Hd;r$mTpRYyOj&TQ!NA;IxVo9U=QE ze$b%f3~fTbI9=m?1Z_^5f|y3LncP4l6Lp%Q7n!J3ifr)6fSO~bT4L3N_G1&`?lZ?H zoI5NX1KntNJ}qan0&05#hb@Ue_;qrz!Q{JIWI3naLvBUY7x@E*tpe|5mQBm$A(RZV zPye!p_z6m8!2cF(@h2ts*2VHk;K(Y!7>1iTcAcy8@IuxkS6`;c~SVlRnSS zQbkZAWxUwIKv`s1vK9|WK6TyA%)+RgxG_*t*uRUTMN|W)13-Hk6_kbzTck zuV85)42LAi-?&5Tw-InMtR)@Y7x~xGUFji6&ekn7bphE*=4p*g3|`nf2NBu{Xe+5H z9JO>NnH=?zlf+I|7;XKN*6bJ(dxt32SRy8~jp0>UlY6vT@$JzppKnFl&PFImEOk9A zc9Ta;-Z(Mh8H)OC8#~%TwW);)!uILDff&4vCnf|co*39X4aDGWJTW0q5yV`Hj({N% z?j>xT15(o{0E?ReMNlFI=B1Goyp5ox1ylqv>ou7ot&LX2+6Kd75d}^aYXb+gj)$kN z>Ch#rSQ|K?jRB{MwSimTL^W0wYXi3!M}bqt+Q8+%0GzTv{_t-Roy;{NWM*||K>j~5 zkhw+#_N`TvW7%r&gpPv~!%!rwHcF2oc$=99Lz&^Nrgg0-KK(R@t_PV)KsF}GbT zx&Y$oCxKVzvl5pc1YVv#7B7KUdWSyn{%l^%c7b=Nt4Zk9`KE-wGEfi48zv>(jpeKi zHRlRPoA<<%0ElaPzg}S?4HUQ(1>lG>RgdQ6#rA8t-iO{^B3J0{{%IDdeEo!7@69Ak z-Ef#szdUVsGYU2e0io746&N1#+192a7x($}z6`P8qFBwsZ!ak+f5YpC)v5vZDK`EC z4Lik>HSp@Nf438N`@pUzujb6|mJxDIMMe%i7Zbt0HOlFe?48Ja| zkI!cKFuq>ga}Q*@QAfC!MDHs)-I-}4Sq6=lVZX4PcdUQ0CBITv>=)bnr^UK!?ei_9 z<)F&T&T?|ST|e#avEMxzaSV2{JX~&{;7vGyeBkej`<#eJ+kfsjNW?-;>#oTe+2}K%(X zL$i1X>ep;Su%1Y-eYQS`aaHYf#;p%v9B$tg)w@jx#P_w}yJb2>3u|CzOlHExf%6*A zUVYDL47BI@?CgNajP2k>zI^REDO|kJlybnVz*nHrZcfMP^!(|7%GVg+ldojScC;nX z{KF=OE43vA0vvnmef;Tlv7J&4ky8Om?g9nOP|Qgm>u&Fun)Za0jux>H?o=2>@q9bF z{Tt1L(CD_QKTN0(Q}SB05)0??p7#IgzOsV=YMXb2{pF63T$g7|Pk*(r0&y>%Dts5yHmL2MyLOZ+5ji@G^?>7j3@EH7YwP*9EEoG}Tokwwl<$PDn=XIxY zOgEp?dVB3(DtDnofb%cu`@OXe+*8pwbp_*8pmPGeT5Fz>V=cLLr|{(^S2|ZP3;2)`L_FHF_co#8`M#VM%aQH$ zZKYUd$%&m0+u_k|;MyA$FSTb}uV(SLU@x@leS#MDn(??eKOSnsq$iX9Sh-3w;j`Ik_wl-&8(Q0?{n zi>UT`{#8_aJ^wPQy`Fy^)n3oPkZP~zUrDvs^Dm{^>-pDG?e+YNsrGvQ)l_@ETgRA+ zlkAI!3F7pnNt>wj_?iHFVva+~74PiXIiY54H!(`#F;Z0RjFyfvBrQ9e`%EyQ0cICM zFKNfNL>k9#JTj|yL4P3j_2jbL)wgB|ar~>H#FaWdA^M?O zDPYA(2R@j<69iSw@~1ftKgwtFKq@K)-dM}q;ki>Usl{&PK(lMb{B3uOg&E+M)Tc&V zcDe;U-W-#gK{y7-1&H6sIYCLK)EOoFL|VDTn77U^eS4($Q}pEr`Wc-=ldt(?iqY5C zQo6B7*YE->j3EvU?{L1APbqmkF2e*^Q`aq#QdxzYRzoTQGb*!v+KmV2#jj5}9e^Y+ zf`@g9O2UZyJwarxJZFvExy1&NR`YUE?zZDC-=BQCKmeF+>a-9QYa-6;U!O{>+is?I<0xcARwZ!5AqUdH!()Vp|N2x=!i{moE)K^Kk!lq+!J=X})L^T>q_QGf z3$APO9w5`_Q1IjCyf?_2LdiiX>xLbI*IylNQns-TX)>@^hcf~8ycTHaIdlZHz^%^d zq0U$PDOZw#9;~`oio~}^og|{lLn2X!RnWY%^77SmM>VTRPK7~svR`$1N84QJtrS(@ zt5S8WPvfW>DQdu5Ck~D3Xs-(3l?8Z|(BF!b*70u?Y#jZnT+7&3#ac$bD%LjcRk`?4 z-@Qi5h*yAP#=9!3M!VxFH^;gvssz9u>D2R``aNNkmz_tsucm*L!-Ps4D%Uc`Rk4;au8OsdaaAsUjCZfmGR76) zm@%%(sxj{DzL{fO6;=Ijk8xgJbm;bkA&#+x?FPNQdR{!^pd)tshgk{pzv}`e4X9r+ z$aZ5{U?q7`hfm+VV^Wxl?pDVi!3+`+^t`Tile zj``y^hxT;BK#6EStIlh8qo6Xi$8j(kwQ2;27KIxDp+y%*Kxk9b5g_6<`0ov@Mej$D z6Eh`5fKjsr0{Sf%lD%AP(5%1#pUp@OHOOuyt(A}EAZ6O`5UWj7t+8RX8r;}1W-xWA zxt5+S&$r0sinLx7j)s{A838F-Yl&?3Mpj1TYrIlr#10^(cICu%Bbm2RrFY}=AQ#zy z!qn_NAaSnRcD@J#Z~0O(D{b7{(nUed@>ZQncSoLN3^4f?!O>u}nfmT++hAV~q?;i* zN5{>LOu<(Z8o&`QGgo(H`6((JOQ5 zkWr1w6Us&@sDyF!J+ePekX~T5LHa%Hi|-%H3EvH;S*;k{ykq}i=sLKfLJrh@KN?%O zWBq9jMm@9afR0sLxzx84N^Yrk9c^WB{e+x`vwTwQNM)UKNj`Ic?aR-|$ccwaj}3HD zTgTYY-E(*eyRJVXMKFyQx36?ax$c)`5!ikn-HRXzFV@c)lAhwA8?F~uDR=(IzbUpj zR=aToLzVbmG_CR@Yi=P$<7i(MB%@sQ>fWg<0NsncDe*s`f|5{J?YvFyb z+L#2wW4Ji_&_8UVC}=*(DM1`a0ZCx!TxPSzk@zKm`vJD+X$MWojw4-%1_d~S%pSy- z61NaQ??~`>1GLvDe%L!Ltc{KX$YASUWGx_tpj`o@yDuWXxsuN}!ooh#H^<^+8-1I$ zkh-(>o!$n`9S2IkImLZ;pjy4Bi}z8$7OOVDGskHFq`7 z96?*Lr5as5KspdXb^$Ff0hm#9fs%e}qg~4bx76|;TpH3op|U3yFrI8*EMR=?3yRT1RzYN$7ALbhOM~r!Noc)eR!cf$)(6kj&`qdL zQEh}d+n%uZd>qNq3%w%n&D6aj@Xc$zBJfRVy&~|^)Tgv2yQj^m*)w0;*D8ia9k6A1r_vS-& z|4gk!#>D{ku66H1MiCO35uCN~(WQT^xsO1yN#S80+AE(E@hYQRirLlK%NDKO1G15Q zyF+mSP2C-eyiUrG&mk7y4}SApWn%S#?zx(FY2UjL*Ju5rM_>Kipx=QF;m|n}8Y=tU z3^gxn9jm`$O~EEq^pNYg83QdHj{HaWCv~sn@Ctp!hi-5W-|lfy?8?db-VfL7=@fS| z!9#hO;oc(BzYetbl-?SbNWp3Ec$CZ)1buc5^-~XR*&bA8P!HBYl0ND6VNmB6IyAz| z;9Z{tSNC_xQx+YljAnJ&C*@vNbF@x}CU_bBrB8AzM)ykNyjL1UKx1G0Tl7ksb-7(9 zmEi5y=W@WZxfgMX$thKTlVHw_BCE^pS#d_ z6`DH5YNH!@j;RndPyD8W$ggP`ZOS#-ys7kK$oS|CQQC-~pO3R8?)Nn;zo;fkUuoy+ zHG9)zm5lHG>^;b0(&wJ7RUt{L%(JH)v)%2cKB@Lj=F%eR+!U|A-}Om$HK`v;YrGBB zC;eWwvwhMp)4%jdbj9>Hpmg3VrNR>EmzRrPDYWbXoe!a5ttA`dstxa0d+C)_!?x;| zqp!V^X>n9qSpCvF>y=((+%wFX9cF7nnZ8Y)KbH!#mpf98@#3vXr;==?@qpKO6=-28R0 z7Jp{T!ECu5;Ks9;?P0f)vxKOt$+eICbmHF7cDAoSLasySvbOVm{n^KUVjkFuwtdcKK$9-&6dfJJYv=-^NIrW0j_x(re{-ud%eV(%(Q%xJiq9 z`fCBXxeyPj9<|$fDIQ|O?B4VCQa)vzU{I~D;1D6Gy`{R6fq-0pO^BK2jHCAcN)h$62C%=GG(0i4WQ>L8@ zPKAmMBmshWDFWtp_Ry-fA61QW5`{YDs>Zo@<2eP}8yC~X4p497{GDeC(_};jB(jNY z|2DoE-By=MVwlYAcn(MK!}V~J0A>&Zu-MJ)e%2Sl+5uvgCUxT2<>(ymClzr?!HccK z+da{N8vs}#*eHjm`Fx+hLVvEHUY`;CflYZeOsD}>d>gXV%#l}XT$ZB=WdJPsGyy*o zS02N>u?N)YB7YgvZRbW+G?Gr=;A9kjuqix18BrZr-@VJS<@D>2{t~VVt`jdRAWKjP zEI=|s35O}Di1xSoO3f`I*rlyFUocCD^l?EXsJ_F$+X-!CU&jP zuv-k<7+8?C?PG~cml@!Mq7vo77Of|>oqI->4kX$M@Uq5O!%#7TVO;GI941B`n~eI3 z!yd48o7{ZAAJyMG&1fm0ApHBy$G`q?0~vq1&&HfYj;um9X4y`nv|TVLaSJSekee8I z0y9OvgJsE|V4}RxQ~{kZ!3=?jh8I|Fuv_?#v{vw7N%@WOcl(Tyb%5nftD$+pr1Gh@ ztz++8=mnFyV22i4Fj=?TRi@vKX<;qTy`3|h(aqxIij>clEJXKDoM%{I+|c^shdJ^- z4v_fqVF}wy9$H8eYD%pXS2UO zI=QlSRXq41k`-!3-9q&^QMB=puAs9x-q2M;@gRy{(O0#DZP9&>H07eY!y`)<3%Psu zj)jG?2i17jx8&7AR?p;$S_$@TU5H1xP?~OhFR<;kLaQ((UexI%SaOm^97N$b5`j!gQLiF^IZ%RiA!0Eu?r0ymk0dSJ5#gdCCzy(F=E*dU)d zDfL~x+>P%!>nzsH#)LOKxb=w?97AWn0R>tsHMjk(x*!5QHT*5mpOPaeO8$O-*7QMJ z#W!sZs2BlDF*+tgqh{pkz%kFmnJnviyL;NJx*b!`poJ0Z$bD#mE*q54cuF2UWT(OzHR3vwL1WQiS#$?C zfVP&{dKGD|q&&iQ!BLq0F>%r@8`Ik$3N(oZWUR6LmaGlaQ8$@;p~KJkFd4Y9!m-@{ zOUMx1Ftu!>hVNOyUkL5qL9q)55rz=mfKtLW^)D)jCzDP@jYn6Knj1A6Z24)^@Nco0_#W&2IO z=G&hd;tyLr22l(xWIKyKfL$ z5ZP(&Mp*ZT_D!4WRmbq{PT<+5*N*KO+{Hw7t-Y_49^+%Tm)&pVZvkf*3`Wqc4ydKCyfbB%yt=mVB8sPdMZkq4% z{#bWbf$M>|>-E$25k4TWuTKNk0Q<2&v-oPgS_@kHQdn3TKw<4D?+S%sXtQU0OV&I# zLSz=i9yr~Gsz*Mxp<4Wo&1zi2^uSi!k_!iBumgKq<+Wg;jM=8gsr$raI{SLy&IKl9 zGHd#pk2SnLm4)((3%6Y#3Vet(T;=i^=~S?vycN2)2X3Aq){el=OX%Q&md$zr)gux( zPYon$g|@|wo469P=0@!sihCTzv7H*uRy22dUtUX6 z43tJJL#!#{6*rToIWhzwd~t@xa&CHDZ@yj6%bk2k9!QFUaXi(*ZE%M1_WR(6qj7gN z#r>BD?p@*rtdwhXVa(YvnEqy=3wqfLPlB#zA@8N1_08~B;D_yor-ARCcs27=s&Q9x z8b|Np`{94E$NtbApdGqG?3{?O^@>$J01oc8_YS*PvfVxLO569rZ5Mj4q@yc8$^!_! z!mTzZ%+nuzu)~DhE6Kk7j6Mji;Py(cxq#|d;Ldyw;yyTW?)B^T0XgV|?gKbk`s@~j zWs`4euJc|{U>!%kDHB7#(&F`N_CdPW!`TO5!#UZrd{<7?UU?kY6zGE&&D#ULU^r$6 zsSuO;f~XG^hOhK(5a93zIeA4JYHr4!oA5^P;rKO%YOnGc@+$YimafL1;Y~$rNemZ*!QCdKg+CghWMFz9FJ;d*6off%b;UcoVj( zb*g(LxfdaC@>TbO0K)5wp}gcfAYwyG`;e&)gvcmL(|6YB7&thL((wy)cdsAd6RauI z?o`lD2zUM_Up^G(Jms909?e>y{#G&7kE%kGE1t&CI&VF%EkI@nJ?v z;#;^9CM6sNp3f;!;c+H2Da;X(&QEQgAT7vzjEd}yK?HTvb==_)&Yy`GCpBxZJrVY%wU<2khzBF_sTDlji-4hW6znT-}Dk(5_UfhpB`u4vo7kV z9X=J_Hx8ew>l=qp%k_=Jr+50s;Zr$%<8afA9WX#xMeNE&!MQ31*)y^S{!gUrrYBIz z*+eDIvo+}nQcl&&&@vG^peVj_$gcPlSrM_33pivRMNRQBvMO-qxbuBMt`G4kvLX}~ zEw(K;K(J*fEYI*()Z19^Jcl{wA zp2DiIMx>>s4jBN$p;+d&4mqP(j}24U+lHXTPQ`k}ekQ?2j7Ym=k2J{Dk(lq=#;Bx1 zkLMogP(9H$a3u*;tUv6{OGHvneU4+=Y+yzFh%*ut@iq|&WNCHth1WOdlill@9Nk#q zxJCPGHO2K29qVF)8~~IITezA6G{|B-;#YhS6A}yGUD-l~94l0~M@q2KLY&ZoJ!+*x z7wwMCBF9emib%dXLy)z7uvH`K=A_ci^j*6V$WzmUFTGTmHCu z!s($l$){31;+BISaRYJaWx*aPkWwd>ORdf4Vm)FrG!V^NL^kjEg#* zOhSj4x60{REsF!IbnLwv&I&UWAXve2Qbg4-eG^d?AS1CpiTwzLV|@}_IMye@g@sQ- z^>^h73V3O&K1<(tbDR%>rA|8BLp%!|v9&F0dTZOEo`v-GiG+6A3Ts$`hcs3?PVPZA zQ_}qy>DXG9`{5Ny@2Kd;9(We|la^S2LV8Q0{R#awMy*_bzrmK^H|VdKNsfa4&?@f! zZo}>nUqA)^N3sQq|CTp?Vap z*w%4Ok}A~1c3H5w1Fb?$(5^t5=*JM>s}ds6GT77C0M*vnMwvi=A7nqul~to#tu~ww z!l;x;yCbb%ys>VxUa_{j$$CYnTtsYYhSsP3VvKNz^@~t?Vj8_*{bH0&Y;ryIi%<^A z7I#;_IAa`K{bG!AYP|`{W%^1Qls#s^x(o% zqKfvb*5nB7 z)`Yqvv|@;mSr3^a^m}MfhC>qcpTE1Y)__=%Mdx=`5as>i^7~-A;R$xKXqMT@eof(F zU_kpA3{@pUZtrew;ogS9RJ_VaKGWMgJmxp+r{x4g{pKD=HW6S_Ov(lBhUA++-C#9u zjU8->?pJh{&C(rSYSybQE>U^Lc0O+S zjjFLM9`d9b!`UXEWYh8i*Q~~1z)h|=6o^xA$Tc3(gkum?75}a3qxRO5=(-)~K8l0l zb}FD)kJ_QIzlg%eMNb2O>i71#lrM;sJaJOIUd)DDGOV~dRa zpdA9aX)PhLzQ@(Kqzd(`?}Kbi7Y#2l3g~j-K_zi=dg9xLo$P(}ajj++ecr({KF@HJ zV2)UtCN+e75{YVvYgpphHqKBZS`88O6g9-uSb`Qo&G6I`s+bxnYKUk`P(xh25|9{b ze5$9lo2gQ2zln{7O0l#esVkG#Dn9KIRVld>>$;&8PfZy_)v$WAHo|dnV9`9lArh?v z9A#Pu_&(XrP&MKOMbwBJ;1YWD09Vw+4{%i@UN#g>_M{Q+W?4RVfUDw`NVGyv8{iU0 z+5lJWhE`CvLZj-DW@L057QQe%=kF=c>D;t~e9QN!v@V}R>5O4}?hU^NeNQ6^@P z(-e}hm;hj|ku=CrBYKb%^pru))Fg=r*GQ5NrYT{NQ~88J&c!XUXdL8JJb93-N~!%8 zKZ{GrNF3yfuH+s}9^`~6agbA$v_YzzG_I&qHq`&GmfHk8d2NrGaRugLUjJ`i?Mu(ET&S-b& z2mBu4mboAK?`ZVtrwl(l&sXeK8?pAtFc_1*4cl>Y?-@~jMx$^+dvfP3xE@>HHp_-B zoAk!F;Yw=1)(8i6eCmu2_Sa_geKn)+c}6!(=J0g9?>v$FYP$22n8@WwNu0}7dlKey zUlrX!-aD974QpPmtkn2AacGn(_s-=8o9b%aG#;&4O|_tPIyVY7PUosz%XF@awM^%# zSle{2%EeF4-D|W==L&Glbgs&(>D*3;=6O>cpKdbzkaIy0qWuaW zu)(ju z*8Vy!P7Y1~e({u64d+CV2Wm1^ziDP352jsTOW*=!f)v zX8o{$=MMRyx1R98EA}^TY1l|mk`4^NgBzu{ALWGQ(TG%>f=E1qOxoBg39a~HLp}F zwCXJ~%=gSIn1_BuO%mc&pSDnXoF`^8w1folzkyr?aka?9;mtMWL5qP>J0zzbNuUF- z;tB)(QjYJlC2aVSRZYH8+5EjPg*oqibw!GGmv3IZZz%+x0fz>NWeslj+&UfW9+vWH3!omQ#MO^hW7R;0D#XYW6K)$%0 zmj6mY>2iCs+{L_DKI|T`Q%EOnX!+`#5BFEYayEa-WL;+)&0mA`#0qOjfr!mwAj9V3 zWp*cTplYL)&sAfp*QDMNgna@8K5YE7+&-2wNy&r`1mPdCv<*K8h7?Qi+jBy|-)fFp z$>;n0b(<|$xWMVz-E{QVqtnM7dxoMn+|JSC(T`2Zo`(S+wx+b4Rz3J(ODmg*F0>(B zrf}b`dQ#T<9z-;Xj}73eweRfmL+IIWU)eJLEC3PX&nh21{;XOFe5XUKIdGPBS%$4bdkzbV3P^T#aT9(P+S9o?$NNLvdmo!B#4XMAg* zoNj(ITWfwDsFwRY3hEuYv#y#ey2wo(+1XSyk}dEgD=`a81PU4K2uK)i-!q#ZES1v5 zXb27b=(a?5F~B-q9H!RoR@Ga|TWL?ZW_PL1)aEclZqEC1>0BR!ye9vC^YO1g++^7=*kQzOt1dW^CzvbF zAWO*ZX$@ouS(}Y-7RRHHv?UM*A;LWoW`LXK-LS!qz>KYMh{M6ORWSzDLI(}%)J_G< zsQey%XlX)(%1z$sDs#g~aN-&Hj zQs>TX(KNeQXx2CGwbQjCi?R*KV%!R(d}%FmM$tm9ZRJq&bD;BRg5Dj;?T5B51dz5q zq#`YyD2g=pB8s$iqbSnckA$hEBdJJRPZFw@uB0MueTg!yory9=Z|Y%if&lS(c|TdN z$-JZe7kph{@Qq*iFy|>U^$P(=sFKTM=z9HLQP;aps~EO)PoJh}e$sf6YHOa4n@#o;NXz=4&$eCSg97gFbcuM)Z-cvBp+n$n59qcI{>QhhAU^jZoHus#b zg56m**Q-9VdnY`8U(?60s#5E>HZ1;5Y^xRM(Y9($-P=|-)YonGf*s#hu~`aQYuh3b zP}T3TQ^XtGJci>3@@v#UrcyP5sEP0E$S(t)f`M-Llx*s0Pw`OadWr`7(^Iy&3w;&r zUULR=y|cbI?*@gTPnkHkv~okd1a3{GPkdbueVEX%7y9*2Tuz83oVv|b#x~eaz9B*_ z-4f(^#S$5=DN3=gZv}Op*sD`N7@RIIu{lgvNb44DUDGG_O$^_$Cv=enAB-QjFFyU%U*n48{xpumES`?+Ra_dq_nONh=}00-gv zO5VPi0%NpxLrx#e2Hg6I)*cuQxV3wCdZL%E=y3#@#ouv{_>QcIjaAFRW(K0tXC0+( ztWY8%Gw9< z{_?v|`}iW^qqUC<-%qa(g}-F5Wtdc|{Ig^_S^0$MftB!y9vJzYWCeM2OqSN)jLfcz zZ`OX?@RCmx@Se9UptAJR?qK7lXiMG3oyCT_PEOZYa@%q@H8<2^dCe?ou50y9Lfy86 zPGPJqd7YXoTIrpv-MC;qFOIGV3 zS_ZMnqGi-g7A=F~MA4Ep(?!dum?T=FUXy6)IXYHz0VGLzr&-ac+eN$xZwK+BYTd+3 zHMEO(sk&XnOHrIIUR1M_c&Uo1;)Qxq;w6-qJ_4wWFm?XPoJGIahvU>!WdIL;QxQVa zqhx=TrmwJUjeupRlot86g7iKR1MPsMk`d9GVLvi%ga9W!8#e7#YEIv_Dt-@eTdjaQ zxUE`~Z@8^)$Wh!@FX%OHtJv&9ZmoSBwTmaDPEY0$dzwORCJBeCk{}$SN~&;(TFJs8 zs&x|%Q8!&UM7<8eA&Kp{#Vc#a35V8ADf00pU3sV~3GyMTq{@e=l`J2kS~vL+b<^cT z)axK0lGu*&A#2CUhu)RK!Bt-rKv+lZ(uG7-Ne~iIB~?g7tz;n))w&6ZsGBY%qFx6f zk;HZs5?MP@NVbowjaN+2K?p-E&S&|g*nKz=%VIqf;ZWCnj!j2wL5AP$>+k5=yeWM5 zIf5U@xRH#LJPpsCaKZ8C47(N6ayBbAIKPOqy|3#+W;Vta<;lec_gk$NSw2Bf@RlPF zMX+K1fSn1A;Jq(!O*i4{FgolV5IgZRyNKO%F(BN?1Wox4E;1zNE_a#_*Eq<6lg?Q= z8~<~=IYBgG$rn}a^UYK@l6W&Zf6nJm2$qZ$t`Ac@`U%qcOu6Q+IZAmp$H4mdIs35w`1u%d z-YPuV4k>OA<_2LI!JNFOo>%05;v&fDnYmWxHwB6~5HsZ}D5i29& z?)B{DOr&+y7MlnvX$Izb2DlPuU~4GYvk^xy;8cKP0mx}8qN2GiV@~P6Cr4}@j&n>- z5`IqkJHCC?(-o#K$|vOX*xG5lx^L2pMXNx<2yikf-z9`m#BI@eT@f5So+JJKStfqSO1mmoB4gkP*PO8V zf`EjoJV%_fb?`>?ymX+4gPTFrf69pG{@4YrBb%?r_jngepsG>H1uu|$WS)n*FWsqw zkLPV^!^$I0)asn0V<>M+-0NY)DG}^xoRVWr3f>H>wjCYx;cL6cvsgOqdhhvbe=H0W zIPFN_boB&>#qU93(UC$v5M_{QTMcRRO`t3_?UvRU5{aF(K2Rxo9YoGAoHj^Z2dO>Y)TL0Q0}C|K zq9M{5+51vRx30r#$gFGjZu5fZ?f4Ry%o*WzQs{QN?c>$vePC|2a{9vTF%en~m^Z}T zYM#6y?pE{T4RNK^lpXG)byl4ez>zD7 z!z)!L-x3dK(|{b|wLPXgGErdcZ1?$Ecq9ke-&Pyin^J@iYfnxrTCd5;mk|K44Q^xR z99ca2xn=gqOcRyGX8JAE<&kW2lv|O;IGYd3EhjX_CvzS&I}E~+++kXD*wob&Rh^@O zT4+V*;2mVc+}wNH&Z&gk7#b$;_kP~%M(XiV>w!+&oUkPq5qCgIKgx8LKh0roX8W)B z#fKm9H|LEaWXhrO%Fm|*Nc4JAz!;O;;bK1jgGdnm0_R$X}Md?NJA`cVR2(Ik33EMOpRirvgVzz zmpsi39ktzUrP<&^fQcB%H6|*mtbu<*D<_eQ1wp2p z-D*GCX7kbQ{uU=g7PnQ-a%YX@sRUu4BB2WY(9x%2$)D^ye#MP~uJ78nIU3$!;G2(c z%Av?;N1LIi)n=&U#Ft|NY1~|#wtDpK!RzaYfr65nLmqj{l{c2Ntn$pF)$@Yq3#^Cp z;(ZG$-`oHca<5+K0!a6?z{M$u!Q6332`%_fU~LDn5*J3Jf6~?_b?L)uHO)4Ny}3+@?Y zRXhg9EZ=PMS4%91m6 z)=e;@VB;p3DmN|M%~4A_Rk4;$FjcH=6HJwh-_q({qh%9J0gl-OQ)SgA*cW@Sn<`Ni zRe})M1cL;4l{(Em$R|if*s|EGPuXgQ@TF|EUv6#8UNu7trP>9(k!psGCkw}U@#|AA zvV_`M_kadUn@m5bMJ|->R=6hw+H!Oc`{yDfBahT20k9)3jP!kSj;rUM)CvBAB@|Mr zjHTh1LcO5$j417m%$n1*n)Jp>I%*DFCpa%MrsN`D(=5wtWADnREwFLBIYrU~X+Vj% zMcU4!>qLr|NwLPAK5|(;#>AwTs^pAU5s}wCWeGx5Php0X@s+;xq@K7GC#1>_>yfvc zuIYjuItV@_35)k?SBJ@^oNze5(@V`5ITh{!7{z%$7p39bAj=@tw_(q`w&hc;mo;Q- zSeT2{FaAZU4gT9B`#YIEjya|l7TOp)`r|i$`XkSA-~7oY&pT7A+l;;Ts$rK|^OI3Y zS)jZ+`8_RAz4%HrLaRH>Ta3_s$Ox5~r5$SW$U8BR@1*O*;9Y$!N{U2AD%#P9&x>+0 zpYCSsOr*>dUykKBk@3pTf=aeNCBiz-#!$b=bb|}@IF;?6>!H({#VkivaD_GXz#EB# zymvp--JB3lJv(SFdD{@2-_R=0{6;R%wE3-~-C1&*lVC%ka624@($bQIxvqhlYF4fa zIdl}iB0DiF6?qx0WjCm9KXJSL-~O%AAVJ625{_W>KnO6olav_!4+EZ~emZ&A^kfVC z|1Bolssj?{TUqJ*qxdOT9GdGm57yUc_*dXBQsWoBe-^yaCX?zEIgZJhg;(e{x7&K@QMI1dxOLNF zdvW_xu!!>3B}TRK)~Pkxcz_VYSLduxFEAi*x~ zM()sUHLi5;n}7t=Myzp?l)LkXV{1uh@5G!faLW%3R-@JkYe@t>Llq9_tv#CLF;!k- z!O7ICwYjYthF6QkwwAJ3W z49Z_!L^}J=!8p}ORxj20NsMJUSV&?)-eSGMv06~N&dZJ1T(Tx-M@4;mgiC;`+(4B_ z+B#sU9GX}Q)mvnBd5{w{G`uk7sDlTlYKIw^(htN4&IFG6ZLpPa(03r;s~Bos z6>j_};k-^)uvMpGyUdZ0fS&R9)F@@gBZXQEZhzz|hdJNB zuC3Em=+ssgww(KsVl{p-Dyj{ShJoui!%~K=HWT*95eHSg5+3V&nEE42Pb$M>v6*w(L%P%-+DmbLY%g~(|f1eaI**d?tZlTu{Z zQ@cf+xrW^M5}u_h8DA$h_}kDT=S@_Ecx3rE62`gUkySg2M^ZTIm#iPgCYzAPK_P@g zdBN+1gg9lpc9L0TSC8TqNs>Ps<6+ElNQvQAn3N#9EYDUtyR7Qb>^k*cAbudbY*J#` zmPcltM#k6~H##xF!qwDr8&|NE@iR_^xn7Cl-Z&0hi#Nrn+qHX3JXURZsy4Ez7DFez(4DyD!`;M%0PYrM zz(w7a85CcrSI(X_bB!PlDC~t7BD68Q@!?0^#0n8d(TNo@1S66aQb^SX#o_GG5g<|Q zaL~7~q^op*rUdEGH1#AP5_{xev9UW0xn@bCS+ql*q*!S>2ub@8JkTOMjJnoNsHh9G zUd$IMX&O4PJ{?IU>!pCzc6+1jafACE2#n*tBGBIf-HfEf4(Ns?q64%o)=AMy?sufF zo%@=)FzeH8r4Fo5M-s_;C0d7azXO4B+*brT9dM=YM}0%Je+Z67_AA;CSRNfjTNCGP z+Jan9*LAT{U$rb9M;zCcNOh9=gUE|wyduxb`)-;pjrZMfwDVpo(<9Q75jIipAX|z(g0-P=(Iv(au3kwFuGS!C|d6 zkln*tYoMCrK`SmQdmr?Taao&)2jlup?Ru$e z1=D#)nq{VPZQ7 zzisPzJCRhOwcp}rs3o-(KhuqpP%Mfj}Zd7zNM>RHCHfCHxZL+Rj%6rRjTP)vWX3Pr4F>cI%=35BN@E94sDGVGZ zIcRFYxD-DmvCTD4P;*B|p=PViLe@npHWPtoVzD@69!ep*!>miv++?rWrA_m+f$Y88 zU^>Je)nL?g8_Wmb9WuPrRD7G;q8=>{sR*|3VX6K$p@2w#ub-IjRG;rwPe^LA8R60@ ztD_qWBiR|Oho}n3ARZ506c*4;Vw2>@rMy{s40Z)%$A-5bokQNstxWxB$XK8pGB!Z4 zZdoril;#1ro#ab~Eh;r~7=lO_f^!vQJfj4DA`?SHH%hTrea^`%+h|gSk>l^@$O@tx zlM2T`ze02OC6e5=23wvA}GTA{i!d6b%(>7 z&dJ-MA9;K{ijCZtVk_LQ9^6U69}2hRxC%ju?rA^%^tNmKY0a-KrA0nvUsynBHQ6`} z98ZC1Rp{fJ;m)a1m%h+XqAq#Z)YgrHeJP9ab^@zqX(#qo)%%VSRC_+o7$DQz^lCNq zue%^^S>8CsQ`zBEhkw42`A%^)y*4&)cp{SqWV6j`K}ig(Luq$>yRTWqKBdT(Q+u=O zSoE<(!NFEMV$F0ACc(W}Off^N-mL0?9ag=qsG5$ySwdJx6h2wjidCMR5;LFpT^)04 z8VU_m)a|YmGScm?CQ@ovR|+ZVR#yWlHN!ZT5}d^1n2 zJyjm0ynt!zQw6@`0;bxT?Y6j$BCn&&RkXd0(5V$}SJtT|q};b_V}&Z-Ns3fuxvY)G z)jXhhZ~YV9C;P*6`Wf44*3#b2)J8YY$b9}tyNRUSSw5YP%aShYyTx8SviFt9Jy$F8 zo^PbUFWYb6+5F_aUfdNx8;rR94WC|Sn}u@^T&>=I#Px7JldQMj4hQ?~$pBAe{c^kK zjT*jOuKL8=fev`Rps#H_5ADqhx%({li~wb~Qjkseh*L`v3xc-md{Qt$`}GFg5g+g8 z`SPpyI9cvC#0HdAgyLg9Uq9yJsk$W(Px%G|@l;={V=cpwxW7*&)^00$VZPmINcV zrCi(scQZVBnrzQ-TTJ$}n_U4ET|q&2l-)jJXZjBR78G1_qVgjz;NBSx%sPX==P&ej zkjW3wjeo~?&Shq7AR`y30z#;umM^fex_a7;?y3Y#v}t+{wC5Qv%e=$~kv6vx4DY!w zZ7353WgiQL_t=rl;<23B6itxn_zwSwZ;f>DmV2>8BXPl4E%jf$`9o@dKHulBbjJ%) z6hB8)q77zr)miWa2pmlq%?s4Cx<=3L9#KK&94#ulNKw&sT3GmD z>lcX+Th*J9G66u1LIHqLvIRJYiUon7P>g7~pbF`Nfm(-11|hABhAkB2DI^2Qj-XweAeFca$P2GJGN8%ggC)^R?$$P;D+5ATrV3rz zB6MY>(3OV^9YCZB9V&DXy7Dlg1JW3wqfT^%?%bGxh8On~mY6zmQ8h<4uorJkQNxR| z@a}e+rvk7V^-^H63V=#gO(8Iik`k)aE-itYDQYSJ!Xq^|q*umm1o0ur?s#XVqmsJmv zc!j=I95sjRnBFD za&B9o)dfL7YnINyDlG);aOo68rAnu))kQgrs)tFZL?0!cBIc>OE2nWb24IN2UmbPo za6s#?!)Zhwtd2wzJ9Ic<@7Up}dT@sm`h*VG>Zt1P6C9Q`7T8zhbEZ|czrR~N!9ie+ z-R)mu2Vo`lb{J067KhBvcp?B=Uf?-gh^)$VFRd zGcde4Y?iT5-kcs!9*fCW++v7O5bQ!y=g>&Sth;lT}*)fWri&2T8**yZ?}w;&?acaIvN z_~sPExfVifmy}lHGmbJR~wQhi-YNIHP(kj;j*KWBJlu0K@&C%ZYQJ=zYFL?2?cu8H)AI_k(g* zY>eB4?Sni1D%SAuw_{H?JSVq9#%zV}cLp-mHom!W*y-ANgcnjU#JSUSx{7>wJ}qan zVuO8N_*W4ZHu`j(;RoeUE|36Yx>{uUWP&S3v#NIfFhaj5!WuZJW73lNZq_ncf2A<~ zzO1n1y;}!dh^ySkBqZSMwZ4;m{Lehcle7$%d%<-rkz7 zBj%(+?u;KOb{Ktz@o}+P?eZPp8co->?>G6HC3{TM1jU~sph^6oqZj3LDm=y7A_>=r zEZOy8&6#U@vhIxU!wctuTtHZobVxLMO{6Md>E{({z+@&YnmX@am-(XTklQT+Xb+TD zq2K9Y=`{)~VCiw>HDENxs~M+$4|dX|dXas)=su|m%lX|qz6kv2o3`1sUOX_3_R%P7 zL?CiJpFWc*Hoo-%f5zqSUQ>i7s=6%_F`YB(yS>bYba0U6$@ z{}S{5mc}P>RKVYrLbsG8Q+^g$w^ZS7|U*40mw7E27)f7G?LL>gvWdm9r`uRA6 ziU+B<0hkIlQu$31;^77OwVD`~KeHV3?RHDytn!_w>uwe&S2TH?@LmdfX7e=JWw4DO z3T3j5^|ZvzKwsJ>9vOM3L#yMejwWy=^_|tvS}?@DyGj67s~cixHbi>4UGcEV=R#WY zn@+-D9F3N{?S`i7$9yY_5S}qOOJadxs34A>rHpX&@~6LLpMFN%@JI-Xx3!JE z(%dPBytM_XdsbjNEx;p;`!U}k#&tTr^$pM%%UrV$V+%hbCRwpf0B_`%Gd{XEORq6} zEs0%a3@;$0nmH_$07vpxTRft%qw7r}*Nzw;Qt*^G34W*r$96Y;_YPjQ>DS@AcaB1F zSTIEV_jWypo8tb7mZqK|dB+sFLl=~)u?m}fv4A46bWeBQVuAJ}>12|a&y*H2$BA?{0*X?1vp9(ixHKduE%b4@?g)U(<1T)@s zHo%#$btA=ZFi?cmJ4OI1d_2}@p%Xh3%!}EITtmpAnu|O*yQekgs-Hg65VR7-(t>T4 ze?_9sayg|5a|CO!cqt}NSkV21ug`MSG6W>-W}M@n{<&S#Y&0UDk}Uq-?i+Gxk8c*o zqZq7A*r~u#;E+gxnem@M0OaSA_77{GYDaS7`}pZ98vw=oV`qB$W4>H1Ul*&V?Gde^ z_#oe(NR8=c9{u4DHmR6f%H{Lwt2F4cf4}+o*B@@O>=*a~EdCHfK75|cCv(U@v?EMM zQjVib=>;P5Z??`x+jY1E?84cajKk4KXoU~!j~KCFq9DMQr1qxp{)Xjyu*AWz?5P_) zi}SE;4?WVKZEtu5*trA$5oPDm4lv5wTf#Gj>~wRR2cDYW9_j6Vt-$s2pr3YHTs&JA zFFQ6oJq!ds(`TX|fUS*|zK5Sq zo}@(y#|_Takf`Gv@qD_2NT0#UUW~+-WBE;9ykIeflma=HPBUQ{4_3(OOZNMpWxpFc z0EP<*N+}awr0iib4e{FcBvs{Om;%q!5CXSAcv<#`^zfpdFUd{7eIWLqK zGF#grX~QAue6g0;`bkCe)w&4N9mcm&qm@`kpS5=wUEd*@F)wC8NmblKciFY3hWMcxRRk2kthiSVt*mJ{E zy8-ciSi!c|F`n_1-kGqy^ZCPymDQYG)WZxa6Jn?yzn`y`54I3C&c^KO{x6t~s|_8N zplZJ`Wgo0BX4fVt7rvQ^6*&NMUc-(Y6e2*Z2YZS!+& zr$%c#%;#a{r7@E^Sk1@sv3{hdWc|WqOWTAD+GBs+01 zymxEmHIvqSwXs4Q_$OFi`NcVQ7Hc4!GGpUvZ-HqFD zwsa$F)RtHXZAwANmM(=6`!6&|22HDC9ecp5J^VdD7Zce%KzfDU%%TVQYhOK}r_Ep| z$P!Wgpv(HZLcg}hfsq$*yW~`M+#gO_G4zkwAG)C3BUr%79?Q2CC}e~)^NQJ^s)9Bs zsPc6_%@C_fS-EuPQg;pzYUkRQY4tOuG=yb;ff*f&6x#v#p*_Z{a$d-BktbHHcw05RVi>2*G3$n@V&8W<6J$?Kj5%J z_OQWSc7*JZ5X;*yB+p+!tqs)1>0Tf_G4Ii;O?a69vz2oXQeT2=_aqG>@*;N21i>d2Ek_^^oB;{lKMT+^xc|zud`p( zFf+X+4q+$GtF(cK*$`0*0dmLLImdgB?1h^}b1i7qe(PGR@+~?Os;f>Yo@2@lyg7s| zL6B%9FnamH5{LJP;B5qq14rKXg6lO6Q%gszP7OE;!HS6pO#_EC%3`LUszbm#&8gp9 z+s+wvbf5)P-`5tqq^c#EA?R{(6n=wb&+edc5<7>wosE7SZQrwAu4SZdAu`YdHkiKo z??SI}(tkTsxR_;92<2pplm=*(3Tats@|B##PTU#$IT!`fA;0X^#}R~zqjU;%wt1LkWcHt1DYoX0@oa9`8A2OkF6 z-nIkN>)AuGIR71jT>nZxA^#mMUXNT?&S8!>*Jp|R@%2`Dy=8W*8hm1Ht&$7%=7wnp zi`#tRRMf8>PZq*7Ri9!d0GEIN-+BSr~qWXb-BQPK`Snort| z*Sz*1(fe!>iR1=iHw0ceTyI3TYmwv}^YwY`OuNJj9KuKH`?^Sp<6+kNSZx^?V}&1$ zM)#8mCCrCkgR>d{tne^5&;xn=UFlH*XpuxZ!#Hb7cM8;Xm|F%pZXybmo@MC6qH#nBTGiY6v^6RV2adawUXMdvCTtw^&3bpw!mtEgJ}F(k`;I*L@8PsflV^PQka%X}y3(K6o&x-0Wl zo(VAn`KB}Pk}o`+>3wVO4mDG4&Hucx@|k8lO8}a7MUs*21sYAE9O4F0!9`!Q<0%y@ z0>030JmI73HLJmMTXu69v02qx#%q9H@(M*he`xQLXD+W zHa!Mvh)W(?Q8boTS=9AR8+TjxV6GX^(noTwcZ`dpdl<+Dv>wLCmA(kn=a|zkJ*$-A zxq7R0fJZQEg%qT0^74{B%vblwErC>-`D-?XhlGL$e9!-K1)px<)%A7o)$jzDX9cPa z&o0C7&X4V-G-gKQl=5cv@=Eb_>ZEVXDdo{K2XZ)2?4US4IBY*^KT%7EgWU)cEU~p2 zPx;BatBrHvSTm9@9gx&+_iaY8=zt=XSFas$cshkfp6V2iESDf`GAdyY`&u7 z&W|Pip0DWC^J7WB=PUk*Ut5|U7Wwuo{&1!Q{GC&D9MZDxki`X`zEafjS42ibU2hA- zenaMWaE-Ehx%`T)BxIDe3n9a- z3E}H2${^*$3;nS(zEM5p2LjLjlIj47>+9nmN6FupV ziPXn4v!&?S=Q*f-S#K~g)1D{&CaTqAlA7h3=w6Z>OzFh@c8w;@UNan4n3P*&(xJEa z)YB{eJzMNZT=0hlWxEg@CQNa z!-m+!c|5pR=+~4UJ#asWl2qcA(QKJ6{!NkYbIMFjni?gR1bVUB6u?qU3l`nig#a!4 zjueST1&DMrGBR3Y!vs}lRHGoSVAp~^61uD++H-V?=-RQHjnVAANu z=IoKiK=DEk7c|K&s6lkOF)TU!+A^xe_MxP@)7gACn31GybEKQ2@mCCRsWxTY-VK)b zuR93TeuB%@C%9Z4i1&0KSvGxIERb=IT7l-=uW)fYUv17!5>F_N&@L~RO3t5|--HC= zuS?Pwb0UXeATNu4h@K)6@RrEiEszqSfUx`sg6{C)yZfhdKD}S~GE`R>M=P z>}arfqQPc_5kXyU*BKt4A(hov$04R)UOX+;Ygyb6q)Njsi-C&>8YZ-Ss?Dl(bEO`S z2H6iEv%6xRzmWXl^N%=w@kBk3&p%9leJVHNGs+N`)N`uCpFb7963@Y|^_o=`(q-d- zO0gMWU?TI@hTvM)(4DakDj)zjw6%MkJeO$vZ}$kl-xv8;b&jpNO@p?b4x3>niFR2D0r}FxX z)eU}Rh~KNJnQT4w($HaJIFbun|<^V|Y>3NG1_3K8WNgOmx*dsCh#w)N>2 z_?lSP3w!MS1{~8O0f#Q^!2y9ZazfEAq1`H+ADyZ-i-=J56ljHu%PyR1bTkly3UdV1 zHBwg+j{9324ny7(1j5psVH4t3P&l)E21!8i?UTq0FEj=v#VV03jMaxZER9zdDjW1Ymf<&jrkM_`c3fh`KS&Ooo)tmA?7l422a zEMmn-4Ob5=<_<40+U6wLkR*sUPDJy;9IGQ$k>yGl(U?$1w-Y;-^kn$743+b~vB|h1 z`s~>eGFg9U)gsBLVA~Dwy|5~u=X2Pi$a8sj`+T<;tnR-Q$V)4x%R@{i8l-G7P00qp zD$fyTTsov*j0PCZ6!}^&H8kFg2Kf~ByQkD~^#b;c(P=lQ7%R@BlgYFFsTm;S9EM1&J&nS&-tb#m4{G0(vj3& z*v*6A$mt`eRlDxcc;lBsvxHXy%>qH`GYbVI5Bj$J^{HT@*=Ns_qd3t96OOhmPYoTC zkv0%EZl=c}jXrzU=LN1DrS#d9b#%Ud1NST3CIv4?#3yqM8(gwLoD8cTGRk;487S-H zX`pC`yMf|)h(P(x=*S<~}u*Q7VhnuF|bo7LiTEsKL~ zw^#NxR%)~W=P=@8{Er1(-p{bBaiYAEO{>g%m4eDP-F%i@rS@&?Rh!Ad$d_Ef6=fl> z8}#J=ExI5-!LnBNgkseF2FnyUay@*mT3st_bzE(_6FSTsukN&2w>M2SQ?GBnt@h`ZPXc|bdZMNE4JNJWk7 zOyJTb3AiiPd6PfA&raAaqg;j#~jaWt@A z#}I&y#XN?sIiQ6Lefs5TizOz$a&v45ZL|S`AdRTtrddw}u;HndFGCns(r6eC=c@-y zcAQBA+@V7+J32mxyy^AxR>!_H3&*t+R}!rQS~I?m^OK^+rnF~zYQQUsYOl~q*&!o~ zg|t4VI-OuUTdr4Idy(#RjW<9L#=dd9heAgbAna(aXk&A|+T&o+>4_zC=zMz3M~+kh znr_ACi?f!(7iZ*{m{P_xcrO|chjZg|~eyEqUG13%es~I+^7uYI8rZ~)hf(rgTL&9*H z<|mtSO@UYRUIugxV0V4R1;pzTyPpytEd%p=L9h8pQU%i2o7Drg(X0V2f)-8fN3=^g z*{r~gY4MB;Awd7~>ws*7lAHpBNOEffBOSX-Q@rGYs|^&ycJ;JDrTeGt>tKqvWTXg= zBG75~IuMsT5YH(4AGYtsNFH#5ix==}D?T&Fz^#J6Qb0k)MCAo_dg>9esPLF+7utX> zYTlKz5*{p(40bvw=X2~c&Jh&1qW}b~J#n)IF5g8)!p#avsIUc@mAH5qTbP>_%r!PT zXmgrki8h<3HT5knSHOf0bN~Nm?`@tVN0NLo*zDTalS~I4ba+P|o{de9b$1cTk0Q%j zZI4A}b>|eD%q3Ypqm{`ZWF|;vSAGqEWRYXC(p4WOd;frBrh|?;%1nEB2OZww9ahrn zsQ*BRcho^g{oEr0hzJ0gKmtgzX1A@oi3H-q-NW6(!^6V^=O`SMW@Y5S$LwS0R^sf) z;SwACvmi#=w~rWZY(=Xdy!K3f>43vWiH%?Kyz%a;gWtn@Y=6=)(mky7g2#paV!f|% zBHpN;Q}#?>QcW}x&xed14Jf@5o46QUF_!!)1|ezU6hq2=!rgzb_yWVNIF=enzi?&x z$zzIQDNR(t6b%TG@tuB01F_;xaf zH})AHx^*9;0k+)KR|Cy{h5FY9IKJc9GxHTkJ|!C;i8UbS z1=_uow}FsB*!$(7i&Y2C(8u>(WW&q8E)CxpbhBEJcW^O^B%=glILTKxx)^(nx?%vGv%Xf<}U;awI^dG9=*0 z#8Py4sz8Ulct`jKp$;JaxB_oDC6}vl$OMN>k+$M!fB*3H{{HUkz1O?P2M6wl`h?P*$IaY26*PEz+!OM2llJR$_iL@ZF66p_x zp52-jBY9~E{OI%~})sDI>TqSCyZ?uIBm4>vf;ujQ# zHv#;b1n}xwatR;~X$g4S2)iWAmozJfS?PQ!2}Zg~f>SC)aoqpwojevbH6L*!6I;RW z(G|5&q8(3>oH3#6j);bbv3TCq*%v`D3gqm$lm4z+$ZzI zoY4#`VDpw!!-wHyqasDO>?EeJFEut9qX9R4Aej~x0}UDt$$0?zkTo6ThtzsVURd*P zLzK=LLzv%+ITG`s2A5c4Y0UdAk7>Sb@=4hybeBsN+awtZW!Y&j5(`DXORmyMhu9iG zGUII)gnzM^Wbd8bV~I{i7C*Y1dY%S_q9(K!p6ZJ9K`p*1RluVgx2jF?bdYr z@8tDFV^%S+#a>gEK`ia3W2`)Jd%M*cM}b>*hK{aUk+EZr*Pq(jQmjLFeupI|Q26S5 zIO!i9I7-Pij59*!6m6otn?lkXZ;mhNQ3FX0L-H@K#cbu^?Cpy1g>F zD^oin+37lgqPABNuOq5TcEPrM$AAhM@oHp{mvD*3g&gRu%h|;2vf0g2I4Q*zuyL~D zI7=_JcZ02^riVgny3$A-Y883U5Yb}|kA~fY8j(!bTNss+>Z_#c7wYR%zyC?8uM6mF zax&u1Xsl>2uqL6uxcjM=PLtCfE;zE(n*2akaPpWaH^YTiNt=~LUud&+I9E_{3elBX z&ee5sjk#x~E*3ih#%!6LW@>@i9+B6{c^cxsfW%Z~b=|srovtG=hp7i$^d~Z8fx9&N!AONOdh& z8TZQL`?$FY+JE<0Q4)F5S*KLUou(!zuCUhlE-8UEP+cj3<*{mFbjmUtk4}B*D}`Jt zc}a0iZ#E%yIb&Cr5Y?qFL1NV+O5t32OrPpV+*3t~GZaYP9_0E7kg3s>4Aww?r3`L> zXA=WgmIwRqFmUySu^N_&L+$y{8qg-hGiO-KlBT+NZbpUG!+ij+3}?bpuBh8OQhF<- zG~P+t;V$EVQW#SKLBM} zs{alHK++}$V9mO6qftqP%O03qdD?t<$|7A#jw+0qLa^enjq1qFsDj*xbaQLD?rVAJ zdu_?7fmpHRltiNb7?kCr{yU68J<(Z@lVYu$v8f|GIU`gS?TW%v9>t0y7u1oSpn~+U z4X_>!eJv(R*OsFiC>G066?EzkNm;Jyzr&E!6Q+`gr4pr8(1xmxSmg{@SprlPD-HHl zdR-yAdLZ3#8o0%AV4Jxc;bjy@;I-z8_ej;IAvWN?cX0TH^I{@?jN~YyQz$suVA^Sj zqE5ck39ueIBqeZ=ycM;O<%f50>Dz1GHVttAh~r&-^cc5^y0meixx#7P6)Fg#M< zd*kyl^1QF?39;r=4CO*?TCAg#wk0_VjH#w;=}POmLKgp%Md1KTGaxk14B7s<0Y0^!3haUgK=c#k`h{b^&|3x%Qu0`2CqKk( z5AxtuPYc$2kVg!zk3IZr*&Mn9KR>n|y30yQ(3A~R68~;R8zvoqtemvNAr)s+6Tq$U zaYcQbLRqYG+aYH~?U)1Twg$eU8Y_S_R5o<3;FijZ@>C_haK|YBc(sWR^wY7)u+ok3fE~(W6zhQU}AhO?1h`op0;#e zY#QU>na7)Sh4k_>+BIab?1WZP29?^_Tnx(sMq>Dh!mgSULj`&&iSkV*W497U?Ykk5 zrU-6kwsbEM2)n5;Z$QIlgt-A4)|BcEP;W-68$jI_?<6;hWsH|R8_coc;36EJ*tc0} zL#9Mi8Lq6;RMVjG(PRtReI!vG*E&0ZgEh#@Ge>$>ZEh`YwloXUtv^9hxvI@g;UrGKt;v@eM$d1sJcyYFM@>VR-{6K2 z5|iV`lRC$Q`evG^6)kQE<1zNY#A2muDkkj%ay)1nOZ$LJ`tm=R=~J{CCOX;&GnbRQ z3$Q*VaHT(t4vkVKkj5tyOyiRYsPV}J)%aurt6^d8z-b@M1ozqpYwf1vZ8l~AU^Zub zG8@>4mPPBT7wMSB3|mLcy9V?j&Dvf!EPzej>2>_d*}t~eYBA4j$F1amGuk(N>9 zG<{ga;lJQ?d`MD)gR_(}@U!(>=QnrX{3vqJip=%eBFQSXPiZQ}Z5hRdI(xV}#iu-d zvI}*QgAkJ9ita8Y+=M>>NiDl$A^8V(8%|n=__<_jqOo1o*eF;B%WIiqa$PxG0D$pb zN4Hr}rqm?PErk>Cqa^2L5nOc1z+He#pO zjuRtFxkTkfqnb|TvEki0HSY385xynLkOp%fb`SJU+77`2#&6CPjTY&qN3A#0UE0B| zRCKkB)(++TS%$MNoME`4D*q#_W{Hw0jO3}GNQ|t$iiZzN82gGGIciER;Jfw4L<9F- z2sY9x*sqKloOB|OGXyNSI0$#O=&WPOZAbsMKb%82EfkCra>oRsLPM*IbXEzMT=yYj zK_5u1O`sqZk);Vyg(SeNXu!#L3gAA+RCeihM@31=k%_7<5H7QQ3x@1iTLp6N9Mfry z`Zfvcm|G^S1}$=Wf;+fch1I1CMyWk~3OZbiRzbZL*kwkM?o$-!{`Jv>ULlg^d@{cS}An{4m3sM5){(kWeeKU;Z!ePxA7 zX9XtdxApBwOx!FmZt2Q<*~)wCD05_~(G{tFX=Ul9d+`Dk3;@iZtJpmfGBY69BwsU)AFk3et)24qHtKJ2PKyl7<6E}RUX8lc zujx!E+3V=%O>2ff)vCE6mG7iZq4=E&=m&jBDWra*Nnx5){uoRPiK0pv8A{M}pv`0cW(w#{S=Xf{s^x1@= zwq{Zw?lz^OEIpSFLfX^UJ8`%S5P;xMq5xab6dkWrZKP{c8Qr3Pr#p})Ce~}}tF-Dg zrSKh^{^UFEStj@4eKX|n;lHxSQ(TLZ!en;0f#yz8Z*U$sW#3%`Y+Asb3DEMp;M?@A zm}rS_`AkK^yK=;nf;9bMj1AGLP0>cUH32c(S{@RTVFmXRN(*aWl%m7M_2%$g;Kshh zkBGId@xiddIF4Gc);T~j$?+}j`M?!|SQp5uxGx8nFVZ44=Q>#aAnxz$()B6%)z|ck zt1|eq4Z2(cz323d5`KgmTPVRlyg690)7rnVlF=WzMyyLEBV1>Vn?Ex*ccRVQl16)S z#>5q9Qcsps%FNA%8cx_iGP;%Pn(h=q;Hm0G4>-li78!C%Yip=?#51v*JDG17re?T3 z(N85bEbPQ2U-x%H*&3GV209EfLe?j)mcv~EefU=ABf9h;SRjM9_-S5tActo<&N0w+ zieo51IDJMW7I!uE+xxva(eiEr&8LSTxa-}BY@hpNsMGX`>+jxQpW+U?g}9pG8+}GG zsE|K5t*0{+LUWSkT$jq1>Xf~fwtqy$qXjK>Y{pL-Nd=vS{;3>TvnSNlguiA(w zk%w1?)KD0;(naVH_hk(|Y?pAHrLDiZU7^7`rk<N zTE~01qFC6Eo3=2@Z0}TqU?KZYB5|r!cU@f1h8+2HiZSf=>41**0wl~Kn5k;gB0L{K zd^N76fl=2jgHecDSVUQ`R@I=pw8yw6)u=-^%IUqVn#`_>CNtIm1($_)op?eVTf<8x z=*Hd#KYE&BHlvv=GPxXH5xSz5E_YFvF)_HFcRwEC?k{nJEq(6sq?|J~Vm>*NjX*QO z(6@Gi;i4(uR@zdXR@_}&Ve;+#Sq?kDv-z4h7s1F62p#X}@sr+})(;9HR#%n6rW~=98p6-`%wq{oj56<_!|r`gRWDjEzN< zs@%3Ah0QRt!92vzeJo}zZfr(s628j1XPQA}?{$Q01BbY{26qVJ`bS)-hxFRR`GRlt z6y`gei)2q&?xAM-r;9EUIb_uUP9^=a>dd;Kyqge~icpASnyo;Q4ESmqv^g9lKp+CN z1;QTPZc&OSpNB+Ez?ag`=3ZM_+H;WoJv*0JX9hahxx*S_fvga?_10VXXyp+n0%1fI;n_#BR!QOOLdlj=P7a4 zXjIF)C#sMuitvLy0A+B%mw(u+jFvh`mJtoMe<-%vTExKUp$!!Fqfh<<1{#MHS|VRY zv@vGoqW&aU%@Ew8qZt`G%^Ns zLnvFzn26!TmAneu$UflHSZ`BYXHCv$t+)0%D?p7UncOjV`AMbpNv1KxE5njC(;I^& ze-NI9ELA}fRM9o_+R4Fkv^Ov}9Eyoy!#P2CV+sh_@mfqwPfKkmGN(&x zw}>l>a61hj)labM(M)LQu6o@Z3hmLQ3rH=Ob~6pHL?WF9>viUmUt9SO=5n4&CX#w> z9}I#!6?BopOE+kL3jGD=Tq#~Zbw}hbS9w{~ea)72m07n5Ct&r?GQRb)P%iA4rV16! zAfvJsGf_aT|hZ#D?%!LWrvq7=K$3c9tJ zZAz35g6Tpnkeh1rC~@wa+ky2M>NT9pLHH1K%{{Psjk#&<{8NHRRgoc%vMMBcl+0c~(F*Yt#t%_ck3{Pzt}>JSq>nNLm5^GTacD;BjM zCOq*?P4zg@kL0`$emKT83UoY95Av&L@lg1zys{c$c;wnj7I+PJg#8h%Bju`!5FHR9 zw7yv_OfrS^9UMZ~Ea&hBqZY>3s5wGlhd6#Yozh~dNrtD;LSEA9+f(g#(6o2~3vrIQ zQQ~N=HVrV1D4)sA5wLTbTh9-9=NRd!5fHz;p-f$camlHqq zC?5(C=U`);*N+yHaV%fb4g&?>(KQ{~-d$l>jR;uI?gJI>=XARwt_GV=72|4}>8ho` znw{TpXpK6*r;)BwXi6cDY*024TvMTk#8hY!1ta(+6}i^BXaxynP>_9ZGt^okN9>xl z1yntbYv(tnmT+w`E()<(GyGydmEwkU4sNLN!T_FD+D`|*q2^Zv@wC)K<0xQwFF7i# zh0!h8DQ$=}dh3moC2z;4DTzwkZXE1_u&jnCzMtnFZ;C4U9_^-DFLc8<)d8(H*zpP5 z$qzG|2#s}v6()Jw^j@0hqFfJdQz+#6a+_*gbHQqsL{t2qx{MpAdBHYGQ*>FqVbWMH zyX*=U?2}!hHPwyg6>hH+oNObvw!kIhNNoX?7W;s!TNCNVdAG=y-V~8aI7Qm+szok? z38_aTiyi%pm#s1M3cD)~Pt8WkHl$7|JUSouVqhq3St~1%a$(_3VO|h}UW|8pgHRci z)`mbWp~YIW`RRM5cfLsp%Zs``^oj?!HHwmiRRuwf>71+!ytCOEz?JW^`{o zNQmip2tt2$C$b4(xoxkwYxaS)hc?XEWj?6FZQJZTqsMA?UZA~bibxemy*~Efy!U5F z7e)JSaL32vyXAZt@gtvz@8VQC_VvZTP4-MWDd`z`y_=2up&2h}eS~Ab$WztqE*Z2> z(!qF!cs<%lZ#1^bz(ItBp#yP#WGh+=KGzePqRX(lQ(l^mJ@e<%6>a#CUua3)=o3Q2-my35V*W>1%K@Q8qH>osTfFn!k5 zAkG}HsZd?n8rc7@g_Akbc_&q?j%lS7HdPxpl9Ti?3t7^bo7tvnCq^9UnuIsCh;PMw zS4cWi6{U=ztxuU#wF@hg4vgSLw9;IhhFq=6c2ke8MM-z+wYoY#PrbIS;~uTDf+0j# zNN?E3)NjUUwAz0vU+_yDSsQb0PBsM2a6;@PC0|r_`>OnW&zs&mfqBWNtsUor}xC<;_F}RELQ4 zYiV@o$T3zXtyGJhrVP_2qHxe5fW1r-szy<@yWI}51+h_W($|VQ+76!iJDGL>XPamj z=Do6xFxg4q8fCJgy{~Ptw17Vs@3*xnhqcQk2!x7j}-Qn&7TW za#j`nb-B+rXm4dow5si`%apc3d#e+uRc&ywCa+rM_SU6atJ>hYENqqATbG=zYJ+QY zwpDF#Z7R2BCAt+ApXxd-865UVk?hTIL^Od)vQldWlk@;ks@hUjK)(T>)53{w>rAp%0GIywM+MTYGjDIa- zll0RrI{JaqmNC-1Y8R>8gRHHvw$@Y2D5aSPTOOwUw5N7aGEbsz!_lSnn91AF3VReC z?rf#ART&0pJOAqXtr_q5EKqER@at%SY>O{}7%M%l?MmN@jETf7?R&Y`0C0V_1!mQ^ zwc90kl8mu^!X{lIN^%=oRRzt6&Eb}3rugKt*|{)=y{L|NIKw1~6G+hkCaeH^=WxiQsi zCb3Ghk|N^5DA-+#Kx?_r!uW7IJy5f#n%$mSbwOQRyKBMw^ zUz_b)-}KrVKkJ=tOK`QFu&v>#^|>uH3%2T8m!DNv_O;!)p3F7tMrpZsZO?A&eOqa4 zEl=zA5YOzHwcd5vq_@o~%cAYlmeJiLMQ*c*=R>f4e#d$xFRAQy8NVpC?W!!G*+X^h zuCF$Maeb!JhM5X$UVSv_x-Cjuw$0Uk(Ro^6T5$Mq>myk}rD6!TJ&wxPC6?7&Gp<(d zw6?90p@{NMt)5gmwc5T4s0yPzw_2PZxK=FxmJhC4cP72Gt)PsmYX!heiels^KB0dN zE!$4lIF+q2AmY0!9qN7oFlBUoJ1`Y!cp9Npo3_$*x%9_xJp`l4c(j%QBE6lY6<(1Q zxuPXPlVx7IDX}3(MnKZ(>SW2y_KR60>33ZY`S2X66WH2||rSO8ucraWn6nx`owwz3m z(tLtl$-GaQ*D>D2)?6WonNm>vHi&kZl)1bHk@f96`AHd#;;W`rM9rgL=Hr<^m{8Vo z^_bfXeYEdl7EK(Eg4iG4XVRX_uXh0$VU%Ch-JALG_#yD_{n?0N$ibkqd+&#%Pq+_^ zf~1DaFbrnHCp4J%+JL=-%$z3m8H;{)ROr1~H8Z9X%bd#M3su+1JG>9)vpM;@N6QdM z&S%~v?pd82y$ZZe21r;vG~s%?n0D9R$P)J%qddg5mgfJoFZE2s!jzV5&axbk*&ib}Tj3YSO4PySG*> z&rB~iPDMA`^6Z)obD@i@p_($yD&QMxuHB5y;EE*PwuijqzsG+->Va^6J)XtEUFc6l z5q}o<2Im7>p>US+8}Dp!3AF=;OPVkhZj+W=t+p&>+bT(q6JqG}v?!(p7b$iD#hXi0 zD&jnm%Yv=X`7B_aFdOxLFV-IqG<3$ud1;{r2hk#YJGi>uDW&ZoRBv!CQsfWG$jFW4 z+9m*nilNz&h6MA?l43i5GXLZ){P@1dcN}?fIDQx-i|mu|Zzb@Iv0&+G#k&vP{rG7Su!_EZ=i%Qg{HN>a1cml^ zfR|d8GcV_mGYUI|J^S=boNqJ=xksuDR;S}T9*-V)MA1+q%CUES>Nylj-z4_-bs_D# z*)xiz0{a&kC79IdoJK<99@ZJZ$8w8S8|$rsePY^m)vENs zM7eL$x2CGd+mFZsZo7e)D6a;~@nkfZ$FHJr_zKSHa6TTrnvFhw6XK3fKMKBqiS{aZ zjDv9IPhOF)>hY1w-Y(;17<`M(00Jg;2zTHK7T>%e4Cf*43xJzp9zN~Q{AuRS(8AKM zr$H3?xC3|W$kzOc*trM;Sj)jfFme{*d^(P>_?2HGxSyljF}}>^V*kP!g!7NV%#$Tm zQvhrTn>lzK1`GCBoAk`?gSdwtR?yy`gAfhF9Us_!e%|pj_fF_iD%wc-(z_dFJHa4dtFlN}9yXYZi7KEh@x11G&1=Uu&@d3-~eZVaO38FQEBmZ4+es zVxwae+=7UL491JK4Pd_^-G*WS(x2;*2TdV;%m`dp{aDxSF#)YemOQVk)!9#ql7~fl zQF&AD!72K*u2JM811t&eb&(QfFZo4ITW&ddv#z<$k(?>H+i z`^@uZ9=RM=hTaMugCQ<_<*}5{U`ZwM%&QP*L&3NmUA+LJ5mo=JzckP|6kmD|UEwow zO+(B0e0hzpvZ;bb4p{!tBmZ?i3w0ntHtJB~IZ_q!TM+=c#TXD1?M!QX*m1PSB2!3h ziwdk$HJ$C191?2(a#cAsxCV0HJz(B2ZLXBCIe?}givUbZc22M3S%CF~EwjWodjIZ$gW<#{A&ADN_%5H|V2O z_wv0^=0ZS{^B{#u0N89K{Vlk1IA6|UTz9tHWv@TxhJ>He;ji5oZ1?FR#9R(JASZwB z(R>{uavSV^y>shNqQGP*f<;;-1`gOc&P5Hh$}4Wry%0Z;zo@^wE8+|b2yo_MO;diA zHgg*>{aX1LR=h2a*ReWJtb()Rjc}W{o$xbF92PmnjpsHiuLQed%7AKc8;v&%xYCdN z!pmz2lg$ja92uF;^LfP-F?Uy*sA})H5{)sxUc#kl2w3eFS?g-+i+T;RtzgcpwNO^q zNu(OH9(*}dWxWPnm*SE{3}Ps(g{EL_vFYK%z_x5^4HFJA@@lrxMh`Hp!2;`N=Kfls zDtU(-rLwq6(5=9w_QgE4k+3R;tH8}M?b*!wtd`xnW%OFU6y~t9a}%X$eukxG8CKeN zMXBNv?k+LEFqSa%=?_CiX-yi-!~&?-uipwPu3SwP)v3C=lhnkcs1y2F4#~SqiV-+iZKFD;B%3ClR|5) z_*Ao>>_U`T71dHZT60L5l?{~6b}daoj&v;lvHh+$m20GDiy0lI>z0fhX^hD7Q@|6l z9@Zd7V$qPevBaz$E3q_CLX@SwXhDcbwgFSs=-663kXdSG@X65&S;7{%3%TTG?#XYz zeT9E5r=>p_v)^*~=%>yXc3+ZOc)(dfum&8U-o&5XE#Y}|K3*=vuA=Sf1gyue&VmIB z2Ut6q-@Ff3r{2Y-chx<)zPxbw=jD6x_ub`HxA((^*Zt#Zw|~>Syzov>KK$_Gjr@9Y zb8_zWe>}PFVngWa>hdb{-qqhR(1ELXicsq~P%ls-r4@piDFQka?aLq6pT_a<{%4Aua71{| zRWO`~BS($JwTx*z^JCw^l6rW56HFJ5Kl)`Eq3b@JX3N>9@oe-Xg4=^Ih147JxOpG= zt9J#LHvG7!SYX3@JbnO_o|`;%uwpdWgT74t@F^K-Szx4CAmt>Iaq{@WJq}KLaLJhu z#!6~3{~%BvG9h6}KB3V}Nnjv2&T96&vj;ED-3-c`FC7*E*U|XT0pezyf=@PV=lcf+ znjY2nZsAQ&@e$f?#-F-Vr&9S$e|sHPiZgFM_yxQox-yy+N*_K5^R2V4UQSm=3!*Ed zm2UsRLWeOo%Gk})Xp*gGNPM@SGniA1W~OAqHVE*YLUU+jhQP5ShI&klAe^!L;r#L~ zWZb)e7YLopi5t=0Q$+UqqfrkRyV1Oj&;kT$;!3t`k?)o>3YQ5+GS=Jp31!Z-z72yQ z1;+{fPu^g83nk#(vnYA<+gspc6NHS3agz^0Z(DgC4b(?25Qti zyNL`49d{JSF_PMg^;8je<`&L2x;u`tlSV%Hc_sCcDxrDK5mPm*fJAO#+268pGOG?ESVAU#T z+O#Z94@+!~lE%ss8h)5KOKGWkbA*+4S_;Zba1~-H1PYM^%9IL1qF9k+VcSJtIr35f zRi4tEilq)8@_6*zo0vTmNp(&*z=jIqanX64n-^a_f&<6USfl(=Ym0zR}qW=gW9JQ!GM!Cbf)r z>qi7483Ees)xf#CNnoUhbzk~pb+zLp*9e&u$qx)}3{$qPam3mr9P!wl^HI#7uzkvh zii*e4b+w}YHLbse&!l9PeF|6*3*wSB4wo}o=LgpQ*Emc%9)3sTBFy7AZ+`2~=Ch~i zd>QRfU`Vv^hrw5G-e{2WdUHjG9ldR=ZgycRY1O;kqcP46_~6>EBi^6l4DHW8)R3tQ zOjdRGjKU@9WmXbfk_h^+VXD;iF``%e(GVOB;_JwkC#1x915%m@8N}>e^lrS~wRd)T z(RI|1J{F<9iyxem;h&b{Ft`e$Rp6FtfwQeiFl{hK#xdTp~WHGx&_ z&DNSY;SblN3fx7a21Hyg7T{4wtv-^8!$D9X%`48i|K}&+lw4^r94F;^zpPcj+We z$*V6OCyKdvj{`9)y&^g5P{+1J)->@_jgEA5vmp$ITFNRBRtdd(sJ;grD$d=B<07Vb ze7%$G#R*kNmMNW?fS4%frM?O_-br)8c*hejZ{7*H6Z@>vVZzSzYXrazJ;T=fc zH!d@&nl;|M5i17b{qG&oW`Mm&z16lHpE6b;5`Js;@FJh1%&5k?yGZq8TYe(a)=AaR z(-m?oktc;?pZ1HUEIQV(^V{Ej_1mw=g+>uH3Mqry^-wgea5#CLt+; z6ydfeq)Ku3QfT2S!oS%aUsaStzY>_e7#nuHe|sGtCxFt?93X>0^%O4d0bG^75rq)V zs6sqsHSGN+EvZ_`3sLC+yIr0(JffKOQWhn0X+;ISv=?nL6tbsb69zF8@sr@G56ENN zJ-IslQN-dPZ05u}J@1}eeCTU$lF*u~lb>)X17#51bDBiZ&>B^lmgd}kwS?^P_KP|Jj)@J>AZ`Qvh;5$lb=xmUcMm zsfT)k0^J!-$?@D`A=}x9){tjlDQ_IM`sH?icS0TZDH9$YezlK z1zV0W0=Ot{OGI<=ey;_b7>R3pB;*Ss8|mW#b|#a4)3C|x2kd%z&Pl|bTZ3+~6r#ob zQ6HHy!J0n?6X=Ov-0e=U6fYQ`(wRNF$69yYPD@VPzm#Yjux!wBRNV5Wz>bTX6fk;s zkB^?FTD^zeEQh-+f(QI=qv5A6@Sd$1%A*y4#s7u#pP4 zx)Ntn$NWZpNd^B>gl!S1*JB*8RaM3d>&p!##TAXH!X%a=3=?Ur!YBEhSMNNS-NpAz zCF+IS>cX2NYHLl;Cz_P1NCz24WPEd$iA5JDPh<=vGH%s2zO`j4NZ&BRMUi-ujfKx= za0Wy_`7=aPgwBY5AR-g{12#8Uy2aIsc4a+;S*)&gEGnT~*P(vTF>9`_alkcTo|rn- z0;WTaDI}EcEZ(j;4wo}eG>m|UiLS}`h>0sVk;Kai?q|h;K`LI9& z3s1h5NQi?{qvUN1!8kbCI^k@7Q#{Ov3=cwo7Sbt7BW5bY-SlhMp?J*+4L?Oydov1T z=Fc)rlb<;_j-U8@ro|)GNZ0wXd(!u=dw(l9#prjRTIf2|nTLRP9#Nyfk^0nirtu>@ zBJ9;gOn9cl*Yb;So`|y_CX%WIxgy*H6>-GXDCEed$uaxS8Nde-5k$|~a_%8fKm-8` z3Uxs_>s7Xzf=0OmOjz9mY!D@*$i^OkFkfZcJn(N}PH^<_&CsR@-5o1-q=v^+3MWhse77i zY`8KlAl;h6g9DXKETDu|ea}H+F9DgFqp&UGMW%nyv8dnddy)d27ziF9oA9zkZA?b$ z&;l(CXk8%YBHKPEJl-36JY&M+zJd9|#oikKEn9&yIa7sBi3-Q*S^}rbcD*Yet_7Pz z0iESqaBxqu#K|^^^ITRLqs{!KiRcD7T`@E;)>i%+N_Du48Z&^3If5G}Dx>%V_s=gi9b4stDZ(2k0&r$?v}4^h0dO7mio zy-1|+cGOo~5K&NqGQtvE+=y9Oe3D>NAL~EMhMd`QItc6v=}T1%ijN+dLNY=^s4j%w zA?A-isJ7;}Nm=I>2aFI?x(pSK0iAs5&z{svY8GpHKSa)=5pozq;4?(ud_)HUCDaA@ zt4DMUsm`)PQn^(B`>F|nH?ux--Kwr1(w^;VWjb{c56_gVz_|lO?W9hno)V(0LhJp* zIO!&-P^O!*;%{p|${<1Kz)~&Hc}*_&CB%0yzFQ&)6^SDU6R;}{%qrM1Br9sNS`!OC zlC)_cL`ZpYGB|diM1)3UL9@$mi0_(Ku`Q^)Jn*~H`8i=>^izxk%q__Mf=?nMVEzD$t++2ZAt5EuMRsCU(a8jJ+P`}|gMLIp4$&(G@ zd=B<{Cjnw?vu}hD$@g)ZjNOa;+ob$#E|%)5K63Hl)EiBmbOr#~o&_FwjR0Nq9eqkT zNFIw59747Z3D?7PY>RT1t*}3lQ?4PdTGMz9rpj-*9#0|0-W!emDMD;WVsX8QqQ82J zoG}ZW?UAFB4pC(2vO*0;hZ7SGrb=z7w{qL6qOJI(|BQWvsW!>-2U+#-oN?yI#QZD| z^J>GI*Ng&?5zaNtVw_e>I?2Mq$KPk!k|n`GM}8RkPb<2>2{XG)`Njhne5=~Vy230{ zzUiohBx9tq#TpXi)os_1 zo0YM{kKseO4GwMtn&3~>`==lQtXNbNIAvpi=kS`3`PY%=0f<9(mh*t^mI>BS7C))X zymD)j=%^0f^ZHx;kme~bBdLsvoTil<+FYX-Wl9yjl*rPUqy1Ex5WR4Y9?L66!HHSz zo>!9WT~m4GmdY+3@`_QnSyh!=GJl@WD@rI^9+2E(d2?`H!8Hp5QN>tbtD#SqPwI_6 z>BHeg%Lu~|5F5Liv8F1j!O@sg`VAblv}X=fKZv_V^FVVmaMz?{H17ddX~A2M6ncor zNq3)w!_C-qmhxonIPZVD_vrx4XDTb^Xxgfph#fN_f}P#GkE$l?#N%Y&OF5&V;nR0X zo+7JvHTo#bU68L;ZSd&t(sKE*q;>MYbN%+n4(bbB#jcGWIE6__hDsrQfKciwg>y99mmAMvXP2$6#ya zT@4TI^}dOb_T|9BjX$-=79{M6_uG4bhWHosie0d}VL`*J8$@FN2|HCan#t-c`s5pyC5}iG>9@gX$y>oN*WK6e)!w-&Vgzwr{3S5A0TZC>@t|}9o#M~`pj(z zkxrb8KK+hDYO+w<|khi=#v zB4>q`BQo< zu0#z-sJ#p5BIiB*|AgEC;^)~szD5qG@uTzpXU=QaeT=D>8zT4n^a;>mii&WX;w1vM z5E~te68(7;qc#=9MY6$2yzNd%01*PizmbvcR=mFevBcBKV0`1>oy0KM-gm_{ZMWhV zPT!yQ!+AWX!p{4?aFL5zKuDyV6F=3r`A_UTmn{==;_;oNgZOnJosEFG1XI?28uM={JQWtFUisy5>u0=fljM&$N zj^oE*V!ZG};E%rhJ~AA>oOar+hy*YU`D!~Kndk;MFZIf&wMjASbWLGDYU7KITB^wXygvl#$k zUJ;*8C-VrBL*pi1T=Sitcr|)UQNy!4@ftrk<=z5Z#7s><48t)}EkDvb$(`Z{Sa^hE z6BNcRUI?xc&lqs@Np1+PcuI*h_~{ziqvp3vXrj6LjGOHF^F{DUJe*-4AF*?yTZroT zQ9LV-;uf6usT_&VbR3sLv}9q#w~414iV_x&A3pTXE^o#2+xc8}j8jzs!pTxV6(&|cTQ*~R`H5q|2>A530$fK>)~v$nhUDFn$s$ZUGu z>A*2wRB!PByDpSDdWb-ns?aRXamEoe+y(W(+CPuMtWNq&4Xzy=z49UMD2foU&Y)DP zxql0>?Ft+!RZP09-sdqcs9L-W5#0fRljq7vA5qn}B>JKidaT^Y0TL7f4!-8568`%X z{wM0K^;gFMEsh>3)lS!p2k;2_Ym`E5$G+}jz zPWq$rXc#SR0t%FSb$&eH42c`?z#a^<4XW)^Z082`4q$4;^5&+sJZGq9=o@h~)QJ6r zyTP(|O`SQ3asus5s|vA*!me6tQc7$LngXv4G(T$L)L+&40=0fACrk#2 zd-CU<@a7V745GZ{oVkKP;&}tQ zbkc@cIp{w(Xzq1V|I}ajLmYF|;ZyHQ5t*&IBiLzd6Bb%={Iz_8u8S6xX<68)Dp0;% zLi|11Cd{w&RKBiDK0e(Vy@m(35H`DDg?>7UnkzeCic*OREtAo$h_w|M=LR-pus zIpueD-!5_ZQaE9_KKXvcB8jcpGR55k4&aCT;wMB_;@}fhxb>!N&qu0W-mI7ptXx51 zdo2$YwSsh*2tNh5G@uOkboPt9DiyRs&5lZ_g_=E-Qx7#eDWfCmb+Jy$>$SdK;7hgN z$#>?_0q@g$T)ZrVo*&C`XhDPPh;e<5dqK)L298sWlQ{nPo-a*JZQRg0C@+@Nu82jF zvBGOi@nh1FJVWZn+giIXtyX09#IarWF2Jphne!8u6~!_ZkT5&4w@p)nS-mD{e=1o6^E~ z4QR@&vsBcLS=K!~6X7Ds@-0~rW!lY_MV4J!HDc|SSWw#PEqO;$wys+R-dd~6-S1zX zUDIiFu_I1*IPXd|eLmgm&e*T=WQVqiUcS6cn7Z%$hk)kjow$k%U7t%mBibigVAisrMal^pYDd6Q5W zbzkr7b&wYmJL-;FE3pTl+Wc>vNltrJzFm}(PopX5Fj?E2}NVgC_=Q=ydFfO zjjBOvuSqS4_L@_IXsj_ENPubk+cixQwAPpgq_!#qd#s$*&{i}0kI1FeUtM)~#90Y9 zq!dLqxUQon6yv%+>TAmqJ=9a7>pEyoudeH<5oNo!lO{Cqx=!k= z<#j#O*467eXh4Cl>!P++U)w=lRllx-disA|>$N9^qTSP--+jHa|Gje)KHbb=4o88q zjX5;EPxr;gMRg;GY9P?{9I1LnzO<%KaFxCAVC1D6%&r$Zof8UjMOxCILI_IBo+VKG8}@V^pj+Yqx5%M2I`2%N7*5LI&!C=GG1;OEI}&;0hvci8R+k} z4Ah}PD*$Cv3a_>cl8`w%J*Pn7lXNBAm(5KX?g5jfpBxL!F&(TD+a;0&Fg;FL1YlZX z%K(aDl;V2yDbAH*d|RUpy-pn*)l+aZO($>B-VyY{oXP#2o}T=frEkd@k(B7 z7o3g&CnuMM8nv8H+Xc}TGYE%_b+PExsb;)<7O>Rvlk-O?ni(&*43=Pal|n>8q<(K1 z7@-PI5leN+*E}h3(l=WMNEk@+?0^hiW`WdRZ5O1@Awsg|lZPPdSdJ(L`M^6SIC1e6 z5_~wtWgV5@BsCcv+;GJQ){Qk;5)-VrG<0&hev2CqXHL@dc4;E!RvsP%-Bcv@u3FbW!`X|f6iIxVne_=IdL z_0BZB(qfYHM_ezyWq8HXTI5*6g}G_;wD5w<4_gLGOer5`asm~sD4iqb+bsho?6qso zZVm^y1WEngE-)Pd3>~2~X`;Z&e%UU7auXv3PG1a|Z=VIQGs>5^9Lg+nifZQD?E)s0 z8z9M#D=6Ciw*%wfyxA~n;OnB}X3rd7fa4&Pm>#hO@5Ui+opH{Qbg$&e1Cta8&B%?y zIPG;v^%Xku5u}0Re~8u~I1Wp8ZH7T+kEWtk=-GxS!IkYk9;_ z2lS=9bIuj6m%x?pV(*%yFgd??z!y*S#7zY>oXC;SuaLXFHymP&x`P`J_WsSTcjI~v zfBTN258|ESy&qECkogPwz~8*VNy*Vim;S28zN6A8i~oPW!x1(4Fo^#4sK2$Heeawj z4#CG&og*AIrreK&+uE3f<0Sd&y3=$y7OgG3M^pbJAJG!RU~7-GukP>3bWx{X=}AxV zM}+R*cxQ`CLR__3UPmP;6>1$DvNvzUd5GUsr~zJ*`3$!l6SYqi;Ycu>pz3^DCMXC5 zy*}0n`jUx>?H82-Wu5*?3BUrL+L##%NSW|(*o86;m(sI*CL0Z3AU)qcpVg+P15PSR z!F6<+OwXvqA3QA&DP|R!{a1damb2 z!TdU|%0Jh%Zd$6>x;X!TKE+{&W*VXss@#%vX_lG|Tvu~|wm%^l-C<5R+1vNt5A~^` z=1ibrBc@xG``|ZU{il2T|5*iXFXxA6Q}xB9Qc9n6{OM*o{&~n`pu}p{N)t?(F%))= zgwb<2`;bT44SCqrUzHtD+VQj=bgly!W9+wcdeP70Fm`C&nrwme$&ovHh6uCNkq@N% zFel-lmx;ff9>jG05$eLl1W$XF!o%%-qVC1}50i&3?m@z0F=x86wfh>A&lqEpaNIk! zH3{$Re$f)1kV?rwOA@{znXZD^q1zHlo)tb+rjQaqKA9i_cPVC{#Qt3~@+ zqCNSe+{~AOkJ6+$~#q@0*ZEWD0Y7Hdb-v`UEVtYp~b}u^8E4 zDe^M?SssgR>QGQ5`X~0nT}5HE1@_A7I5Ipn;~L3!Y+ev=3|3&?$Z!Jusc@K!$q~K} zG6-O!i-`yT_?7Ls|q?eGYW#(v(Om&%~^Ll&C(RuwvGe<(I zmYJhDGSy`ccZ(Zu?w7ssmXNAt=4g&gwVC61dz!;N{-QO9t4P&0b2LV#y3C;vR>52~ z*Eg%Sq8r2cS62rf{rs=CN)_v7rTmU?493L*)4eP zppun@ReXw#0$Mn27(V#IiJH&SS@*aI52vkLL=Yx%C9SORI|tjFZ94~F^lY1uO7Ut- zEBxljRB^UVZabpYJ=+#FbsQZVBQDNF!@=%)HrHT2mNmVBl`*X|G$gWZjm*Id85o6Q zTjNrIXPsf8MQvNdvj0McMd8@iuoU1~XIRJ*ZfjUxiW*ZmwlypTc-9#fc5JjYF7Rf& zkol!;fhoeY&d?mTC^3gGWMCAIZAnZ4o^^(WJnC%;%X}9HdtHZ z;<_(nU=l3b8kr(Y>kJJ=<+L?2M=xYx6pn3;3*mV-o(8jMjEETWAzg;zFlxCl@{V2w zml%q=;<(3JC!lN8J{(8X80w0L4FGsOj=IxDOesp`(*}(k`L(d{6&B)wsLKg@5q1=p zJxJZzm8DhiET25uf^#&tU(+{wb)wAC8mFrB(A&g2$|vQ;G5O!(7+!%PyA2n8{*VdM zDUVV@x=kIR+a+5?-MoqdYC{K(rv~QJmdH>vN4*^OQN(*;{8L1@iVS4B?$pdzL(3Gq z?Ow|C&f&6T!?ZQOBTn{vhf|vJG1gLttB!N>vo?K!cwQeR=C}1GMP9>OIfa$iu{m?% z*i}t)HD_QpnKggw&*rnI>3kXO%;3Y17XC2!>dhNl&n1aWp3T|f786y?sr7agUot^+ zkjoVW?XU^e7!9+R2*{9syuGn&-oZlkwW`8w%|zX7mD4jFrP6kA+W9l4;n3NY&0;MnEz_j2F>Q}72@a6v3=VlBZO`%MrcrJyoPPNf z32_|}UdxYVTwlk@l}QcHs9M9Fdq3iC>ZL$RTWn&2PFvf??40&yPR$}Ik+CUQSJaaM ztv*>-tfBTzpHV;9bX8Nl%=D^n)e>Ddo%UZWO;h|WQ-KwY$yc1e(M$Kfn{Xp^I-I&D zh=Z{24?kkt*XMn8lgmN*Iti)syQs*lI9l>-Zm-o;QaoFOKetSw{O&9cbh?v(ubE3Z zP9}|~Jfh_GDi^7+o8EX>Lhsi!k6o=dlZTtO$WpATGjfF*sTKEZ+@GbX;`od;R6_(_ zCOviBE%_+Y&?Fg6sAj!ula=f5%590*&+bFWXamK$_4eSNfqd(|YX|-DV=zfU+k&#S zy9Apyt!6ExHqxBWXy3ZIB(f5HlX*qjq(<_mEs`mN67*u8F0AkCD%OCFvso%O6*x?) zw+c1V+59uhITqIqqDLcF5P5Z+*zSnPrbzP*SCd-ySmW&3@Z)pR? zYkQ3H8zuuJ)f066ijF`NHb;KHO0&+$X2@Ro^HsTJ(Shcsic> zNGrqFA9g%(H>~-oOq=s7nW6NDq+55MVrd_ zz7^OR$Q}x{QD)o2-Aykd-bgWM^|zoBwBAf*P=6_((xJL0s9xjwbVr7SN^8`dIB{34 zxRSd%F{;-nMLwOkP4z-1Um58*KA#W$2~C>q^LE--)0~|kQJv1!Ym^$9HiETm`ZdGW zFOPO9o>`t&cVW;~U}Q};vy{;mM@t+R#cf8|;1V7x?Pi&p=2%`Q6}gW$C!f(D(AmvH zf+^K>j`F;Y+N4%4X5c?sMQc33TV3D~T-|}&S8AIvTZ2g zz{7PSUG(4`2Qz;#3B2)b?~lG8g*fW#MbOE7J8&lqrt^mYE#vy+-i_DYkFjsi#f`t+ z?!kjUSq4$q!RcfV>#7IbZaR5lAUr>c#&_Iqk0(A+7We2OO`T|>kL$dzyWaI%NDyx}ZFk-CQpR5!B-{#=&=Sv4Xpwep2Tx>g?2~ttA~*pi5f2 z^g)U?W>mL`UU0kT(JOVSZFKKKiuIOgmVZC5c7rYy+$EHda~aCx6lFmzAts zHP&&Vl~UamE{E|LYL0YRqPbksTwF%iSFe*2-3O_xu1I80Jcr<_EV8UM*1CJ$JtN$q zvzJ~lZHBzam?PuXY3*`pqcBmmYR?S^=vjEV4MpkM%^o25Pu*EoFaFPNneK$VewxMp zBh3QRfzdI^zX6#`EO{!A-0lM2&G>43cOMtRSy#)OY})k2Ife{W(CIWZY@j~d0?A?< zB8*|YkpW**g>Q#A79u%j=$Rk;y!J_LPgs85{IDYt$Z7F55f%@8;nrKO8B9k~9NwtxapX9gCX&dS{9F{kvH( z+L_E}chBinT#J59qpe{Q6oL!pm^!`LD0s9cp3-i?6`Vj;*q7-mEF%9-6;E1mBQ<=A z#f@(2XIwRa^_-6@V68AMtZ1d2kEHXOPyUR8QI0ojll}FT4VGA;*VVnN@R55!xxT;} zsUTKRu)`kZ83g|f5}GF;A) z!rjVQwzP9V)wZ)^?{@V5APrc-sce^nt8q=sL~pwS-;0eP+#WTU&nI8+z}xnWyq`xQ zwJ$Fyv}sWEwy9%c0v_(aPtC5uIN@7QGOnjM7qP|uT{-sMJsFHq_#}?Q_BFe!^=7he z<7Wa=v^L@6(z}T-iVZrX>Di(SQWecr8w6@+TqtI;5_uCZ6jI~I|18IJD|Ks@=G z0!Ezc`}uM*x+VH*tKETP{H7Vgw$;nDx*G~8 zFXo@nWcp*n_WbMa)q5B*jtT#FWK4YT2x7erK&lPfhfcT}3>-;XjuHaN^BSw@BuaA2 zKi>JFG1s}RyKbOJeh!(G7zF!pG*5s{IPWvXO1in~~g=~@Nt9(XkQDG8Uvv32Oz73M81gD)&<`E1563uOKn$@M`G%f70an7@P ztiX9mn88k!3xrP2NsB!MM>vtgvnahr}O13X8U>rv*N6S zgS(&A#DJ&daEJ4`$Vcj2E?oRahonkGbRDt5N`aU-yS0entlGw!H>X!HndY{se~c)L zS4D>UvabGi3rVWhz4eY2y8>bICyk{n_(%TWAq$|jbxXi~8on!34)k<%sFv*(S?grP3R~Nfyi_FU>Y$8Bs zMA++7ZzJpe`H6Zu2P=0cQOPuC2ULDcq51w~JA94#)$B4eC)A%7tRAW}=Qe6Qn*bDy zKq3Jr6x&WhaJ-=qnB%(*T2}9)6!kNd%FZ}6=@7eN=ixq>;V2+PubiXx_~t%@A89ML zSlX8;ruk*OW0r9jt;as%r&d8PC6b3x79MO z4aAzVudN$c3oiZHhF^RYAr&7pA&=^q(l3aJ7Q)gYWbChMd#|*i!(!m!_AI`N*mKT* zymqeeUny_RuDD%pOH!frX4(c zX7-tTE4*6Ng_p&91Hu~%S{%mHSBCF>&(Xsh@XSSS77IEms6?vO|Q_shkIW#gn z+_WyJxzV|8I=Kc;mZ5Ap@SPhZYhm|axuqJ;=8yjz%x`&1UY@Alh6g>bTT@BbT)^d^ zRgsaO^MZriVG;CEinhk8ZhN%J#lzxYgo6w}=I$`nTG-JQoZDL1bvBs0zaVZj{mP24 ziV@pd*lm%h>!*5Le#ZvymS%drJ5wzR+qI^0)R3vphB=n&^G)|zLMgUP2(_uRw|OG< zq8}#nfrwLE&vLtGIH4a0TjDsaH;ds0gPPoy;;{*{QOF<#p@`7I65);Qtanl*%xM^5 zh&5*7wAHPU#??ldX5rKjMlhw~&SZnR`8k=EhTEExH(5_tAB1PqeCC|22&~g+F%IfVb+Eq`G0!wupi>!U`Y5*rl%~ia_s-iToUaoY8q=x<% zP6FjDc*cAM#=sc12n~!9vFjrm7!elpcC&!Qztlld1k9R1I{i8x+!iEiB%7&};)xS| ztUIvMoTJFyoBAJv#7Ly6W^!V8DJo64HI;r^ zGxHw&W0`r=IakfW&*q#mhQ?65#@u`Sk74dDIV@FOt1FedZHm@3JD)=VJ)`Alt2HrU zD!mTc8XWzFDfR-oR%Jgkyc!fbad)karL9Ce?`{1;(DL` zL2niZcR{F*fNa5QZ+B^$z>TMTun=t3VtXO!9xRk|RHhNoUPEbGJ-saAx;Cffn8XGl z5GTsQkZTaPcif`0yYRy(csH5*vACi-2>nTKWCZ3uh?{qsN1|t=SO;AQ` zIQ4w1vI8)-AUir9e*pp{iM9m++7{t*q$ud-O3_P@o!c_9b4&A7OEV4t*n-pu4E_S- zMUra^^3p!ZawO%pP*T<|Y>wU{N_IOg{iLhz@9U-}S3q-m@mvvW&kEhA4H(?~yX)Bq z(K~T@=SGQgsw0&E07Xe*xO9usyZNMK-XPz{PH&kC0 zs%^IM{G6x6juesPfLMyr@ORhBzM%T~OBsxWa3pag?}ml1r{uprpm2C4k(7W9%SCxJ zgxGPW|06Sm`cQ5ob{F}_{qSi!a_efnfm5(IorFTuqk((B7X;r{xTj)l~AhOg>?Kc97!KLVQ6 z)H9L(a;Wdxl*&pQ*;YAwAXRs;1z1s85_j#nXeC6_7VY+hOXwU4$lh?IKf%!b^dPH{I&n70$XSExM`;I7%KnpiZ z%Bon@a?X{#cgxw3ZnfZyjqBv=vr!s7l(7vyt^VE$Vzu znEu^3ME+bXJP}goybW$~Q|jq_I`y5CTc9Q$QCegca4z0H#X*GX##uk-bDBr16xc`G zyWBnL%3QA2oR1Xz6=ov2y!h+g;^+=O+vnU&myNQlh0Yhms|9pvfJwJQ zlMMX%YzaG2&AqxQrudJvr}No@*!i5ZCFgujuX=DkbFLWUDp%N}$!3>&PPQCq0hM0A z;C$Bd_0mnVoP)>tY+Sa&(CU{0I-hfLp`$i(kTEp$;CxPQ!4lzLC2!PpcRzgSon79R zvW?TC0Qqs@&ql%MdJzoA{)8wJkK-jR`hWm}&r;%_48}M9-ANpW&S&fXY!o%GxCX9q zxE#i~^?C#|e}uDFtYbc(&xig*Jmz+3EHpq3+{iWYV-V;LmN?b>!#KV--(JTfb0*en zEy>oWMGK9NkMmr;TY-UEtYXaO1RmII9$znSOJBUyxtIr!!(b5;9$Qd@Mt_a!Kpl}U zNde|iqyg=>1!}kkqB%H=xnFRiom)S)yhM0`HkT!dDs7Z{Ad45_3Q;`@_=Z!ga5W zC%?!JCqhgNTcn)!Kca?N@e74VKUueci7b833X#8;QvGSm%}yz4yB*9XVi{R$j!GMB zZhA`EY+`0g8gsWWDJ7ld%twY=sp-U4eAns>L!Hp+jxZ|7MrCg@w&ByXC~7Efo1&XW zK)+0CCYa}FI0N%M|GGUineEj+Hd5TZ=zhMOjIM$Ru95&JYB$*g=9cR3B~vqEHyOIv z+zbA0h_tQo4yObAU8!BUTy#OltLr@v|3cSu+S~PJ?dzX|*=Qc3yke3PI;pN@o9#4L zourX3&?dEFb}~q|s#j9DpHZ*4MMSnVObRR!c~cGZ!U>#1j9jIo5raf1H!Qc5=Hal6 z9A#5=4Y+qX_~o=8&f_^bS6h}6qpyDi5|T&UR;1$v6V^3}uvRLV7l-pnx%ES*)1CN( zIgZH(BU(nl3wld`+n-~KdWHyPVnX#}@HHozd~_?wQmTQzC?CX1a$9ktdM*l@ayGp0 z;L9L&K9mqMv2ag^+ca#kRMvUfgkyXS*lFw)g~Sibn*A?v23 zpJU4I<8fz*bgbIl)qBb@kaUP)^CaNco_pkZ%h{*UUwDXo^hUwZf9l*knf$(32;i!@U_~?E5inZ<9WkJAEG7v zsHN8Lu8dqDi}`F90qHq*xUFS6E(KHk98(Cw2Gx`B#vZ{v5TQA8?A=q)>)-}9g#F`EmI@Wb8Gy1C?3)xy*VFFEE?vjW z8&kGg5@BApLQyPi+4`CIzS0%*l691>yqiY(m9BFnws8>qHVns$O01%%IVjzqePX+G zMdRwv(zRSITCr>;b+b*`@~(L}ymYk#gedDllBFvi=LA!hu58|YTejM95}R4Jh8~t# zwod2uikQr@jkp~>cC&P?-89Ctbe#h$7PNdtD`vE8#g2Rx|Zo~EnO|UnNzlEvddbwf_q>&hDul5O&v&O z>l`P3rm{8MW94Gf{842q7r80R)^{;iC;qL{l~NBDEp*FP>+DLqz*rD-?VmWPh?D8@ z#Vz3sM+0I%UPjKDTq%dn$@LA=)plni96L}!^x{x0N9*&MT539Sus!b3ySKsJc;=+a z)Zt)$AEEs?SfDgWu^$f@W2=%da!#tDbdfOX4I%hY|O`i{G@M{IWC=-NJYOdd9Y&Gck2r~M?hTHXg84d$d*j(ovixgzV z@&};Ltur6|GUQUu>3lNr7ZGqh`-6Ac_kOte;K9R&t5sw9W)#jB^6`G`Eh8Wp-;X0I z6$jX-N4?W`C*EW(zAa}cGV;R6p|@AvAH2(V@2j8s# z@fg|2Kg>Rni~2gAFT8g%XFQ8$-U262;(;FpvSXq|7_hi3!az|2fXCoD(c~Ub?4*x->EnL-c#u9GrjM`F$D{P|*r9G0 z7;9$)7tF0U95b3k)Sr6&YtJ7&_;68U6o*F%dHM(~nnO0n@e@(WqfvrK>thhkf(ZyY z4MGob8Uq~haVVXDKk;ruVmLva#WK40z-e&Nqx}(GTIxg*0Qqy^#C~`e#NP1MPkMVt zBl7O7>nuNc7?2nT;;X@OJQ)q< z@vA5tz5;0Bd^~z}Hypl-aj^hmRK_z=U=wt zh!7`?aZ+eJ9LL^5XwU@gAAp8rr$5X?79*l67?rT|qFZW2e>19`dJC-`(@8!Bf*fes`e>PwT4i!jgC(Q_($vvt)zN6x z(P-7tXw}hZ)zN6x(P-7tXw}hZ)j4(|ef%|cJrxQZLx1P}?1K*860)zvdodni^ofPT z;LeHsPu`y;j=*3~!(h*a@M8>Eff}?#qshPwNOZ;l=%$MFqHER}?^tE1x1)x4k2u_*<1B`r&{@uW30Y&!1)b+lV${X?KQXvMoSACD<3hd!{W=ay6P`%> zMUumAaUxUHBMrmq5_3zUD-{wLG7J$N!U6;_BM4P|#|xnZQxxj;k-mTKV6uvqli0!B z9B>{LZ|aB8+0+&3p%4j5rURfLkWSvRe0y9ACpMFYg^G}HlJJnKm-DKF4%f-B4&{B!W(eD7Mgfw4y!-x*y6PhmvAJ|W0@60M^*wUqI=9wf{hqc=hg?GC*mT$MEA-N z16K-Jp>dQd3jN~=fYTeMYye3SHDNTfjY_?p_PUtCCvnQwXTe~3_v3u7Bt7~#UO3c_ z2m9!5mW&s{xd`WXP-@PSY$wXHIXt&b#F57^?z%)`T`EDVr(xfo$8 zSA>QXP5ryEGD{*PWCB}|fshcJmFYFl|5HC6-h213fF=-r#lWTk;YsZ#$3d7Ti4Gv+ z#bZ0b!4%>}=xyPvg+lNrQ1Z`#CdP9t8XPj9z4 zA(&ILtdrp+zJQcs;owoj;d17Hv4}_@i7%-x>S75YA7C#@wGDmv!xg=zcA$%)6gj69 zQ`n6JrCl<}76sG{jp z2i12@cVGs8`?%BDbq{vk&fd;%LA5ZL1Q^nca|XFB{IjJ|nvk9NK>o@euKm_g9ua*9f~Y{Fyy2j$2n z#~Ug_n0y1-iaF*7FPFkpXN5)8`n^;9KTy_jM3eS_odQ^PDVti1{Jtdj{?fUlbx67# zB0^$zmFtuU3-wf$LHl1Xuwq_LXOisDl!E?=8d2+D$$GRz#9$omtA!WYFhZ@3X|{$@ zq_1YXf8^PPnATV)%v3+gIz(6e1hbe`#e|vB9BRnbssyYx#{RujI7gBgM~e4I_bOYI zp7$Mn4yBobVHcQVMxDWG@T4_EpaV7uKB*95z7H2?-FLly?kT)ee z<$9lxiUDiOWIfIZLUKi~;@8p{E@6wMo(So|zyuXOsi`}nLo$;Q3>VUi09`h*7$D=v)I4OsxM}O4Ag^n0O5fVLAIan}1Rm0}ZUHfP@;pl+O~Sj~QMrV?j$= z*^9P_#Za9fVg*CGKda|?7^R_-&_y?=$ts0HpC4 zaGKqdi*_hbGBq@-s>N_tkLq-RAwdL}0m8zU*l zEPPtr(RzuNZNWXy-{LcBBFmZPNrZeQnK*srW%=up#)RC))z5>KU=cXSBwj_m+&F~(2+uqJ=x1CMW4qCtjv`3KKh~*ePT=z>+2kf|>N{!ob2DOa6H* z4WZKg;e7y@X+OndV^nA=-Q0mHfFGW&9VFxI9tkMKW&#-xqlw2?*kg`f+@sNgHsp{m zM6{8R%egi+u_PkL*VJ%!5QWjOZ1uFCwgV@N+(eB^mle4GaQnZJieE#iGRw zFkg(l8F|j5fSl}-z77Tpzp-sYonGGF%Ar_-W3Uur%EJcsfH7HV?9bx%XjzZVDE5bm zy&BlJ3lDxDAeSX8ANAXBQDRy!Od>5oA zu^<=TBqflbH<4^O2MRnk0z*}S2Lxsg; zNZ7taE}M=@7;TW*ppyO@)azizgL_Bpzz7~=#(iRrC$zA%!3GyrA z!B4=4l?4<70WR#te5A!RK*YkP6#M}TZzPVJfOlCyq;O(T7{kRqSxQf7k0dvO;?xwx z6v8_kcq~q0L{CW3iDqCBVvCr(FL{D3MnI}50_lMltcRgoelS;Fp>hf!|W3Bk_bC$u8u9Z4z3)BIp)eeBJS zEylJG27HmtB4R`sL>?PFVR=Y13Q8waJ8usvH43(&ox&lxB*_ygfhI?h&@utwhcoG8 z052sLCB*3|w)7U>J=mpAOc?;3v@}Y|A4GA2iFPg1s_+Lzl*S{{58`JL>u0$#>MA^K13%|4m9R?8cmbIrwXS_g~1rzj8uHJ^$xJ@eR2C z_SYl%<6eJhH}`k{>#zCM-^;(ha{go&aa5UqlavV^^}PFcqCR@u`Srg1ajw6#oBNOc zUex%P@-OwMo+tl%(%L`&^+NvmU-XxDYyb1$um8t* zYqxjwe~UWj@^9X-{Ja0=-{)%opZrT@)boG!-->U!sQ*v@gZTIl^6&r8-TTJXy7%iM zW6sqfc4!mggb+e#Z*6jf5JI>|D^AZoA;vxC)3e3OIUPF0lcT-0kG2&;h#5i%A%qZm z(TiU6q8GjBMKAggLI@#$M$PNGe&hVE-`yN@tmb^yI_u5-UElBZy}p0%-+hl!bIvD6 z%Cqm~IBh-Kfy22Re@BUOo#SMoe|DEVNA@&5-AjFZNnu3@IRouEqRMCc{o?c39 zwFzo@2}I+IOs!xb=xym2ELt;|#GGQ9?>U4W=?p#gGo~RBS1+$;iZ`t`=fU^fwHqwh zvy!XTg{65`#%r?(?p0iCr$7;8xfnvz3oI*9pwz-NgGp>dO!Ga5uxT6U(DR*pg8#X! zSH_b`dd480Qe>(fO*2@N{ctoLKs*ep&qj2En(lC|JqSAQ5SK^flP*pm_Iqwr3?k`6 zARpx6%9FK5KKL=eEt z2qYeOa+rL+j)wEmpO^&k37nib8D0d9Aq+vOX?+SNE1nib{{2@d@V1_(1{K5rerGjYNUq^)ny<5Jl1PKzAF9d8+#W`DjSGj z`y3mi;{R_5Voh|G1|T-AW(U~JVx|tPxQf&_4>9IV>0PXf|NnI$UzL9Cr?v=jsD?ld z<okV5quqvVv0lmy*{*#Lc9yAmfH{3R$LQ>+<@~A z*QZ?}(*~GQ`$POgo!=Vp*L8k3kZy z#zarwNX1M~x|k~U&DH1Rdj38tPV8A3XO{ft>T{-6dwY%(tEu9&67Sfa)VHOW>FHal znCeLv{}*#LofPk&Hr+{fYP7@DQ4ERGOS~{O07)DpZ%X!d)DTevr=t;fqQ0R}C&h*T zfu~Wv3Gq6pZXn(URq21k0flR=v<`^fLDdIwFsQ~LP6Sn4F!LN!o>mG?vw+loWOGxp zW4t+3?K80kxs>Y?!YD*+zgpTx&V^T93|Qye!VL@EEdb zwQL#!bz=>CwT{-n*MTs=Gy>Hc*!n)cKc1DmLwH*}E8`^^22G&*jf0O+)5o6a11Ro7vckBUWTtUa>3BK1KBvRg9(EfrZ3|*I&+9-A5a2?AGKvHLlb$xi z5O;zqZuJ!i?r?p2sioU0+@5r65moBt_W>Mz^82=x9Q04E>TCJc9+Ppn#7hCAwW=xh z0Hle9)NXDkw#hc<#o3%Hos44tohCU1aVx0eNs{P9L}iMBs6wJu5m_B1x)IU%9mGL+ z)uz}&rcp7CFGF0ZgT-l*syAR-6MlA{HS5=cIE+{O$P|Z5d@0hL7pHTIn6(#Kir4=$ zXIbt2Up|O^xYojtK+J+_2I5>$T|>MHs(Xl!LDllVexPr~HBlY&yi}fc3lMT5$T-Cg z#majib}N>B>vI8ub~K=N0AG}tV+Z`6mGP!D@5#Ctvv!_8l-|cdKWO8q-^KSnsx=*< z1)T`l{l<=e_p=Ptx)#SijuWz4458@-mbEBQ>Z`M6Fo{obG0pcJ!lrGZL$xjSAG(~t zc%~uPf!Y9s-j`sh9k87|A9y%C>EdmT{SvRCF(g?<3~H8#`SZ9-2BWbXr$?=@L7pT$ z9G`UOuwT{T;s%hb4VYTM!S^xQvoiL)MXTxg;bx6p)3-2vSwStpLn(HBR`RUoLH(?Z zQ@OWPo=$|AuceeaC+N$@)qdA;=cjxe@W^{s#!=(_s-@=Z%_q_X`kVM>ijbLN2)$o` zOv0Ox)G_oam?>prZ|S7@fk2i}$!c*$2QZxqVuw%zkobP9ErkCz&<#Rxq0=`=ynyN5 z{VnGkV#yhKEu%MzE1ZLQKdfXOarqnzi(T~ zLI2trX0NfY_I3W*+svN}kV2{JwjaSPYl6kEu&7hrb~@9SXk2|EHC*`F4PRP=w+k%JYd z7LIAHg?O#xpnq!Nn)RDS9LB4CjEKV}K3O#9#k%`6@r>e%RQWo@$DoQEJ^<4Qu1}4m z+f|+J8ZxO;4Icw$Nq*n9l7s%KhQF3y?RJjCCGK!Wn?ja}JDesKQoF;Q*zSzxyx7p5 z|DE@4MsZWBd>3Nh|3Q?U)g)PW>>ac#&m^@CQXK=wv3$sdb0LzFloVwx8VW8Z2wT6a9QCtZ91 zG(}!ZGUk3EZ>Chc8QshFm|dsWbG7v2jFT;($GTRqau4w#sNx2^j#sUmsm2=ydTZwZtp>iVoB$3GIwY+SToY)`@6=5fRqKJgb!`q4Yc_7K( zhD$0Nh@ZHx8}M?7HL)qks|~Q3#Y}y`j;lz$7sZ%{e&5U!gg6{j8N`X8iW|cMGgUKAaa~DOnR+fFJKjh%CZew?u8Amj zA{!m2u?nKvM_Zk9Sf}w<^uWjn!d#*ii{bwa_e%|rVO5WJL zxYM4M@yd08yGJ*c{q&2Fu3`vHFR*k+fl>?83?{J+G0pcJ!lw13L$x_|zK;+6XJtIR zq-PA80&R|K?W02{p9p*$JnJII*e{s@NjC!d;5B3}WsQ804;MaJo^(;X61kS)|Gcj; z*|ReCoP`HHKb)?yYr&Zd-%UlWo!7Bz?Z-L?Kjov3Pp)TWoJ!o;WY_rg?bI{SZ#tNG z6DNKgMDG_MT@g#_ru!63w-UD38`AthAn`&b_i7mBj^LUcCP93}CqZO*5j2W01f{0+ zDVVY1X_4j!0?ARyTBwNPiBwgJXHwagl4w&^M*8Dc;GeQu@C>yu!EPn)u#e9cU(9+e81&WP)x0{s01L3$8DE{$BL0@aXzv z&$tcSQTB-f33;KJg#2Df7KM65$l9~0mHq8TA3aoa7KDTC0=dvQ(87h^s*rbCalF zkTS(#sqD69tSLckh7CYA;e9BUjN++OMoh0`LCO?I|8IU3P|YAN1yx)+iH<}xPVqsi zycGnUBFZNrP6gF0#JQk~!?C1maa(Dx17Y&aJb9zAoE{|n44T0Iu)w4zJG!P)Gm2YM zS!vra?Fo`mJd|oO?%6&}2ZGo$?*gXQN6tQ@I4V_T65^Cp**wH0sVr%7KPY^eV&Kln zy(=R7s)iYL3u0djIpm`(zp2#zyO&z*&*w16kb)Ug3`u=KdkFVa(PR{_rLvaM>r4_n9%^Rhm^me)@_ z)=xg3VUu3dsB0G2pDX=(>9_Q>FD)(o=C1cthE^3OG7A61o52W7p9J|)TyX}LFkCx$ z8-TF2E5+&3v{ejQhbchH6n9{HTN-#z`BY4Hti()Tm443~`R&2)SsC|(0SQVpo^j6< z-*)yKrkn2s;VBi4Jqtugd+|9$Q)e-x113VAx*RvA8BF4hJEr+;5H@W@WoHy;|35x# zDvJ&^Sv?^zjpt|Hz#u1}BSOUT#K{lfcu$StVm>C3VX$X#{1kMsNAQOO*b zaAJ^a2p=H!zWT)=Y*omm!mh9*wF=mjK8@eb%?&H60f@aTI!hyvc*eD_4>;mn8Rx#R z#=VCk4slI3;nqD{ph7e#xf$UuSnL$!Z z5+{?wjG>k()nvySA(a?bf&3jY&$tmDhYVA+1A%?NpM_4DS9GRCj?X|pS`VebCNzYI`km@HCLme~mt}&x_ zd0EnJFntolK8kmMC3N2I%myIc5zAMlg}3%dW+yn1#L@f-kfGwv(3BNJhGEJDnVEsO z7gX_7Mq!!|q)dWYsNR--%X`Xe0anDs6u&C1ypi8L{GOGuCu1{kqKi}T|0IZQ2ECb0 zA`lDQP@%S^H0^vR$S%CY>e!Yx0NFPdE4l&5VZ@T$btZaJTsBQt#gKED0;Ejw2BxQd zqui#)f_*m?GksP1^*8dn1J|=M-Zus$D6s~N+phSw1|2YkBhMgwI)*23AtWmfMAKw3 zWCA8a-j;sR&Z=fGi5J$G=CeWAv?Z0DQSAPTFFBPyh?7ATkDElhA}Uinkm^SiucUfM z@mi`M-9qe9xOdE8K&mpuDXHvBl4TIBio3D_aXYBuQW9PEEO!GCdcTkhP5VmM z-unp&-Ku(P%xf2ff%r#>NyK%>Ue8|@#eT`}k4_Np4A-Z(xsJCVHmnQRr|*jTAP?2) zE+Ajk>Eg_s-@iX1h6yL8c8c@@#6H|6Aje4T1lKpE-*yU-xz|*2$_b(-AZ%#JxWe9z zDxC^jcNbJ~taB^f&QXWtEd5Nxzx;7x`xuiTZh$4;pW1g*T%S%I3Kr`Ybw1#l`ol0N zrUlohW#y9g*6D^3WenHUN0buq^nb$e{-pm)e$1ivIf@iap{61OGpMQJ#xa3*BvOOK z@n7)z8HI1NuKBZ;m{6GAtG*!>ZU}FZ+9AMuls8G@TtwS~gtQ1^he7MdSr{N3p%!QjEb9tncOFgK0dffO zB&g!e-iL|M#4jse0CF!D`_R(X^5MN=2G_*RK*$6j$v-_9gWi^Y$zJ#!-pOfF?Rf$ORzJ9lXZ>&@b86*z>8av16*$?)M7`KX1SL zH5>2K{Mdxlm|A|*hZP;fwbo#YH&W#*zuyPcDz3HLVGCmK@BhJ6Q_Vq~532aSVz^Op zmnkwv?V(38gex;#;I_knM2F(8(Cb=xS3F50ng&5GB0E)RnlFZ|!L(isp=qZWvI!F* zsTszY#II2wfTlMzf;|ZXtjuC?>`~(V;}S$y#VONtTMTJM8f{9)I!se{F{A?~LQ=hn zF^S%cf@Z8Z5>1oEkQtcf1hJ30G%X2YRWHC4Aa*3~0dgu9gWSW^t{c%HgD_1LLwKvL z3X)MQweqH~P;8MZYlk=~mEB^y;M@z`@liq3Q8DBarmJEIP4~r+8<+@5tx=3gtWh_r z9a7cS^d*=M1j#7&{sHW0bqL~QP)$SJ4yw3a!K-S{EiuiP8;#7dByW`Vrx6os~c9# zGKYFsRktl2cV=IZjN-9W7W)LI8$mLPJwL})t@J}Y45~Oo58vkco30o1x>BW&>)>K zbqiweMKlcxVl2Hdg$k^0hgd~~gg`d(DFj+jE(SS+=~56&_Z+4xK`fVhm>vbOifHQo zL%2wl1&EtL^$4-lE>yf*B#{*!AH;c9;-*Z<}#2mQSNd%&k)xKQHu_p*F( zNL`0Yi4MihC^13$CBE4{w=!)$E$DYUuC>2@rVAoRlK2~GUhv{j6J9jEK-?R}PW{a& zpMvRAS#}qY<_7|qMkR}?$Y!|-)3zX1^cGAzg4l6+0@JA=#zND%AjU$-&Br0FKhG1_ zST5lmSghzfKuTgUNE=K&f@BnTq^j;idTb?q^`&!NC;%}q<08peK|%hS4!7d zIOn!MlsHPCSaNp#6CaJG$)7! z%3-RjAg-H`z+ye#0L#7t8HA0!79^uM`G;{b)oF;^K^3P%qI(gQDNe|%;zTwE65WYt zoMIr#oyhNUgl$)NYcoyV#gKlO1_iO3lP2br_(p9Q-k}1kn~=a_!6d{D(1 zlW1Q=Wr{uW%ALrzf<${F8mHJHqKXq)^`{^>6Oj#zrmJGe9ZU~`*jCWguJkNW38uPM z#0?~*uE-)t2xRjdMxZI>Vh|2-RgjEg`yZi^cS4*BsyH1IZHlN&u}xmN6WPc~v>~E# zijPuNoXAGL5A=b&Y!Wn`6hkgxx)Q`jPSb-R7U%}1x>m#uB&4p$B1i~i^Q3nOWPRzy zI7T!UW8s|V1<5ErNL4NUkslUh1lPphctoOQd6g;NOO-p3Z3T&zWVCagg`b=dWS&Pmj~q1p(&5!tY4S}umH!?Y=gZ3RvHf>@w!m_h|s zw?nKVLP8*$=K%tpcD+AU+0Fyn-Ye5Tr~o5LKPXetJrxei4mR+>k1F zBI|Po^n|=@S~TUwka?IE1+hQuPt&>}7HAo!x>m#uB&4p$B1i~iYeDZ_sKQMqwf(^;5lOFp2LuW18GL zQoSqvF&~bl5nL00z?4Lb@+wmdL{%rUyM;sxA{wW7B~|W3wtyQzZ_3LK5}J04A%`#> z3t|r~nl1&gK&LR(w<3BZ5mH}d0VD*nTZ-QI%EkK9jv@AGn8w06FA9=T9Q$MSgqnwV z5LAZ{PlGC|p)?E51##O=|2mLO1lU#}8_O08yX;F@^Ok*G~xWs1vERY^1{BDne!rCM2-f82Z36s_q$tjhz=Hqj)7%ehabxPtauIbV#%$uQJ6zRB<93 z!v+X8MPy^3X}1`12-C43HU^q51hGJ;Fx6EM*G))Zu^vByrBmHA2pc;hNJep2s(c^f zLr}%(kSG(ROfe8uoXEy71A6* zIVHxB!@I76xNbrMi}iRFEIZ1@AZ+ZpAQ{D>9!@47fw&S>aXKWr5>c6AAgVZ#jo|?V zk0P=$(A1`M4AKQtk03S%nwV2!41Msft01nMkicR+o&d|7axn-SyD3OUvE@(F7}_9a zK^3P%q8$;HDF&j76WJJ!KyWM~>oHB|#gJ>5ZUwP1(8Qb)W4MQRT?KL7gaj7raTmHa zsO}krjm-tgD4t4{pF`~YlQo$*9TLsSt4uKvRh-DiumXZr5!o1M+AN0b!n7}lje#cS zlo-Pyyz456>n0?ySdXv4Qd0K}!p8Osl2P1|s=5d9KB(e!NHio!nc}uoxf9u^ok^gl z6RwB@C!byKe&?foZxJ!ZEK3l2I)EX}YOe zA&v!Ayl*7h6j7Ptqf`|qvWGv3Hsm!5 z*Eq#Mlsl2la}@+@BC>hXv{ek*gXusJn4}2Jt+o;(3y&N02hb zWvMDoWOb3KTVCT715xfoHqRjt42#I-NmEt~nTBab5Su4W%qcO?Id}(%O=2F9P^7hn zkicSh`4(6Xm97Qi5N`#^C{F(w+=A*1#ND8ZM^2(g5tS)U$*bZ-Ru_pLL^Mt@5amu} zBkw@iPKCFT)6`oG8H8zA5F0s7%qcPQQFsT4O=1j?P^7hnkicRiUjWOx(zQSw;;|qZ z#lb&QBOivi98~ehNpvovGQ|OTRh-D`BGH+M#wiA(+=*=Dw;;F^k&T?Dk}@<%J4~H| z*vM&OPKl9s!#hB15L^~oHrx=KGC$gCzgWyC&Hc*-_iXk^J-3ekdr-?ZwX8r*00I^9t z0uqX})(}FL)XaO)>=8BHB5{iIf@Bo$rONyIKa774*Ti44L!xDQl__@1tKvjf7>Sld zG)}QcL{%rU&#{{z*cOq^d<&*sLF@zb5lkn7*vx4P=^4w<5Mq7tTs{-z8ZEm~>umk* zV5(b@_%I=)Rl_$HZfan$1K@QaL&#yWI2Ya`>w;tyw|;?#Xub!r;}@lh>n72*h{_ZL zQH4Y$5!nqzqAd}PQ+$-FN}_uuX7L<#z5R!i! zGV*cAc7U+{Fqy*Gb=`}H$Milsqz#$x;#&Jl=#qN7-YzDvA+m) z43IExTXTolIgx=S?3L{}At6v9BrHvp9e+T8#2?gW%nd=laW9(zy_SMkJV}~XiXqD| z5t90+a+<*;UT$KV&jvX{O_wU$#?3RaMQ5Y+mymF`8-(6%#VoBb5t8a}Gnhp4Vw%qe zVMhj4c1CgN&(=e04B}o;#rsL3Q4y6X2BHdyHbrDNIEh9?G){3{sw#=rL}WK`4)m^U|A)4U+|6j*_2O%QvI(bS<_jD?WW$01h=RLC+MSXh6UjCpN=a1>ro&xzPA_3YS# zUr5MqnlA>quw3lfaRW$bv8|Rv>@c|nOPHnY6(J!|AtVf{%8svVcIL&H1A=_xUN!@I zbp@~Z-lVCg7}5oXD1#M3*8Orx=KGC$b(s zfZ$O?w!}2GDMN#F!PFy&Eip~ZDRJWT!Mm=4xPgQO7F)l5W3lcL5?Ji#B2!>lP(>Dq zbKVgoquBT7Xe$OFE(BFv6p0Q*RHoP?uZj~{T_oBU(Ky9Glsl1a#Tf|BMPwtV>ADzl z57VO{wiPtBs!j`3f~j2)`xjSRUQB%|2> z=W;75gAf;kD&C5H5F7@g7;*s9u^=|d3z)71vF8{~y~@Q{z8K^NY2GVcYw#mXAziEJ zbs(eYN3OnDE*#&XAQ{E6K@Ph*@aKIH7jR8{B}Aef5tS+KiYUK>7>M#Ea6XFLhDYvg zagS4+7k9;ztdM(I+;-12SM4P-xmHGY*I&VOBZ$58Ji^qXBJ6mfDGb9{z8ItpX?7}I zTc>WALb_Jb>p&P_Lb=$P`U#LZu+;wbkyiW1o5>SEiGO{>LCrF8qtEJd;(fy%e@>J) z5w|><{T66;)F|83ZI})Ov0j#N19j;}veA#gG+hkYhv}>satG6cAeQbuOs&6#=aZ$| z1=D~a8O1%Rss|8<{(KVIIZUDvd6g;dN>w3IpNQ<3Ary4F9>VL9C|cG z`}+SAAe&;z+pq&+^=ubN9K619uflYK*E{#JGudN(idX1PAu%Cem440ti9$vvDDih; zy$+-U131$ls%#E#{MtwOKFo%Tk@!^K1%lA!MkeZBjZCx;u||}%4ZZ*4kU@jko2^6g z9A5K^ZENaYKb`_QbjMZCt7=*>Hg^DP45A(&e+WHrN z5XW#$Jd{YZD55gOB@yMv5Cc&@0nRgV+bK`(1#yp492IxPldOfHK$Mf{QYbqM`(YXo#2Q4?NHJsrrYS+}KBZ}15DP@ef*{tw z1|T`S1B(^y5Nj|YAzfQPn%L#qE6W*TpQ{2ZaucQlL5!FS)TjAp6gQ=+>_KcD;ks2i zAZ`U!{MOePH;E<#(dNgw$BI;z=llaGp&Omcs z9Eql@V#pm#4}#cY)5Ojv-hWG&K!Dih^Z+ufxfx^zrsZM?*XKZxjN;K>re!;Yc=(q~ z6)zi!jzv_aI3S{&MC~HVGl(631-b1W{+!&G$oEQl+al9+R}3kk#8#DR?^-l<3Sxl> z=@P_R(GAm>Ahuqg067jUoCwE}cu)TX;v*4PoY)Rv5_3DA|K6;;#pIt zV9EutrY^v=B#2FqrXxX&<#iyJ2=Jglc3XGjjv3NTWRQ87)`}r}FzpLst)uCv7;*;F zg&?+%G+hf~fqHQ7kLV1@DBep|DUE(OAx3ab{55GLnw3|X;+0gn6WK6HG$XHZih-!= zL{>eCSWoS+rx=KSn58YFH>>KA4R!^lbwTXT+JR|L5PP4bDKyMj2ssr?A>@--Y%v%h zuo$Er``M>GwfmDRJS#{>@m#8W{;&M7@CUdizT;c~`bJ(=_p+tj0D4niHaVJhiy?%?ji!LE095G+71wkhf>+Q5xsT}^$GMb5&sB8U-lfgS|OD9(>*-4-F1{u-&`Eg?~> zyvh{kq^gkUE~tu#S_B!V7>IHboeE{0?}n*I5Ni-k1I3ULn8pOLb)zX4!~zjABZ#eA z1CR-L2No;ZA+~OWgmi5yXkwRZ>vn|L$Ev`JT!m>z5F_RS^=XkZiWgEGuF0Q1J1FrhQ4UJ{N>mI=yer0# z+WUw9{*{A%K*2bU)Hi@5n8Tz7>p!Dy9C9X>d>A_rR?luR#tvTJxL091!RwuS*&CY2 z`V_CwokC(llD`tg=maHxCF*q`qZmMo?!YRW!yCW$71lJYT#UrGS{aB!mm8U=do?oA zX~bI4_Sn$#k3(h+V$T!Okz;t5fDR?Ji9h?+tM!vxj-)WxYpXob2i-O zmL9z>gID}`rs=vEas?A1sl{#vllXa0O!Ga5@cn6Chp&x*kZ|%EWC7lbVzKwb9~gwi zZib2|mi{_^4$5~S-UU^>okt)z4n#48rt@ORHB7gH*h8JBM?q``gw$0K=h6V=9sxoi zf73@l*q`U`$JnI)>_h*OUz#zsEp@aK`z5|Kqt};?7qZMfOM56Y%jUfL)R98s7a)W1 z9u|vj#}G^-g4oB@NtmVuu{ES=TM%P;9mpX9TquyQAvUcG*Tk<1a2baL@xH(`8z2;y z%Q^}UA(qCaYJr#qReZZKY%cCH#Wks_>kvx{S9NY{^BlYuMPvn~x;3ZGe68wBZ_PS^5`#~uA3`?G+ zpH4R%vhxLFRxg&&6J?v)oln8A`ov<8<_7{9L1#vBO;q#)gK+usP!Yv5sq!m`Jzwh$ zEPmZ0(VV=>6a!JkiR{NHD&m?Rnzq)agoRh-D`ngYSJh^)sn%@sqI zU|JExhDj51O5B-*gbHk!4M5hALtwF@2?@E_qz=Gxu8Iu8@suWb&t(*6rOFo|9tKrB zOcJ#TQl=P)Do$i|^?;yPL^e#C28$u1FlB<+FlovKu|R}`3T&7SKqe6&uvpQAgj{S= zD`44Hx(4BR&IHLQ4*vC=Z$1ohIjG`clIT)IWr~5Q;zU;0JqR8|WId*-Rp}U{6Q*uK zY?w4Lr^KB}NT|Su*#M*$IRq9fnvjr-O)3M+tST}H$Fm_wMzQoaXqc@K$AT&zCW*F1 zRHhh+Do$i|9fIIUL^dg!&Wa&dFx?1Z!=#BhC5A~zsKAEV0OSri1QsirkdTW_suR5* z&VKAT~^zm{VeygoFxg zm<>Qikwajyq6rDP*revbvZ{&AV zVQvDwB`@nSO?$75DToCkq^=e57#e__AwXRpVirO|E;cE8vxUz;<>x?3 zQy&JD{Lw!>=QO=a?3eh_zkB8GWz(Zqn_@Ks>4bN;SZp+1F!cyxKRz9VX;=_{)WS3` zh_TT7yFpeFU`K&$z-KVs7DG7ZPK>+uWTnVbUC=y+Ws7!HCUKJ;@x=3^`qH&6WD0d>;iaQY8i^#TurWR#rkPeu-1hK84 zi8&>WE4C8W-U$^#Oa`l z>n72jh{_b(g#W?}NsfcVVXu2$h+`@D(h%F9H%qg)rgw*vk zZeRnDN8}LtVBI4m6fIHw zvc*{d!J>$4acEjChHS#LEr=}+P0T5=IE2*oG+vwrAiKyR1hRSV0TNne4JIV8*y3D* zd9DBwT4fC;ge-4MYr}Ce`=B{f)fS1n zQ2JYWm}C^^rK&DMJPN8f7Kz#gDN~%2s^Uae7>U~CHBK=Q3 zgK0t#+Z>vhQ(|)nsq1Onzy=^w$RPx>c}@coT4fC;ge;cath>L`Zvz|<#*Z4OP$ zDX}?()b%uOU;~f=_y=sqz%rv;ED*P4Ly(MOXO+8^XAswe zD&8#;?TDyMaYSAfC$hRov@N1>ilZW`I*|?Q2m~i0vXLLdbS8*>(SHrotsu5rG==nx zGQ` z)H%e#A4?V2O`;PKl_>_I3W<6|WH%Ivjzu(1v0E8cNz^GK+lp%t+=|F1+iP9 z6*1ct+iobDHU%*jLRLNwnfW;6BtTeym`q{py6(lpV|t$*(vQr~aD7|)wiK7}q>KL> z1U@v!{tAIF2AQ^8><@m<0TRY-Ywi#`ZRWue_R4mgkPxU45|*aQj&~K`JWgz9R09xZ zeuzqHe`SZqwn@@!J9x$WK+|q9WCtcf-j;sR{;{iOFp1avnC7!Vu2EA-gR`aK$=WN3 z^_P%vW*CIt{lzSOFcFgKZ!?%g^J1FM24P1sm7P&Mk*azIv15i$L%ZonG%c?(#bc>* zC$gK2L{st_rx=JTPGslJ0tgmGWKTnyR*NBkA}A8HB6QrIjLku_)n=t+6mJZYLKhAhCeB#12zO&fw(AVTVT8ZS-*kQD@|YiP_uNL{OnAR%4b z3VMe?*4$y4coS4{#w6+$q)c%`s@#cew@B0@uW^biQdOMD zsvib=L|!&>nkI@NIZU&H*ly9ZEQkdnq^_rN0~>(MBS2k4V-`Z{T2%xI>DpG%I|Q=s z?jx5o6>TgxFqM9VCsIanS*q$P#IvA^GbT~HAZ3b6Qsqu$yG5cld5u$?ld9rGR(&tf zee$xA(==2J8G~s;5Zf)9W(Bc8gw*vkZeRnDDFmo%Xv{)LU8{;9Azj;wO$0hnMFu&8 z=|+%@;_TnXU8>GQJP4{d9TGi=s7!H2Ubz$5;*jWGMB@}EMO1MjTby>FJLF~aq^YME zG62(%AhtL(O$cIv2&wC7+`tAPBM4B}(3pjgx>glILb|pU^bUcnyUWOBOGO(Cx8+Qb zjN-(sc54daR#3$mljurBWr~@+awoFgBGILY#wiYqsNzIc{R0RdMPwtVsZGQN>4K?8 z5Zf)9h6FJdLh5=NH?RRn9|F`hG-e^Bu2n^lkgjb7y+a`D?ksXyQPIZ2Z8;Dmqd4@p zYqv%qt^`$_F^Nt@RHis6uiS}jw@7p>qH&77BC0r%ReuG7YZ2MVX}T|lv>;}iV%u)f z)FX%mBBZXTaRVEGbRa-oLt_>~>RMF<3F+Ea&^rXO?oJ?=ITdXz+?H)YGKxKahjwcK z;zCfx8Ix#VL}iNI^2(jac8f%NA{wU{h$>EG)t`dkOhh(vny!i=cQ8E&V!K6CyXv$+ zgw*vkZeRnD5(0!iSoa)aeIX>IYg^HQK>fJZeq&=a&UXa1XFuPWKBE-!I6k;<}{rZL#|-D5yX~@rjqKk zK!nuwG;Ux6kUQiM`e5C2i1me#kghFP3o7ZxHMLv=uw|;+Xt*v*f@Boi=D1w%Iv`F4 zRoojAt%;~iF%VUq$i6@&(W;2XDc(z!JCXHy7wA2C+01D=Du$fFbRo!0Tslp6f>-L82vjl_>_IsuNjvNVF)Taf;Vc^cd&Q6=m`((--J| zXoc-o1CTQW2rSk;Lh4!-?-n5;UE2zJKd2(>ZU6e|=t$hw9TLsSYn`w;F&PBS2k4<1r9Y*Qz2&NY}Q4-m^+K=fuJaSi`@YS7=Qk@e7bkw1#`};m^EB zYn%Kt@AM3{R=iewv*-YImpWuK?}Vva5ZiU$Vnc%1TF^8nh_Sp5WEBB+6v)=%45r&+ z2-l-iCq+haL#lUM5U+zO-cl0v2~wsQh^kIx-62u0h{h?dOO-p3Z6S$z*}z+rS1O3kVSUVBI4m1hPpH5?HKtgoKLh zH;49+%c+XCJ?7dy3X)M=nb#9;9pXh$#Y;+}c0tM%15wq9taK8!iD;bSvQ)VfS({1J zDzC38&P!EsBI|T7(0%f<-Jxly7%~Ragdn!0G|dTOfd~mbwIyu;GKBzj4UOkXNC;$; zB4l3aTI&c271@%~JLF<4+X!%^K(@!+%sW9cii^Kfd%O(sB&g!LNz@`pnPMQSI+1mU zL?sc8Q(TZLcOu(k5#Qm1+hScgr3?S zHvq{Hpsu0uJP8SbY*K{GC|zqEA)zAMV|s^NjAb1G_7uqW_yndaK{AT7f0y=n9^yez z#dVYDUPNVzfvD<4)*TYviD;bSjKb$mWP41aTM>OtaZ*GTC$cuS0o^VyTQ8criy{3m z4GLm=Ow)uQ7Ko70Q`_SPAj1ey*U)&LgoHpgDMBWduCtbxNZ`ii>OR75LKPXx!EF zDx$9`4vMJaMApVz5ZsB#){CZ+hz-&XQ>P%d$21KHVl0G&p4uKa0O>}6x`xK{BqRi~ zNf9!rbggxSgo_IsuNjvNVG4aaf-bPpF5H5F^Tp>^fkpmRB<9};~5CfMP%zm({(ZA z9;Qb@Y>#Q`RGk)xkkC`x;|3rt2oU;U-6JFfvPlsVSgdt~go*}zTjT~HkH{hP!MaCC2xOBYB(PZP z2niM0B6pzJeq2+FJObOa8e=CiS94vEjAGv+7x~8n5Ep_fUStyOh^S1lS6=U&$mT$z zZ4r%A3`A8YvObe&OGIB&Y*$9P6WL6UL2x1>+b^0fiXk^J-3juOxQ8^gDLo5BNZoLX zSYCiUAcwk!#w-r8NfA=l%_5diku5U4dsMUyU<9UVL41#4S{Edv*!TB^J%+dtRB^^! z@f{JBDfY_i-GC8UcSy7?qH&6WsOm(%#~|1e(bp8)l~L|Q*2ZHHoQTNQi>8ZW$PG+) zg7_Z8)TZ<-5WVY$6HlT6$O8h^H8f^%h)s%+x^5P+go=ERQEZQjwgHU5G%bklF-+@% zWE6M*e(mu-#KE6R6=%#9-w{!n;;e|?IgxdTMB5@7r`RK+Dv2I~swkr^5q(XuU0%5p zSsRZ*a3UgGFPbijAvZAH3F3PUQ=8JWK=d9K#D0&o0muUa)ipHk9w8x+O^T4ZZWghG zihPez$+jxWIn=OjHWS8d&MOpENc;k%1DSGlo`3Zv&N=z}F!T&rS7N`!zX36ZcoXW7 ztwjdYq#$;z^Ddkh#0E;!jv&VJI*?-oxKbcHm|Ahv^ytVj2-jmmkc?u_5)Z0(vk>os zD&A5O8#6HW=bS#Jk zBIH33Tbu?U`|z%7Xgmf&>RMF<3F+Ea(0fW_$~m#H0@m>F<`r5~Nc;li6s_T2JRco# z&dKwHo}t!C?3XxCTF{v`b;xGk3RAlvw(Gpb`UJ7HplMnVV|g9OA_8nEkgdfLOqazF zu1D)Xz{4Y>I4f0U9^yt&#al|E7D37s=cKASk#(mV=s|heetjPy*~imu0P+JVy3b~0 zyVn4O#fHAvGQ19C66xlek)_)JWEtKoxV|m@g8lVX&0rFLcT!CAJ%?11hI!DO;dtcAVO9Jv2>?lVr8}0hSK{% z^ojj?R>mEpXJ}6z`@JdI&iz!qUBmH!FMI^wX$c$@QmaXipydCDxx_OG>HgUbfrx z3WXS?4}|?9wsz1oR16t|X+jWNf0}YZEKmcG4S4U1#n%54riWq(7rIA_ol$K6HSKyA z#I2x;*PlfFA}Ui1L=`8peHsP9n24-9G))ylW?`Ba#MYmtWkDW_cAH+I5Q7|{kYm+q?V#zb7;**EjUcxEG(8Anff|7H zq5e_z!Pb8crqyBy7y3YujNv9jk)zlW0jO0GXWLwoYrFR}jg+EGeX_p;rlS180F z6Cj)vv9*JyycjYM)1n}@{xq!$Vu2cf9KriiEVlkF*w$`stwA`TF+nnlgTJm_AAxuh zRPp+gXi`LFih-!&M7B?JAea}Cb%&do8x(S@TCE*4JrqM)kyg9Xv-PK`TM!G>0AvE* zb7HaG-hgSp7;*yBl^_|#)8C`@zkoRP4@(uVKZ$NdRHhh+Do$kk)Ph*83UA$^sk0c; z3sb)!w*E8?3u1u?nG?j)9f66JJ#Ts!`ow-E*PouDJ$dYxSbut*DW$4=*>2M-6k?D? z5H5+>+CkH5F=P{_Z9#1PY1$XW0yO}+fp?2m($>EZrqN;u2Q)88Msa#oyFLr?E~w)5 zC()9K$`k`p#ffa6HbAf`BI^!KyTy=0n2rUp^{44v5DP>|i|V#?FW}9}o;Q6j>Q{38 z=^5IS$9{?Rr&q3&s_tdGO|MXhLE1ssA!2I>P2I(iewYRYvGu2ER1gc)0Avx~8)C8b zKZ5D97;*u+$^Gm7_8<)we*gLN6##8^nwA+IvUKvZ!e+owJd^oz*4L(_0EB!g*E z5LCVE$%APlUBIq_6`%ej zIuKErVj!xJXhKA`Pv;=G5|MT10;UH+Y`1ADeanmuLR0^zKrG#Mc$4L;(zmVl6S;;! zoe|U9Qoj+!m^UR`$}#*;R{ze0Pv27g3pFAgYk4BqDnVEP-HEMApD%n6?G6d!MG=VhBx_p8~OT z58+Lg0C%`PuM<0dkIp|UAMihq^~!i4OQ2aP&U@J) z@7AH(kk`9Ih{r({$6^e6*B%<*&FiA6SnOQlnRQ@A*t%Q+5?JiW974k-mM6F-eif9a^J2&yO!vhQnp)HjTgs*&){9mI*u?dDo!Id$bpBbnjsMxH zSH^c`A7}=O^X@muyJ4tCq^Fz+y+{ z4InML4-C==(`Yed7N(VA$R$h<#gI-M$lW@atsf@Bmo{uw@3@@vO!HsxZ02pJN@>L#SF$he{gAdg6sfl?1XVnV+D z=SGny+x+~*V6V9a$;SxO4@1vmzr+{*^x9N^s_tc9gVKw|CZ6D(jc@Z3OY3by53Q zfL~Ptwnj8<7DIMn+84z3m8LU6ED#|#g5*s7g%&pFb%+>@^}L#KwB)|Vo=>|OJErzE z_Ny&t?3UP9dWE*xGPYy9eOfbvuzj_=5BoZSYhqtXv>>lC#XwYXBHPz> z5NwFZ)`6y-V#onZM}pYi(R3+@1tR2LkUaZ%E1L5e@a_?f#ryYwOQ+r3h zYeY_+0>m(@+9Jl(iQS}EXss6T=XH)W80&cr<7mmCn8%JnvRMgXE0p|V!KJxy&x8dkhW0w%*R{NoYxi7V65jgjH4xY zGxmJi!`LykoAi4`C-3Ink996+}-4ZtAW$u&VT zirxQ$Hn<<+LQusUOrlK@l_>_IiW6B~2Ou~Uku4TYr^S#qwe2lY=8$Tu8dD{yi`w2Hh|570w~<6UA}Ui1L=`8px{g6`A|hKVnl6eVH!$4^ zV%tkon~JhPg!BlKFMYff&3Qc_Q^tBeYU60h^EdW<+Sb@HwZZi3KuJ&MFJ%s@_LtKR zJJ;H9JbrR9``QT{yCvQs=oLm_3p$46W;6nWa4UBN$tVu~OWNU4h-*O=7eS(Z5tS(h zqKXsQ4xfSGTtv27G+h@%?qPZq#CDjbP8DT=2+80roVu!qPC$euS&p>c4B3mn(u8Se}Fg*%lU!>F2uJkMrA$6^Y>uvzj zf&g`Wh*<~;x!5r2-K%u1bt5oM3t}vs;F=&A#g2bj^X`H;9aM3~B-#{Fnc|~Vxf5B^ z2S6Xn%f>*{X))vyrfWfL-ZVW3Vu1*$Yeigl1CUz;sOv+_LP*HPCPnXd&A?jM2h*q^ z#=;3M2$E5JkgB@;uY4H&39gBsZ;@zOUS*2cQsqu$NpAtYEiW4bP5Z@=W0+0_v3b*U zC5Qzgq^=e5q#A&nBS2jrVirO|E;cE8FK7li$I<$)^3JqwemAd<5G&4@#4kW@P&bEO z`!Vg?_i@h8%9xy_IiWAv8=l}>tMf9UJh^M$dzwjd! zru3wXS0zCeL#9AEt!TCvG|d%5mS9>D#P))wZ9yy$AqRrw9Z{8uAG|c@#g;PG^9Qsz zTJlp{?D_PD8#|`ndSk!ZO&Yr;?pu0=w%L|npTy=4rh3tXQzJZ4U9{S5H4qP9(=X|Wix3e&nEw$e2131Wc= zITj@EMt5K6a&umrh{0IT+Z#tqu5|4Aw7#)pYNcbp+Wy9FiIt{TXq)ZpElO$CCK`n8 z8xKFI;I7O~|WEF%VUp$X1#}(;~8!-ht^F*QfRELuyPhwbJvzFNoSU zji!}i$OcSXg4jyabSQ`gBIHbvJT4(|N;l`lelgbb_QuhYD;;}2t#9m@TItxYw!g7k zVx{R7+GhLufOd6g6Ai)*m=GkRcr8_a4{_+YbU zO2?j0>l-_!Ryy{p?QiUsSZR8Nw%NY6V9edxM1ybxrUl6;-bt00c0a80D6WZSlW106 zWr~5Q;zYL6Bw7%Wt@IpBb&w;d9&vrz=#ePv)RwOTzlLk#r${ty6+`x5IuOLRoThU@ zY|9C`5hRaGNHo4VFZPSEo)FuPWLr+6Wf9qyFTzv@Ifbef8P+zslto!T z>Ei!3;J2x0wtO`07DEnUIu^vXoTe*5ED$00g5+@tiN-hQ#eRiY-*_zhu}SRpw9Ti4CV$Xql~V7e+j&#WVbYJ>~+s4&?ZBYEMOZr%v*1`0e1DILT=`D2ANCbS8-HI8C>L*p3rY z3Vn`CNbGoXUhEfRJs;X}wB$)1dp_-S?3mi~*sr$Kv0Gx#=@r^$OWccgji_w~;pQ$2 zl2PpVx3%Xz5NCrbUOf`6iKt955LKMW_MAkUAWH4|I&AfrYv{U>3oWpb}i0wH|4}#d96Vev?9G8&T^X9zRuMq1Sk7Z|h?De$Iv0G}#W53!$ z$8L!or&nm1E${$Zm8oS0;npq-l2L5m(~gfpTnnmr$4RsKOC1;@UUvbEYX$h%{xPUZFP2I5^%#jzOUFhIViUaYV7XM~v{ z8=LrJ!>lWKRq1uFQtih&KMSwWd1V;pWf>A(S64jJE1SCgY?J|BXa!9zx()0uY=f!p zPKk3Nq^FpLH*8?BpK`tqWC}Sf6z9T|VqcJq;>o|GbL9f!(7!8HTsMi1MO3C3h$#s6J_<3>r@xpHlg>LXMwYCyFcVsB8zu^8h{ zvA(ZftgrS<53K7n)Wv>=S=%kiQUlRD5`_lYyTi}ID-5HN42iC*E1q(vErK02eSnqzbz0qQTkH@afSfi1n9{aEcj(-UG!f{V)-d>TffcMDt>r&jw*fCRBDt@l>knImFI? zk57Di3Xmw5SDE68R23((V}eA}@OpaUQzp~f(sC)LdeX)JErMf78Q2q_rnO?o7EC*W z*eOrbksua`kh-?U={5k_Lx2+nvLnbL)?-3Kx^`FXBS3(B9jAK@NJ(2^EL@n80O{WU zutNj5CVne>5a@ecpPr9&oB8)YxIgJ;Aus(0K^G_KT>bBztN*=o`QI4LDrQuT9V4#; zSx11w;y_;va)2Cel}m-aYC+!<-*cP+eIqaX+eAp%rbYOM!)1WPOAo!c8wm(akBV($ zdVqU=rtaO!Ga5@ZJ~*MSTnz=#6b=|R&1AhqwPJME2zpvjj&V=xkw zICL6-(7P@lKO|yMV%{^zW)9cXUmisaW4%E00)!C=Np_H+rI$KLh8IDLU?3=UTQ!48 z6d%)k&mru{4my-Lwqi(aR=!kA3#Rc! zrhSAVD7AN=f;rHX>@|)wKM)8za-)jA>A~E3_4KyK3_2jq4)UN}1K!9GnrzU>VRf4HS5PJ#^z{HoM8Vg^%S~WuZ6fgv@;bLOG zWi0@b>Xl=D$)3QD@q67d&a;d>4wQ0ULV+we(ZN-q*W_g#B;h$APlY~0W`tDn?)OUx zKQF}nK5x8}sFp;R&H!Nx5-&jUxt=_Z2^zv+k{~`AUIdMRVKgu$UhZHVdkI8_7eVnI zo_JqKe2i&K<=nP{iIF5!PGrxYL`JXWWoL*J8>FEk?E8mA5eb!tw{M+359F)TufDNU zE~#uFe&P?4HsIwDYhqK7R~uk6iYi>pYT!!aiD^X|_B`Kt75Kea`OLp20yDCGu5 zY;BLTY2ZHks?^{8(W)A_v6DQvIH~V(t^IAYaf**H_5X+bHaVlXEmeLA@$`VGy!}7^ zAYS5H%dzV}`Jh_E^(pPc52_Yi6O|;wk$WO=H$XIjBqx=(4Tz?hV#qQ~E5#6+Hj5!^ zFcFfvlVVKbHGqAe4}IV8zQ;3d0lH0I)`(V^+6A%Wya%Q}LF~tLG==nx<%>ZEkmj(` zwdejQOd(yX=yf0ru&7+@zWW5oCRl2(cm7gFo&frJe_T4KS*A7QGWZ{TxUZjc;%&;+ zd{#c<5a5lQ%${^1`&wc=M()7y?D>HIA#LMy@!fHP63#RnyE{$|l3zk~C9k{%J!r!< zakeoAy=#!~=GEO)EKVztVabZHZgc<=V%we73rGlL5SnHHeL4{-??U&c^vm(I=*CCF z(~p|2a0GHulE1P6N`|O?$2SYrvZC2{EsXXhyqLzO(y`(lVi`98IYNMYT$8sBLFX@l zPGBS`@x*EXLT~1icuR7KZRIs`xy3d0ge4|KDx`S&>i=|&|(s>lxd z9HymW$PP@$#gH4AZgEZCbOe>^-xT5}2pL`k-60G?sfm9I=3bTA#7Xl5fiO*Wrgqb{ zpxu1_Cho%*yxQQM@S^Dj;`S(ZYEYko=}u|RYi7duEMk~h!wpC(}p1S zE!6=`hk_UjO~-;53n3RDhujrIPGJfxR`eAhfyE&4k&$=~CcZgLsGP`RCEmdkDkri} zkcro(pRJdD_V;vb3z~x1r}l=v(6jU!nxB0Q*lgPq^D~uqID%s`&q3 z2l7?v*Bkk9Lj$0O@@Zz5z3>KDz7V9bdH+HKKl-qj3orY74dIVII`t!vjN+P9l?{lO zK^50Yq8>rY6a!K2M0WcQfnZof)mRm;GG~D#j*eN!?)(OcZf-dn?V)V-40WSAl5yadWsqirFO03@*yaUAQz6YdT6&ZxZjtP=c>^@Q-`XDX_Roog9&4|ciWiWjoAk3i` z6+QjDgjKH9>EbfiP{X>)v<;wXyBKl=({V9`ru$EU*cZFb@|hraNHe5se+2gdkdl_j zav`KMK;|IM2UR>161EmYT3{k1^+zL{!6fd>nC7!VhEUU_%C_v?}%)^b9)^og$^ z>Ah0SvJ4X;ss1*DNi;8}`D_q&WKU&h6qo)B9gV9HFM}%HPZAx7s7$dWubf0@K@}4n zv&(=y9a?m|tJB4PcksJc0(NN8)S~DH>4vGN7(&y;r$B5ao#it@GNc*OwL@zXkZDz9 zxe&4tAe`ZOP{lJL;Y=|khl!BXP1Ou0amU0opAE8!nhsR99a_ATt^~1`6T+oW99s0g zDQ3BbiI7x(o53WS7t?$;2s_g9U-E>?C{9aNnT5C)RPlcHz|<><9SAfH7DGm1$^@}j zU7DCvqBWE74iH?7cx$q}!4%lywf>;u94W6&00Me4?UqTe`&- z6%`c~HM1`Fn$?%?i;~o(`=N(cRQicN^zhbVz*@zC0Rz@L3>YwAz<>b*1`JS9QBhG* zQBhG*(T9qP@1f63&iBR66JKQVla+bljtHq*fe*I@E9tfsNou@Fum{1nKbWGt5$7q+ znMz(e7BMw}@yp!T`h(B}l|C9Y2?jDn?avswq? z2F7sH3EKK-&?Xqj6m5DVm|#ae&1VidKxR%bmcylZVJg}5OHADxBu{buU$Z{B0r4uS zd}HavRJTE-qjd?S)CbjoS(Sd? zBsmhu4j{)EgP-5zrrjANPciqe+ZOvAw_vKnAbE;Crjl~%#nhld@)So+C01jYnlMP7 z;;gB}Y7SFN2FX)gGnH7aV`|$Vd5Zg{5~~ADofsrf@xoMMb&084gXAebno6v4|HikQ z(vGowkSTVXO00S?HDHiD#Sv49)hMQl2FX*LF_l=&VrtPKd5Wv15-VR}K|c*1Mbt{p zz?+=>2lGIsMDl4l(@*WlK@NfrRO&tpky-_-&!SQy*`G{7i*o&AA)<66O>y0NLBKk zfKyBSa((w1xg6Mq{2vi$s_l$a;XRC3K>Y2+vN-sHZw zN?Z1G&PEF4TPgT&@qx-)g+F;4D!t{K+#m5O|8=HvekGP{KbHAyFwx5wUG}V3`LEyP zUJW8W+sBgenWQ;98J$U6_dy2@+e2Q_Rq(maN0SMX;l^(cM4o>d2scxHGl7CPI2zBh z&rn&8W)@7Qu9e{uZY0Nn?@Y-NUzwikC8cY4m9b^7H1ZVpOeJS?A5+%`$x}Qy`S!(5 zIh<37H%a9;nM65*6euR55{b?eieloH{ULYJtlpC7DyeEk^k_@_A;n{}`W+H6j5oO- zQcMxaPy92Y2jd>6cx2o&$~~^!@>oXhd*l8Q#Y5wMuiQUUZh2HE_nmS7m}26dR_-4w zw|rFMcDGxQQf-8^)P``Xtu};HbsTZ3+gRiZY%V12`p+~~;=3PVjaYc{->f_&e6FK? z9z2x?CAz<=()pv|?aD{on*~j%F{^RJF=_D($p5(@CLM5TiW4wD##nxc;0n_@l@Efn znoCyK5HnaYs|RR_Y#==?W%0p=+_{99B_wf)=QirpB414E(#BPvi#L?se+7*T;@ z;+8v++^fd@mPE-)s*6_rX7xjgE$04rNyIS9cOu2aEoY6~ea1abF=yOAQ|@u)mP#ad zuW|o~Vv75Bl>0}@Eq6J&dyM6EW#@Ym0|@ zTD&~%tvOG@|59&9>bfn3k_?5&uZbe0>v@(AgZ!jZeE-BhsF1kI%0qg=a%9A^f&g+1 z^m%QoAxy0qElU1N-X zFgFW^_UUSqUUv%@bs#>v;N44b)2fv`?_~N9{c>Su`W|lZogBHZH9|Sj!MXxfV?=5t zo1+kEC_w|s@SZx;A~J-N0TS%GsC1nfh%-Rs@(;erpuU5O6V=bxD#Ow<_29sCqqpi=kJ?}7xWRhFPL-8@-{)P05oH3uSHDANIGj_(XC@{Hh9)x6Fn zKl$-LD@jHp2I)`&_ZYB8cx zJH)P}>Vw#yRNftfJchgSUjgaWm)V${x0vJzljq|glW?$WjwI29FyLUj2uZQjWcfG< ztv3*E`4_6TO7dPAwB=G5#zfF|y}&ui%?O!xoV(~-+Kpg>Zsch`bI2Yt!$OT-oDtKB zlU+W2{on8)ci_}MDgC)6>rM3zs%21*zgU)cSl?syI(;$-x~~V~WL>5Q=PoMeMleCG zdYaE1vWpTuwNedg>nIC|m*1q_N_mQNrjm|Ls~Lk7DBhZC`W|A>zgzQyB~i(&-csB& zRcROEVNyLp%o%s79b!jP`P$@?R*XoN)*J|fXXIhK=5kID%@gPWUvPn;B{Mo~OU+X} zGS$>E#FM1*38B^GM?pMmaC(9#1GNf1^2xJJrZ=WpKJo>h0<)D#i(T>pv6-g`lD?>6^agC$qOMb=4t3mRJA+1|tA!NLExSXoPQgn`@ySWie&^kQL zXAa>(Dcb3fEg&S7qCjX}2QmQ%ghX5L63nCpEU&Cc^9us;-5{u#;Pf|U6%Yj~k0?D)pxj}7utBtfkJhagVYWomQoqMM)*Oz`aIX+CpE2QtG7imHs5W!s14!EcW7#Ywf&pC_`8 z8K_)(Y8lkyFP7yv);C$bPM-{diuFL8tjjdv+(qTw2qvgiPxF~WW{{awszGfnWC8Kz zF<)4h7fz9Haf6$QR(xSyerllj{k!YRf%wGluJ5t6UH<_elkyY?O(l1FH>N%g(gT)J zjNx@f7cT+@g|-GK2N=ucN%7oNvd}|JeH`QnEY}#rh0?`~K*2)${=;u~vWT&~P>Lhx z+~iUoVlk;o5a*I=3F2~6`6fL9Hw)%Yo`stODZ#-B#;0dtA7J=^Ov^nBQTCY-l9%)9 zse@G0Dy_XH@y9`Ey=iNYx-=$V3A7D&%xYNF1ntxdoRf8#cAdNE3U34x+|QooGl%RW zGpya{iIkWg9OS3ZJv{I;)k=T9$$DG8gK8Pn<1d!wJ=T}AWCTkh=%G3pK4YA$%k=2n zMdjQGCa6_U^O-|hu>q-6gN^9S0$K;?2xEES6zBdUy9pN|E+^F*#Eqodfw-Gge&3Jb z=F;5BP1qdBDIDBme7f{}fZTAdfRZlIE>*CHoDg8z>@10m#c=Nq7s2i~`+hI%u_0$WTlXaPTox7-gHG&Cx zlc)L2Ap^)vDyyJN7C}75;l7ihE@%sG2#U7!C75mS1^Y#sUl7P4R&tY8 zL~-;#wtHk8;zUx-K%7k~-%D=6*^(eHuo_NQuj&3CLHEM_(_Q1k4lf{YS-x$&U2p+4 zX7wnkm3yKU3rGtI4r^By&>}!P7|T^pvGku#P^8i z5o7dBMob2pIuLrO8!U$Y2Htt?8;I_u(if-*xn;;5>9AoL-Dk3W=e! zIy7}4^gu|t=rlV74c1E`8R~)tz(7#+?9m7&SiGnC%puIkXv(qvKPrNT>w!2~muUnH z1VtOs2qws~r}@kw%*b}i@lkFEUmR5{ee0*?EI{$`e|^+E;#vDnTwD@wzBpRiE_}z< zubi_>by16$B`T`9MleA^d7950vX9Ih)Xg7JEW&ul$Wb440#BzH!@f_@RXq?H>VnR| zKv1;xFTtFHFW6Vo{DMFjCNuN&)OU^L-KE6qWl-1hww@&?>(cu(9;7;WY|o}rZu!I( z{-B|J98w~A91S9BmQ{vu1QM)E!;w#8!6E{c5@q=DhNj|?oCe&jk6D1)<1CqVjv=0;ANhh+SDYB}o-@<_;;78-O=`PC}l z|Kc9MCDmVNO0%@f?|*Smbq=fLW*wVMRV#<4I+BVUJijR9*;bILMl$@KGJ#|&BeD8a zE0Amkk1c^p!wI@laDoJ-M8W?p7nNECzr$00Q}p+Ljm_mPIB&u4$`4SEC-?ndV=H$Z z`30grO93QMeQ)J6Q2lkLgh}_z&~wAz5gsb5!>P#M|1~zB5q|xOe`+nm-*l6|O29BV zW_*lk4o^mB8J<(*FF9~M9AD8@re`mC=3t;4-{dmf_|1W2h~-&Gru=3C1>cQiPB>U2x3w-1qEf;l@fL@SS1hfv-%@@$y*8A2aCrPx%uFd5XFJjH*%_#L1*$ z?l_XD%ZLgTFHAMn4uVc2n(BermsBGVN0W+fI1Yew6ywuNW^ebTqy&cE1l$oUNR zDFcKNSNYfPPZKl?m%)A)F*S)XdTT~Z2AVn$dZ-&QLF))7{PxQXCdm|JFaw0vbQOQs z$fJT3E+d@PIw>TE&g#(AfzSgXVRi`Gtd~ME)CFyTfuN{SHi8Kj?`b}B2s5&qa;)En zB51oFh?8}hcECVTv=NP9f-HNQ&m6*xw4%qCPsCA<_YCiZCnXy5tZay;#hUIuk7 z^Ytt_S(l!V)GH~~6iffPJ%GZPmRrte@c5Vk!icN<>zO3z3@(EcaEPg6jL`!)F&Sv;KS;^r#?(HwfphP6~;kvpO_&AoM^;m>q(0DEkmZhPt3f zEQp|}5jTPf7Vl|3a|koio^q@`m!Q^qAWqh0Y6Am7(MB|a39{^IK63~&GMjRIl$*mB zE7eLiZjQ7Z04P5GuaDw2SNu*~ToP}-I9l2cf5(<9=E&L6x~LJ%5*5{4BbcC|Jk4hg z;Zw&_-TV>7B8+#89Q9Fa@U)IGZ0Q8;)B};BE@%S`1Vvl_63iy}f_){;F9?KTGBf3k zX#Hjv%R5Mk*UO-;<$gU&PS&O8BlT5EHO0wGK7db^AkHKen*v8#` zE~)5-BbRh-+_JRhKo~qDe=0vl!I8`9LBLO-aeToAhL#K1^KIMvJjLGsf<;ssfH;&? zqY%fEiqUY~0q2Qv%eSJM1KATtvKcpkv?AOv8IM^&Tph=t!!`CDt>A~P0~OtJ489W^ zerHZnpAAJf95XFVvQKM{8Cb#%qCLkD6e=gM?+aG0d5YVnn%aT5n^bhgkyaZof@C13 z1CH71sul1yjDb}K$UPSGV2hG(sXt<>^}l3Ss0nE^h6hx zY#8L-7Q|%rj)WWoD^77-5tiTN6vyU3GUS0dKd?pSGvu6T?$npL_TaaOgOZ@&=ZP-? zxiRm>TZrvfECSg(S|y0=T?Pn!(%~=X+K=A+>L31wU*{}4BzBtA4PV({FoZ{FVNQQ8`k%yw4#-C6und-MFrhS(k>;q9h#xHWeCY^2o zb0ZkvM&PWOxEo3kLZuitDEOZHhal`sqHzlcYL_c#~B35L^FiR_jkYAoeEJ z0L0Ox8izQORPzv5l4>2|PEzedJV~l^h&M@f53%*XNpV5!O{xKiqe(RmaVDweA+99V zI>eo%+J|_OROb+HlIk8}>wlZ#g4ml>0}w}(Y8>KBQq4nLNvd^-J4v+<@g%9vA>Jg_ zJ;c`Q6c@zaq#A%YnpEQuXOe0j;!0AjL)=NKeTXMXbq?_+sqP`R{&y)Zh`mWQ0C6;_ z#v#rm)jY(Nq*{l#lT`ZxRgDk+hC@;L>;g%QbCkoeIck_``u zcB>O{^;mr3sS8u17{AEA zYJ{>i>MM&CD|iR%D>oI2=cbZsqSdZJ3KWx-RPq+kduAnzxW-iL|H!kJr`Y>HQ}ws6nVlWKN~9CGD>V zQ@ynzc}$JhhAd!eu{LBKQ#-XG8v>DQ>I#rMW0~s2`g<%7Qc-GEY6H5%tfZpG|EF(j zVix0@+|P1Ax0;pw2ciR@Pt0oO9^zwCafdkGVTul-4oY)|9$^?5lM-RLWENwDVKuT8 zE0{SfnuS-6a?rlQwGIxRyo!z-96eY0O7K)=m1hbrjv|~* zVk~bs&l}fVsR8%TTUA2zW>MHao#nUeKAU9~lfh&L@8X%8T?<=IIj0U2gyN~G3dgskYL-<|Bb2RCUsJUsuN@78yS>)O!vog zl>1CK=POgb4stdE^E}2(5P4ou7WuEHbTCodkwV0gLNYj#Uv$A3W@^Wx5MlA@4N^x3 z3(3(U#FeD-M4Z}85Q_JvntFhk`(IgsQcHD+_7l+|#Pg)`5$$4%&~m4|fT}7YZ{@!Z z5)`N!vuZ&W+ASM$9u*?xr4T7EI_OW11|W_km0v_BriKh6zG*#Sko+XXxuo*M{_7y2 zfl93;oQ5Eh^M+U?=Uo3v$^*q6Q%UvjV(P>od5VvwlBXD29UG)TFJke+)VBsg{1-&FbbETJ!fie|!BWElq9$jc-#PWM?Gc7`PFFa6!(x8KrDGwVNPG+X(j598o+m zmGs0@Ox+kHPqFL&;LgZxN~>$LDo{*T;;S2k14f*uSTdFPqE){^3KWx-_?iKF-K_Ey zhwp7&d5Ggl<+qqbYerO{n24s7NFrJV!Jzq?Rx5dK+Hh8tH#y!cdb{K8${#|!S@5~! z#Cdyqk>l;cw>xTCevzY=!P}h+_1PI%ey#6l)Ux~{C-AA3H|n!Hu>4xz(WqtlMNZ&T zEg#fpZ(#YgzN1mg@{63nr&_k6)>w1pt?Lgg%SvDNYFU1f6ZlliPW3q$SO#x*)Uy0` zC-A9nch=!^)6SMWFA%a}5NWbonA$Ojufim3-19_my!MD3Y-J!iQqwE-1G&BXVCF_gji2EPt+|n7H36x3u|laNc38d|;&9 zX3L$T*a_9sYaxC?&*e|{6d6Q?j`C8X)4-%}Gq5%D*sq71k>-s0X9Ez&l1jbF2fs%w zKM~0eGX*0?JgvmCckMtYE2)1*oFG3_Vu^SH#LRf`NrQQqD%JJXaG$o-cF1r=W2-DVa0* zztMA;+A)YMd|n{Z^OhW>CAYky-(^$O*8yrxxz?0RQC|nB4RGyZ4F10}r`jIaD)OBW zyON6H=Kn*~)Ct7Xr1B-A+y!#?7r~UXukZUaN5#ulAem^(xD{|171IF`3ZlEE|FqS-Cd+B2Wk={V- zlCgZ{i*626D+ZC;A!NzQOCCuVg+;a@1B7LlVwqkC@qvXm-HkAMEF7uGfXJ^q1LOog z&&_xK8scM8dE!%NRr%F#H_j~jb#UIU{GQC41+UJSgt6MmC}N7+_eJj4r6e1{1b<`7 z(=-N|M8I0g_`Ry@(laftk)tLc=V9z`xI&qP%S$07&1}g6@fCQ>$SxJ3n*tQ^?K*a}#qQ~d_XQyevw5YuYNAVNHb zsTqUhDPH_3E@J8m;^3pHd|{Ai$A}6P7mcX21aUK|ZXvc9w>%V-z1ECW>_{2D z;h`nh6m%s{F{H}d9m=N~<{eZO7-fcDIpmZ_YcFRG%UG~f$?0eevIWB3=ZOgojv;-2 z9Aq9btYWNOtidxZb3kX&Gi(;jDcrC`%CGG%p}NHw{19lZvh8*J@_($TSO81x9(rV6w@}U>Y{F5A9stVU^A=Zv}R1 z7|V~b`mS*clRFrLr;BZY$d=IhAi2`_U7Wl!SF-yGkqi9<)`>-at}FxOR9IwFJ*1qz z4*4MGL2q&rjfYfr-EWo01V5R7hls1{$+KjDJbRjCgd83?k*I5UG4xUnLfbxBs6tqX&qSf7(=j^GI}UL4pxJZ@^TZGahdvJQ{9KHcS@^(I@NAe8L8$>EwA##Lhy`ESoPUgP-)!*e0rLz#v zlge)%i8hR=K(XDdN{bMelFAe9fPhw&!tDgS-^|{TX&tHxjPjnrq^s?Mea6f_v~zXW zRXQKl9_$Vx;{>C~7%FUMn7%RCJH|DJxGFHpGZw3~wr((Vo7snU=4!J_=aba~ zyFQFzYa7Dk2*#kWhXo=VOzUxDkq0(TEgD2BNg>kMO0Z5W(n>NwW*kfSz!re?fz5-0 z2R09hTARlNt!)J{vr5Yw<*T!-ItJ@^O7TG;vL&=`Lx^FU;N*ZURd!z?($~6Romix=Wq@=Gi(GsjQeKmGH4h59 znukPP&0~VD7Sxm9@C=YKtb5M(ptuQ<)frU4Yg$bpoRUQ-&FC0Ymj;nDbB?JygGe*t z(dn=TA?2tLseD=wBo>OfU$V~A25~;A{N|Bp(1;2Y_e@pl0ztPCN!^YDO{+@19YA+x zOz+4v0Hz9za^Bb_v14FpHM0-xT-|b&&Mz+yyCTN08O>mF4r5S?vjUMVq4iR7rJo)- zxnr(m_Z1?|XbskhMVe6t$hxq|rg})&j65i4MjjG1BaaE1QBY5Q!!tmRuYYR z^|l4wfib-!Qx}*jFv^3*E{Pog!yU%TM>4K%)~NJj+92@57{g|i$7B&>P>SOMku9P1 zOmd~oh?8sPN_Jl%vS|yjPAt-lGC&rEMK;w#!e-<_K{N7@s2O=o(2Rn5^35m%WC!a$ zwLK_4KxB0W74Vu?2MFiLB9vy-jiRq}X8HjcvtuRAh(~A6AX1JBk;4+ znSpqgRDSbFv~ENNifv|9T7bBiRGw%X1hlHuTL<8MX7-LuYfx2Sly?m#&1eVgB{Tcb z&edI2>3meXu-nHNHlt%qo?;A2@kAi9CA7XwuCy6(vc;AvyRQ&wMz?U0Sfm+cfZPd- zG$RiQn~?_v&B#NdX5=wJGYaa-Z+Hes7ji#rdr+K($m$F#;5DsyUIr{eX-4aqs&i(x z0XZ@jX+}Ic*9MVtREShQty}&OJ5QeCnW?5OA&&f6L`hwfsMV|r6qig@x`lX`RK5y2 zF-5CNy{$mEWoGZl)Pj&IFv{H)rZl52FkE1)JQ;Cy<3^=VM%}>oVho$nASQ<~2BkP8 z5ZMx1=aVaKMx0zQSF-yGkxiR~bz+fblmSu_7HLKv5;h|b3Yw9JM9s)!f@T!dlP|*z zkTtA(-}az*1(DSmRKROmZ6TZ;i%^bwPBcHtt|M4x@mJBSx|H%nd zN+hQ&_=UHD$`eKP7W}W67$(g~*|qUR-%ay&VKefepcEA%Y4VV=D{V#|lxg>+87Yf2 zqlO^Tj66%&j65i4MjjIFy2oUydO4)Zk^v&+mZ<_>)2fk0Xey)`@g6T)zmmIAAyWCY zUPvqyN80Q$C=c-LZGxCtA8F@_5jDmXd8=e8uf_mvqmhzb;EjHq-D z@gk`_Q4UkIs?^&YbSq}|j!d^uRbZ4`Elg=fEr1`H*@t$nZU|=4lTj=1?HI#m)Q!nr zj6o^(2t>Ao)`Q8FHX}|>nk(6Tg-A0Rg>_<)W|RRkCM?p7JS1#J9uzbq4~d$Q#{|tN zs3%{B86XQ-_onSZ@dP5PGpK;qv|2$pYZjq2qdQF1IWsw&i!M7>(u{a?mJO0$g}9bf z6np<%Ya@dYhm&dy;#yMq%^3yf1I9`jQ0_3Zcb>cgBl{L$Q3d5edyFysr49t0RfG7& zIh5u7r+8hB;}>b!MITt`v48q;oc%C@zaZTSJ2bn+&^B8OV(gx;$&Z1x1 zkOi{_H^;Vg>681IIy8t}EUyMRKnzzFi*)`6OjR8Pe}XbVT5v+rX_aH&90M=nmF0`}HPA@~; zOe&va5Rybs4oB z*9?#jSSJ>FRO3{iIgr*km%Hi3KR$a zJQ7V0L7Y#j3y4=qbp!D(sU9KbEQ0A4h?7ahI2V#?3F3KD)e8N{LVrs!<)B3FL?i{u z9JE^8KcqNf?%y-GL?pii@(_{qfGE7PxlaTIuaya5swxj9lshb3QR-EvpaDoX zSVrtDNu4$a(hmoN=16XyHB9Ydj1H{F1m6kbd4DiZd5SZC0sDAq9^z_J`Sg+K-iQhm z6VVij7L7=5>sCxnVys+aG^79MYNK6;QA^G;K-yrPSmd_mRF655+nQ4Y29X2eA<>e! z+?_;2vGXtF=1g@%98M~~IV8F@q5{P>vzqP`BKiHmB)T!8w-ggmNr~j{+y+5=$G7VU zuRJc6py0|Qx<1&UXuDk+gPT@uZj z)mw^*Xo^G+hLSsa5mOf!E0-6|xRB^Vquq*8OV%<#mSCM&3;AHILI(!C}OPf@WUL?S@iIe z1+xk_Ri)#PVFt(=SoSdn*=Y`hVeXhCY1j{#;@NwX`x!e@pH;N{k+r5-`RoP69>Pdl zExi0Z#MPwoR^6EDPmlqK!%5|>h$gi1I0rO+mR0LeZPz9m#nkxoke3l}fpEu&Ws5UF z82O>G_QYr1GbLXhO@Kj_AqSR&$tIOpq;z2TA395xr`V;xWY2r1Dn5 z5oiE%4F~CHOZ7Jg!jt+~dqqPyxkWp{Kag*1dQ5O)c-W7v$K_8Uo+TB<;$LQ6b{^tE zQu&OofS?zUN|T{HVrK8iv`_`3d}2CX-5TgyfC*bBL0#1#elY`OxgjzLIt`vlgq0?9uPyP zm5#hkV0E$7%hlyihKGdJM*FIx;(0Pa1`ue`0+ydpX%2*8j+rAV&}B?*VT_(IJSON_ zJfqjNKlDH^jcAqBw7=>0^i;#w{=Nl>05YdyVKV#l&4w zZh2U|!oo`+3d@HerY1O8oTB$igQmP@K^7U&2~-srWo97S%3FkaZ~G(_(HMk@?6(+e z5~r>GM36fyt`)J=XqU_ZZK;!zXbxlz4mQk@?9n-L95oP8!klEX2d4@>`?aZ^^xH+;1r+?vip#C+q{k492HUNcNj*rH_i1%vaDJIYshH z-=n;2kr(Oi0jdg&@}uc~^&84uVFkw}&LMpj9c898s*OSL4qF&f%Z)*}n8W9ZQ?1nW z{c(^X#4wJrMr&mb=qzfjSunxY`l87InMbf2wG-GJ2rF>a97&hCz|_@e0J%gAw-!sD z2cp$_hjf0T2`#@_AbPmARWGK-3?hxAA5#Mck?duF&^kGi>rElzXb~}NV2lpD#{`!F z`$flJ$u^&-xMHfQHHf)xqNds)jwO{Zd~%N(QGrAoNkuVnm&iR~+_DuHSoWoDh4hmQ zkQ-R9S~$~;F!`3)b{v_{>LFm2TqOM7t*7}JchgjS>#v1L8Ibb|dyUT*PftyZSy3|t! z$i1*gJv9f?f-u`GT-k;(Or;W(SY8d1M=XmLuC%*tOr01+HegpEvgjK?`u-~Rw)`-} zk))z{V5+HOh;4s04duYTjC(F|`@ZRko(?&~q+NLO@7?k$AF^q<0*4hHHFg#Er_8DV~u9R9MD&+!Yw*antEHxCcNn zWK^>EjX{|1h3ARWCe`%)agag8kjGe~i7*Fr7B!J9n02_>w53a#zZzr%G3;afA~z^M z!l4+g6UFG?t0!j9)-4T-VN_MFKNT4uM{tnNtrSjkAPn=uRwO&whQrlc=a6|!(6D$$ zH$hWw_7qEhjkTf$hzCjK(>Di#bt96HUk$P(vB*!Iy#Uf{i+)eBXsQxZvuvvO6i-Yg z53bB{mqFy=(nG>7y^WRbTGpi^8-tvK@cMaTLWAm}?~jA*AciB1HQFe1Kxa`K&4S5c zPg-qnq>^6^(t;RRCs7;qnBaLWs9S%2Ge8CqOsalKOmiS3a5QE+AXUvXwqp=EW2=}- z5Men1r2P-G)#WK(m}=@4V&7j&lpIzPjhj`0;;E^oNi<|c@&b=Ud9!*;ann>K5>*)4?u31}@kq@z z1{nom@p)oGgMLik9|!3|3$T_|YMS zNFz{)Jk$o&@4G+-$PSj2&XAS^uXTbTWI zgtBKLNn&>~b%ZhG@u1-6#xg*T;o`A&G=${-I##BX9U){XXG4GWFG1w_GWUB5xLdZ2S~Ey~ z6XI41P6w z-azXcW0BvCagV7s+j6NLLb|QI;7Ap?YEmsqAdK|EyPN%@UpYTO|5AJ7Sz zs}14QvO(k#g^(44NFF>S`tHa+%x{fG;(fprGyX;H*QL@L!2}n#r)dn5Lus^QtbEe> zbv+$@nC`bqk}}BvVVm1DmORDLJ~pnYafo|Ko+BM zoyGX1^!~kN`7y%V1y2^o@N-%_>K8!HYqMNqst;=@|BZvzB4ox{(Q%CnRXD%YJ8(Uk zJ9+YIhk1|D{NNjPr{DQ#mR-5>y}RHrcyFK5s?%kp{Gvi5l#*SA)fUEbggX#-lge+< z5vGm}A{(R-xo~KGkyt3+nMxiRX?1N7A-=~{>)*%&o~PJtDj}v-he3q62UEia$x}S| zo9Jum2x8~oY$~5X5-k}~fnv#sN;41_lj;=Wby9imA#m>9pzq2l{`?4Vi|c$l@xJfkOdGfKTk|(@bZtoKMpd6 z7)lsxy!>Mh=q!3*%!1j58G*R#6q#N-&%SP#MPwodqASR5fvz&n5r}Y zfC4)6}DweZyM|!W zJS1vu9uu^-VZ_WTEpL>s&a%o^Vz8Y-VfxdN0kVp4_Ar(mT|#7;2fkm^iU)7oB9tE4 z^8DfJ0Hoi}r}Rjk!Eu8~Wh+FE5UuAE3&r8T#Tw!m#Qmi5n@6GrBPvk5GgWB<1d~Q2 zcl!#^w5k;D19a_X_Kr;RP*q@**9<0IZ52$TX7-_-t2?gJ`Q@#_ZUbZ3)pjtshcPI{ zU4h7!(E2F3(g!w9-k2-deT7J0JA-v%k-nAzaxN^gsU8wOuz66>)jTBXY914GwVrWMair$s2uXaQ4o&ddrR+r}czh)3tdAX1JBk;3IA{$KW z0b`K|Hcm|#L@G%k(%42|omix?Wq^!2mhgcs0O;;NUVjYDF!w%md%AX?23g&MZRdk^P9c&fyydWCCOGp_XTG z$skhM3Xvm3>#f8>arW1(M=n6TN-Dp3B-%Ej0>v(~Dy=|VO)5{c4+2_M3bzOFAv1eN zrY)!{Fv^Dpldg6E_IWe=(9YG}Rq1?Ghp;=w7>O|JBTjguX= zRM~xnNMCz|i^L**EdwNn7!r$Id>#@$uz66>)jTBXY914GwVyE#bohMK6%2ZRg5XT3J zlDZ~Qr&$#!u9>Rz2r*|wQn$T;(5g~z8_?|;(>pSCfT;qb+;8mCjQYTEgR%Tm8SPwM z$*A<5SU>QC7{g{Xipf02pcKahB3nZ1$>d6#5hqv7mF&JkWYgwgomiw9Wq`~Ji)^Zg zgw4o zV#i9F5s%J{L8KfNB9%|;mBd1E{BN_)GYRn|sr=@VXw`@c6kE)yGzW1$sXWmp2xwKQ zw>H3g%LZGxCtA8F@_5jDmXd8=e8Of_3lO9uzMivO0qbculJfgtKK4N;Ar#= zRjIdo=-SNe9hv5!s=z3(8cdqe3YbRB>_axXWZDVp5V^E4a0+B7D z^87K(d+hc%-^ zh&_L&sr=@V=*EZ&6eo?SbPDk-sXWmG2xwKQw;8~f%HDCaCpX-1D=KQOZo z?Ofde%%Ufw9Pq6e!)DZp$!?56DRv1&wuILG$(1%EP8Q9T?7l*z84bfau}Cw@02vV$ zX+|CrHX{!TnvsV@&B$YdW)#$uFT)IwIjno#_MmtKk<}Sgz-wA9A)FP9P@2&Vrs|xT z2S7UPSV=SD(HS&|l%qnV@@ZX6EEIeGF6%t~5I2&_Zyt#zjHp2I+*GAu5R4d+)a@+L zw5rtGC3N@3^o~qLFjZib=Z#&O(Ht21%uycuHUN>;8C1Y)THPbUM~uP$L7PCtb`X+}Icy9SYRREShQtxppR#f@QW zM%xhE{%%wG%_Gs75fvzo8c}H<;z3e*qAL*4s#0%xz-P?t9hpv{s=z4U7)+YcHQ2Yz z>_aolmK%3F_#XtV z*rxWhUA|^s4bp}f`Ye__OKdc$e0W7nRh@(eASJM@m?L@KXbyy7E}A2$wS7#TeQL;| zIFdy_0Ma(Xj+Lj_Ybv=`Y1L|w0>xw{cVs)zJ!U0WdLO376NKWKsirR>-Y1nW2@>TE zQlNNhs*(~(&?G9F)mw^*Xo^JFhLW7kVCop-7rEc~hGtwyMdw#SyLqFQXTA)OSy(3) zc`W19vN@9f)WWHCgUAkgNVKGTn0NhsR&*2({(h>aP9S#w1E%u1AyJPJ6)3KnYI+^w zSyByvd&t~Pk3bwxs!524NyVVflj;&;zr`uPHivO`S_E$?rUjSCort6wNi=ChKcu*2 z5xr+{iAa9&Uy>WW z7^Dco((}ZG25;Ty`{N*eh+za{ji(0YfXj6YWyARDmWF_!#3#G|D0 z#6%NX{vA$4-zFpC@;UP$sEZg%c(VkNJV-`v?MOKWt7)vp5nqkNY&I5#I2W;#5CkuiQ$Mi?*~PBU-P5 zQD)wv6V!(AI&8gi;v0hufpF}3VnTz{OWz*{X-5pb7;9W!%mJN6msb|d4BX7x(%&yY zTuCZl!cDWvKiWCZ|(`rmk_#zgwZi~tvKs-(=?`u`83MWvVn^mC?ZdvNV z`$H1ZXBk4G>z@zNCfuforn#gPk+hrW`Ho#USr9#X^kY6&&CR-wlPLs$76z%&!+W|JW-tc zN9{IUfOwKrJ{}Sc{Ufw0P%N3%^fJVYq^d5Mv|0tD%;iR#ltXx}wqEJrjY0ZBIQ%>@p+SMr_s2n65JMNn8dn2z zKxfg_kOfnMn+03CJn6guGV?r39mp)KmyIRA25~c~{3#%s&~mdQ`na~$C8qAHASlN+ zt5oTSMCTHO=-#CA5e7$~0mv{Mq@yj>-y8@}YSC6Cy?O&v`xv9s>M_BI;bHIo$Jhz; zy%777isHVhrp_RCcLOjc}Q4owBIsUvf~*bYp~uo7Wr|K=0F(cjyaNW zuQ2t9F*?;A6Pz)g(P3*nd5UcX>qZ?ACzHyzd=kwYQDG6{N>WigGu3oAIOmL8UScZu zTXHWO(OZg%yQJLmus8&QBaC7B5X9632a8kmUTM&jZ!O3oBkI9wD=^B;K(v*kpvW7Q zR77JCCUW(8;ej+2|6K9->NMsPciq_I$yJqW$QgpYue~$Pfv^H^ z%#qv#1K7kN+svOIWDqfoSuA-Th?%7F2`8G+@|y*sw`yChU~1PO(m2*IwQdkeO$G?9 zlOySV3K2(_h~WWabl^QEIG5}f^VW*<6mLv5bq8^F+%AI!hzCjK_kr9yMpPitLsC(k zFrpHx()Ve&1zL#x?j<-^MW8H06Vkv+};;bx^A+h%oJ z_T(jtw|ctlxN_QsH{c?oUbeMM-W!9^`{VP(X{|MVe;i~9F>GM0afdJmbQawqSuneB zb7@PLlFI-&5EiMY=0Hy1=*+^EZRkYlv6On%D zsz4+!Y${zpVjs;@Tr<_wI>eSA6E)QiF`rbv;Y+?kxSkigV6it^TcVbHGO{^ zq!%#^W315;nFBhDI${>gINU7T(xsjZv)9IXGIdaAg|~FvU^|I^wHA4iU?R zg`2;Ic%M{qLU8Cj0bH3z~ld*Cq0?l`9AFh-wlJtinVo|_Bvl)r{}lT;KZiq>uBAs!}`PuI)1`<^Ev zBy22O2$!Hr6QMk6+(pK{096G>`P6jUM0P>HZ&{JOZw$h8-#t&9HmRoXkAv(Xh7*i6 znh0}1XHgT$f@wp(JJR;}8hSNIJ7QqTe32WJ|9-9*trNxQpPwhD*VZi!i(yn%u1`${ z$RHe~b1Q|@90*!LKZRAgh2 zF%V8XPfTb~UG)8NkZ!~IwR?{TfPpVo(Cr0#^Vux9kNHmvJo@fFDOGYG{^=gn=iADPH3m_>E?PR5_$jhmvE>E#0VPyZdEsPUC5aXCVuZoSzJ?f*0lBalTD#;10jtwH2-Nn?tL8Rx_Z5YJ^Q|W2M)UH9~G#+B=%piG+H>MI| zT3s4Mh;K2~@!NL#D31J;s;MHx)1>mJPl*ac;OsW5(gei0q?(7gm{dy;my^o7vmh<* zsac>&7+gA?K#!Q!S864{n57Ts0ke|wc>!d&HcK8;y;w>4FMs5iF~(WZafRzuIG>;i zaFxuR^sz~SNO{nD9?f1m^yFJ0-!cEP%ba3};VyIX#CYT~ z@{lkduHeCVCY5)`ASW#DscoQ17~DPmKqsrO)JpE25m=3xFWH|LK#H|l zW-v90l~nE-W{h!GbX?(S70xGU0bEPwPRc$5WKme8anZpVpkd?M#N>fRBi9olsamG} z+RJwlm(CIiuBRRGC7tU9kOzzSJ$>(4S=J#1qmLgooGV(4I(!fAsq&h6VNS=%EN&csSRBkK(FRRYml?&FZ{MW&+!u61_ad}Xt z#7nCP?xH}YzT_5Z4&+U)5#q+IG-A1)JS6P=q0(D6Z4PO2J^-E-LHc-5~#jw zQ)xcm-(Wr`{_EgQ4OD6+ACI&R;6W#8%ebZ zaXYDYAnqoWcQ*_-v*vDU9cU5;caK_qrB-qsjl;);`I2XW7eHoevn*gLkCjwD6)|Is zv!de)536uKLCfG;HFxstxFQhwXhiExK*PId2b0IVT19Zt1S%zxw$vO*rjIA$yD=+`SneJV3EO(8^p<~sziT9SkIzl?9im9rEW6-? zN1*cF0!W~0mX%yI!E3n2e6^Im{czKVv3&PXoS3%HJ#!GRlghgz(YO&6C=QxcX&&NA zQmsNv;{FGB z&$jrI{{I5Vy+!<*sMS|$C3nvNd<>Z{N&X8UqqSLz znCiz$D)$UC#yBfFu5hyo=Mz){*Q~jdnw}AebR}9Z0vdLu6-;iME4h0JNu@CD7goM# zxGwI0aQCc>FKJ6JfLvR|@9BHVYOW@6V^&AWm*1;RS(My8%q@LCwRInJ*z0#dzGwbr zmpR1{!(Ha&neoWo;~`-@TtUtfEq4zgEe4UjP>9?;3X!{~0}fc0m3zk5Wpwv6%dUKj z(A}J^RnDpR_9?BpTt>=wk47l%Zx2?-X%VLo&yvcQ{WYfAW_Z!$DGvP(Ra1G0$4OO- zXaGcCj|qfsa1(C7FEzWUw~N zD5kn?;U98L2IH(;EL`Dg70xGU99$FTP71at5NSEIo&_{)ISZIvH&=485W;OP|M3hz6*CcMtYA^Znd$lTyl19qh()Ux(_A!Tzd;{cL z=3jQ1Qw%ZOWlkO$k6bJs62`+7+!>EtEQH(}ME2qmQwbuaLI@pI+KtbA3wE1zS-C}g zVMaGgv+T-u1l>(q;mJYu-ae&Oo6AV~X3+?x|82o)KP}=A;!#rh?4M)m(I9z>eSgGm zmSKqdNmYxe=Xbxgs%$moR+v?8mJ!IuRXWd=14kdm@-;FJ_yoq_W>KrJ)Jkra4*2LY zUy|7uKzeJl3}UL?7XBf}WH8Rk&B7HfR^fbtM!+>@?xbKx1tL9%))Rn+J!b}!%jQaM z7DBkqHDc^ z` z&VR~omR^XPNmYxeeKy@Jl)Fs#AvXky5sZ~)>i^v$m`>Q0uMuw++$`Se=?Hnd@Lc8K zr`7yPc3%MLsLj%YsYi_E#kcn%5sb8=V{%Frp_<`RSJ5 zRx*ysIddhq3nBLgDfxv}E*z|93}ad4mo+KAr187}vS;B;)Ay+Pu1VaO)oSwP7d0b` zlG}y3rSGT4?PCtR`8>!M&A;q2rx;?m%beUa9=TmSB#ehEI5i%*T?jcdi0p+zq*Od4 zY9&|jz`Cs5B)%}C+of4{<$Hqe2CeYqpn7kg((1-#qO5d3Od#5%-{r1EvY zi>Y&iJ-GAm}%u(g4Jvq#A}el2qQ^1>Ce4_f#Ly zBn&Pfwfah}69Z#PF#u#Ts#}$ra#nG|q0!NRzlbY@p zh_oeI4*(io&cm3TFjsQ<5OQUZX}_@Yw_dm|?tk#zm@)AsefkBEO$+BeeGgjA)g*4r zY9aaZ#XK&HlJCYaxAgtg*L}=kv!4X{jQN*c<`hE=cbStb#v_-HhlKHP1qa3>mk%L_ z29do`h}=&Kk^AWs4p^3zd&bvgboVsNu6&EoU9Z)hoKx@ZQ(B$7jFj&ljZhlb41!-w zi&%!Zl2pFz{nriu1a#2p1C_dygAhFJHmp*2(iJlVSw4#T%g95e`jc(?G?4P`)9RT& zM(4T8&76Tot5+_U8mHLhdlimP_J}f2luK&l>f(fhG3cjiGD4$4<-wy+^D>n z|2q29B$2LJc0qjwD(@|T1ghp()%cq(%^?q>4pf`CACB#wkjDxQM<78b4OB|hycAYQVGy>Jn z*GeiZL%9Tt2vj`%*QpCo?49G=gQ)?Ck4fbdLZTLf6lgV^R1|kjHN6M1?f2+TK2Rw4 zTXGK>(OZg%yF~7NLzRvo9w(Jw$_;XnmSPDQH>)Wnk~8Fqp85$RC)JbElZBnt-?WC zrv4q>Mliu?^fZk@)?L6sv$z1{){50JXV`+KW*{ylm5-2CXGSCqU=34*gvXko5?ob|4Bf9)>Ae4K zknfuRpL_&lzc$Mirfv)(?cvoR*NEW};}^MM`JSA|1g|&Rk=H@X@4z>+kQb|TKB3LB zD<5pSTY$UZtb1>t(y9|-^kS^>355l@Z&BwduKcrhde$NCCY8@5i4KgYKylTqrb%>| zRJDlqjOZ=J6j4cumlKv#XN=mWo@1dOkH98G8g!#qp9Eb{uIP__3M%@Opi4llV+=l8aq7q*d5Y(zlAO@$ z)F6`CeM}u1M6T@@Ku&72Tw$v7pXW)*Q=B!`)B?oyr1JOTBZyiIA`!m;()K({9Y{Z{ z2WzurfDFKT*jVJm7BR(CRo+1|SId}--b*&iuG|g1yP!dOZ=cd?(q*K4Xf#53#mTzb zsGVws$f2S2ZepQ$Y$`d8v^p?|5T9V`(ja+?_ofnJTHP2#h#xT3{V&+*qnKZyYN`bB zBB}i8Q=-BsIQz`1Gy`!lsg@wFB-JX!wWRXyEJ%xcY5`~x2KQ1A(0Q}^O0DDv!v=vK zHY+Kg7eK~pvrJ%W04phfZp$%ajI*NS3b(3oK0!0!nlpFO4QB-+=P`M&v=UFH-+40oB6=f)$Kk%xrwa0RWF=oz06g~(ngL_UId z!U1cp@)KUZ=%SzcYL;F3lB2tMTdN#G@9k4sb-Rp|uSShfdfPs%PSPUIAf6|c-@_YB zwf{bEkvzr8KT6fqJj9!%dY-5-2+kq1DlI@R%eeWg}%vGl^K-+W2(UjP}Z%`%3m5v-(gi7;b~v!de)_o{F{K@;FAnLDZJ43J4- zk*-7s^MHn3X$g~?7LD9JgrsVj_G>R+G+a7MB)EH4#h0|D7eFp7;`j8uZe>}MxG}4P zQIqdaYAm1_nvdf%eh~X}C^2B)L?(vW?o@>~5)=soS^m+oz zy+tD@AO{D@kz7xNbXY9%H`jVG#mcSRR=#wj8?0G&m5*r%VcDXTwR&%#(yHHOr1IfT zB9tb249G=V#1+Krr1B@@0aM-oBCo4F#rz^wQzeKON%cHYVHBKwW>uPjxR_K+5Lc3F z72;Y_d3P41#XYqEGzo(ntOw}4S$(Bea)S*5J#1Ez{1-sRYO_pWY5*&F`e+21aXx)C zf^Mq{=Myvot~qljH9ad3X@ueqVz|qk zJU1S>o;)Oshbw5cMC;uH7YQPpd@B&SdkASUM{@UcVv1$?^yvvY)@5|}G|R5?ISB6N zElN43-rJ|N>UJ5ae0q`yrTy&#a*`Ht2Jt+peA(Y%s{LQ$MU$sE`7cv7H4pJ7scI1o z8c~7bkXe-$Ag(6W8pMsH+Jv~3RNh?&+zgw$sTH6}7~DN-^_5!5-O~#n{pL%O{{qNR zZI&@ijbJ5DpPnEy&ZkdL(Ct;>e1ayxRWf%{(-|O>!Xk}}4(0(38`lyhH!T{uo(M_R zGRz_fLvI_@9BFTF$C8Wi5s&zNWT1buFIn2dSY(r`>FH$ zn8WK}3*f}N&X8UW3^c(Fg1XcJbikC%s8JuJwdlsh4TrT0oR@ueqVz|qkJU1S>o;)Oshbw5cMC;uH z7YQPpd@B&SdkASUM{@UcVv1$?^yvvY)@5|}G|R5?ISB6NElN43-rJ|N>UJ5ae0q`y zrTy&#a*`Ht2Jt+peA(Y%s{LQ#MU$sE{I60qH4gD4scI1o8c~5_msypH5NDHW?*C`+ z?Sd-Xwltx|J=DEa71c#mQB_no-Gz!RDn?)hM)1G`541rTJnYQmTz6*jKm?mi&b>rj zjNpNYCM+U~?n2$|MK3BUx=~S4Q$aC*`}@Y+ImXzF z#Xfn?fzb1^#vJn--}sq-YfU%_#Kovug18)2+Fd8yjEKAGS)fVioITd+C)UcGJ$>*o zAihlT9|0L|%rcIyUSyJ3vMC*A#-Cb!3og3oH zoIQlZsW77x3kMDJ;`lpf&#LidwxvfvP9@@Z^t~W+t|4)AR(sKx9;-EzlsS7?Tl%hU z>pEt4uipguw)i)r%r1uLjxswBg~yyd8sf&o4DN)-oIMs|#==6(*<&H*w^`dT*qoN> zIiu&LclLZPyKsuoT}kGhS*P0DH)++ODiY2f8==|$wqdm&lQ@8Q7*%@OpP?)HJsva# ziUTWDO^-s{kE%vQeM0ntV!K$C#vo2c)fB|psG5T~A6432E8Gl-yXhj(By`RmYxNUr zWzL>1_~;Q|rudJ5^fzW1Mpq{?NzWNpjB%zqX1H93(*+s>S3%sFIX!M5W>=#16rk>| zG>6Vrab?aPLgG}I(TRnFhIw)PowH}r_%hqlBOr$o@jLo1$((CQ+?>^R^rgpY*(7Do z9@dt=tJ}Jc+1=~QAYT{%W|Y~*5ZzH`=brGGvqwYRc$mSJ@R+m5Ld;lLh&g*K#GE~M zh=J2GJ!ka1^v<5oWfx8nx|@)BXV$6q_DxzP2!j;~XOE50Y=7&p+KEZ*LfnfgJ?)Rs zbt8}h#hyPYXU`zSov3O=)b%H5^@8HPs7ga17#E^a0b((#CLvBmm3DWFczc9xI8z-noUg;_0u6y{MBJG}mv&TZr*>i>%I4#q2M$b#{?D<@F;S`~}L78`Eooa92q}7G0NH}|Jgl79& zK=7+Ei8YApQKhH-4!TYRQlOapl{`hJJ0Y${RU@K15T$>Wjq>?lQDaK~bW#^6Ht_WR zoYE;c64-@Pqz~|c#t~SnpI9q%uw22{jTFFC_7RZ##w_hf=2D9B(}cxfoarIL3=2{q zd$4qYqelv4CTzEXm@S9a1Aw|)&M-QQ;>sK>gm9R{Kl`H-3o7O{BqM0Hf-&REY$%U_ ztV_f*^gSrP8xl8XwGe&jg;6j`nT?dSrSIyVtz&jK@=1`F#J?G3b}>YEl-ao=Jmz50 z5H}uXurEC36txgD7Mrk+EM}?@vIl6o-RR06p^x)2Jw^1y^iGz~Wf#r}y6csRXBMjV z_Dx!ysEUM>#YSlMzY>C9j7cm*T!|`O{S9;-2&6#q=C6{IrL|lW7x8pH7)W#lqI9S! zAA>19McP2Iil=w79D?IUf|~9Eyr*#l*6JtL%A71`@Npr&Ol2Pdxo*sIkFHZG#!nL# zgK?%O3o{&%0@;(L4ICXZL}tRa8;IF+Xx#&-yXW+yb4*;BlZ6ltb2vtHVnM~c`eX#n zb}?jpnN8;rkQIq|hQ52ncSGXltV+?BUST69DRZ*0w)9=yv~|qxPCgFu3Gr`6nOzLg z9c6Yd2#+~gG{lXE8SDs;Iaw^kjD>}msiGm?HnNW(I4{#vL{CibWcgfn;f$cWPMLUS zp=xj6q}73{NH|$+gl7MnK=89MiFt?%QKjeoD!M)hq(JffPsz!04RPwP7F8pnQxK&m z3*`&Zg-sF^ZFqWjJ-fi4OHk9=%sJb%Rc#3=cka46gr8&aXR7-M$XR2SD|8*8o+0^; z8_3Ks)v-8zu}B@d;J4tq7k6gT-WiD5cWB*?C_;Vg-}~%B=OCU=@d?=%NJ%G_9yrLS z1J9t+Y4sXkX5)DTWM0CVq3?F_-H^CBt3vdplj=7~nbU=}rSIy-tz&j~^C6Irh<`K6 z>|%)SD6?})c+BadA#Oa(U|o33>0%*fEG)!K6%FyWl5GURd6}LhH_*iu_ZOLeOzLyl zg>!=L?xh}Pp=xj6q}2yik#M@$2+jUCj8#*R)l)1&oQx_x@8{9AA&>&aqo2xAat^Vu zCaOk62SW6M;YEl-W5hJm&Dx5H}uXuq-_0r!f{{2H8T)`D7vHd|E>coR;a? zqvxgfW%If0!YM*`*HR9%PPMmh(rQChB%D1qLbLt#V38zh!sx;FUp8O)or+56|g^I&?-sxZ62Bp~y6hP)ObE=83d)=hNn zM#w(Ik5Q$q&e3%*kOIZypUEzK261p*RE>yw#p(scWl@#xAl^rnCQ8uNFOX?#WtOhC zs&4Jt&fV`j;ip^tnE`nOq^~i{5W05pOgH0m$c)t6phtnJE2FL%A!C3#A031&3BVkOavSiPXtK~z!f7owQ~h~=ni6lCOnN$!ur{gPtj zE|GgsxJx4tN25x+n+0cdCj~eachi>0>>!$`x>+!CQdO0j%-vR&OkC#er#T2iI+W}T zF>6r92bji?t2i$whs2BKt z@o)Zc;3FV|jajD9H7gLaJ$!4B5@J}w)B8i98sq#S&^4Iv3(a8V8uEReP7mnkvI`5F z?(X2uS?k){H)*wjFm~{4@Xf*rIVkI*K(TE@mP#kY{;1NGB+-x%y`b1GRx>0Tj;cmP z148tYVvML{iOgv+41y&gGD}`V-1SUQ2Vzdwu6FOO=K}l|#lKn4kAO@yW+|g>x1Ke|`I)(en3LW@%+c@>L0n2OgOx6fVxNqry^#1^c42+fU9U`dGd9}W zH)(Z zNJzWOT%K_!Ey)BcP`nV8-T2V8BM>uGWXS=^aI^pigt$560@;F@^{ye|Pk7pbX^=Cw zn}CGBaGJ-JS^PO%h(T3gZ8XSc~%h zMC_pDa{ffDMR|WBb{Jd*Je`m3Npvj<#Ed*43j#4CZzsHAan?XSmE|_>oior;S)x2a zel9CBX)LjU#_4z0!o@`7Sf zR3;o+6$E0!SwPpKK+J%$Yc)bBZivc6+?>@W2=|4!K(YOA=6hDD6Jl3X>5(AOo)EpD zcp|D9il?G7=i~=;9pd@DWHF)4kiM7vUc#9A5L2qt|LuaKL*jm?&75V);97;*{@g-i zoKx@&&M)wE?kO4j2t0j}{7PbW8wX_1CJpj_IZ$JQx8{gO5$>#%wLr0blapq;3*uN* z>G2`amJpfgFo~{ZffUyvZbX$PE}^SKe802dm|yduRauDNSzpF#9%x$qV$$)a@!xM( zwEZWYI%+0#EB@cxsLgNS?gAaH%)U*QeksTF@WZ2{tH za?MI+1&TMKn!bbB_qWLG)U_wkwpf{|SVGsWKxQnld9|d~TD01LxEWPCoMm*a2*liI z%%h9MpG+<7;*(D8jB%Wavv)QzGw*kRJ`$?}tvaO6g>HyFQKj7EHO(H?=B#RjpNl2FW&u!X)MIV%Zc476TCpN zS5#((^`UE0ASO#fN&>O_I=U7GQlQvZX}I3jfWE}jtBu7BnAbatv2UBitV@KZ6dzPL z&ZR>R2$Sh;oc9pAmIPvIPRO!AOwHM~A&>&aWUFD#X|*m^FDOPUTN1GV|7{Y^IK)C!H6rR4q8Ah+(X=HpLHB`RM10LyE4z2YYVc83gUTvg;k;7w2B4KV>PB?3{~pzO4nfu zU@ccX%b?Wxv1C(?OINgEb$MagAEjB#70)s#byy5%zHwNyHmn{mEPFX+Emu6tpwwY8 zoaM%0E!wbpy|8)>xwTyJEQ3;q#cXGj?AJJ)Z}K5V<<+NN4<%TjbVE=i{iZMnspok6SVt?i0y zn`*T!L+WoF+9bMW1!6vS*tIB-0>xEPnHPaWbPfIOd=L3Lkom~c^>@_>yYUP^H=x)r zD)R|*iEtv(S0sv7U+Dtg!Kzo>o9VuSt{Z`vJRbq+`#Yps*MDbCyumZ%Nik`h=N`g1 zmvBtPC+Ld4zM`*IAvUF$*sg^$i>GrZkOOi7>)XaGIUt=V$&!@jt4)YoQKbiyR^0+I zpL4zFio`#%#6Qx+wCZn6JfMhMlaA$)isr6qH9c)d9;VNL48nR$Sj<8n{Te~ic0%Y) zadSWz+_jC77FU5{@^{N}?|?WMReB>7yqCu5l3oj7{O z@R+ajZNyrZB!dFQJ5f!y?bHULA5Z58(Ii?Ds}~eMit1gvAu^RG(V|$rq!=SAF`^EM z$W(q71p7i{D!=_OWXC{E<(c1&IC{tMn6Fd$VMIP68JOFa33L@3L-Yc0ev!`^EJtOD z%&FJ}#QnbkT%{#9qxG#t?c7-C@Vx(9!P99wXM8loyKdB&Z;!_Dl zuI)`8PgiGB6`k?XkneUvEnxF1$4!jlwy4ZnZ_a85goi?0pxE*E$a_R5#Ga_qB_q+k z5WS#yB&s6CV^Ntc{Ie0!$9ZF47wEbbh!RkES3w zCTtFfNz%shAS72kbAg;m&HbxS_A#@@*fr1?!mdJuP#peyxo4KfAdW|sE(eK9LiB>- zov5ZM-izu*D>yrZdzxaWs9sR)5tTVKX2Cg!XE;AQb(9O}+Y1b6t6{P z-uOtqC6FKL0pd7!W1QX9p+U|LsCk_Q^cl|%^Yz*6*(>qbO_=%=W0}l?*$3x|aGPbvu5&=b@zPD1p@kouT%((Dq_8zL zPN`0h!X4}eBo$MW1YLyq*HISKZH`li$^K3UL3Nq5=~9MF%)c1w*mXE|9l8Rv>yrwY zF<{qdgpheBsxqRyW5S_d0gJm=Xi$zl$2p0djUgXOuLkFO#Mz$np)9v^K$z9w z+^giMiCbG8fPadZ{W2#k*S4Bx&&;*)n+q9dSaiP56tIvy5n3y=MR12blqF*zN9ekU z5Q=xAGV`H1s~i#MfaI8XPL1!8Oz%IybErUZ;UA=GdKF?hs&qt_=tUnmyTqzA3UM;3 zG|>>O#$!Yp!mcSm{A-fWiK3@P3CgTQLRJOxehuP>sG`^=1$f^Mk+lg+jAAU4nfbHe zTo!IKhs)?<7~!LH1FEfPwF{A9q&Fhkf2z}iumigbp)w^QH6iXTi375?Bo4^lk`Ppv zNt=_2IeQ(u4#%!TSAceBQUNmr?7EE*G8bhA7^^#=nTWG)xu$xA<@0=6npm3KR+_WY z1^zB?No*{pG-cF&TgIS3@uR5B8PS~80SHfpxInRESN3TgG_B6W>IKDXQI#m(h{~jT zfv)Jwobj|yBpk!iiLT)Yp?D;!=`)DuQKj=5Lf0yuVPmn|K`zjUVshS8#sHbZ(^-v# z)Wu`J6$sh_PuNt=RzytnWji*eO;e67@z^BcfX&dPy-7O_Qi7MAH-} zMfHy2l&H)e(2A})ZXFRJ^yv*VF_FfsN(Um)y{OU!A@`;by`WeYt7#JLN0lbp1_2{WUv54^cZ6rEV|bgO zN_C8n^r=qs-+^O3+I282+6TK1ZD(V!|Eqs9n6Nq87b;EU%nObfhs!zBuaN33o>f-3$k$ZJ)#@WpDa%zi|xKJjHBHz1A>vmY_y2r;kQIUpSOZi&SlfP~PIdu}-( zdzcW^6DL_4XiI2b6Uh|AHb+iB2sxu$l37bUtLO75tfnMHJD-UuO2}q=;xsA= z#0(B0^yEyhZCJ+zXoG16wz2%&f@ zs_E9fT8eFWI@7BJ^d6q>=9CLGrIFc`csh%Okh*y6K1k3pc*4PIUaEB@z{)su59-KweUeMAIZ%5!5urRZ+d8SQeF8m;LC9+-5lq7>HpZgkhzB zJyj>BG0q`C^CCQ^Z_AXKUKnScmiJP<1&Rwi!&0G`{G;5sO6?H0qUsppMO5ib$bBT- zFDUMd)ijANqe>I?qH7b+^aYn@^zXg&+DxWxCK3RdoZagR8QkLOtze6>W2-UF*e1x4 zfjZH20@8zL^~IQtB`CvdiY}4!=F$Z;D;r*nt(DnRXf+|e45S-f5n}cfMjRpL-HQW1 zCXUQGM+jNmgT(>a-JYOvI7@eX%5xGx(bmVj&yXpGZO()u2xH-AEwOp)orhIfLbNZM z#H>ij<|N@9Srdq z{{&ra0_1+c^y7Gjp_zm@8&y{jucN9F(V#$H zP`nV;42f<;Wls78T>}DnN%34%)0W8miV%sq#i~egR8%EqyA)NH+kCr_n<<9hYohq{ zvh9zlH5xS*Cj5|>Vun>02rq^By{(yfxuI1g{v41mlHa%g|8yS$``Y8|%sgE}LWZRn zW@pF&;p{mOmKlnNqADIkJc%kD4vAto=365Ngw}Nh)Q;FSDY2C1ATEijKygDG0t7mHv@71%8_=J3*>}sN7)q6LS!Pa zrrtFq%Fdy7Ae=jgG7HQr)(yJu1ybnVuN`tdcslPNv`Pf>f>ymzrDvRD)d_Uh!&Zzi zy=S7_DrN^V-%1Kkeer{Gu|g`vhWGazJQ36j>;aiOTGl z-=@_#!YE5Pg*AxlQMCbaGph7#*g{wPKOr9yI}kra)h@)nsA@!XF1}t++!Cu9a+5H; zgHZe!QH{9Ig!?7MO|hD`+%GM+88sH*qi`1~UW=-92eC)omFOXkAxkJ;B(;#Td@o4n!K)Wr1Q*k|;6NxLKH` z>Tr{&FB0X5$g#3zHSX^*y7ZNvh`RLNk9OJ+8|}g`R_GX;fP9gx+P_Mvd2)fAczDt< zWbfx=#Bg|>mmhYq-p-4cg~;TfbH}R7Oer&3oKJO2M^~Mv!jVj#!WG2psA^<&ERYwp zx{0bBRu@2DK5WGZ)9FR|M9c~l$ryHZiVQ7`4n^jcl2MM4n|HBO_&F1Q=8cZl1OFsn zP+n4;64lHi#LIt*sG0GPHE{yZ@MEtc#Qmt!wWPbEa2LqE99501dIa){Vy8s(z7=k} z#r=B*S%|7e+}*-GL2*c|N+gP@nOV!!x`gOUijioVL?z*#UVyk1RT~huqG}IfjKCaJ zL-1U{GyH|f->tAQ31#?^TpwkYK1@0muR}bVuc#F;+zI_p!(WR5o)r#1JG4I*Y~FGW zzBcgue)6-nfy&R?*xrNw2gz5p4n4diATY$&XFkd`$oay}0a-^Zbk&lWeC%`>VD6;aX6tnz zcBGBfEeN?_!(8Rsi(B!#B9`T(Ea!LJX5t27ew~294q{Vv7jrv07wbVfgsP#}3o+7_v#tr52Q&l1@dyw-8bPJU!XfH?I2=NX zjlTaULt}69jd;-@uc!qn3uF4%6+(+Fh=vtB{m*rKxPg>Hq>+@Pg zoBpKXUIpv@^x<>ah0hJTOJsn|r-khQql)Ag zQAP1eR3(c22qAC{Kx9G2d0>@p6?g|ot`S7K?R&h5$@kHGHi0)$C z=Ie+==Q1u|Qmh-7Hq8{q%KR?{mgpNB>~MySEE$jlCGNvB z>@&j^HU^~r(-hZ4^%cd9dQ&!5Wt_fZN#d0IigRE{=D;+?IGW}!r7>1QzL)%t`S7+F z`^&f%V}Ghn%%tS|<7J2|QNA!sS`uT$5f~C*(=2v$Z*FkD zp4GVc`ide`Zb{x+_g@|VGqqi7`Jd(PHGKlHTe5v^cQ2VF+@Hc<9~;5s7>$!eSCZK= zxbzm2atw4v2b#iIvt3DXh9VoAv*W{<#{%e4$9D zaJg>%n;!!*r%OrSRLDZiXC5IXls+tkfgQ*UHPz|yNOig*-vrkUvP=E7A+CW3V%2e7 zfP-9N$Vt@&s-V(V1$418VN@Q5nEK{mnS-N^y0o+>PLWfI_eGzYf6l+GcM0^3SeX=_ zBINGja9feQGbqgH>p?oj(aYP>s9BQ;Ockc>cRf+#jpYVzSs>^ z^e0^U>cZUO%Z7b_9fTjwjMT0G9bYn2ogO^)&B{4tes|tN%x}e8h`H{u5c7Y;S;)l0 z;eM$h%w$tCGO<|5E28fnw%QQL1jUs@zW$arA-4aEqG}Xj^ktIRf{%UiRXBrq5mlO) zR+o(-d+3S~v&`64mZaX>q|Bj2tC4@cmUsBDyhw^@Ox7#6(HQ?1>X5T=wt;8W`~Z!k zdgU=1C-urpG_LEFtr!9hMU_+6jByk6z2q-3i-efE;EobqlfZtY$rBE7XDq-#1|~9m{iR2d&ysHl1z2FJlZalFlTk>scyE}5^9jQ|7lD$1RZBC zP%nmf7t^{m`RQd+Ve1ImaDGxe5!IVJhzVv!_*aMZG_TR=$ok7uoblg2hvam!dMq%peF30ZB)TaxB$rT^Daq zhd>pRnHhs>T*5T3t=4LqRz!_A{W&i4TATQO{|GlK52a${#E6FWN^Pb3X-BceU$XfBX9*P0@7y)l$QNzL5u z5yGR>nMUid{(xuLH;(Kdn97Ih#C9}*r9f;%VSd2ii`3VypKx_ReOaO6VoZ8=+<}PWd&>6Nj9kGUs?!mkQrl z@9UMi@~))@k(P|Lp}qw#-*5d1kZsG@d|Ub>%H08O5C%cstauEDX*okqnr8w@@Rh=^ z6(^%-2H{lekWXOqvS%UYPQgOVcf5s|I|U0dcM29_KF68KsAObfv5;3pZ#`@^B9IA+ z{YP?vFbZ)ms`TQg`{>IgF$Nz~;;XO>aW$$mF|EptA(QBe5Ob%%u0hG*y-mv8DbVT) z4#LiIktF|8tuC#2R+Zyu+}0~Q;A{lXDsmQ$`FiC78jJPHG8*gk$`5F8C~6_8qA_lQ zygLPA>Vi8;bWH-gy;I;2e~eWbsLUa*y0q*E@poy-Jk$FFou+rEu#N1PWqN<0ll1Ns zv|T7+&g#%p-E6ZZ)FAJbSYxUos40@<0v)3W#eW%dzIvy?);zS~PJ!a0sNQTr+!57F zJ;9zUsJL{e&=ph^*F^R97~+Yj zic3hWED4%p<{YWa0g{duGc$`29-YoK8piUOz|;Q@$cOp}jjP$n>2%Q-sCmS6Nj*DJs61E!1EP~r-45mXxsLQtsZLj@?Fj6 zY6k~V-Uu~=amuf0o;YL~m07{Fx(e3O*sfRV%Da{tL|QV|hG!GJdwBYTmTk+}d|Ub> z%3a(WDot-zJO;zGoFOO8GlA@&G9U1CGJ0kZPPKi>$h_=Xh`Cd+5c3^xA?8lOLd>0l zg_zHAW^yeVnOH33713k=3U3D*T3re81jW;TjaH>=h?B>n(u<$&qc4-h4Scl4aQYw) zM3p9{)nH>tE4m`Y+$pf@T#|ZklQMS-v|59Mu(MnwJ7|2USKgwr`LEV0R7LK?*%h8u zWd~~5g=baSjYdzsauAK-dgTNf9Ez&Bt{LMd$h%V@rY^XnMAsy++dBmgaVZvHpwfxB z>e8~WVc(@C^Gxp#bei6s!Z@;Hmg)V0PSU$m&~~AOIjciYb+gTuP=mZr0*$GLpyx;~ z&;p8(UOT^(paG&6Z%}dRwqfZ86~!S@yBD1xZRw9FcLx|zX?nBbF&L)h3^{3@38a9^OyKEc^vocf zYEzPtdD*iNbEjY-=8N1y%$bx=J1G*x_+$peYMUr}NlQMS-v>N)?>uw4P zXiU^AH_;gVH|mg6aJGhL*qAPoeKZd0m4|2?)ho}@xU5&+qrsu5a_X8fZi2i!1!C%g zJ4$p-0=vCa;1IXR0t{3>BCfi$><968X~{g(`vaY(cc*ZRNyRMF`vaY%cc-B3s;7}Q ztSa@W(No=QvnA9Z?~_1dn)lX?A>P5X4hL|!Q()@=+Hj{p@kmr}ZXn)?>ZP9MH9B2~ zUO0_wb(RChI)?9lPBbo=plU?Kf(D3Qyg|jKy9>8LMe#yZZ@ZC2k7QFkhIlS2bIkOE z;3FXEXi<)(dadi?4e9`>Vlp!$P>o8M=Kp=LR@1a9h}HBm#I>l>wIrImUik9c0Gb7K zJ_dIIIl|MOiMc>z;E=dXr*QKqkn;sk`}?f03A)Jwu``p2oo$ULl7_hH)1GrQ7s#7y zO%b`?7)rmSX6_US;nC?#qcW_w@$|m~@}b&sQ1#*IV1v9Q<&8Lrzec zQ#`9ng>S64^-5iN*HVK>OUBwzUxSzLxBdjkwqj&5suk-R&nmJF&W7-;DyPtxtyj*WF<-A-L8Dx++(v^# zQRUP%W84IJcM8PR1$UI_ngn)xr@$fJiv<{{ln_^4TK0qZyR>AU>HUFD)4NmHM0U(F zy+6=NdUp!iE|f55b?B*Xw%HPDkoQWgG1UD!LDh(e1q~3rc!P>dw}_=1R1{Z5 z_4W|rk*JCbNNhzCG{?*-QYitFjuz!us@J+M-k_d=Dkd{?1=Tg4&hIH$t7%%X6yY1L z4@nJ4a^}mAXzqH!Y6NH&(D@i-A?E>gXJRf888{>^(-Pb~3gp}=(0)5BY=SnjKLhMY9d1hR$7Y~$%<^vocfYP*t=dD*iNbEjY-<~!a(%$D?)4yHLWM)uE@l*=9?qLEa~U##BSl zb0imN4n?@bvD! zLDh(e1q~3rc!P>dH$jdm5ySyey`6(NFREfU66==)%`vltRN4VaM~iYS)oWcBZ%~&( z6_c4+gK8a5=T5;|P1A~{2;XogAh-}B^W{f0cfDYB1vCrjd!rV58nHF<4fv5We|M&kVw; zR+Nm)%btapI|U0dU*r~I?i4J<+$mUy`5b2^tCEq4#X?>Yz5B4$jzA_TPX32-fv^Da zGOG0Ar~5@A`jX;2tkN$x&E$Q}t%HJgVLjg@+OVqBLC~`OOup<_TYAyxt5?pW(e)qH zA%_uYo#WM(4Jfzp431Y@w$a$BSAIm}uwHqN21{2p&k=Xoi@V(7#9eN2;x2n}m%X^l zEl%9!7ANjlh;z_UE&tvWb*gv6}X&+13s6nK!%6bim0TvShaDje^eAyJgUJ zkEs%UaYp;K)F|&eL1XeU`KWVL;vUcRFr{2q*8{05%M@n+LBe@aw|EYcUAs;W%m`e< z-zrvZh;FT=!qyhF;nyZ8?uhEm3B*%Tz0|9?MyI`A!RfUm`_o~{-Llj>{#b<#Rv_$c z!`!yGi+qs;ARDYo3baKDKwXp+sKdKKSewWz9ec_#{nt8IZ;IT4s)VdslJ|_Cp$3(X zG^lh;B;u?M5WNcr75B0g?8QMvaZgllZy?@^s`vq^?#ob`^Su@57{N>@R9!-3{!bBW zHBGBtv6`NMSc)oL0HS&3gzw}zpqaJv>AV8SCZ7J{%ZDPzUMANLdLM^!?mS3vlIf19 z!%P%=v$@!N4lXAs4e{$qg4@iXG|F2)8uNAhF`7i?xVelWgzqrUj4Hu;1zcthUqPDYi9=YCLacHadwur!GlI5* zpV;bMj=jT~s3G(c<&97?7^nQ2=7~diyzj;Oh1cgpv`#e~CZ8bxMu)<*jn%$L!F zvnyoV)^CuIM=QuBlFH?A?8lT zLd-pgg_t`T3o&;x7GmyXm`T@v#CsAGi-o)*dgNiNA%RR#y#9~rtJM0R)WiimTauDq zUv%FlL|;-&V3pp#Xr@%Bsd_;{yXy6eHmoWeS#E-%dI7SB#(uprIj?23gJ%_ajEw6X zueS6d`T;zv$U!uQ>XqYYOw=pq&|vAR<~ianw>WW!TM-*~xy6aQ?8RMfapEqwIB}O- zoVe|s3@6qkN?Usc>qpA0nEzt-UE9_T@>$}{E_)|4iY%FJdjFzx_3mV}-D9dmU!2i? zEj7w}UDlXUtn`Wtqb4KS($)>K4yIGGf=sfnFxb0{nGhp@!(f zoeWz8vSAe|4vFf`6vUFKUh36Qqtjj&;dDuo{pm2}4SlmUbKsH#F z6ljYQ?qqaPQlJiR8DaG!lyvMV$Mj$8T)io>0;*dn(R;?vP{X~6jx?xrOeER_VSwn} zEVaU3)`@3OQ5+T3+hvF=qACs}zA=f@obT)K93z<7hH6KGGIui8YMNGzKYaLJg5Xw& z%;z%EJadB8J%WKNMKvrX?`bgtf=jJA7BmFSBz+OMTXd9TYFlaI+q-J=rS zSVie!O1ZAC2U1s-Da`(Zg!7_q@f;*4cAXsPDU-Cq-wsx7h%Vg8uyp`!`cIZZJQCHL z8;G}}dZ|}KjZS-QgVT0N_NT*?hY@x4s)Y?!AiY81w#8kf3S@&-NrAQ~;Z8;uB?ap6 zIuO=J!qqD>5Ie9L8RsJ^qZK?ZhXxdY5DGWG1SJUZT7aY6jz!U(-Bs z2#@#ESif*{af#OLCt6*5-&Ui@OwQV9Uy~W1bN(F2wylfK*-_}P4&~g*T&YaGneiA5 z^KyorG|vQbhsxaJ>16cGApHIvk}CvrgJB`Bh@N=ZYEU2(6c_(Xxvp4)xb$C%O0N~V z9}uE1DJ}`oJ4^IV6ODp^L5JmaV1G&Mn?RKjXZ15nM_N_tSQ+CnVh*68$~9`l`?{2j~az1AT)5Ib{>6$!6|*zCgR=!y{YaeZkZ=JK4@?f-?`uMSl@ zu=#f4S>0@OVmBbKv+VIK?fm*KExGfivxgfm$0OBoD`o1bZUkj0;pxr1TUCwpeo>dv zyK~fb)fuY|-D%9akHnF)rPd(tTTo+~_tuS2SmfFsq|02>ve3-6re&$eQ0kgiPrW|) zIlSac!uwGe(9k(7XvKmBND)Mnc&0a75ci{s;+3f0_QG?YL{QX04gwu#*FZ%loeqai z*&CuEaK+GP#-JLPpv*0qwVI|?QLLs{A#OyKPKD@Lrs*x9SuW>JV;_(cJl%Pf3q%GE zfXj3aH;)22mr=BD#n8IW2)fJ4jh&fH?Cg-4WVUe)aU-HVXJjsrH`kgXa=kH>K}pSA zjS({57_y139XwrE8sv;C?T@o~zGYAwUfg@}^u}WtedF;Z-|q7Sjb?$^naMP!+nKAuQV*DiqG9@VUq>{q_^B-a%vEW6Ozi)U?C45G!uy{2Udyxgd1^;~I&aqbiEnz3I+6H4IR z69B{@-8vN&$envlV7!T?Xr4G^9^o$F>4f{tAe^NuF{4$8CsB0)vGc#?yLh1&;zU#x zA&&nyf+|2TJ~CBh=bF{r*s7F#N86e5n9lp^kX6*lG~ zj^bj(eNka!IpQdmBd)c=#(Kn2+={rLtFW;XaTNC=?)w!sK1LkHqlo)Kg^iPlqj(;1 zZ51{yBaY%t#Ql7Qjk}1W*m}hahs9s0u+a`>_{|WCT@m+-6*hVzj$(hrwO7~}j5vxT z5%)_KHpU{3;zY##feIUw5l3-0;(ocp#(cz4T#C4k3L7gCM{zCUex<_3M#NFvj<{c~ zu<;?{DDFqxuT|JMh&YPJ5!YE^<22$ZUPRolSJ=3UIEuFs_Zt;9?jw$38`gSQZ@*b# zqeC`;BE{~A>#DHP8*vl|BJQ^;Yz##l#bHss(HjW6$`Qhy=`^ae)!=_yo6r+@hJRp} z;*_Wg^AMM!N)wHvs}La+Ba!(?B!oW02RX%P^>V?uH$=;T?1=m6eTWB9rGp;%?`qjE za^nN5h>QMCiH?SBwdBX>K(T_E>KR5h}i7sxA$rEB_nKLPi1 z6484GxfNB7xaWj>g5s)Jl}Hp*Gyl^xD>*AfUs8-j(wpEx9D_m9T8aHow z0iRcR@<&;0w<4AwBwy8jl%-vhfWQ!6pZURw2DK#SXO1}_mxz(BT9O~>Xb2gRS=$i8 zDhC!_V~6K120s`IXtwGLDEpk9+5hGnW>za@QKr{ z)^8Q|;ZEm)i%3<1F?f|tVnn-#P99vh54m(T3t0|mB>!? zo^Lm|QPqU|>TaU#s!F{V_rT8xo?j%t-&GkygZrpE1zk(hX zR>oDZsZMA4x$MFP7~K`%*0~eY-kzS-8G^sS(=B!`&?y)Q_Nw0u#wn|&`NkmpvbfEv zPA(ANC#K}9uRw9(f9A*8>p)&thX#vqJ;u+T4V1OOpMMStF*_k{By4 z&pGjBW@}Rrvz{!Afp9jgN-XbgAjVRd50$THwJE-SM3LohN#0ubKkB=w?PKS7hC906 z|EZ>$$Fn7QZFeSb!fs=zc4WxRJr1*DaOrOsP>z94>p)Z3JyL7?AGz~RQ)I;H+bHE2 z{WQh89i)eIi8C=Z)vGJj>1nAG2>-;OjsJ~~-}#3KX|*FG_T~^`Ts!6-IKzr7uO)dy zf{Vzl^TiuRqBAHoxCS zq8RiniROfR_6TC+p0(WO&jCIi?vt2`u75kaVgU+$Pz{S!VGQC#RB0j-bODmSE$l*O z{ZidSb}h+V8D<;eZEi;~1ym!VIN5R%aa6hO1a9suTQYOz>}F{qC}ZlK;_3Zn1IrVm zEYUx=_OSU-BvZIqv;NIdG>;-JNZkq@2!%eJmw0RS-ddRzXsz=2T0&&o5}{c&t%$fC z&+r2QJ<^0QsV|ZNdmFm!4U>XwBrhGFImQiLmb@X8sMr=ZN_JI*_r4SxSu|+_d%t zGJ62AO*XGt?qjU1^T%ty4Wh#sq@D-2=t?ALQ&U2im%HpoVLydu`X;&xIlepEPooWB zIEhlbJ?M_=xOCj?I|j!2tzio>{|k+Un0aX-=HH*P5cBU(S%~@frRw7UL2>+lqp#@_#HFaxHK+UN%Ouf?FuG$n!w^TKN)yv+tTChuT@hmDDZ3^l zgZE5oH>$L6S`p&?4RvC+5k$DxxJ(YwIH_0m-_{CxhG!MY#vPO`$(OSTXb#URZXS(= zdS#<{ry}Sm(Rl{CBW;*)*cM~J0~IF_yGXxFOXe94qXC^}s?%vsAvyW z(srSQIjciYb+f~kP=nHaPKT~B)exEjt)d7+|7&eJhTm4cN-As>pbf8h6pNyIvkY-n zR4?_!tkLPn*5EX*zgZ3#2Oyk(objCG&XGtW7BoQgVhbuRwGmlWvlQn=_4WhAT~QS$ zk=UFhXx=?Hkjgk9>1a`orFyOF;tlF1sA4ju4^Zvm>D_vKCaW3xVgbXiwsFI{5clTu z{0Loy2CHkRZW>#WFha};rXlXT1c$MRF>}{JE)W?wAzY>s+&l{8yl>FHoE0`f%UK|H zW-_sJ158dt8ser;``xUFG{~Fj8q>TthVoHTGc%Ns)5ef)EZ#vp!>)Cdm`yhy>Hr)k zcsk$n8sbjvTgHOZ+u_j=m!|{vJ@GBTo+ku#Wr5h4$<(dfc{eQ0V4UPY$K>p zZIbD8&!2j5nLPw_R6hdb8p&7^dY6Icc5=WE+*)!PCj;nL#+!_9P?o zT5BQZM#MtQJDi1>8xadJHzF2dE)$r^m1JaMv5;3pkN)qx+h}NYDZ~>L2meo6O^-t? zMU`IsbRT`0B(CA3HHOm*u|KLbF|7s~LlSgFh`AAA*RW*po=I&)mG(_5LcALhV#)|2 z>^_&t2Q>EUm7RCBf*#;mMY3@LWw;S3AfO36tGFT>ll96*@s35%QKIt-H2$rP{N$mp{KgpVN0k%-Y12|R723? zp9?gPBJ}(p^*17H4M7`jL@17k>dh>~c~QO86EmFA;etg+wg{(j{mpW~H~`@ygEO9! z+_@1U5eph1da(r+ms+2!s#%IfQN3MHmK>J+N8##SVZ5OWr3i2J$6VI0Aj zx$7Vohzy(%F4H*NJPPF8KhS<5D{O*hvq0?3WMbzsn4E|-#7&>}8(9%)kT=scrg?7+ zWm{4+Gn9~zjUlaAyxn;EUl#dLJK)&I(|Li`5O->y!~VK4kA}EBcd&1ZZvpnqAt=cL zu``pY6$}JNG$F$;(<>^_&tIvQK`%6l|+?rVjuBH1{CGTev^A)sMA ztGE#~M(dT0;vI;fqeSN!=^sfM7(KNqNoBDDSA^*17H^*|eLL@4%&>P-P+QB*JW z#0+P&b0abZr*Zwwa=VeN{0`@M-S zLW9*us16!ikuXBcS)?KE=N^Z#4`b%8gIpjoa6-6DgK+aGkaPb)`^l`Z2`XfP*qO=1 z&RH-y5ow5|-WW<*QZqA@knP5hYjm|@5&K^j`A}=%*pfZNOl=Ku zr}iQ2PaE@Sh|6;U`x`vnS`&1Y1!89=)3tKveOWbwalS(|%@c>PY#n$Vt4%U}?)g)X zws)wmk794~i3j~!a1Rcmyb)>!^CuIMr4pBlB8oA?8NJ zLd-#DA?8NJLd=bbg_z3(X0k6CnOH33715o4ns*xwt@ea?f@16UeyO^`!@mL04RJ84 z^x~)c=*uMW5k5}ESK$`oeN<^;S|yE>IDvJ9m>UsxwMz!?nbd4lY2UOW#Jdq8W)ks* z-RCk{LSwaFd5OkaQY&l~$;K{};YOqf0rlcp#r2`lU$1NwZ&w5zB|6VQXKzF}Yy&ai zfr=A|{ha?UEtzL}`=QhHZbZ6}9kWbtKXj7bjfl1jCCphJda9cpwuBnweNt#lH3U8W zxj-W*!VP9zI8?(G23u_{T=hkY9in;54qkSq>NnAY5c{#&eQ8 zHzFirK?6iDwxHrtyMx=HqSz-3?QIF-tf-2eNUT>9G)G4PoUMSQqeVHE>b0(mH>eY! zipi8pP|Zr@=3kQeTvjvm#R7)A4Q^N);@*C5qKnXAwGGuyV=EFyh&hWi#QogkFm_m#G_W9tCplA80?C6*fUbSs-?1GO@D&CMO~danq;$Y*s`XYy_*aXPBw2A@0=v0Q--Pc{If3IfDHeo^GuPI>`dD zGn465x%0lPn!z~VA)4liLs+&uRH!z|^ttCxJ=$J;Vyll;_FiS8F40SrH$u%|obqd$ zCl28U%}{({9;l3=QLI<$%Da{tL|QV|hPnXWSv>s-kZsG@d|Ub>%H09RRhr(ccnpSV zIYUmGX9Af-Wv1|SGJ0kZPPIA7$h_8Ch`AB55OdI3h`AB55OX79A?7lHnQTc$CKd~M zMfCl{R+|Eupm_ar{5G0y{eDgC#?$%hqI4g9nIyL1X0oI|{fD!r@F>Z&nhA6*e* zZbaC1D@na)QUyuM{KH(dBE-89A!hW8x_gci8uRtaV>A|9>yT`0KpAdC+7M7Xo?$<` zOghl$tXJwdN(2ovSXI%?T1d% zyAjcL)e}Y=y2lPZ)y)oDLJjghDKw^eZ+$4j8D?BKRKtx3TQ@Qfixlrf^`-~Qr%#sA zOFc1bbb4kEz-e56vm7wiG2B{k#&ePfRU;x6G(hxX3o0(P3%Cs`iXD>8+i{2mQ5EkY zwo8KM=okX$HK6HeQI4g0t?S|q>M*EcGNo~-3KF@w5&2wJGxWs*hPw@JSj*zxes7|S z&|p=DYOS#q2_wXuU>f3n?r|9J;L2SGxjs0^SnQm@pNcP%xDv}CLe^$>Uq zc={6{+m^BUw)97oy8{fWG`(5z7!1>LhMY9d1Tu=sjN$2I^vocfY7>%?d9Ae&b0cCQ z=Ag3>b0cCQ=0?Oq%w+;IS(S`TEEe*L=*x$#Rs=FZ@$~2AM&ue|>o15(FMhg@zDyEj z_}CU-g+qwPQKgA#bL6w$5Z87Aanc>P;IaRtKKp4=wA7S) z7h6zqsU5*>P*J=S)!RWNHY5oaFCpHF${Za%AUFji9WBbSRIhbiyg}^+RZONd2-T2; zX>LS5m(>h?v4G)jgB#YYxVPV%=pr;&EkL!{*ouS^Voop(aX-TyG3zR8liDl#t2B zkZp8*#MA$>$cGxkW>}O>(M)X(ai{hY?8}XLG{oiEfc*}hZW#&M$^x-7lWAMI^S-Q_ z!8qR`n&yc^Shgcns5Z&;x#v$k+U|a0t4~Ar?q{O*&`XpzLd{^D@@twW4&et)8@>Um zOQj2qzIvsuylbgJq$Oi*sC&T6uL^$xWZN<}-GOx83Vs1n%#2j=MVs1n%#N3Ejh`CH)CUcUJiN!)*5xxGfRaqbt z6nB0}u0K9PJdG;7`00L9h`yw_1*`NMl}v4aphoU}w=RN$c40l=B-*g5)Irel1`GkT z+S2ihHCNquR+Wor^tQ|G#A*v0qfoXaKRiI}hj>`#X&&&o>e_+u3|Sb?wy4Rd>8 z0aBgKKN#!$Q=pFI6cKD8g>;xH$4p=Aw7l7H2C7{o(2~5@p$3(XG^lh;B)S1%far}e zsJIoCu{{PA#gC$Tdk67eRK;DS`cX#B9JyEU93v>*L3J-dnd_g=Wi>-z%sO1;@I>gB zJj};+C%Om?Rzpw?H?|^SgqY)6L)>p$)_xnV{8gS0MUIb|T)XIf9Ll)@BEeavJED#= zQS8m;V(%rmoS-zsuO|uaGlSA7Z}n=-*YU?_+GK^9$x291W5_JJR`CoG-PnHzJ0GeO zds46LO=gyBh&#*2U_aTIM?+j5?(2)-@vBYLd?t#$*<1_YAj&WMpEokXJ;P9=4hk$OOg3Uy%!; zGQ{nu((8-v`-SLBiu15aFMr5%R;SZcW1yg2_~yJxv|&}*$npRT0kqn3fyQ;ca_pCD z$=%{vMY7S^!OVZShB(*ptl~D%*sNFPh^6esQf_f#DYw{IzI0+Kw>Yub3n5N`Wt5=y zs-*d9TAjytZCf`B&b(P*FN9{1C9_R0e{`U50%0seJ!<`NrtU!9F!|jCyNOd;G>L67s3?|2_4Wwj zv8am6NVP1ZW{%u_xQh{#j-Wc0pv;BP=dzliFJ>LCc9{6RxHsR}m*^riShXSRcFEpY zkuXBcajhZlCoXHh09XEAkPk%;j-$`D3{Q_kId?B4*vSl?sLf0id$YONy9X{OC=Kyz zK!W4Upft)`y&Cg%{4ts{NzY6>LT(yEhOj=1c!r3aPpW*VOK{xEnm4mtL)=;3g$=D= z_Bg|%AubR1^)c}H)h22r6UE+au2FCh<$Y8(gK<8=G|dx-up+au%3+@AqsyOtv@LvM zs}D5x7Bf*3=q1V(m&>QK&w&_|W2H!~iCVP4L#ljfN~j!~HtJe`c58H97~Trx6mrxs!^ge=6I zQx;+_ge=5d2w8}^5Mn0nzsjo$6N`nsB6{#)tA2q@P#pVp`kJ1ExDZu(_0#>m)ci|| zBd|&@gvhj0r_)qjh=q3HoAV~ohE-)F%QY|r&}z#r8XxPGUB6aK?hwx^l8s9!!*2*p zARopBZbM?v`v6Q`7$}LVTaA;bw#KnZHEN}A7qf%>j(>t?~3 zHw)~A&=9g@w&~@M&egjR(sqxj5`C?GQeizOG|Kyk&=`MI@}Z^>%`%?pp+~u{t_Mc`_AzTQtH41I`V@4FmMfGL@;-aWt>N#Gc z(@y8$bY7DE=`iIsS*hVphYeOBz0=|L!UCi^n}0CY`Fj^a3y5F@DWtC-t zqB=5B?9Jxt1P4*xM`be@=MzlRJaGssG8C&E=9xaa{Mkp_o=^CuIM>b_XJjF-h`xK+>P#RL6qkQXu1_`~o=4R! z#QUgf`-3%u4m`s@)!PekAgc5tW89|_!Iu=zx){N`ONjST#h^|lf_G;S>9!?#*9Xu2 z62Uti!4*8SOyP@g$oxLu=LfAL*zf^1#9XEjWvbI*GQ9cUs8uC|IZ!zP35!rwem=`q z_-e=V`^nGR1}Z;mW4j0XA0)+E2NiwFK!-$P;`~<~jdDH_^!oMV>lc0}X zK&u-K4}m-ELRF=IvzV?aTho9b3;`l zy~owX@a}fCU3Fe-!>Ur(pLM^CBWFvkLEdG6#x(Ek0HLtRwVg_rxu#{InQKkUQuA1^ zX?5zy@KctzhWGY;z}z&_iUkX&PU~;t)dtU?nuE9;RTOtc_4XR#ji`z`$TI{PXIJ{ZT{QOBW8>23)zbIv0oxyID-z=zJ8&xe28Gah5ZJ4zfV(%w%Hc8JL`iG{h|= z?QgOo(jaf9YfSUr7|Ok*W@acMowAP@NC{o@c)IaukW)q4uV?Xm%b;7t(u!Tl`JUDg zcd7NkeyA~zhPXVVu%E!wtu;a8Ss-?1G8L3N@1ms{j8jHU^TZ)6+d{1Ikepp-^-6u{ z(Q+~i#LiL{XbPPKd85+|#wop~dE$^OROU98udBkFm=V0Ax@#xXawyA^*Fn4s3iLyj zE?DplrmAEByz;0j^)z`rT_HwiFL8J?RTqf;2Vj{W19U4i3^xRMv#uG8Go>`m6NgNo zGDSR{aGx23Gjum*bO7--s#^b0?Gs@T&ye>J#Qs0bd(6TB#JQ*{L)?ohy$t5zrY!D$ z*aU$FQ zs9KZ7gYeT+v`P_3aXtbMlL}jl5lC?*0*{gkTjdC(xDkQJNrkPg2&DKS0>dRBTYC{m z@gM?E!#_`k)=>mfJdMEcb33-qBaq@%1fGX~+yJec2&8x)ffq?dTC!slTOoGf847-x zRM_f@K#IMhdZV|JA#}}02=}P{sM1!)=xYBXoTcV_oRCByFDPz{>fPdR*9eyI3_rwK zfw&q~jojZ$gfA)1iq#CcH>0W%(VY;zqF55Ek|i>~_|=M(7GM=_2-~z-s?!0mfXlEC z?;mXy8nP%=<>#~Pg0CJt`Ewq&hoS#LGF$sOk9JK00z-Tq=9*c9oS&EEfOI1kx@t*& zq@y8Z5zq_>s~jM@#*Wp%!@dcbYV2D>++vNuo;-O$_J#I2FolIMpht03RUlycG-eK% zWvRCLL5c&hBW z@;<`jj==UI^bL0e5)kOlUkwU-y-pzqWCyX(m9wu9lE@Zreg;eks~lK#jUD2>hkX-r z1!x8fA#SmbVE@h;-NUtuHpGdPHEDYiou^8G=Djn0Up z*b{MW6*l@Jj^bd%{d|Ru;fSL+7ID8&VWSXn6elC@7b|R(B97vG#I;x0Sd2J|D-rig z6*kHdM{y(K{y>F|t%#%eA>w|y!p2_2Q9OvajtUz`5l8Vf;(n#V#(Bh1yo$JAt*~(u zaTM<(?$;`8wEmeg4=8p(73M)_g^jL=qu3j9zg}UZKjJ73Mci*x*cgd8isKRYn-w-D zB97uz#C28Jn2k7!3laBQ6*iV4j^b*>{lN+wYY|6rGvfYGg^lfqqqrM!-4! z#Qot48^;kx@hsy0NQI4yh@*HNalc(*<2K?b-ic~bZ@cVDWb>Zn7C#zQMTn)S;;!G? z%jsmew}9RkE3;qcfY8B+I5IElgbWJg1;sN_&20SHwMaMd48Ml34RI%`bb-h{AVe=I zu838M+#jP#6Agi29gy&D)27W*owj4%d$6w_@ib&E?z!K*0B8n;RSpncW5=rWux~=v8~fG}w^$3XCr@6G z{Wy3IOy0-AqN;%Raj*rbes<~tBO(#DE}Cqis?Aqz3TL~;o0$YQPwjt#_I7tneb zJ4to%b0^rUSL(f_c}wo2*9eb00^4`cH{20OK%hH+H7IP+I)xmNbHqYd&b~s(pzPP? zZ(kC^DhC!_V~6<$@@4Pc?4MH;=kN@d8Ve8?qpFenYvF!Lu_#tERSpncW5;UyVc&$DHTJC` zZn5@ZPoBIWyCXaYCT~ahs4C#?2$#UzNwv+|b|7}7jTH&ov^bH$ef(uxSXC1}Hv12O^YIbnIr)R&BCHdZ5!;(EljRoK{! zIEp(F*Ir>`H{vLMjJS>p8;21`@g(9pD{P!a9L39s>#DGE9dQ)zBCfl_M)K!!u-{T_ zhbq*ir@}^O#8K>txZVmIeGx}-Fyi_uYz#*n#j%L%udq>wIEs@IH&9`t6mb;iBW|$5 z#$v=#T#2}$3LE8!qqq@q!xc8RB97t*s9KXh9)A6it-T1Oco2c%*B{wBia?5|5g2~` zk*)Ixq<9s9;nyG8x`{xF_YoL={ZU%78N6+U*nwwACj9y%TU`-Iu{Q$4uRpTYAAuBy zA~5{=BU>X8NO3#@!>>QGH4%Xnry?-?`XgJj5lC?%0;Ho z+>F5RPr9(R9f1^gBk(queVEY)c{=Dh{`>d{X_=Hk8& zG;cWsUn6+(qk-*7=o{YUl7K+>6<33t%hDW>VZ=gL&bvJ!8-Qj&SmglGHFm5D5Bnx$ zxv_5zaf>wtd-CK3*^h?jz~p^2lvD-0kA^ZZTT*TF`tLyONE<5>eiUM}3t5P{?%joT zWHHwW`vzjJ5oq0qous<>xf7J@m3l8}-je(18N%a^!1g8d4R-_*5a`Zd4RY?jb3l#| z3tc(;3L!nRUz?xq5W*@47F}b9`1Jo}?`?u&Te~!&Joi#j3>aVp10rNVL=y&s)5_PP zqN1XrqGFpsaw~5&RZU9*dCoyEDk`nmg%;gSbyF7FsHiBYsHmu@sHmu@sHmu@sHkW# zV8DO@0|pEj_-67vYvo;QZAkde`RX34ne4UK`>bdEyg&QhJ9j28`zE9@+qZ>;#kzqj z^3)6RE5g^n6s-uirUKE5(1I#!H@dkUKzvU-D-!0V8{Kp#WKJQRp4@o^Bb-(}YGvm! zeU<^Kt^k(0syHavLEnfvXd5&oxjXwfCK-q>k!-4#}Vacw&MS$rCLR%4IFOErNOFDq2 zyg=OM`zwWvBcrf`22I-0FHF>fSpg46Z#dky0or*kB7!*n!?4M)_Z-tM8VQPWdkZGm zyjYr_IE1xr=;HIPA&NUcqiXU1V#gm4m7O&t+7+Tatqz6AO(a_7#A=x0wpf)&r0(5o zGbFl2Pru8JP*kD`5Jv^xTnZ{C)`u_5a}cMi0%=bEL-^d zQv?;o+xI1iWmU~UoK=Q z{5aq;Al*{OvM+7fm)6}S2u291cm$^FS3L*kIE=i9!Jey5>67dJ`>x1{@z9GvYuq%aM&RM2! za?3eORnghM5;)dzOg~J!{2QB=?MZ8GXJNC1WAJme9^!5_S=2FEY4RnA2dc8ZX;l=6 ze~5>s++WDmIZv@)R8tfSqH?2=VYCZmh~j{#CMhaWW<;%GHB7NhRC$W;Mdfbl84;mr zS*Ms6s}e0QUQ_!s>>X(>CDAvT(YMD|@?zfalwIoypimQJy>ohZm@U|t)8Im_j>1LWB zwyG+t1dHNsl;XW`Pm^1_#V!7fyCg*4QSAGR7`OXTlLF9dV&ztPLe5@>Tx3JW&@_wV zx4DTw)5sHg|K*CZ@~;4FmCCSE2QHI3Al6;F*JyW-w=5`lB3}n&9sx76U=bnY0MI%h zVZiIKCr@3V^wZYqK;cvsOEVN3sdI2Cjo)s*tVcxBGm!8MvQb7%zHw5Wj%HG zBZTy4L+)O7L`cWWEQExWX@LE!K=IP>)lm7Rq0v+!S{k~5>6ePTrJ)W8t>=WrU8Y_E zS(NR@N59?p==TEXeq4AnpkS!|M^25=A9;NinQ~SiJ=@2y1oZ z-VK}uge9x|z&~XzpL_84oY|qo{OJVZ4UQFd%F6!9R(=EUT^z%y^yNUoAhU^t5!D6i zz?dAAvFX-KLi!X!Q74!i5AT64ik0hZLh{)VHjN9!IjRG~7&KfL3m4~AaWu)rnM+4- z8||%1-pb8EZ#Chq+!#MbWT!ZWeNNDIEr^#3IteXFdtPg4XTlj835q_Rc?%}^?8Vaj z#3AjtuJG<5tT90y0EZwpzJCtXiAI8=j(7_usIsN`i9_s=4Z;mRN)A+>$ZZEa#67VK z7L7pViQGf!;D#trc_R0KHF)wCs65fASGg@zaKGiP+zKAN-4m!hky}_j#9hoh#NEON zFLc*cX-DLJxd(n<2J&t0Prh@{g}#idx;mVUXOx=Q7UgGp!ej;?VY<6pY7nBaFGz6|8s+@Jc57pGxe zpt?e?qsv{{ZQ|jFU~dA|HL2zSbfc)7Z!_xEaY5})D>E9$$Z2!yn`RHU9#0^!EfJYK_{H3(Y z)2dsn+-n!Kniu!O6x+nAL?U(Xh8u~>LNr2Ai6%%iE8G)H5LZ;ilz1d}Nw^CX2PE4m za+if@Y6c>G1e@MDaI$RS<$|Cy3E=xnh*zq*hIpeYX22u6c1a+vkjrRV6-aRn;*P2) z9zm5}g8OEZCwGdYV;*nO#B`(kB$RYlN?Z1&E&I~CZBy=Z5jBCR1KnA9;f*12NJcNg z^}_BzGI8UdY!(s;?XKWK3~%%wrKv%r;nQX8}1Bma?yG*;m%B zw4aS=0g>#WH!G_uL*j^xR@z#d@*f8*d- z!|`d^wQTWXJOi6W9D_HKJ;W`>tb1A3q9KYMe-)S2$!>^SsxMTl#vqPPoHb=%96OU2m$ zF3`kmgT?p`kY1^5*;lsgE9<86XCrzluX?4=kOU2i0cqS z)?Wj0i!oVrPET>1vXp6Xa-1@&V7!t@!*Po-n^>>37<*r3@5}Yz7E<1p)ZJpdho<+^ zH@}s$&MFJ9^%gD0SKw*^*VD3V+2Y0c7PdLq28*$WxW$-tzZI4tiaUP|m(@v%`=XjS zgLwSc3d&ABav$~)lD~s^uc|Do8;NL`qPj16_ih-|{e=*XP+atR^hq8Q{SXILH4bq` zRf`apRkaFnT~#{}cU6^@@HyiACb!y0`2>L`-GEKGqO)Ar;OInsD^J^cArI8(vh2F0 zU%sc=n5xDhmQ*zZaZXk95EoUo1aVnaD-c&zwFYrrRW?qJ&3oxn*X<8z$_Y!c0b;AF zD6&x1%Lz}IdU{!jDKpRD{iSxWZV9{lU&CzTWC?oT`=~wn#$xPKaHqVvgskYDC;kGTri=%>$~kqpApZj3n42tO2qwLAs03DGHhX+fRE~Bg(he=ZTvEjHG*^%V=(Q|+F+#fx+dxx0Z zZQxGt9lhV=2}eo#1ePKPOclqIV+rh&59|{I%gd1Yz`zbg<=(6$cdu}N*a3P^tlWdP zz{(EKF%T{ZvHKvVjHU&FxW{B3;x+@kEUtnjx-(co+fEI}mN2s8#gsLzV3tu9UN@{RN+$()NPSzDU#} z5ce7gA$Jn;&o=3oPNR>|u7U3n>hJp?4yY;*aa>hph_kA)VV|MtP9T#MA4QdK{_9W@ z98*aw(GAeIYDH0rTuBI_&$K#IRIA|@=iU+Z0MaiJx^;6NO*aC`Q@r|{p7KjC;dEX@ z9{ihCXOkt>wNMRFT>9&u%+i|>6l>U9$^M`oTOYm0)+~=#;&GVb8O+n|71KA^UJ}g5$Tj$v@M`6MFyUiZc50 z>JhBefy<;0h;^4Pu>O4|3rhP3+h=t^&JZv&3$~+#G-nshLc)OW;EFtTfzqZq{i?W4 z?5m+VvytcSeHBg|s12poVdUOWtpoBNEEh6AKX86>4M@8=E(5x1xt$b=G@Rc95GMP~ zqErWj)`RE^el3>gW6)==C?p^-oHZ5{yr*6Vq!+Q!Rj?KivH|EbknL>9z{`#ZS$vs= zkgzi2uzwXOUUa@1D!=HId=>nnvkH)QoLhA2fYAC>I?lal_jw@?va^}=tJ`D_JDLXB z*-ZM)PG*EPd$KM|p7vy2cI~X_>|%a|LR{cj+2vBcf$o=+ZmltWC6$W18ZhNY=+fSn zVheIlZwJ5I>?l>z|c@J2Z^p)F%9-{_2y4<}8YqP9npvcW|3W?&qq9_&zSeH*@5Zg54pe`)J zy`p@^pX$i26~VCEf=8k&fUHT}Zj;Lik&`^!_-0;n0{M6eu`Hv)efyYJD{5s2J0Xh# z`9yI?RPKWxS}DYJyob2QSA=L%pN^2sr6iR}tX3br)r-EuYmW`+?I2csBfExmK-OTb zWp>|hJp|+u$I9~{$~rRKkbBOoQEETg0~%22_vct zG>cL!OO@R0AY?xqvVf)yfw&J!2wBgDuxUpiE|xkVTd>w}-6%T&M5m>DV9IOFe9f9_ z7Ml{96yiQO@DS%{8!WpxhFwX}aV^MR=t4`N{Q}z7_o)jfecj-NWt8;Prt1Kw1_%8RWtez6N zodBCS&%#$GEGT+qVhq9d|1D3mF+Da(|7VbAb29v=InFpEo`5{#Oi0g?C~_t|0edjg z8F28>X#t^ZNc~(duAzwwMp{N6plU(_N!1DQy{h^ko~r5!;*F}9V4r+opBPw! ztoI)n*sQ4BZ7sR)rE@>>qGV%YQq#cdjl9_vH!b9BFya(0; zI7Tlg^rLOO24jmD+3`xus#Y+(?((8r(G^fE7O$e?m3Ibh&+&7pRxreK9gFOEp{KvF zyd*f4o*bfB9OBMsat7k1s%&SH=v;{Mw3-zw_p$-4PQ+@MVnM7*BvSWoVIa}25RFh& zq6rf13HQV?#8XverM4s71&X;mYcxgfZ6TW4g-9R4r}&59WNP2!`rSvA_rT1GGgn8( z(JT;GAwtTpfw+qSS#)qrF=1w#vSh-{DoC6}8nN@mNXMn3AHA=S-j`ci=aBM^r2Yem zc7)r#uJtynMfh08k)P7>d;@yFyQ|Im%f1OY$@Xm_VX<~#Po8=~ov!R(15@Q=5j&=KO$8FB-D1vxxshtS z&+-C@?`da6!aB)t;XJDrM`afzT67X1|PlR%WW(=9mH)9caw{l6)S5Alv6dOhubm;)%p{kA`UZ~3E!C()-U7ci>Dx7(5 zx6H#=5l61UJfDGH)?g~;jDbyt#Kfhz{f^awf?waO15!XJbQP@RgzN$O420EB5L^4e zs{FEVLe{f=TS!=}dDxSuUXXu@?Q394>#O@vf5B8BTBo;xIgo0*)ii+ko_1FIAZ(He z>^?FhM18*nLhBPa3}^fi8n+NlDn&Dwmiro=ot9UyYXK%4M6UupYM6e4-=OhFplbq z0|Ie{97Iz=AjKlY8C6kSf~xv43{UnIX9L(n6VnYIyB`D6ETt{`(w2Q`-4p50Ms$XV zI3d2t{fQhy;*hN9+#fPnmrUIF=lE$8i0cqSW?lnv4~)ptprexmm8DFhlLM7m1p}5u z8jiaUWs~|UdtYVm%k|(qQeKeM-PLaeO^wK_@+$?_Sw&~PMZacn2(CLEpMJN%vcc14^ z3B70jYq4WksRNfu9T4j-ZT$Sd6ttk=TUm8L&Ji#(3syTqTC$5~Az{Gxa7CWFKVWhi7P<=NJt6CWJ_Fgxh77*!h>*pXSqKR$ zGY*^-L8rJ)W8tsH@c|wiK^4xzF9!++qfIW1s4mbFa@xW% zeOSl!j8iN4{LWiVc`H9gov#UR<$mOWV?igq8>57rNfHinjHYXWxR-eexypvH=}sWd zQ5}#QSZhXZzO-ODYr`?@V1l}9LAI#stkhS7SCVJO`RbBSBF|yaf|f+0y*PA?$!XR49c@@$?VzQOiWn*ppbmF?|A9 zhB%`tJN(I=6C$^5Ammcq4^zwu@g&`=FZTg5i7td_gyMy`pYlY0i3P#A5EUqDL?ut; z9%3<~Ga(wKxF->nJ(1ge9fIIgh`zsqs1Z$jBKK(P7*@H9{)agM$W zB>WG7U&d8%+kNLM;|4P!jZ!>!DfW;L9G>@L<;G-SW#?Kmtaors_d+=ii6UlFMQ5jN zMQ8skSNg3yQVq(a{J}B>zo_SlWV|a;*%P@bK%x$*k$cmw4oHisQMw=UdDRn+CwgOn z-Xo&E?7X^OhV(dydmiT@LTig6~n09UG!mead1R8 zFL`4Zyf*v>$hWya?f>ne<*5r4#8WUKM=wMWQv^2HHn7gDSTNx{#MONP4z#!2RQf!S z4d=+Mh92V9)IG2qOI=*JgzRTS*mRf;IY1L3Q763x6Lh4d`C^a@~xL)!Q zcY&gVM{(q~LlzRvZEi1l!3st=AzWbs2(8EUT4k?rV`w5I>g=~*f}XTAUkt*{@xG)z zL~-udxs#t-?u<)RaG0rc2(I- z4&d!jGI51GLeq&ril-2-R7LRts_HkudD1BXxTiE7Xkxm-%|s6%OTtq2r7io?y6xX* zBkD&aoDh}Qkr)z(Wb}&C9PFB8M7Z(K@v|z)x(*@a>NOCz){|m4j~$$s6-Pa8kC48#vztfW!Errw+nZHVv__pMecqfni_yeAHiEx z-QZ-|qU{DTtK$Fr4TxK++J?BJDw{|jn)(Ie>NtR=yg-Tth-Fn#T!gCnz9>)j6lVk2 zMbnKyTmZ*tYL?2DePzqOvTiDWHli~`ltXV;{?iph;)sm?`&AAZtVt$r_;dKQ3B=Wd zkeSy&+yY4!ozqhsrz~X}oE)djDj2UM(s10u&nDI@J-+b1%HEgj!8xQnFR8o5co|I% z(l@`Av(73Duk{u!#s}cKC1>upmw#i^vc-$>F>Eey3>IS#af>nQek4oC5XHp_S&Ua9 zKB~&jGZM}GZM4eMYE7)%Xr$GlxF4ptAXX(3se3nONwh0OBNUZrf<$M+J#h{3R#jQ4 z?Fe^);;LjjMeY+JnmUC@AHm>004K{9Eyl#Oh_mn8A$F*$6XJVS*+h=v>_ifAbv#AW zxj>2+5N}mQu>roGej5oV-4cMCJ6&jEw!zML0FX6dDf`NneP!KL{%k}AM6!h5tSr0? zi6b&vjF({7Dg(j|e-585N!E1;A$PBVxW$+(I;W>NPFcz{I5|$4RWM#jq~W;5m`$u# zT8zD~viIeB@Bt}5O6qPvHKDf4(l@`Av(73Duk{u!#=YQ}#qnv`wQTWXJOG<99D~K! zL)>D_x-XTuh7M6&7u5vCZBY$TyqTimMDz5M*oI^JT(Sq^j;eMc9;oUR;)SYiA>OO% z5n@AGJhnh=Rh3_$H6L!Tzg zRMBO{)CH=_Pxn#o60X$&&*lGRVIMdah3jXV?BtyqosEHZtH7k6?xWeEs*WHYtLhZu zxvDN8Ua9ID;*F|qA>OI#9^!+lY@GdQ8W4!1 zMNZ5o;2oG4aPVNG10nQF+O8{l(Zq?Fp2}`PwJ%orGl=J^x`8++i%@k z!ID*8WkuCEOp?lv4ad#MI;G|xJ@-e?{n2x~ca+J!h(e{8ntC^R!cmew9i_+tQ^oP* zy#)4&f$ge_BI{5!WweLDRh5jlQ?3;LhmsKIw)FWVFK=yPjQUhCwziSo0r0GA1#=JGV+~gmipAnpaNHkspzS$+ zj^GN0crI^|9k(O&m-^e6mjv6=lX;3efBVzMBwg}5cOkd@9jde4NvbWO8lu?ufqR^f z6l>U<$$q3Bn~%N6<}8mJ;&GVbI?U6yo$QP~*vT{Wf)I^RtckPTGNsD2XT`KGR0WD> zQiV?xw?9ff8_8Z%g+|J(MtW`F1eu*`u^Mk7-$~YP7Bj^)iEEVNnpl+>gVxHe%p{r@ zqVFi)i^_dEJdUOvfw&6?A=fWMZnGh?Xj;Ot`oHjaLhqUXxoQDc>cC}E2gJHdGtd8w zkOid+lO0QSKvobiGYj@Pgq#9e2P6!57xv_-3zWWE75p!}uZHT(c1do}SK-8gE&#ff zlDqF#)d9JI^_I-f51gM|7t%I?OM^~X_c9NOG@Rc95GMP~qErWj){R)Z`F&2Fw?dz} zqL6^VaMoB*@W1ftfIMKl&{Z(e2`S2@$SuQ!jAug{(DaNWLV90jAtbC!8|+^NiWi-) zhRQEG?Y;_r(HR6tJI*aSbwFsnEFI^z_MaEBhb>V0P@7`QCvF$Z6x&2KNwGszWr}N} znxxn}BRi}d<$36mOTVB_+6`7h-MIZ#W>ISPi(QsH?H9Z3a$V8c>&F6WzlLLF2Tpk# zI{Ei|RP5G(DIY+W{&^k6bEvBSevcMZC~}l0 z6h)5Glpe))8J(XvV6UI89!qto*|9_{M)Fuk4K7dvc5d)Z$3bLOknG%*;Q&oX0&%l| zdG$)FAGaZPORDb6yR<5(m7NlV3<%^C#aU6gk3?vt5H~zL#67SfM3ef&m82+1WfH5^ zM{o6_ukfO11A04%6)$Diunx!=thLPUdzOoUY~xsYU_n_&#`GNO$rU{cD~lqF1T}OBq;hW>{~Fwi|v-?Cl0wpWo~NA_lOhTg@=WI*0KSQRzpiR zHa!PwL?b~_m%RlO^oOPSi9^^c8>mqF|9%wrMKwY3SX4t4oBmGTkxX<$>{C?{;)$wG zAzrBJ7UF}dn*OdQ+7=wseSaIo4pntS>`|4StxT}*2gaG7gE+6MEUN)Yc$lJQS7LT~ zaqpf9)BUOtjZiEg+q7G6vP>0SR!lvhs=Q1y;bs<*ydx#IJYC?MJI3~kAh=;0Tj$@K`eih=Hs?H#utI7_@OL%4^ z!Fvd;aN8s9-S+1dkY!526FB(ILWV&$Gn1XgzB-hi+X5v5(2|Dn`-0}9?n@DO*8&;%E) zI7aulZ0oMU*y=`h7r?Wy6%02Q+*wp~?@=rkucG7jq91L~@!!_OMLd_d$d0=i`U}fT zf^F%^A&Omd+}BL@L)=%D?MxEw3Q?X`17elWvf2`>VT$j?szf4n@74^uUlO7bib^y= zqGjQp*nqgLs;nRvg}XrULR3@aUJ#!bJOR^36Qd?cy=K%zzA zc0XS5Hmf3hjN`};FL^!(z5IJBDi(}^9fc$&E=_0uF9Izn*!t7~8AB*^l^%H8Xb3p~ z^cjd&{gbb{Bc6TPHz8ZuzAYpy)*|f5Q!mK>i@>jesq)c{?ZqWifrM$dm|b9wq}uKy z&H&Km6nJc_1uq;r9^#NgJ$>vsq5i^q>%m^M8~VoexV8cU5KcCQ-}ZL#q*rb7EEY zL~avKqGll~P@EB>2@-9nDl4KUAsVH)2&**eo5{r7D!P}cz9Uus?`6K9D6WWVn&Pgg ziiZ$yMD>Z{ov5bU|Gp>M8ywRrOYu%rGsp8!s52ZBY6YpSN?|^&L1c!(ip`?uq*lK| z@mjd2?jb&?%DbEL?%egg9d6ceOf#u<(^6HHwkO_h`5wNyapdKh=L68o<(Z1SF|Z+# zn797vmyO2J0fK6Wfnrh$`oM#Dp0zG4gS5v zS3`AVdo5QqRYGIi8Mkt zK7UU_SdU%wT)4Cyqwz$#*F9PxQFHf#jDUZm7x<&lsyphbH9=8{To>hmUJ)xdTz+8?hIt{e3{!mg2Y4qo z*|_i|cH)@UK0EG6bR1e(RkC&8$6~MrasLCYv_|f6%G<1N5$rvVykp~eBVv#{ zHY%FYKm*(NBqlCx$NYCSEhxBSs{?X}*y$>Lz-OZ&WKc?)3DK&5@KtwK4Iq5RHzD2G zzAYpyRtxOOQ!mJWQSWPDN;hX+wijDX1ro+RbnOGCAk}uaVgbbWw6h}Ng%G>z6CsZZ z;e_Ri7L0IOZHSed+hb@_-){A>kTg2{2N)joo2_osPf*PgZ99SxjmNG1gfw8COMTU7 zi&4>8>RFenTl&`k*~Rgfa`U-?KX>yGr{_2ZFBx|tm_b>5M<~vSYKr2bsN6<~M12Cu z7a)$Q%H~F^qCkcyo{7p`4roOO=`(tYWwDy3s6o381c?U3sz7mGRFf2y$Zb|g)Gt<} z6z4=$qNqe}`!o*pg;=>q)k|pFz!9Cji_>GVbgyV#qN(j4Dgsn1h-8P1hUWIVNazzV9IIXTEVmG(9(4@ZI>SH0{HpYW~ z)8AVVv@P+t#g`C`$8BQ>=|?RpTNYc4XdAQdQgz-h0J+5xSGGr-wn+8em931X6@iRU z+!fUn#UoL)?Z48N) z#i~H@Kva_ymB?*lNVFtYqZIc=RidawZX2@&bcTa{ri7*?fs9aG6_wjV&}v>F?y^G2fKiouJ7qa`r+6aVQ+@yN6G1oNnqf&SnW}gkraFml=T)xeE%3nuMr8@x2h0Jdqm|Bx)3* zQHn}5L82zf){SHmJxUjRN3lmD`amL0&E2Mxs9hp*uYRy;O&~w`{&36V+pONhM>me# z`tW=JdfEC=kv9f*%#xV6v=j%g`+Yseo9dZB5 zz6qJj_H7|yu?ny!PrV@j@xa%>l&+kuc1#sb1rny&Viti}lWMz7OaSpc?W|Tos4Lkt zr#r1HV-rgVSIc0yl1L+Tk8l1gBz5agymaioV;N{a?EL1_W%dxq^bbB8m!4E@I40E= z#3NPNK}^nO5LLF3y^v>WbPJH_xPqhe>l$1huIRdgyM}H6dxMH@7IFhFX%(Fv<@*A0&{=TT{Rl`ic2RiX(~i>~*=M<( zA4!h{;+{$pQnOpLRV9QhsUChU_n@F278KN@fKcfysK-1Yt2m+_TR1(yG5FAyr1t`G z^{|kXY?Hey^PnJE3ks6GKpYy6y9u$=Ef~@kl0t59A$w2|vIPYp7tQn!e%xlktOh~I z7Lr2t_r4w!gls`U$m=d1SLH)MxL5@tTSyAIakCiq+ zSWLOl2ED_kC0X{}9I%j-mH$x0gMzFqD9CCCaV+5YZEp5AHhH2!y0wkhjV6>n=rRil zd&h%*N_eRYLiP}M3uqzX!zBv}0`5lPG#VE$uftnfV}FzGhL5#M zWpCNEc2%XFDc&;mg|`ek$Xcd+tzA%p738%c`Q<5U%0&{L%MEs(;)ST(_$0xZaJxcT zNUBMjTev+aNZ*2jTn`b4#^bu1P26^+@i~VCS%akF;~Bl%aEXzq=6R3pYC`C%IybGi zs?z$aDqp5cRq}L6>FI)c+UQa}Em=}os-WsOsQRsp0=L~HdRHX8R#Cda^bM4 ztdL!Z$EvbDL8~!=3{l+qQ|z3{J%~4|$|5QV(FnzDv6}Eiu0V_^FGK~31tD@fY6h*@ zmu5jQFGQt&5afl(jRj9MNuo<3n)F2Oe(V=P#12l|-#Q{1NBml&={cx2B(>=QS0nck z6$!Mm`S-A57{Nm@Z#CKJe7Q1SBeGWMG6%T<Y0i^pH<2GI#bmJ#2Z!Fm4LHUiKg~|J`pQ7 zfy-!Os?l#=&}q}3=E^ie@l;f9w9+akkbDcoHdWayXw@o^A&SSMa*G$O=pel%O;ICs zue{KzQHTo^)t6hTXw@KAqZCg>jP_ZdWkkuU;bFlx)Q31`JVQ7`^Bs=w zaw8NUMdfx~w7M3ETS^JJ5y%k5julQ-H-2fQ#KROdoJ?O=;;TSWeYtr_Uk_q6N>P2e zT~`jlcS;g295xLIWQ1ZtRIaA9>J>;Pai2hjC@zS~)zlLY(}#wW>8nSG3l!Ctt0{fu z#cGtI`f@cb0=+0!E*v&(31o!guBcp1X|*PhOyYHc3{gB5mCMr;57UQ+lj&wRvaOwo&xvDzB*(2QU!b5HbpMF7yVqS74^3({MXMXJa`7BHt4X3C#A=cwxhx~vxqpVJU9EnRM9f2L z=CXf8ii|MojTJt26%52^2B{yr8Ze1z13(@2a#0OPnm5tV4g6K>NFquOn zuM2V)1WHsUQLCipZnMr|MQE_Xb;5c;SSHyYv#PQ+d+)6Bv?_^}Tj6@0)leBK_2m}5 zXRKDl*APd{v8rw{cphXB4K-o*^vW!Hjk`tVwgu@!6U+E*uDNe>21?phl`mPQha%Q4 zcuvA}FC`>5`79(_dro0~BQ$x=lm@Aq>&G)^HR-L~0&cCo%`N9QX;*}|s*)$;62dga znOYoA<`hS9xfaKhZt3;u0f1geot2d{~62MDE)|B+$xEvNmcpX}dCbGlE2{a9ZL$ zQNG`diQr-AA%fQaa5pp_;+Ew)AeV5|f|!D&ZUK3~G40H`ys4F2-k!1Q5MR#f&iJaX zWX-_SE?nNMWm?OuU9h}yrgC~lYnR0YG&Dbz%-mpo1*EJj>kv;=WheLrni~HxZej8i zPyPw2KAc0mS5+2KhY*cWJQl06CvwA%5w#0Zf#RVMO_1nXRap_W3DGFUGgzhXO*E5< zxm9#8Q+-FO@jt^VeWJJ_s%eS`qAH$3ycN}_wzVgYE*#T0;VAZqYPt+@K~$gS|M4fo zMybLlrgNdHONh)c_@W()-Ym8H6^ieLXsQ=tK~>(}ly~PY`dx6djbnOkw{_D}Rh70U z-fr0oU;Q}pTa`R7LNDK{q+;9{*pNs}T=*S83ktqSRR^RGq0m+EJNATZ0QwAMD;rXH z*%2X2FS8I5R;C2|SApVxqVUyF9oaFIE1N2$Rj9{;R)N`;iu*4_dWfA?!LPJ)An1z! zk;?}sb1;l(rQx{$nDBcN!g?H_FT!<!-WkdUVjpfMbyJrXf_@#VI5vuIj@SrlH5l^H0inB)|l~js+Dz52sc&fHibK<73`pbI~Rs=F2rsoSx7ho zI^m)_+Z7@CYzUi50&zV^NEwi5ATZwzp>b1f8%_J!kY;QETVx~XRxd(21v1I)f#684);OHUlNA*0! z{ea&XGFjD(C|-!FOz}!oE^iX82xOSzmZ+vEDv_%WiRQ#APw`Sz?kO0pmIN|Faa&ZA z6xF>eD~T4xsz7l^R3(Z^+U}k@fcTzvRwQhfiR-RUg!C(f6P7Dl zFv4kdEfKr9y^SXI?N%QPNu$I6UkeWkzN$&kj>O{@UqUnkh@VJlfTuR8zWdtxESlB?GD2}*R8tgBMCCR@Bw7|oegopRs%&nw+7ieR z#nykC7gl#UpcNgYSDh*D3DGn~4ccuWNVFiZnHw76|owncqpn8MJ00E zryZc%C42Yj!6_iuIHI%faoQx7uCqJPR1(NA#l?Sy)t+31xTh-HZ6q2LqCCZ0QB9F( zO^Bw}9k(0H~8CgdpFw}pho+JZfK>IM02%-6saZDY1g1)^=tDKJ-3ZMPu_ zAik%a6$!^>;<{}NAxjG3gyo7BjBr|Yij|w&H%LZ(yVb`+!flKP1wY|L(5+O^Exv?k zJZ>99$O^KmY*}nEqHWBhOVxRA2W2;oxU%)*bPUJfm)`c!bS{t)iuai=ErX zkmy9L@|O^=Rb|&iT3rcbh+;u}xyu2q=pb!lDBcOtG(`>CZDUAuCRPQCIdMNpQHk6( zhD4`AG)nPNR3(Z^@J)Rh^5=cjH78?Aj1?F|5^6zPmCpw+6X zY=PcpwToc)apcy6=O@t1)`N;OV_?G}F>&FA(t?7wk?Mf#Ar!g_{%HjvO;SHM#tG4? zmwnZp)$z-|3AqO}2+u;oVx7aDJoSS7*5hkninbmXrUKE{BZnT=ZgiW70OEVvS&?vD zhLF1^5~3^H6esN3%T~Ptaa)fzG^ua5`dCP~_3)tJw>>Q=_$-o;WyDq4L)c8CeMJxO z1CnZ<;-ILC6pNzDQydeOyVC5U=~N&i6fZ>O_7Jo>5{SF35OOS#A&O1^94}#R5vP?B z4^z}|GJPG2uL4E&<@%n!&c$k!qWW_8+?PP#idCNCov4ZwA4Qd?n3L>XXEdW}Od!J) z%l{&4Hn{+?uq`Tk86i=x5alU0Z_;XN8RCkn8n>QWo5bA|-R-I>2hXh%!BjWI9#!>1 z)HvPLXPiZebA;lIxSM7KO5|=|NK_D_0>zRLl{}Ff6eP+E(I`bFnjlfXWa~yUiTZ`; zJBqUs(FYP~YVJ0jL}ejzud=Y|QXoJ0{&36V+pOl`V*y8QeR#eKy=;A`ST_cC%#xV6 zv=saQYhgjbuAmOcJVK$X;9Xim&H;S}qE-LotM2}<#mdXR2|3L6Z6RT?HegSldO`k| z9KQypbmeTdV`|G(AYqy<<^-5askYn11Q6fT&gue$x{{SS-D#bMFBeR%mcfW7kw)k? z)PEL|y7ebsI(A=^TyEWx%%&nP!uLf*|A#D*}21bxswPsy@b^4J6>W*KPKy68z2u|g*$Z%3ciHej_Q*q zxOwgeq=+M)+mvy-h-2`Oj-=d11@$0gMOfUfh!C=bKd$RR!Dqh~6x3q_anM;%k0U@X za6~Edx!wu@B|vW29O8#f2AP~~x~ zD(!mWErUEPD9ED)t0q^}p!6j`xX=a=HXQ*Pq-r54E587GP>_`c1zGJNjsqO4zctDe z4bt75^19KF(g%51NZ30b6y#w+K_1bhcBS#jr!1^NQnBat zrokmfq9)1RZ7K+%uj<^i-l|ILuc|ZyC+F!>l{{Tidb*&VmM+!Pk|mX;3aZ|Y3Up*w zf{-qS(AR;gY{Il+{n9>(R@zrnK0?3iQpMw^@kPrpd@wpYm2lb z`Hw7*!SJkQ=(8@%(C4$!E+8OQEm+kpBn@HzP{V_QfoVa(kXv{0xQTuX2uBKjL(-0x zjGvY)V9}eC#czb-qNv<6dRmnQ;=&?iMj%5JcSYqMk_?P(T-PP0+57UQ+lj-Y7 zd=)6FFIQ9gx)7^Tit5YN^a|)kNy3H0rcQy3Q0x|!t0}G81d>VIE|4LL)1%V7vJP?(u zsV5$$4-F^N*PIX+D5@`4Q~FvFt5J&T%hhxZ=tHq`;jrmaAR`oSMCEEqt22RQ5}ylX zh+@mXoH_SB@i2X8IGMgq#aDr%`f@d;uWPXyrKrAKO>cpI#IbtI$dd-itVpp5sw&QI zQ(Dp3BX%Pc`$grdPpkI=aTOt?OCUoOXGG;jG_90)n4*T0>8n$S3l!Ctt3G}8iPb1Y z_2sHR0Q9U_xp3ID{xW1uAVU<-{uPeR$xDb2sr?yMNI2?fw(U; z6T+B+N9Pt2eVcz99$q&MKfBevBhHGQVAsEhPN^ffM4qZHMb+i#VDUKJ}B4x9D_ zGD7iCRIaA9+7?JA@s2=-C|--o)zlLY(}#wW>1#`f3l!Ctt0{dQh}9@X_2p`M1oVwq zxp3Ij_^)wIAEDSHDpyllJ-$qwt6_ooUQ{kmPdrQ?8ct>s4-!s+qWW_EM_JPI#i~HDMXcN< zg;tC-{T?mFB_S%ULcCE`R?xKm1rhCJN5rn05lEhSY^ciSv4^H}fw(OIo3t8kxL8QI z9lM4L<#Ddql+)4D1hGw3Hiugft5u#>tzzY3CSk8Y+-M=BOCW9;A%rZ^kHN96C^V%K z#CcWOtoqQTR(V>@ij~W%;H*k>P;H2n%*s<$S@*9adS-fmHX`PsHFMeDBA-Xe>qSU7 zRNJtE^vX(-r`Y;$aY-t5K#l@ zHfc57V6>2MFw*`(T$R{~t3!PefAeX? zo#Gh0VoRcK@#TiJg@nJ}Zb5-7x+rD4vXE#YFTkAnRvtz{wIa-}rbTB}@>Z_@tX1`& zKhW+1lvO29ZY6|iimj-A6~~i9>5^&o&Rs2zCrh%_xMw75aJ3~ar*$-S+XM~c%6Y(j4aKL6Zm4+1dnR35G;dFBO(tg?OV6DdaI(ha&LOQ&8pvp;|gXW z;W|DJ9xjbR3E9MI2TK_t+hD5;;ucoR5-zM3bf{mZ_r4N{;sLa-$T__E@D46r28SswOFRi)w~qkEkXomPPe} z;<~6NDej8u1I0U0O;YTYTFo%SZBzSl-T}RQnUjk5#=wR|V&YQV{>z*e6#RRFIv`C5 zg|32cY7$Zg^ce`NpCGpOfmQpF-(=Yi0{5+VoQ{ zy(V@bo~p{P$L@JYU}gK}%Rr(X%>_b#z_Egv#U+84h+sz3EC*;rO`0{i!nmKAYC#jL z7SSAI7~RNl8lt%V@A7Inu?=xYRko-kY7vOr_Yl%55cf6%A=eU)`^3RR3PiUHai*0* zT)9ZBkne1g_Xw*F$QEMxrQGi{{JzqrtsvCa!FyOONG5Lg)QF~Lfw)ZA)D1}5k(V~D zD}po^S2Q-Qh^u-=LMPDl9^9KS%|RtDLe$Lt)CMHC&w=TN7zgO75D!u86suA<#2!`I z>X7I}h=wUD(S#?;47yQ#xiZt2Lfj9%d5G)uTSR&<5j&O#G_^}C^^~FkXbsP0K*-Na z>^>5qPwgq! zY8XHsF@-yww_C2m=N688KwfC}bLawrXTS!=}BiNItE>L`<^wm%u*soY%AthA^!(9Cugrc_4JqQoDfI3bL_Xmerv%h&QVGJXYNxEDEvP%lyJ1 zy(X6E&V`skiP!BON@!Zbu|o3zS+7Cv*Rf^*S*bCzH6~^OnDow$h0s%*3_!PM+krJN zpHZH~9AtZ%g9lzYQ!u<@UW;=V-`lL#LAbBPycD;}rP%p;o7EwFFqxFsd-&+h_VqR^ zUhCJCm}1WXH%Jo$5C>IdyPZTELgcorglr4M-3Sx1DiF8n_K*V62QORg2xOF^TDdz1 z`q~w%?L?S^iEz{NrIz&AiCM55P}`Cm!2zu+Bi))-boOr@c3V;bmmZt00STW)5u^#a zN*=QQM_Sd?x-qD=`#$2Hv*aJGwBB}$#86p%Sd;`B{Y?@AvxQw6oPT5i>wWh5LP~6EvM>L(b52o(*|KQ|o`s>%9w? zkS2i?DRzr$q6cEHs%-Z?L)7`Xt(Xsqt3$=c7>*xnSs6dpFd9?VE|>*%K-y3U#vRN8 zLRjfA3k!-OCgyd$$jE3F&H~2PC;jS%RX>^rvLSgi6|x~?Xd2Ikl+aYphRmR8E*mnB zrp0W?5}H=BA**Ow&xUNEX)7DDji#M!$S#`pvLX9uI>?3`qUk6ba*U?aY{(g!F0vt) zXu8gZ+@R?$8*-1Phiu3rnsSGk>srhGP}fTm(LWDHH?*^m;N%Gr<^G|gs1=Fqf|4Ov9fayDcIO>5bZbu?{d zL$=YhlMUHL(_S`YA590@kV7=J{wJAZmykzc8KKzqpVDfoAL4+j#*Us^$8k(IHOmlJ zRJ96mM^*MB&j=nQf&#@>aX0PVO?!9K-ktkknC|Yy-6+M2|BMMwbRb^MZlVO$yreSW zBbZxyFTyQ<2n!JP#49mQn{YSPzWl0j+7Cm8|V29LrTFdo`)O!wpdzg&HOP&*2c zo?>*dz~?nOTNN8YL+-Z^|CoD+hA1+n-Hm_IrW2WV;mD6|c|HKWd~8ca-Wb>zNlaY& z{O}~_Vzj8>CI31g?-2`qz01wma0poi^cl#yLj1s*;V4>@LF;_=fPh446t!`JBF z_p~0-)Pi&?FIl|XwC4QrxxjQ7z=?#cV z!II%EPhXZ2XXd%G~85^G3}9=MmGq8ZSw~FAK(~# z{B?n*8yv%(4nZ|beS5Ifw{ufpv#huCCgKQTrlr2!*7_38bAsvG^!#0$p5NaESgw?i zC#xzgTUGf|Xg??26*9fUF?fW^+cmC$(ZIHt-~+l1)N)6LNB#ifiK=Y6)~cE=?evBv zxcmBimX(C9%cux;WTjaBH}x)%YwLf`Tje~(Yf()${1;EHjX0*cRDigxsw0TUs%ri( zp9}|%Nk3VHIIgPZ|LUpr1jj_*@LxZv)^SX#9f%G8op2pNEdTeSYWg3a#JT@TRD1vP zlX!?@;<|&__P+?K17fGDx*&F|st01Ps_YnHN%K-ax4|K#O&}u_%c3e$oEMdQSA;}4 zffOh%A;r|~$GI(>Tp;YKGAr;$8ULdcNtRZpF3VNXy-f98K-C&hwPsN@ONzfj@j_Ie z*r6@bFYXP*2c*Su{Y~z-+wH)v=p=|cbDZx_D=io-Y!|A%*W@Ku#{#JXNrtUouZCf4;R)^&I9%!<`mu6`3_ zx%y33mYf=?6l>quxlvVea&TR)Dmf;%u?$z0JlU7Exo8Jq71xHPsYBPRwQt67Qj^Ns zHyo>{wa9avT+}KradK6wyvE6Gtt#5wc>bILzT%jTPS$xNn6)Yx#reYlpRWwh|aXl3@6<26@;>HPUEoeJ* zq~WFElP2`mH=B0+JZU+Awy{Zg(%SX)Ny`6oTaqWOoXM_a+OE-0K+Xv6Ri3mw>yjPJbU(xaRoT`2$=1%DC+*hR)9Sv5 zWBT$1#bZ$obK>X*Xqw^?Cc_gQ&p5;0<)%4nZhi!`)8@(C&YLGKCk}T}Pg;ASc+%RD z)!{D{SAO~Z5-84wG)1nW<@d@hznwnT6CdlBK-I*062*GrV(s#=2G7#I1ga+1y(m`y zNH|y!Z|pe95p<5kDmO%w7jP?(y7DB)lT(=<)8`N`RmG)`Gbc?1ioD=d*?86A?5HYv zf#D>nD!DP`rmCvsNxSS?rz!F_q>AGd>etK6i7UYwQfJz=CE)cVtq*sAt;=27N4xh- zC@yQAveJFzCBOZIJIasu|Lv2=g)JG{)hnsEbd}_m>?5nuDv5t&;#@?MpIk3C!yc5lJsLu>Vv4eYoOh8@s~Q1ZIf zzR1}j6bdh8m{0Tsy@^bxV9wp zJU7y(vhi`lgI23*W#&sRfN;~EQ)2GWTk+vZaNVR2Mwq(kB4=Z)Ds2cmh>n}PDv0~( zL)>44mbFB1KjQ%Wm2j+#ih0P4siNcU?hI~wqtRozssqK6Rh5=498#n! zBAj=*UnSY1sD9m2z03W&t=bvTx&P+r20wYbu$Y_&{W<f;Gihnm@o8Y7s$24It zAl|9Uy0=!}=92ew;2&_TDqprt$$85l<95(?N?7hzkdP&bAn`DqMm#zR%lY$LcGvnW z;pFv!bik5yY2Qk+IWz@Z*%dS$;TYz)ipDMB$?rluP?ha4q6tj{glKkKaK+jNA+0L& z?+`kgMRU^HRcD$ttSW7s>|Q=0tCoP5+ebVrt18>@p;)JWV&>-;=~`jKRHj%mRUKBRmdY8G7SeM;+&ZWf+(S09RQwzJ*Q&5A&N%|_%Q?mfL7Sf6On z>7savvxgsPE&cD7En_`HbZIKAW327r7|af9RUI;G!0*?NRX(HT!|HHwu{1gH=vGET z#%jsw>9|&DEBo_XHr3Mi;^g&#Jfg&;OUoe120L)Dm+}Hk@fPBvs%$qD;hA?f)xpl!%jTY2t$%*Y8ThXH+<0>!W3VJ$8j&R1MN=?H zXVJ8RWAsMh71|z!Cf|gTwBne?=sa#Bm$GjrNkr>pRpxtpFI&-leDh9jqUuScKBgE& zKg{K6#2^dSB3v_R!OcJwL za#u=gRrO9gE_Go@U&yizu~vO{;DpO?RXGpkv(eqSYJ6&h9X+I#iTvGY3KlDtlQl_| zKgF7UEo-~Gx>&1f;3vS};24&56``Eq7=qT&xGiz#_aGjs%3g4YCN!mT1oTC=)ef3y zRsDqJ*w}?1yLij=yvkb!AG=(GepxGZlj8%Xnztfua#wg)h!3Sxx%?X&mM(p|V9Aoo zQU#wu+##+<9IM`%5M*<0u(tO1u*dJIcwkL5p$XCo0+uEXS)a=%pNo4a*9oFA zi74-h+`#Sux*x}C1qN_3UaPbrggx__>1-fDNoNt`5{?060ZlA%82Ms7ATsO%oS6K* z_X-*}a7@#33nJ};<(?Z$-j9btw&P0Ji(|a4u&C(bZ87yR#VAITuf0xp;?ZTdzCqx?oL-Cs| zd~+=gDt(P@6^_yiYBtROzuB!L)$Ok@<#L8WbXtgB~mb@?b3!aQjd)IA?NvIIV!m8Yg?@3mrLn5AJ%6xk|Rl^qS zvlAWvyb<0ro2F0s$FR66G*<_S-D=`1LOq9%F0Yx->og$y50hQ zk7N3EyKU?i`4&a+gLkxggjHHj)1zx^_@sTw<7;dg<&XVZ4-bfnsOUq5w_t+nilzC9 zLs*dp{qjJ%$amnZ`$t+^)!5de$lRn{>4lE>IP3qB_I0*3(FL!F&|iysNFNmR;;ir^ zt@Zo7ZB5L<=kfH{rXJF}Z-Y1+|B=@EecrYv=HP8Q`eWZ!ru!JYE#O$uokQk}@f96k zj=!zJ+1SY24NSaY>O?D1(M)>{<~{g=X+)Z@1j35cjGkcB_8?!PqWZlC)08;1@$A%R|09o7h(9t zm~@kOl^cLEuV4GQvI}RXj+8nlhztPZ%enaEnA=WP=J4;q8@(>Cg^cX^Am@# zBIDXaX>Y_Y60iM8Yx^y>wJ0)|l`CBnR&cicBkk*KYoZITGW0jA9@1L6fwTP|X|3Pq zZEIo_HZ`Xs)ln!zKmWiSvG z&7jv{*#E)wAk9|-VMS_2MKBuIQ9q)h`n?9jaU9f-G+zmX6{#8B!K~Ur{fLU{_Zkf6 zV^BZRd?gT8OXR10`P4;g^XRBf(NVEFZzt&C^nbK$N{zs~r>7!=cx@qf~%Fw#W@*N@A zs?tXGnd#OL)dr6I32mP5K`%d{O~rvRuyK-@xKzRPvyv~Ng0JaYq5!gvSm-NwS%i># zK%arIqY}h+Q&QPZ3W#=J4u_D->~Jh3F5n>uNK`lK%6G=s!d1O3wj=4t6e5BAr_?t9 zJxbZ#4@(CSKMI^x4ohW^ESYYpZ$#4|jw!&S98U^jSEN{~#qnfDalAfoX{+*aedgj^ zRq`6ap<7k*l5new&5^BXjxmn`l;$2+PZlMq=#>1y3?-4)$9=H(3P`h7!G_$6rm{fX zM_q*UXG7S;z6dU4782dt(fpZUiU@)o9K7^0W>ShgSxgWxgIEMzx>)^ww;nH}aYI2} zoBQZ}j-zDh?_;-MafV~?i{6Cnz6?1ONb%SayU!CnM0O{PJt&B`a>PugNhe9qrkw$4 zI`z0h{`{8L$h%5UpR2WjtmA}JF%0A!G^9&~AlV}9gWBA{szD&`Q+BRD-5OG>D+56@ z0HwWFE0>GC8Xbogmyin1u22=7o$j6B7!j|_To3~p~u(4^b%{54ef^;=crq@C_;gKfI?_jb$5l4e~-%bXn&$)g{0jCn=w z-}1*0bN>hLXxys|wAv7>AzC$ymAmPr)u31nQ+&LjuMds?=ablsPMiTZ`8Kv9V%J(0UilBiFJMk(G&L?ut;777w|3(NL=uL zatJw)@Z3+P5W?vau*|;fh>)#pM;_uzwFqlvc@dJG-K>z5r7 z((*EkLR_it;pi2RaLoSHd7?4e-2W!<5XV9XryPNjzroB72Cu72S zaW_hFSyGws?j|nLdZ#EK!2}~{mV_smdxxsBYA`54eMhlV+)Z{v>{XSIbCPjtFHABh zMiShJkHhmkj%nrh4;$VDN>7UK{4Z0#is}Ffr&YU$84seG6`d_-8A%WmeqOQ!&YGsoe~w)YYPO=RDBN+vc$du)PbKX0V)_! z0qPgbmHP0&{eJ4cFGLVlfC}CYv8d$G|1$n19Nys={P5fV$KKmSMYeTYLczWH>Y=73 zrKqT>qAyicN-0G}O%)Y2Rn*9P`MwV*svc!PLf(rODq3ivGDcA)jdTpgcr<7*#-%}n z1`QfCXk>#14H`6PWP=7{h>D7uYN|LyO@9u-oNGs}xejq667ox)+{QgS_L*z0pS|`x z=R^dN0mL_HV08(??sQf14f_d@H9#_Pdd@Mgp&2uW+chwbca437*P|Nwd(QnxmB03I z0eSq8Wb*kZjJeOQae2|E%j~pX(d1T@Ii@n?LY`PIa?3V^Q!_Yb`{R1SAuYUiVb%pc z>}-RN0LC07Bf9Q7r4M>BwmkylF^(;zKgr>Hn;PTr#HRifho?66r#U>cso&@D+@{7k zys)W1!{G;;Dsy;cQ?EFDa>^UHp$-i9Z0c39VsL#{L4TuTe8oo2K273q>oXuHci{ZuNVCygpeq%B?VH$1(WOqaUXx3?gqp^Ayt#SUlwWQjfkVxC|F-IEME| z1l3#|x`K;C7p1i3LeRx0k-l^f-Q`#3Eu8P*c)j|{-}8&|>nC2GD@&+P$f}c`tvXpR zv@fJvL53SR2Fu20K5AyP6+9;Rc0xPq-HBu7sRzUUH09IvR@HQAmmYC~=e4`DyiVA= zjEdkpD~naXcE_0Crkpt(`k#2onr#1gGwi@IduV-*VSkz$z;G^2&0|>ppN-3xlo1?Q z1oF-lAu9&?k;7A)8s_kWP09OLB$_kG5QkUDHmlN6iTN_@>SSKvvqttS4oPGi*M>1%pD=Zkth=c{@>=gWFM=j(bs$HESx zu-9`Ok6|ur)|D2%*sTF_%%!LT`GV_m&B*Zy7N`pJt91?Z%XK~H*Q-kS-`p(JERI#e z^2N<0SF<|F7hKwFYrnSFb6n?MtWnkY1zu2-s*|&roU29p-ngb@pRh@))_lQ^xd!@{ zxt@CmcJ|EmoNt;{Gz|qRyFpw2PCkab4;1w%OKJH#uOijS0ye%Be(}V;iYrpp)(r715) zH@44lr_f{fM?Z5oU{gO(w7MV+Stwq!Zs>Xec#(h$7*cd@fL?ZPX1(y-%=)%kQ|Spl z2)GXvw?ei*K1SR5qipAOjrByO=RQz1v7SV+o=B{l8tcBsdLO8oSofn?_a)Xq4X;XG zS+ZriDtTe4PWqN2-7r-5`VoZVbKIC^hQ}qo7_`mt6XlSbB)b{pu;$u*TpGYen8UHk z$7c%elIkQc-rO?PNxtCD$=q;wP|N638$wD_s@)4ucuC6) zy?A9)UZ%1ss?WlI$GhB#9Sl#>)ES1Q|K3o?7|wsNsbvg#Tb0qTqXHW^W>cFOvToTF zZ;N*mY9B+EFhltQvT&(buUV`W6fJus_q~@*vGcAHsy_E5xjU@t^36t#=nJh*Ey76# zot~V;{TN%ttjcdO+(=U_$U&M?Zu!~(i#%;s!^60S&DgbUcnG)N3pi$P6VKx@Y8A)p zcaAY+?*)IFFbg*eIA%NT%CAvr7%P#s#_JhO&DkQo=59$3ldpM4a+*+{T)8XcPWKlT z4tbw(y@xqIvD=V}-da@jCZfXIg=MQ}Wdp&3T26#E&GYHcR0&!6#VL$ zW_X{~n`HGqS_@;HgLGs~d>TqL z>y=3$(JxZzxYt>);7>wHK%Z5iWXTUfRh=XW9|fwDzUFt6G4AF#U5PD%Lv+sd0$z5BM8J}W?@(BiC zAbA3U#9b!$ym6P6TefAJBdXSE8j}k+7GK&srt3oh132dV^DR9%%_sIu4Yk!Jb)RLh zs;eO0!7+eruCH6M$qw6Fg-WLk)qWhAVgqEQXo^*Rq9P z=KcJs-Qvpv&}u$e`N9Q|R@}R^+dWK~4+^XH>>$4ABSko=5z3`+1(ETFE4%c~pWi&6 zEaMnl4OhjgOsgfck_ZoBbz;>R<{jKKOI3uQ=!;}Ube~!MOpQ)Ad2%%*!4pK7wN~(E z%Uz;6;HmpFkHdJyip6pKwrqP5-2jf)KaaDCdt*L;Mn9S3?J`9@DS5-{q~8JFGWf0% zTX7vh6@Y}UJWrI!27DZwFWEF668@`}o3KAJ9@!A5ICYUAhxl0S%sy$WYgP4r06d?P z!jRP8q_+z;`$t4~Wl_qPa|l_qsHJ8NKnC(zE)hekLCT#NcBd)dVM{o*Z4e1>8K<@k zB6X+rzCq*@aSsWb(1W5TTM$4z_7->_cZ~?yjhiLwVkHC)frBu zBqVhY3BTJ!`)Br+kgU%qxO!@kavO%pO1yUh(qmR~vF*aCvO&amw?M?vI3WC7IqQoh zyo0rFZ)z2=np_ks35P!BEn-n8Lf#u>@(jaPeApex-j`XeCto`l*0}erGY81BS(Rz^ zE=_r>k2sZ*keYf(*l@J($uGuJoa#1+xT5udK|~%sB$P)51@A`;!$}_+BxAZN@!qfI zvx=+IEbd+AaI7MIB?G#(mVj=pC7{zs^9e*Zhhx>}GG4r`o%DfB>kl|N#5nWmIm`eO&^101VGImU~N+DXq}Mfy;~ zb^IDW81gwn&Wh~=4wmQ>&`)hWM0>eZpY^nFkY}*J6~vR{=1gSs1x^hbq&$RSvXV7C z0^|dZ@uSOKqK@Hd*gjg5=eiROD)_cbW2j4Twv_&~UjgRcjfk=u1n!EVo`a*;vXg%# zdkm-eapO(NS1`*@9^-}hZP_x`B}=QkfHz52^WQ8{tI2tw*UV~?pNsO*GPrWHD0}8! zZV3qKPsH@Go~HcLf0@;jeBxb1dT0@s`2q5WH08q?0O52#@k^Wbx? z;_kXj)JJ%HY7aN%XBc*+sY?t?_61W3okXI_`xIA*t^>FZQin9RP^(RuY3)r8BBHu zTF=$JL72;Ys(5x+w}w|+pUwIpV_T0R^J3!4?wU66YVWhz#%yb%3+}_{Z#j9$KFr<0 ztHaM`z2DnyYhn&Q9;UyQAaxh-yu?>qRbn?aIXZJljhzb%;om|dW6i0iaw}q1jGFrWKNm~0vUvo z4C9zx>?bhf`}En=TTHDb)FFn)Y04{+=f1hpd-|JM@8M>aPEO$DX7>L4Fqzm7&)y!* zd&Ejqw9A^o1ij{I?hV3R&eA$uUsLd#18q2FRST{(Iks*Q$$XJKWZK;d=Fa3HQ1shv zYoZHm>F;Cmn<-}p{PiTifu7!OTN86&OMh3%Z+5TH1%EG+-{217cH5em16%sz+FjpO z^ub#h$Ll$_JSF05su`^H6EF}J^?oB5u7A+jq`7wpbE#R+ppV*-IZ;vOjbPY;LFS~n zcL;OoL2lXp4m$Zc&Jq=6-Ux?VC4y7p#YEpxmWKfJGcw2G}o_BD}-VoPo zK~tb>@z5WJZHVd^31>g>)5DC}7}s;YoEu1jnDCcznd$TY<)*{3j5~iJI~Tb+$?`qH z0^UqIr*};E4k;Yq$lvYd>l4h|@Ah)y%o(^aOC%;PTb}HfoWp)!bHrfVxK4i_mPdS5>rLZ0M@;~{YY&*6(ig;5u}7!QRj+ZPwUkxCb? z5E z<)fZZoU4<(Y_N5!le|jwB(XV^dNJlxyAr&n2a*Nbkyfb~@^MfDkiL|%k8c8}Rt+Mb zbr3R>58){m{`=Bjd?G?M3wwg1M;MO@E`Kz?CE_J`TCs@bGnHkWB1;sE#{|L9d>eGx z?E#K<5gtP59W;e^77TvE?bI9o&U` zNcfp0rECYTGJ)!p9Z1kIK-mphC&h?zcRk0Rq(EKId9k~m^Z9Oq_t5xzeo_9OUzA^4 z-*aUNDOq*WvsEYSh4zJXTgY$^$6(o>;;NADcg>sRW(l9rJLm7j^F!h-tt-t zy~{`+eM@8>wdWY~amu;%f4jMjAHXpv1Fg=?>J_bq%u0UQlvXQd^#g~4|2rQ}-wb0o zo~C@akm#)u{m9{fS-n;wxk!^}*@%WXOhl7PBo|>4Eg8|TIPABGCX`47heY#6^lJ_i zQALU5A0;HwoDuzo!E2;$-j6)2)9eXvRmH~A?Nvy6e6WMfOTT23kfykTjzmew0EE`PCX7;LLOK9p3-Wb0=B;NrK~5U@4BBBxT+nTV%vyNTvxLm& zL%QlaB4oHeOM*zL`e5AvB<$I5ohRzq7cTdxXD5J}w<=4|7J$&Y&#n~HV;H8(vRnpu zYT2w_ak&0}+FOJBr9Hf8`&2XOTbE>OMke1JBV^McKXADBfAD_dr*{}0q^VN`(D8p6 z>KTT!X=)Y2?KG7a z`EP7lxGr0iN*{(}p8H_ixptr02<2xiHGlAB#x^_bNRha}3b0>`CUP|O>Z zJQ9$Kc0s{;Y8&3J-;r*ycIZIfH?w}RzQnd4{$Aq9t3F?kVcu>NI5FW2d{87NE(`rk ze<9eTg146nKn4&CeYKS2iGz?$KyQI?2{H(~lJyU)hU@z#=D`R*Ub=EY_{4@LN&gx2*6r`ERuZ`K!2bHEJ>o#O*Fo7h20e zDDMMRQ}LCk;ww?bSE7oqL=|6&Dz56jgHGdPU3Qu0lU=%N{mC~(_ScwxJ7iOSGh|#` z^<7g~`ODRAM9^m%KS`nmFl~%cw$r^p4m?j3s(f zo;)sOa0N&0vBq^)%l&gcVswg|Z9oVI=>DExc9z03EC%eW6Lm=ku(=4}-gZ zI9tFm+A8xnw_1bo${*Pk+f47k%BGGQq7e)?Sg_ipc_0v0tDVRKG?r z6pEmJqKsFE-Rpk^1aH}= z_pRlY* zRJ3l5V3zaOjWiDg!Z2BxY`zy^Ptuep zrd7!xuQ*)#e@XOa1;e#8l}Gf_h<>2^vow`w^~v)3k;6svHLdRTLqQN+8PO1j3r6%> ziR3Al1-Ue$UvZd-CY4COB1fVNBliLHlx z6!q00jG@P3k*~fG(hdke{^RQ|%-hF*oFFF+eABhTkhtJmLWIm%c=ColA#?eV=k*;C zGE|=>L8Mf@ux9S(W9(t^$x*ST7ih>>oRCasmUbpc2#R=V9*T-ut~{jSm%-yplbfk5KHrcf znsu7lD-LOvt=CDeUCHdScbae9tifII58Tq*C%d}-$RWLDLH2oXG&?i1A)0NPGx<=2 zR##^AD-M&DeA|asmuB^A4*SiQ+}qIV)U1BPVNGJaKCwf<*Ns_jc8&n4p?T(MPJn5* z#Te$W4^vrLpRTpsEYLoV+1v|`Ptx2|j-P$UR{D7k!$lmg>2@(bPOy*P-&kDYcn#yY zWI4(g1h}p#*zD&^5cr(sG_`~0 zDb+T)S(`?D3pi$q)GvQ#=|O=a5i)1_%8dk_zFqRI8nLqZr=|2`3|Zh;(v4x>N zvB*7P1CVk)%L|-J5NY26kbVhQq?M55NFXd3A>rTm7Xs}do-0fI6^HGAgm?eb9B%yX z%~bWqauY8OYbW{Q2$R_*h{Lm59AA`L%?XDcm9#k_mQR>anZBj0i4>*tuawO?9GC|UvAE70~s;1>{<7ZOOVw`Ur83ZWEa?19M)Wwj!M2wvc5ek zu~C>;b<(#=b<#IWbuurO_lP9}?Y8j6Ckt?78W*yf0C!u0Saw?&3oq(b#yqzt$?Z-H zUtF5o(ZKCaE>rGD(9M&vnJKGmLOGC?jVUkx$hEnfSp)V+~6v3AE=t*E=I*&jEcJ$ z6?ZWzu3n}1sKV!z?6234&{Aty)9kN>yl`Yw+^WY3#o?Jvz2Tm1wM&kCe8wVo+a?wD zE&yqR^$YV|VK^sgis3x5aO9npP7pDin~gPr*%ch)?e-|16O-Hh;D8J=!hgnM)Mvsqt`*w&-SJe;_)#oorN!_Q_Lv#p6PXdn8UP98Fe zf2V!};iv6*6SlPZ+^^4U0?b53-X>S&3_a(g89Z2z$W)#Ww>o zzd=XcZd(&`U`u~J$#16U!|FHCdD?b0VN09O{rakOgPEvkuQY=R_KK(Z#v!Z-J2O^v zo-L;p3Z6*^aF(d3%8g*ywLu9<^FSa&s0{Z*kkJE!P)U}NSxe~^hns&z&1Zc3c+v4! z)=c{CNwPH~lh5P`*)qrv9KQR@`3c~gLky47)Hwp^d}^rY81|&8ehlZ*)Eb66X(})7 zO$+Kr4qw1+_8y`}@R|{@D#1IAOnAe%hd4~!6UsfI-15gJYeL!n^S|)bt}Wg)D?tC*=b{|egp%3v6+_B^95T8r<_ySJ3^W6BIGtk7fPBS9 z%z#?}e8e%E@|l%TGZs7hl!|HfTUwKhw$q3vyD{ubQ;c9HO)-M)G_`}_ZkqBzF@io@ z(8>~md22z*Bf47sJP-7uSxIxNmDGq~>>!-%qIcY4E6AGM%=%Qm#C8Dw265y^u6#X? zdHcwf6VuMX2SsAyvd}N|xy+-o502^)1(27Bg}$ASTumBeu)(ckBnIQ zl#o4Blb=-Yf1(~x&a-Y-4gZN+nbi6x3gejxqeQTW;8KwC!-o3;k#`|40C{J5{H%HW zta<#bdHk$-{H%G%cWxNLCL+j|da=dFP@VKqR408L)kz;ob<)RDo%H&{Xu5G5nClom^YtAZmu$X#mAEDjVKO}Q)^~dYQ9Pvc*bv@?2in5>ts{DaWW6= zkUdi!`EG3woTvNTDRnoc?xxh;6x|(~JGrSCguB_4bFdwYp~jUfXtZJ|#l2A>J&Md@i7Q*|L%cfwY_>7mn&^V| zp}(2rA=C8}^&6-?Z6}(rrOoGleP+{OCMtUSuNh46W|^n?#v!c8CMuNOv>Zp5rQ?<} zsOU!=t4LpH((z$9Yw%-z44H$oB^;xzvWRo*H5f1ZkzKLPbO2U1b@VU5H-g~?3s##n z_YPq$=g2LqeXvpA<1A58=8a&u#e>XAbMFwoFVt@r`Zs*XXFpB(UiDVj-Q>-p4jTgH zc+EyAt>eX3?c@bs)NYwlE8cGA8?4v+$cI)6d>lqT4omcLl^h?|rMphcM|?f!$)fc6 zj@uF(;u?lmho8;*KxjMn8H#IkyDe=#_v<~(gPEwPy&J(SfG=oo(%d_Q4%SlDuCM8M zb^O_^uLo^ej~h`aW=osT{dy0}@K01!@kTIj!537VH1`gn1Ll-fExT`FrO#5ugS(mA zZBK5s<=NXkoPvX>=x(MNOi*!8^NmAT5eja$Zo%ybm3I?LoF(-M!@fVtkA%v;&uKMb zR~83Fpy}>h=w>kH=@@{ zBoALC8aAR|ahQlEl}LU@fkcBw^lJ{!ETRb|lFwI2^wNla!(k$-D3N?0cL)U2MkMbX zd^HGTShZN>N2myy2ZSHq@bz2F+lM!tASVrctIolYxZnp)2syU!w|4z6bNI3S=9VCfuhn-X&8E%l z6^Cm!^)rVxOnrGw6K3`Uho=Z2`0YCSUpA{BIi$0!Uk=0>?fT7bXdJ^2=1q1Et;Wpi zR~%lLm3#}9R>NlXYYxxNN^W;(wPaSm;gFeS3nD*W*AMtQj@2h-jJJ$xatFgf3qbB} z$gpWvV^4ujR%5=h-YTp9S?S#$yXhd>RVTgW1^l!Doc-~pUcNji__hx1dyFUe?XJ56 z^}@~YZSD$z2EZ_jWAJ-(4M3*zS;{yyXAt=ieF&$<4I&?+GhsRkfA6FaXaP=Eam?C7 z-&wjl5Z&zE=FWqnca%IPjJpts8{{m7bmsSm?V?*j$6z2RyG7uz`>*Ds-A~gP&ZMc1 zzvkxb3Xa)VGPW?}whz8@bOCptEb!om)I2EIw1ixNr==thlI@6!;bCAWiLW|hK`yH$q47=n7;4TLdt+8xdqhl4gH z)#}En7heSFg>`ZyKi9@n)8zT!`}&O#j|zTrtpKEq zSm-PG88kw60KEmm<;oy_t+FYlIlS`yUD|}hJzGM#SqmWAQDU_V!lcVnlp9)ScYPE}_G30h?N~7N zo_dQRbt<@Bq`Q=d+`aJBv8DR@3ADb|G+%_XIV<|OO1^jjNU4f1Z*~1N;?1Hb6mOUP z)uT5H{t&V`s|#er%&Nbx=Dk%XeXp^|FRj?GI9#)9*~BxfH7T>Vd$l7b-bzQv$EkEz zbHzK0?xW61Y(l!sHp*GaJFQN7x7EqKJO`0yCT3?PdC+HgcZsS=b;U03+-+H`D=k5) zD=k5)D=k5)Dpx@gfn41s>M4p^Q?@|*?gLd*+^eXMuA)A=iu&lP6cksbnJMx{`sSi& zuWZZM?e$Yk-2l7r>cW6OsQ}xZDz{yBTgoA~Lw2`5i0w9nWAGjzqn)+gE%H_XG6w4< z3%bH^o}2Fq!zrgJzX_K>w1s2535%iDlq=}DVkpM*{?@pPp$@@O!xh9;40Q^wOB}Pm zgWyve+ba0eh;}T~v@Mq`dI3lWtOtx`)GsF?FAO5@rLf;qEN_;9UNI|qqEst+R-A$L zqOr)^2nvxuuwX|smgqXpbL;SQ)3n^RC3Jh-%CW7lBbhgohpc6;@QRm;%tO#fx7*f4 z7ueF@Zt|O5C|Z$Gjo;w%LEG&nY-#hkUtg6SFcTGhC9xSy@O?v1^NmATk)u@mot9sC z7eQ&x`X!t7Rs9H?n$8IBgDxE^`T}kv81`~dSkl}(gc;ZLb+9L%xbBZKZv?~L6l6}C zdx!8MU32fii}aXXtVM*q)wMQyvq&%dLCO1p8)c-U37ox|eT!G?pUwK7ZG_R=(%($- zkgfVEUh&yA*4Eo?Yhn)ii2fFm-%Ld})o-A!w4H0hmNuXJ^;MY%Gf|PYHiHSe+|zvH z5LSep8LKGIuBR0WRCEPriHfwO5e&OFC?RR?9kPL(*vUaGUk$?DyNj5DSoUygzdq!h zLFAJ!vK$yhZZ;JnH=BecM?)MYV)1bY)T^jnpVRIW6Z*lJPSZ*J(E~CT(Bw0^J`iyB8=9*k=%dq<##@G+4eX4a)P#2{5NPX5YZ!@EOd$FD>b}O~2HR zvtCSh6W>T?C(-KIOP+%1q)5_z+~0hR)e z?gmmI+(*dga=>MLtjl9vN{`KuHNlt3;p0Af+((c5=(-0U_tDKxcofygX1M8u?EjC= z@YoEG&2U|T#~UT8L~1w-ZR`Z#bYx(Hp5LPWdDC`hR0@jY=-L!Jl-={A5;f{ zGU(?Wx$oT9RI@p&&x2`5sQ7+=^r^{Hd^FTypHG!JWXRD^;(T4RUIfQPfREesX&}t=F`Nk~(S%&qd zv5f9wxSysx@v2yj(CVF8iGuJ{B5nrq9u8RJP-HwP5}D>O+R(~V1oJ24Yc)l9J|g+2 z&gbw&}CAi7f>TMW}rq_ZeaqkC1lu$rLEg>iU9^JgbdVYAtX%m zIqVw+>GD1VrbyGeTm>Rc<61S=4755(YoskCi%+Y$WaXu&0AvQ%%f>RghT&$K^2GCE zHA1Tmvl7ALsYKiiWDgEl<51H)DAKgM!W_DQf?Y^R_utH07Fo_Su$<#qy>a3T=9(*2 z9vJRnf(|W;N*APx{T4{oMg8;$=`dnR&qKlhui%P2ML{Yu4}mEXnNO|)k;t%#8e2wM zt)(^6#g}EH)yrh%wV(i`AJ${WGCG6de46sagJLy8t2wh01>vbg+zjL`9I(cr$aqjB zGIxbpcL4<=LrCdw$rYJhuW$0Bq1qmk>mu7B`G8D8Re-(2g6 zhj9fzn?%S5E4KXR#Wqgu;8+zcz94n3XnA0`-3eO#TPdBD5=4vr8;I6!{qzVq&ri=o z!T=9oPoAP66|INB6p7ZMt3V`LSHLv3jA}Kdi!Z-_MyqyfnPwnQVclgcqkR|-q$w|2 z9bz>?tA4W*MdGPM+zezG4p`$*v^*#hn!CbGyMO|bA!Of*BOvs^ztLiY00^N=vWHQ1AZeD@+x+xA zBn)r{_T(uFQjvKGOp(aUx(Y-hvjI$F%cxdUy7;0Xw0dVN+YDqE*2l&&dWPYLH0AGP z_Qh(1Ru^U^3c^!~xEV+ZTZA~-16hOhuCa_BV0fISyv}Tj)d;PQ%t}OrrxI~9kaIX-jYFOBph#!# z3RA+KWk7+>5HfDtTXg0bPIcl)o#AV;=jsdz2n=^9L9M@MI6|C`fhYAuvTc^TJgi(wP}x8e2xSn$pD=5uw$xt!y)pMOd#J%jhC9bWPF+BO&JfaT+go(z5-e9ZRv()9g1P33 zj0c9>lb}iA3K*P;4bXRQxv2k^AMOKk=b(LyGnkzCM7;aC3hW}0znQ@2=`z;We`TFS*vX!5n zhlBwx!=5}vK`Js2fhiK1x2^(_$h-rlv1L@NDP4R~5L%ts$~FTzhV=(y8U2J|tM#IM zkbNpvBeZ&AR-zz0m57^xJc9$)I20KVibUqFFx@VoKx7D6vf_xy4B*sD9IGP37tA$R zWIQn3o&cVpgIcJe7!>fqaAm);JUy4~j(Q zt}rF+Sq2n{3?aj|y+vd?aOxS3RgvKfQs;_{2Zq~|pi-BKOdmvs{T7H!XZ`dDDd(r> zAz^?$uqRJZkc!MhV2VVh*Hs`AnF(MTTSm2-(#01Aq1B?TY%`E~Sg#t(=q83cY08Vt zl30z6<1J*bc84rp?=B_aBT|j}z5YlbiTSVpqSU%!d6&b!@uDK%P zf#LQf=)FZzc@B|bzXc+5SwB5Oo*S{G=OJN$Phd};q97HShrkqxOslIvBr<)#G`5Ut zHKmI$3PP(PTiIqHgRq`9meF|(m(r9MnPIUSq1B>UiGuJ{B5nq<1_!KhC^8-tiOgML zwp>7g$PiNcyLk^GyKo;Y2RK$mhA)_FuE=;`xIGElvM4HT5E=GcATo#b(<9^x(4Yby z5(anzd-48A7(KI3hCBI5mS~Rb=>rx#o(D2Zq~|pz_~qB69(eVZQ|;Gh07BLN@Z# z^N=vWMc9+4C`d)-AuvTEv*aoeiOeoAjV+^EP3hu`g3#*NR<;?)A*|1hW%LrmlJ%l| zy7XSGMrifPh(tknDiJpWX-8PBaVRn#6p74TVV=8y0+AtP!AdG3^8%;(ajc3AUoh8P zk@3KAdlK}#+eGF)M27tqh|EC!^az>DPtQZb0Eb{to}wTXnTNm>iOjI8KqNBDz%;gu zYBi;cFA74dOaeBGc_E5Q)qfFpVvvT21NVi-OQ<-d465$Skbi8q4T9hFfXM zi_C&pjnHb-tVBV0DiJpWc?SoqaVRn#6p74TVUAot!7e1E+qSoe%mr9J;#d_KzF@Ao zBIAMK_9W=kqNr>`WY}+k$XwP>kC5j^Ea`bj7~m7wlcy+1Mdl$eMIzJcDiDcGA25wA zqgqYr;){aNYRFc$8OR{4r;TNF9>b+Hfvmv+YaEJ<2Sp-t zSC}mqP#`jdwElg(hmc)(0G1;ht0Kb}%r#eJJTTmz1g%>Xl{JVA`z;We=hYPuwe3BeWVbD^U=hO2o}T=HP%e4n@X;B9S5H1ccWZ{+Q=>&5wGvVk36pc;8$* zh=*~tlxBSW32FQLDOv*A2g?DDRng)LQs;`62Zr07pcRXvvV&#Uk5-m1SW6P*kGrIWFm9*-%mT3m^9M=8DGFrxPEKT`M z(<4?Rv>G-mQ6!#9#LYlv;a~;FP_#TK5*lKTKy;0vSe@61)&<5CulwfOL_CZu`0;Q; zp7c<(k!Zbl6^KNOP1M*j(rVTge^M7;x{_9%$;xX>0Z0d|dyQpu0K;;c^2E=@ zYJ^sUW+jTmQ;E14$OIg)#-V6=P$V>Wg_&~!1zU`e6Dy7^=Ubdw!LfR0#23spS7bae z+@1u@{Rv84Weg(2ehWlqwSIbp9OS3xAz^@(K4h)~CDK9ctVl_gmPO}mP;i*L245SYZSmRJ+JSY;G zyTZJ50RaC;K;47YljqVNuocYoQ`OXv<;FwmXp z`WX|lmY=bQgfY*TBg_df7dS?k4>fr2(ycG2e)7jaqi?6%qh-& zxCQeO=lE}CMDaXv|9DS?>2UulS%m2ZhW|Wbgy{!{|JrMW83Km?K6Qkd24)_|2(yTD z%Q&`_%9|J-q$#gZ%~`F3a0AEarluK87PAk~(|qHQ{rV;UtwFvk^~pb$?1PCgeo2BQ z2yV@aO)2*)oth{xr4VVQAfmgnk_eSpAT1@CQmaaHQ)(smMfU^wzVsJcq{+g`0{(;N zmjYG_ks>w)k=1H;0h?*eNMU^z(N)1?g0B(W59IsOU;2-w5xlEHph6)RSYj!=kEVb= zd|&G6teaJVz6g2VqH!Y=z~2;6B<%tLwV5 z(;ll)TaBXowb!X@b~~h;in}@k&99v5ABsuRO5zRU3YsnMI|8Dz+DAJqPqy{MGC6+ z*86(QxCx1J>x4N&$^@rP3RRu-m8wp9mvf+7#IXum#f$aYNiOFe*0PFxhZp;`limlp z_du7ez9-A3JXJPz0aj)bw2kM!E}194p7ZS2bDlmbH~CqL`-q*~_Z2&r^Oo`v5|!Wp z%XVhVC-*?d4ieFP0Hzg-8r()+0n!1;H4WR13m8$q1fF^keNZ;$Fu^BEi@0*E+Xbim z3?HyOw+~w66Qt&>*3_5ZHorAU^!dLJCc?08+g3mML~akKj&O`tv)$D^TFpi<9rm-RsGoU;d!gC*y%Fr9bN-CHN*+@EH&xz4>7( zL>#rlI{^wJbeUQeX>zri(vFt*Eoe1v z5jF!Egmq$(eL={aIht6)a3xLo0@A7g@x4Qa5oXF@R5Os@Rh$s35n8>qyyZL7Je5k* z4CDk3&diZ08dbCJpE8Z*@S{yle!{S$pD6h#k3^kj^@_s}HdRp~iKq?eezTHZB4j=v z(t%UYaja@AUywRiV?8j?*d7p*E6`X%Ci25nhzRHatP@LJNT{*jI!~mrFJ11D#?AtB zZdESQWolKV$<=B~J6Z&kRx1`^Gmr&XCl=Wkglw9liCql$)0Ed(S`{F^cgQlrOc{)7 z2BNX6Vl_gmcb2yZC{Lx*Gy`dcB(|9}ilR|9rwvl(u=AfbLG8xyWt#FUMWV71z2fkh zSyhxsBI*ahtPx2s5wevJd5Kd)I94^5FG!uMu^t#`>^O+Y6=*CWtNCFnLnu^Yg&H`HZnHL1NRHxg%=1af{^#-XyP2h zk7>&9Tv`<%zIVtT!b};AY6haQ2Vylss}Gj92q;gb(li6w$sBu7H?a zfyNSYkRPT(L_jxTomlEZLXG{_c_NM7a=AwudkoA#LtUm;liHi2v1&D?RwAIZ`e=R7 z4CEBniADAWAy2Fn6YUswrYXO3X;pyu-XRxAGG#ET8HmPSiq#0Mo>|@^pgfgI(+p%9 z4ra}fC>mAs&>&?F7ynt)*tZyNr76EsB-$~eR~#;wRYi#;q74un8h9%*a|O)zK8P^8P$ zYEpYsG*+#q)Jg=DR-G1MGmxjSPAt;&g!G!Di2)4DY0B?hS`{F^cSr}qOc{)72BNXg z#cG6BgO;}lC{Lx*Gy_?KgAH>eibmDEGDw-jodMI>cNm_eDZf%AIy0hI9B!LcMTsP$ zV-S?gN_vTqzI@0DSk7^*YAj!nI#**oFwoeK^}{6Od48A*5dnPy>%>wQ5^C(X&J$^D ztIIvo*dAaut;$8ZOsyuhH$`LBYD%p{KxtLB2%CYtfOTS#eL={CIhvTma4}8!olC0% z#P<$)i7-A331V^u?-dX- zlpm%-L_m9ComlEZLXG{_c_NMNbGb(vI}Xfyt8$SpQ>!9Pu2xgp(ITL zXjIK%gOoXJ`xi`5pJCXSru<5gsNaZQaro4%DoP{~^?+d9h@_VYS<8p?;nV<*RgL8f zQs-){2L>8j1~It;jU{9$KTL&)fKI?VvDAfx8vCvDL>fEoa*s521(+udb(vaCYH!Mo zgj!9hl?W)UcB~JYfvm$ivBc zYI%!*@>D8KGmtK{T~BI1Utp@{vO&rm_P;cZ9mH@tP2~~I8qq5bUzk-zi9}<^L9k*( z(o2LK=0m1&Y7WP$#_|QJb2Zij1C3n-F}VVbC1f{0OofPmuEIL8)P;l^`>pdt8oTCl zk2H24nBIoEOsyuhH$`LBYD%p{KxuVmeb5Z#2-b;3_5~rA=4j#xs?uiF$+ap#eD9DG zM4mDj)eJ;q&&6tlR!=Q&5m25=rD+B-3rxliD(4``$i;PLC94;WDTb_aja@AUywRiV?8j?*c}j)E6`X%&hx`mhzRHb ztP@LJNT{*jI!~mrhc5R>V?P2j(NLGE)ui^OXslXIsg(#Qt=cTYW+0!CXJV0kLCAA+ zG|`J;f12_;msSOc?;X;LFjEGjnt^C+yI76T>V@Sk0?JdVG|fPk;b6raiK0<8FAP%V zaN}PxjorrZFirWDBGIuCz2b1)tSU+*5$%KEqY+6j5z=ME0y%{BdmO78%NL~1)mRS< zH1@21n1rKc&t`pJ z#qvBJM6Wp9GOLOb$xX%) z2tFB++~X3`Ys3P159>1=tIvLXLF(LRKMxF^{XWzWlaS8*Fcl&Xb|qLRmb#Ge+3#ED ziJtwQxZI;>ziwbQtja~YOs$GExmrzWN6Uj9tp+W^W*~jAPAt;&gp8Y`iCGL6(v;u1 zv?@S+?~nn6nKBsF4CL9bELJ15nzy{=!H%a=X_|o?z`>C@5=EnGKL1xJsAUfOY^u_a z;ZBM>Im(3{vJWS>+~?AYYG|;oXw=SBG!~!`pX8^W~s+EK(}F zJp0`ZeZWWZtbOoMg?$LRLE8BB1q>S?}l2rI%-8HQ8X@VRJ=woY_Xs+ zqiW139#t8^o%}VZZ3F*&=oPp&7j@4&Bz94n(v!4eB&wf|+!z83T zKTL(lgWXeDCziU9@Y(NM=ZT*E+Fb6@vtJ)D+g9ZwU8Yt=np~}>w4>$0j#k4KVKa~c zSSJ?Q7lh21qlpC!m(!HrxwI-keD9Dl!b};AY6kM`Hzrmiv|6&f<-v}pQfZoj9K*qh zITA&qYWDnVrm-9j*i>Z@!*^-QuM~;;3?k2dguF0_Jfacu%pheBlT~gK3G(%b8Qv{< ze{~2~FuZ+dG+z$t#3H4#%d_9zK!)IG7{{Auzh%5y`)tev@I#vN%0Qw^OX?Me`({;9BDo}=gP`54wVKk7md7AkO<07@K+3RAEV3^MnKwrh%NVYvDZg`RRe<>3A!7(LWiYB4 z$dl5vSdGwX#qyTNAf8I4X$Eo%2j}KU6pgC+;+1JEhh>|p3}bkhru<5gXuu%yq(sO| zgUAC7AzcP3bC|4hlSq)SN6heU$@{BAxPsx$E~EK!P&XDSm0g~c?glarM-w>SJSnZ> z)#hijzAt0jVyI#s7}ZRQBYUn{$E)4XX1(9rZEG?Mo|Ncs4j!tjy^R-#wUgfKt(FWp zY@S8XF5wtGDK&!$ZZkd2Hx6M%*fYVC(i)1!WsRN}8o{u|g36HQ-XY9|T@ybkZ6R}_ zqRbn?u*-wYNptUzJ>>Kb#~_xk2H|e+_`$B?93I=$`nRg_3B z$sbXbPP39bLPCb~Ay;5|0!Z~qi7!Z<`=sQ7!IM%Oh{+W^DG@S|AErX&G3Yt06H8r4 z_@wl$^F&WdT`u?NNvRCXfmOLkm#I~eCReK|?Pz%nqSdTL*bHP0)`>;-1tCl3Xkrz^ zjWp$VF0Bd>-#cU)VWtd5H3NB4niH!LTCH2&@)*QZsWi<%F5uv!ITA&qYQFr@G?v5C z5T_=eV%U|Y{7R9i$B15W_{pX!N+c0=0$nyM=_Nvz^C4Y0)r(_QWBG#Axf<(%fyVZO zm|TIz5;B(`rb0wOhhUvp>Ow+|{nmLRjU9HmM;f~b%%xSiNSCQqktSEGDeY(xP+DzR zgv~(S!aA|Yz93}R98DZxc$}vE&ZSiW;(LdzABfm8Ka; z2PCo6q)`-&syT0vGKW3CGL3zK;c%MrD@CGlBYMSQw^>z`NFpkOV9|)Amk8O*hYaJ? z1ddgW`u2lizdxsn%+?2tnW*{2- zUaUrF^~p*h0?JdVG|fO>qOfHvuqYZ;bITxQ4#$6O8aspGa+>lQOQIDcdd1sV!~)ra^#P7mjpYkc=W4761{!-@KTJZN zer@FGq5l_Jqc^Yx0ucV<;lB8lh>1Z`#|y+p{%e8>e@E^(}C zEMJg1S7SXe(AW}ulPkE7C8Re$OofPmw!=EH)P;l^`>pdt8r$J=k2JO)m|d%KkuFoK zB2BJVQ`*rYptKsd2%CWn!aA|Yz93}I98D}?xRR#)&ZSiW;(Lb-Bg~Y+sAeDaW z^r{=fUYnX6#IT&Ed}9oObKJPgO+b2JJ!~w)B%DrD8uYOD^|gtd|AOvwtomzGbr3FL z8IbQwf3Z#e_M;&X>-t?uf7(%N|Jub<@{sRJeG<>2nZW z;Mh`{ege)`wC-jM-D$)&Qr`eEsWfR9)aLFR^hwS;4eO;>p5Ta zW7vJL0Dj_-RNt4DI)$q``BlgmMoZ}@pHMcH7s8iWU0-j!v*;Sc>d{-HRsULceo23) zwAA){ZIU9UeNFGyI_n(uT%D}vH+xL?ixND!`)I#it3FfA2^Ew-T&c3rzum=PghjXT zM<=)~rAcj0d87AhS}`NG+4rU8wqJasRVV$%qXjSNk@R(r-CXWp;Mh`SWVxGAtJi8(*VlE(-YiOk-o`D)M!bEyR?Em|)AEv4UUiVD zJRTFQ@(yT@@;$wCkjRtA1fCZE)J^AZ;TX|Gm}NBEDvm|$GWXsrh-e9stmBw%$_}|x z`<6j0Wp<-VU)y6#n) z(OJ~L-mbYAi+Wo`CH7NACa_5uY)}!kdQGdEcLIDxyw!D#G^4YqBHk_w$eR_2v8cBb zRHD<~DwuwPige=Mxz zW=EpC$nI0>X5WM?03lJ4&R|YVB(40jPXx$ZOWw}^KO$KcU? z%|W74?*en2PqXhJ5zQrfneUE7pCdJbxw35{pJ6hhu!}^rz!&&w*GmW@{&xV zZXCjW0|HH)V2jR^$x@RG{rbmS*A27`Pl0N)^z|8T)%tk&7zOJE@5|t zWA;fBhoq{0!sWTDlfDf1LdGz%$b1mN$6gHK%dD<D$Ts%|0{ncEQJ9565cQ)M7%F=nq$_Z1g{DOZb@A^`?C|Tkdha z9@p#tZjYZNqBPMr6?brMqr$JF+823W+ILUoN8i-SzFC{BsAz{WR zuqRJZkpBGHLtx4_UXNe0Q&)iu)8#QwuvT2N?@ND4o2MaAhpoPJDtT%k{F3%9{jFAS z^0G+8ZFt zswh!KiDadgkT1gygpZI@TLWo{mHI4%9MoqaBrM@3>>CBC!afA1NMW~J1tNt#2IkzV zExH&$w1o;-iOMMP8zs)QN?Rkc(vB`d)PPlL@?7FuAZI9dN@7}l%kJSKC95Jk_Y-_| zn3jxoVc46dyvDZTRI(bORgYPTfbvu#ZU!<42QMb6eif=-+0?Jn1=VBWfVdLd79y0w7)*_?pJKmxdu25*TPKA=`ikkn#E~gsj$QAtcOr4)%?LRAV0k zQ>3x;t^$$9ZUDnI3-4kdJZRT?Np=r&tAPaD&?}HyiP8oTCC;@<^71CIQdKBI)PNP+ zA-Ml$UbjGYQ0`}@k<;p1t{_~2lzI^vJ%Xd zcLF{Z&DZD(hU;m{YwWC8jnHb%tVBS0DiJpW*@1&Y9I3H<&HQsUmIMTb0zuHml-;}9qKXn#lt?so5BW0eKw}AMv!JC*4(hWIas_DM$V0*sp1__wMM0{u z4}mGt*i%=5NMoO1tvYPYL@fh|wom~p(IO>&qr|yZX=_AQ+R;Ub8n8-Do=bcSq#fm6 zw6agDZ`nOuq?CG*o!bK+gXU{=48!R(b|%K)M+RKQBKNQvJlajsR`8j+QDbP=Kk ztWuNb65j$jL%9cSe^0A#**#pOlzNe!`w6}}%-3iahP`RZYiuh{C94ry^_Z0iC{HEg zW*{%&U>rwkEMGJKT#Y3GfuTSU)c(damfAXd6Cb&-iy@; ztv(r%2q;e_;$|Qn2&?rcs$Ydq@4N_SUyLegA6jFlT+ZFFM@AGHU{XXyW`8XE5r=mm^C8{Wq-0y!tz6?9K&=4|UK}(lh)n_53 zyFLpcVF{nYzEO}~iyi_~bS-Lg6^O1yeZUM_wMAnCh_+AxD-k&*ext;>R%vTQR@%`; zh#Ig;O`c193*;rry=!HkR^PIFxJW7WB0F~iJ{HZ_=n97GY07KttXPfEYR#-fKzS+= zHv`#$gF_stv3$+^b2XL(1cm}Z(8kYvs(4LpolP3siuY3ZI2LHE5>=F_qC}#xd&rkz z2O3LAn*}Xha!{XzkSjm~M;;QE@C5ecDGE}JeF#jE#-6$gL>l`9Yt>%2SEB8OQ=0tl~(GkD&CHm_Qd{Se#y)|@a(M!c zRicU#Rg_3Hb_w}1>_GYmIkh#AE?KG1LdZdV7DB=jZoXr6$iMz6ElIau3@6o>t$od$>p`^&&g> z6MS`;uhA|Hd()KH*jAiMRwK0PF)I;Jo=U{cKwiSZIF8gv#@Uzq#FAW zm?Djxa}|g*b{&`1*D7s|&`P#O5hC3OxmKykn}KYj+#R;R zr`5OY9xhT!y~xfzgs*d3;?YYCOXglb8x*S%T75Di5m25=#LYn35mq;j)L6b|{<#`U z0s=#UAn3`zX&OsyT}T>xh2f_(L%s|<&{#s|Y~`d&y6UqKGFG33 zkg$X=VBaW6HTEGeMH<`hDiCSxG%yQRZBferqAgUwO0-Cc-zageRoWVnm3DLyq6Vx| zljjoO0+~m-&#mm!>RWaX7b&G)WaqBJ$By|L-N*1KO?lzi5UUYd9h#L0C{HEgW*}#9 zaD^i^mamzAuEvspz)&CvI!+o(ZCy-)`Vqs+H04XBL=`2fD3NIF1@dLsfyNTjZ$V3! zT-IkHq^mv)Az=wyVc#f7HTEGeMH>6mRUp#XUSM8YwM8uhh_+AxE72k)ext;>R%vTQ zR@%`;h#Ig;O`c193uFN0-m$Vzt8dvoT%?qGk)1mZ9}DJd^eu*KY03-7j987(YSpYn zKzS+=Hv`#*g999?v3$+^b2XL(1cm}Z(EOjZ`&er0QWDe)3_qkPUn(W4C{aa;L}Pc6 zFT)NrmXN0wv~&N-PTOhGJt3c z6|fR5QsOsCoNJY~Mr5TOU4*CstJLJV#J51&Q0|n(wEC9a!$nF~MRsmCe7&?K9v#MT zB29VW=o70ET8*2P2q;e_;$|QVa4<7V^{Y_zmQCs^pD^T`EW!7PmFTq+y;dUWW)f{6 zvQSJ2S_O!g2EL|o?xkS~h6D!EN60Cl0c52<3n2&fSqKR;-h_RlAl2B1z!Yihma9Od zvB$u0&BE^yKX}l&^^)u!=2im1gs1^4wnOmkU*>fS zx2A-*N@v3Z&GF$ml2d>M&oUT^RPJDZhTLIF+nMXw_p@a(UpXMBEJIB^-?7 zNGaxP=ASFYBp@)9KZ5%HEncTy^ZNAGu2Zl14hY|B05Vpeg^-o{EQEw5oP~X(AiaV-1g7W;GUqA~T|w4?*|BPi#s&~=p#oMSa!UM0 ziF2(|M@LrL(M5{XMO|MPs>0DfJ>d_Yl6$ZHY%OF)W#T{X|c! zMrifPh(thnDiJpWX-8PyI8tNzn)&ByEC~n<1%jX_|F&r?wRI(FEZ+g)8&!eEDp5s= zDoP|8`waOq>_9*XnX{FXF6pYzLdaNs7DB=jzJPtBAl2B1z!Yh0zpFr`vD3gTShYnh z1BkXz0V~lWC4QsCxmIawL{{3-MTi=(N==?id<$eA zYjhvOqcr93V>iTVgjR=UB?8J*iMSca85~^UNR8!d=AWyvBp@&p2!f82#!_2Xlg6H7 zc#)=jsg$UqL=`0xjlDp=3_H+RLi#Oe>5|L(EQEB`XCWjkVJqw#1*yh91g1!1pSlV} z8ruuZORKi1WdP9@DqtmAq{MHOIM*s|jmSznx(HDNR;kHziEn`npxirF_G$GkyN8RE zQZKS|$Khkae2u=va4k)F;g}Jt5n8R9l?W(LCE{iv+i-AzBQ=(4aswk0Y>@Mj$tUxpn>A0a2U2GS*O z>$4EDU!R4Lu!I}1Zxo~&`w*BSjoow=h&1*Hm@})ksAT}r7AjyRTBO8plsMNaZH>rE zJGux_16HZYbBS+(oTA(*iD~sMyN8REtcvX1EBIER-c8CmHI4%gc;AmzEO~B>_cFRG3K#}0|_>d*A2B2eGDKlVm1%H3hgHm$xz z_qhTo^&;YT2w&&6#G{uOmdw3=4kuP4wEAR3BI-Pqh?{}5Bdl&5DWH7K{Bs4A1O$en zMbMLfk5`x18@Re`rWC*j266@m zS2$8*`I`CXYAgu|3>h}8(KR?SKT zl&2DLGmvdKIKYt_%h$|5S7S*)U?>m-&Hp*OkEOP5CqaFO;eML(rBb4b5>=E)GSHEn%(NZOue21BkXz z0V~lWC4QsCxmIawL{{3-MTi=(N==?id<&!v^Pw3n5{~o3L*br0V$)m?HJuautZw^B5SeS@`a6 zL!fh8H|bRJ)IbXKw_1s;1P~?8wMv_Gx;ZPq5f~1O8r%RBfSjR_gQg*}<5XrC!V>z6G+4s-z^Q)VDM_YniNy zY_LQ4I=7V=y~MC&TV6kM5~~qfeKI1^Ii5Ny$u7=4sOaU`sMw8~?L|dJ<+P}%JTQhl@W4X?S$k*g!*SFYBy4u=9Aopq z1CFNqqKA8%?n`^ni%KgBcB7)AqN1XrG87dR6%`c~6%`c~6%`c~z0S=1zKE1ep#_%e(^=jm@$9WTDhrA63sJ#j76CVJt{!8l-$Y3SuH+H{0oD8k?J)S5eMU8 zn4~pHmf4TC&~$+77b&}NH~rr7^GzSFVHhY*&B>$BEW}M!?LwUXeS(TBlH4=GJxp<0 zh^ENBttxUKtBT^OsD>$CiE64D!DJ;Ub7o{v(-PDO#ext`FsLn6*`OwDP$M>|2^*AI zXBkvMf*Pf$K~37ACT&oYHmFesbtb);WKb=VsmWf5eX5E_bOG@#OPppIssWON^`fxk zNVuvh+mBov&L<{%ockoJDeYg zEVo&SEVnE>%Iz&Xtub7~EcGdR$yGrf!2Ft zPgRDl6A-TR-Xl;wm@cUjbM_$3Gl6tRnF(j_eyH>SYdZNjt3g9-CPEF6X|OEd8X~5c z`u%(km~4dDuBv#|BGIxC4O6@q)wm@xdm)LI#A<}166HzMBoXD~h}J-`BSdBqBIHmZ zrw}hx^#Q~+`2H}+7Q)mXd~JJRw%c7}^@djG(r>dO9-)cQhE$$ex)Lih3?wA9A!Ueb zfZV{reX^rwltQbNgsCmoZl;0{@i{3_XJ+czg2# z+E#IGO#N)*3-g#$A8M&8*K*|1+luPJtbi{pgYm2<%`<^;40g0fyAbzO6?gJ+RvREx zUpec`>`srf+BUw-NPTh$JL{dN7)&(`2c*gxbcAl7>DW=c5|vrGuF=%=tK7;>vIuDt z$Z%W~gw(*&{4h%+Ag@x>b}8yY{(QRVL;rv3&dEYk$B zSycHJh;6FsgxIC3IIWCeRoo3zycN|1BcR)c)G$SjV1g0!i92)t-3RBfaDN|1M95(> zgiTdgjv_~1`922Y?9(yLXAWU~w96=&As~eH(~vR{T33Oj;eZft2&}~?Vl88>kYJ_61xSzB{BjnVsOtLErYMA8i zSlo?LRCg2B-KcdpVcnSpG=)f7BqB343291(u&D}5bL7aIy^p~-t7A;_nL}9D`Q-c( zGMx;ebrr}ItO@akpdL&?qA?37X`Ts$^Kn&sMDava<7W`hRTa-(5^V`&nBuOe%wdmK zn*tf3xF@PfiU*<^Npim-kWq^JqMD$nM58g$HPERAF4h@}y`mcLhd7|BB%&693{&hA z)g+0ss!Aei7RU(2w5UvG*^efHj8g0n)da;(QJI7=vN3^}n$MvrFA(#dkWF&}$xz%E z)%YRABUQ!OAknNqhAFO!D!&DBTUAL!O9C08NbB&ClA;ogFvv48G(XK|kc$EtrAWet z)C5K49<|(N-=f>puW5loToBd7GQ?F?b^m(Vpa<6wL7bCDpc?`CBK7O37RZAYy4bD- zcKzbbq{Ko@$r7?BEO{GqqLupoNRW2ZNt3@`12M187$yfOJQ3JVnv=-WSQWRu*qOH# z(%YB}L}EZyAd9fB=qamlGnu%G)mpL@o2n3Rz?u-RJVmfZyQNk$6cxq@unUuflJl zzIzqkg6wulmd(=YKv>R0$yTiNWr1WU9*Qde_79e)NFG<`>o$p&#A=wL5{+9TQwjwT zY~xxyF~(-zDRL#Ub57u&48k7YAg0FDU+4T7>nTyE@YEtBG(xdQRJlHg1EMnTVM)}i zkQ%JmQS~)ut;XWDlve8N7Y9k9zsy=FABx(kH?~t|ry-GcDpP}16Wpt>VQXbR@X<jQBSpvZ;dHKKl?<5FS$xZ_zY`tM_YHVrrnN0^z{T!;^ayAc$#lL1d^3 zT7VmZyj`pw%p&-losKlm1i~96$D~d=o%my!(u*$eKH7BbSOPCk9LGGh0gO9t*bze;D8Ws zmeqqfmVnLXLYij+xk69wwMP`&m*hl~hS;O3xPV*GRAKc92ptTHqYTAqQH{?)TvS!; z>&b}5;G@EQ?5hR{BfXZ0GmU?^oZc2(!?LvVHqz6nn(oxOJDc?#AivSPkQ3?!e8gr0HABZT?&+tqvu~r+~al{XzR!v9-^ zhGceS646^AN`s(FiQmbUvm>#`dt*GJE)R>PV(!Gl&c(PO>-M*HbvG+6t(IhLo&w@7%JXnRSD~Z! z@v|;a#olJSY92F4U9kaME3>uIifJuH9oxBGS%~`UeAKcK7Q9CNyLzX z)fosbl_;LEwOQHp8uy3r!Qj1x+G6ZN9b=pW#M4495%{arui1qcg`~O%pko;;EYU2bBKLr5H2koBe%4k z9<+@FhR2Ym1IT>*E9&CPWdviAc(WAc(4-LaW|K|R$t>KWIl^u}m@I<4Rj(Ed?UxZx zaF$+=(@|2!`Iv>pJg!~@wP226e^MDi?2Mp`Y9KP4RRf)(ksvSZ$6%Z_Gp6~>AJ+PCiY;O_(GIakRpdSp)iA{) zQB52}yi!$MmyDo8A{e2V605v*H)7qHV{0=w&xCu*5}CigORKb6#X&y;68=7_ebLkk z7wXD<3#bEfF9CmVyO~J5i!6r~J4G{&S5X)L*9I^3dE=O>l^HEUx}_T*0;%GN6}~5q zCMfQU>dhgx0=4uHKNwcHxaj58xWJ@zwzdGv+P1 z7Gsy(7~`y8PYYp6+|@L8RTV@gCuAm2A?78kg_s=oBF9x&*u(*TmFl+dek|xmDf1b_ zf*hudDGbxEPX>8wVli9ECxc8OmU&#AKN2)+AZCl5GZ6EfM+Z7HO{WRjkXXJyf_SW| zcyS})ax!EIO@w$;{xKNmDKw_}%ps@9%vo~s2)Rmz(E1`7a*ifKydiiD#>sC?^O-}K z*K0|hnO+uRj&c@aW}t+HsQe+s zBUPP4yi`?^yKaG)-gls>M<8Ycr~y)d^#-n`*RgTT?mOBUSj>xm6C#@`$nBO$(3xDz4tyiI^H_sz5k!JMiSb8zzWpazSLM3fhGmg1kkf9?Ty2oE3sJ&ji9SnVC`v zat?63^Rq0Q`K#(_N^wExYr)>15pYJ3*rk*eaw zk3?+(8K$U2c@k|1D!&79PgP0Wg90(DRvJx10x=6~4UlfbV&0g3G6++&DLpbrRYI6T z=V$G-t^(PD146vXQ4eNY0ycXBX`Tt>2t7I19#Om()p+VR%TuQnSLgM^4bYWVQIXdG zp@U9wl%bdr)p!=-l&T_EsV5`qgO3XLv9B5+jPzV0&RjvfSJlPeQcm+Fu3@{pg?Oi` z*gd%qg=m=K!U~tXNpfEa(J;AFf2*L9xDSMTgyOt#Pgw2|%Wd9WFz$Wf9;J9BLFO&@ zD7(-pahoNK+H@~R88itLt{;y6o6hQ-mV z>hm1k2_NUuWMle@x_I0-&=H2wkot~h%urCpAp}(t5i|2NkXNbSupdUZqnJN1bxxhz z{+gnu)iHu`ejHW@q+*WM;G46)ATx84;Q0Wx35y)yb{>`VdIPx>SR2`s9k~ zR{ALtUKMm6fr`%~NW*}nBg3R=@ta-VA!-Ies}jYNp*AZ!K*s$w`axgC2hTW>-oxk} z>>4FT^Gk+DK*G-y?5D|?rzTKC%EWVTy4qu2OcTSgbRIL=#EiK$6oVX|c$8fp7Er~k zi%WqsU`6(sNiM9q^-OYYZ=LSmu0r4K!)jfiioMwOe%$un zY`pZQY0O)qyd^RRhM1_-x0tHjVT=XG#LdETlq%=IY#}Bn3o!|>kVKXbPBwk@OU>pf z4v6Z_5X6kC;yf0=fks($K8w;F$MyqniOI_^eh0fn#{r#wQ4>HS_6+e)?}y(Vk884Mf@0y zQ|K|xM}x30`Wwxwoxmjr$PY^b4R|9RKksvRxkHI)ei)lU@gfA=Fu%5dq zB#3VUTo4)3)tK7RNRXGp$6%cN#55lb!mM2tWu&RzWA?~TFceVVM zt`FA`&Je_ms^SSi?s*{^ra1q%@wMN?62xs)(OtiA4^tcz)dVBRt7;YErmB*HnvZwhrl#w48YZ8+cCa1wp>AmZY$0B0gkz2kz?{TLr1^LXi2HwAPn(z@nKTxIc0O-=YDS(`i!$;b0;$h8=TxWE%LK(P zQN8Jb*sChrFY`)~+}f`XfoQ*E^6G3d#PrGa$oc%XjC5ClaA8wOW*=55NkxVU%c?4# z6%Nr6h)!hG&5^t|D?2!bXe;tnd^m~+(0gFojqDmy@8X_40`e;LhwKAW%u^G{iDxeg z+1t>G;aEBwB%5?}%nE5CChvBP4GW8>Vz$L8?n7Pa3@|KD1Ia{=ypnhf#`(!8x66B( zGvnMIbeA6I1fP;^)4WHDiHb4DOhsKx<@JqR(;8Gf7BxT$ux8gjB%+urylsj*7gTZI zoOe=|=#lwmZrHop+|ME>OUaqF5VH#|7#6ec$B<(3cVTvjYf;B@A1li%hnOpLHKq!x zn8``LC7ReqESkm%OJsV-^lif0@kPigAnyO}v5ZFY6noDiVi;aV)*?ISPyN&ZVKUvn zDirfn1(C^#XCn&P+Ye%lvmbE0)RP$;3o(n;4uVk@133aj3*#3DIXAJGjpu0~7Y{qS zG!XN|dSf6abrxdw>^s9^o_jeq?XoR>&rOS`D(AdOt46hocNaD_CqtUhM2J_lR|VPU~r58K$@`s_`9&H>!#wUPRMIGNf^>oXaL$ zodwWBOvJQK3(GLYJyDGxLOfDc95IP{1TsQ#TU2=xovSJ)nnlyRK+IrWqUlN?!xV2t zmAQx5^mnr8%#gOCsZAim6sJU$Ifi(mstbshs=9)Bt*W?d*4=2ku`;VDt@1*gWkl*e z8~eHgy5;X;?+vkqm;@2hCM@P3&h0=`uRt;s^P)0~d=5=jAX9+M2}_3Jj;IXrWtd{~hWKiO*siMB7l{^xXoO-) ztnwu4R#i;24T2pZGC|Y2Us#4I&WUP#9^!$jVqarudMgm)>l97b0vV>b_;*W!Rv@mb zD)vR9lt4x(&WS2dqHR^hM4f2r5{L z$Ev!3c%`a%Z0W8?Am&t`MpLgqOwcjJdzJPWjPqm6X+*J!Yw1Tiaoc z;-;v^cOZ8BJ&9{JiN?fgn4%KpNpvQt{1wC-RmH0ox#tC9R;@uaF?eUyBxC_lZ$YXD zQ^i#tF6henWb?@&O!c`W&%B=`ghS!H3#D}x$ORk_;!U!8Fqaar*;`2SOdy;#y)u0= z6c1TswVPE_XTN2^nTj8ME5mHDvEFwO;HI(3hxroWf#ZX%>vAg156R)}F~g>{>- z)BrJ#Xx*F4LP)1ThAHMmWfDxQ9)XNd91@jDFvI8*i0RZAnids8@laIbClK?0ABVw2 zNTLO?8m6d3c@nh?QN9Oaud0S1W>pnWPP*F=cVh`n2hYb}Wu#cG(M66HzMB1HK##7d< zYapO?L+X)4?8i0;i>HoV$cGiWxF^IM0pq-?VAFXrq4jMti-i~#T6g^eT(C0z5HqTZXCJMa1u{%A z^AD29tWLCQ7poD917c-P3baa#)hI=^GQV9O0J>j@%^zbSWK4(?Aww^a_ey}NtCE*7 zBz{Q-AhQi|S5@z^h8tSV3uKt$z%~oZ3^uK%#cG6NMyyOZ(rQkuMk%TdVZOd7ziYYH|Z&ulO?6Tg8f5ab^mwG>78r#j05I z%>1*?Mh0b*mGUu1WD6N4I``C8Bpgd7wh(gyqxD=e3n2x83{zYam6^4)nia?h#br^M zS<5iy1!8i%fu_xRAj3p&J+&1Hx08u2#0&$ikCRyl*%!z##cNTSVW8EKKt?EDh{_BD z!#EL$8HO7)rT$?q_lb}uftY^NS|Ns|5!P+OlJAAsr>b~^%A#prAQ_5>qMAI1c(1A? zqJlt%DV~UGoJ5zZN+OyQ$OuJ^C{Ln$L7Bl}*JcGWN^x0K6Dtr8RAsr%S#}lZ4Y4xg zv4*A{flOUM)S&I3?*ydfACYoth1jmDIAd4pB`|>=cy=nnd&&UQJOP6sz$J z#GI<)h!}sBpr>KIDJ&U^H=_Ecd8eF+E?k}e*Oo*}Vl_(sEdlH?C)iAB@RTY;xt>`m+ z)}*LJwfKsO8R?8foT0cQs_}h@nSU&?UnH6qt6_>tlqXS>5arVlJ5<#Rv0qh5aW9EG z^Yv;TP0Io?2|7a4J+7tCsBu818Iub~RV#_}+Yi%dQf~ppG z%dN|}I=^!v_o{FYQ#^uI_^Wr_$B_5_i85nR7q7OYx)Q1phS!Fef>|5oZi#b*;+%SH zqpY!yFo^pK809ep7XAqRTZnV2qPVT$x9vi%=u%r!mv*H~qZHY-a0F!LyQD|o*vy;% zJ(cO&5$-HS9l{BU+rm9gQ8P1fii}*~8or@Yyb{#}Ma|VXb2TNo8fUInMKwWjLsW@1 zx-GqVO;I!Tj$^+ny?JNH`5oiz7kBR%CxZ)r^o&7qOoJ*OQs+;jG3$pC=a&>U&hI#) zS&8#IJEC7ERm+xee?@UuMj_8CX5BeIhTjLlu@H?=)F3A*wn~sWip+C(i^s0?O9Ybx z5VN8hp*St797PUL;IcW8ImrqPC{|vx4BsS&O~-1|j+J@dVCW0d!AA~yF9?+ATU$Nf z+K9}<#6Uz;Tn1yNqAsTLmP>MRhKGM_hN8wfPWCEOk3<3apbZsgnYyIeYCyun*6dxE52(@}ilSZfn=Q zZtd(pU>@5wrha~yGL~g+oGscONVd$#+@pypD--dq4GH|EqSIe#Sm%8^^uAl}iJDk% z{fvW6VHju?PL93n91v!zq)f8RfFY#6H#RKllI)tK08DxsqoBehiJ6^$q-hUU&Hp4% zM;VICqMDldr^>B!xH_jJ65UIL!xVR66*`vQgM7Uwr=xV-SxYrSs$PkyFa$BDDvCLE z*g{!DFEEDl3fMK|G~x7~-j_lHA>jyDUW=`$>u?lIJOkn$t-J#hix2Wg|RyO9WHQUtU!d zXGAqgk(mu#t7v6MgNh=gQ4x)s#q{}|?ch7xLGw3vIiJp@gI`jtn3|o8{ThD5bnQ&a z)wNK4MUnHd_~*KjHZB{1sg1HG>svZxpNlYdx*`bksL=@e78#ua#gydzn+}LQqAE}v z64f^x)~u>*q_SeLe#4Ut$B@AX6=P>*2GuTd$?gPIoKhxhQ+o5rVIBj)st^@U;9e(0 z!Pbj8xlDn85f#_%xblj+n5w9Ydq=Ki2}%|e(uXM-v)49p$vq?7W>cJwx)O@h`uaBR zi1QEYG^0Mcv`)CxU5IL`5Bb(Qnc}oBpea;Q^!9oXVjR5kT!t~Q|uMh1jRm4nU4%4 z>Uh1kp) zt1F;8|5+AzhT@v2ruHG8t18YUi8=%_Oi_uxu|(!1MWVD2jZjpgNlRo_a1yl((I`bF zny^IX_XH$r6{0LfCCXbOvs5&Kpc_|jHpiG(sUM}*X|N>`jMLqrs^TG`RbC*Ivk>Q1 zMWS<6#Y8=5Qlf7xQ7vOjqCW9u3bGeXS%G|e08t|}?9%6aRD)9PofpEdQDN?zlq0-R?A}bCB*|#wITI&4C#mUl(39YTojdwkXCttj8ar9Gd8q(D^^*G z8=^AvfL1wyyr!tWOqywx6{{~P&WkEXQHjhvAkmmueMNCYRHo>s&{PmehTj1Fw?2CAkDyfL0B>rS43sz+vBWOLAWc#Bl{4S z{$*xpWDVk`s^V0WXh(=%ljufOw}$(*<$j&S{bWHdOFu@fd-Hd0KSkFxqAzVk=Jykf zh*m#Hwfxp^{Wa^cCDcjjq;;`!V^i-5gI=F(7(Pa=9H7ElWr*K&LL5-l7{obM#TjTw znYqh^5$c@jIYah^ICBWG`Cs9DG7I1!nzjV;W*_2(s%{~s|5Xy12z$^pCXf+|bD}ct zX_XVmC`Gk0I|Qw=VwI)1A}Vv1q1BK;UQ<+GiTxTBt1l_eh$=@>iOgAs?lWTb6~z@% znYDEcO>YH~p|}c_cb1`<#$%FbA!c+OPw|XS5u={Weq|vh%d}q8ZpNP2bgz)kqjEV8 z;2LJdAjCygEkn%xYb@T(7{onQ9YQ=(RUAPVh^B;ljNEIgI)-?ys+cGX9}J@*^^+K~ z3&_5NV<0zZx);a@#ioBQ<~qDXNtz7Fwl*I7?Bj%$bZ<3@e<;D5{mII$ANT z@OSGes+Eb5P3hyrt`m}xPGl%{h?S{cLf*p4+n@4iyA|f2w*DLCIJ$6cNc}V(iY_>v z6XzxugiHx!gyN#8%xt37v_M8Fs+GwgtqNk5rMM%i{6543RVDQ+E0EU|)xF6x-Dkw= zONtAk`kJB=nT3`_Lt^z6MeWD9?T1-=b0EkI(Hn|;P!-qSn8{m@Nj0TZan{C+x18gx z#qrjXM5ReGuO8@4A!a}}5s;3wDNi<~{>{WmN65AGe1u}NSeXi@)vZ{KQdBEb!L+&& zt1QJ1@ny~hw7L?j*A&&4$quc~#p+9nP2%foib`b4l|*Mk^c6)7+SKML(3fJBqu2@e zp$_B1NYRX;I?sTFFbCngSWH7t9LQqDQ`VlEL9GEo>n=&5skuQkjnxAgAv*uCRYoAA z6xGVq9K#tBt1QL0qRLTJBC}bNh>?cPlA>BAW`mK2&61*8nV{J;D-jyvIW+A(3^^3Y z$T7sX{}va7ktv7;RmJs0U)w@t9>fWGGG9+dR721U$^Bwe6&6A?fp$W|L0WSBrUzn1 zRdL!$I4clS1#CL}w>h4fBZ$YUI)Qkqs@NBa_QaQ&00I$~*Yu^trZB{+2I3kZkMcb) z#3np8X%Ecc9mD!USiZi5c(1B%MAjz}nmwI9E(Bu6^Bzsp|Bj4jJW@j^<)(r_OvH@_ zV%B=Hi~;JMn%|=B2G@qvUmFKAgCG_q7}KRCG@U;TITFYS#Vb*nE|B;{Afpu3$}Fw4 zIu@%e#g>1UNzb=KOsgvHI*E3L=ru)kZ-$0eJ7V=E#Y<6rO;L%=v4lk1V)Ye8?Z>$7 zhdHV2f#6Vx-cW2q?~CV$n8`aulj=yR;;ii(Z#lf@zfzt1QI@QJGUTtp)}1nxgtL*`ZaRSba%x zN>pD{R3cNZB#YL#RQ#8#Os&k4aggJ0d(eyN=o|-6YPtBm# z0HO7gbjuXf7Mk|!fs7D+_^{QEKt?I5m8m&~vn^IxiU*>~QB)#xh#(Oo4X0>|YL%D` zMjB4h6xGTE&89Pn&=8-aspa3}(w_)v6Uay>#7$LgL)=kSyk61Qy@X>@Jqk5WqwaV@nAB{eXu$oeAv`-Dz()KF{`REh?}a~g}A4xeTWCDiX)=C8;QtF zK0?}rGQ zm?39V`ahH*?}eCGRRQ9zstzF@sp=TwiK^mJr@NFu%<@J^r$AmaqCHj7z4|icL!ugd z)c|?2a86|~OvG%`PMJ~PK?*b#W_hFanPkh1`W>2X&Scc%k?KX$tw2mHDFZRf8(Fe| zddph@ZF}O$EN{nXI!%T!&Zhq;u}jTp>U|iJ7s$vg#5q;Pxgv3wK+Mn*@;KthS=A6u zYjVVFs=`8urpDCB7#zG6N2W$-y(kbUz+0m<*Xg(}qBD+Ypab6&HPGl+A6 zm|k9>srf%)t`Z?V0vQ>EIHan$mn2RJ#MBHSk0XAZRSn@>Nw!SHY^uUSh^EFAUpG?H zFR3vFK3F>R#jZlJ!r}c7*Da3S@5e))bTqfv$ ztwI;~gkcxNyE!<}>!CnQ7LU+$|1hNSKjrE&(h6}|RjUx!R24@|UsvMGlqn%k=IhCb zY6$uyxnFFm!a|59(3DCFxn=sp%cC}^bR^7k&>SEOxSE$oY#>KXFOL}J7FeB^M{K%R zNb7%AuAzQhi@&CXxU8xTh?}a~g1D`!xV-4@T-=$3l8{DWdCiDcR7Lmd%hV}}YVcJ9 zk*=GF*`%E^<+X$qXe!Lp6|HwATV_Q$Mbq(r&gH^DTG4bO5EIKeSQKK`R#0)u`n*R$K@(zd@RplUVsA>n| zuB!GR?yD*ub-KHjh|KavNUN~CW<;B+qI>ma(oCWneANJXvTzQh>n370X{XGnuOS7R z3bVY?`cSfEM*R{^=l`XQdOT7cXu1%HiRBtB3NgzYS^B}^EpIurZHgzeyzQasAQ{3S zZUtg`eTSyO|0=Q9g!Bkxgkn}yrkAwp6UZnQEq~6xGVqH+>z5RhHtZsB#pQ$Q-dq#7M($e<-Sz z$vmwXY546AMYS?Pv*}tQG{iS(>i_R#NaMjGq)Q+p6o*7*Dvnk?0vV;KRwiOvb&FM& z;*6;B^AHzQl@xTFKweW+_hx0G`&O~~lH#DKzNV-|W@RB!i&%X{QTs7&`(YNFb`W$5 z(Hn|$P!*Sen919hN!6uPan{ntTh8&;;&^LGqS7RpEsWk2Vg_Ui0qIDa3TD%xbSn|E zBajh_C!#VHOyWI(j8ar9Q^B;_6{{@8D^Zz^kXG9Qc}-D$ne5PNL#)1}cr2=~DJqdE zR}!s>)mIcXXj7Z3KyQgvj^Z^`-bP3>hU#pDgfIurMo3RP>Zysc_S6h&4G>!2NViNu zHUIbJ)iRB%^X}3@Mu_fw*s4_^qZHN3)Es@ah*g$ihp2KCmB?&PBx0mtbE2qLiP>PJ zVRNFWRwigR^+|+=xF1c+4@2ezGD2}pRHh0@ydaQKifUydrq#SyWhowtDt`j;R8{fX zNTMl$yr!t`&1|PtUaY>PxGJizDJqef?Ie0DR$o!nevI3Gm<6B!f>|MYL-81@;zkrR zd7Bfd=9DVV+O+YObG)@U-dd8VG)ZQ2qBn(@0og-9I?|?s+0^$D zf@#$xkWq?iWh$6fjbfFh*efctInnA~#^yCe^<}a{s~fTUl485~`kJB=nQ|r3wGe$p zQG+(Mc?I;HSmh}8!M(RR(Tt%wn-d|-fwMW$Q%XHGQP!TCL9GEo>wZb0skt#UP1ge% zA$s;-u z4q-;Bj8z|!m%}ymh~m7c%m_cu>MaQKxVm*gP~n3?Q(z#IR~L`LID;P3eC7~lq{;{{ zAbE?pIz3uK({eIo1x>5TkTo=IBttgQw4DsuLDOC`m3ZdBXKXG{*?}C_B)hxs% zRmIQznBt76CP=ibsw5&t7Sc|!MXbzpqs4ub$|L$bm z|3^SxrGEWa?Xz0sswR*VPk+SY{kufOFu%@H%O>XA8F>paZxx23U>uemKu&NCu~57b z)%Y#M&i`4~&3GV4bR|~iJ&1*v*D{2h2#bWH#HPMzrI1fYe1=Hr+dboaWDtj^4Z~A= z476;i+cF;iMle(a>a#HSb)txrS zlbS$>V7L{gp9dzBx1fysAO2NI>(ilY^5~j8x`2%SBV7vPU;1zhxe3?efhvl(2#dq@ zzWI`#Q~{HAxY7<+I*K$!E+(@0FPTSS1y#&cL`DB~p7Jh}Bv&}KCd8LEO- zz(A09-meF<3O?sBPnu@}VVKNJsV-TM2by@hTvWB(sbs`R^HAjliCdN6y*Lq?is z0x94Cu!?IaLW=vM8b5$|tEza}AkmIM%*sZ{u0YJdT`EIW<$vRgkqpINQJIPLIIA`g zw&Utf34%I47?cJBnY=-N48|GJnC3HwFe6n)xDUyDi)-i+#d%SUFF@Q=RlNR_XjUL* z{kIUaOcOFDEE$SQY|4~Y3P~hp=PLTCR*xZ`MxmI6Pa3rS=$Txly-eJpL_5GL(Pl9!>_`oD9*&UZqbQPmQ}WmRoK+*8#t#1mCr zLcCE`D->g?r)}B7Hb7Qt!dpqC|0xwW6s_AZEsX za!9wv!kk`7zsGIAO~fR)7orI!j)YFOdVpTSHM|RJS>J)qH!H5f<}%Z^=kcs^VKRhb!%HrQ?Al7ZVxYf5lWm6*D<+$(GUA zD;bf6*7a=^DJesdwyv{`xssKXaa^Q323xJ zfJvHX0%4fUOc;o!b=KpSCf=?ERV`PmS+cPz{Tdhu@`kJ)%trE%k>;5|+Hq1JlM{P} z;bw6xGU{e`%$VPe(j}NXKw>ADo{ph{>-q zs-Fz9fDBhD!WBSParNf;V=&Ir9MgQ}5GL&qnF--iycU(2SdX(h2H^>=?vx=#RlTBO23u<`8D2$_U>ed9D8^-@RnoAhxS24Y5O2oe;ZJ6>kaTP9;O`;l5iS z<_{b!qG?qirc9R&#OytrfNTqkIk0XSh+)|S139612HUJfb=A@bQ_3a=?7#mnPtF03`-V}v1FEYBI};ff$xeK(>=vwhY9uZ2dpws@ucWnbSK4Vpt9VITjW(r;iN8u$%#M zk<4;#Aco}{klSRI8v`*csrzzXns9YyW21o>mR3O8lUdpf#ISS%(w)rGWgv#750HUm zmVN^vINLVGRv}o7?uq{wvt&k4aBhQ z0HrH0pu>3<<>w9OXL5Gy%ASuHZ~cEVQB*- zoy^j1Acmz2ke+0gZUZqa{eTQ6vkVxBVaWnAmduhf5W_MB$aFGG!9Wbl93TtHEb|6p zSjPUp@<_>A3Vpx^{SxIJDHW0(I0mxP|%cg-CmR&&hlUeo* z#IPIza+1t)Y#@f^9FWUomJ0(hEH{AMC9~Wbh+%2`EvyWNatp|PGRvKT7?!5g zFPB~?w&3c_#%2RCEbV}FB(tOq#ISS&(wofEV<3j5rJ>xTG_KBm)Mg-tr3;WAVKMtr zw}BXz<}b>zwBzc;(rO@vr4x{DVKK3E8Hiz-{$V+mWn9BZQ#=$^{siLNrZU?3Wg&^y z#A=wL5{;9nU5Lg9AP%Z3ewBR=&K5vQU$$e=B|tY4fcXr`rV1YW;|hYBB_5O46q=fF z^?qDIObs+uAk0%*du}6kLEW%mdflI8ke1+5VtcJ+(>h1ztp;L$M^HaqrWzfis@jE~ zC|d9PQ#}~=-dXZU^GqOFWG08J)1zkwVeu_!k0>6BDt`j8`HxFntVlF3R>KsPXq-fM zf->K}me91XkZXuHs*0DY&)DlD;-9#MnEqu^#bZgL86g^`crU8&(tmuJU<}uW)OY6)+y4Y| zf7cH&qpB1ugY0Ij6sg{B*JM-6c_Ru%2 z@(ioIPkNJKm0zkVPW&l|4#fRCM#N%hNWDw4QuhXOVIurCX8B~0+bEXeV%?6MbmQtR z;IUnJe2C4QCkktoqgAI2g!#b=Q`rQ_4^qF88vI@BW4PUUU%ia_+{E<@n zqMzjSM(aMZ3quo|Iip3ZW|{FhYh^~O6KM9gG4*RZKU~j3JB4dm8~2a4-S44jJNBM7 zwx!Mceq$6ls>iVpPe-^q|5OSghYC4D!JKJ{#qJ%e7;*r@6I@@VTKY{P#2{z%(ukrD z*J3@fw8tuRv475n?&My4PLQ6co27K+pe*3(<}kJlIgIU`v|6hit@6nkV<4*nF-MrE zfzUxGw$X4D=~(9m%B7{GjK@8;41JI7oOIA?M>74R#&zCsd;dY|M~y#jU+3+eVqZD2 z{pgh`cY4{D^qE6q4DpuFIIdTz*^G%Q`~|E=B#%if{!uI(0+>SQ@0D@-pG)_gi5r8Q zloE0#oi%GLA;-xOMsXvMT81;WDrPb6x|dm=-nQlRmfL}-2RhRYp854SWo88-E%JC^ zAZ%(&hP0xI5O0rs490ohjA=e|2vgr7$up0n7GhpGTZnm4YayfY3S=SX-&A9mgBmWy z!9ThDv`~Dm8iG7mp^Lp)s$qw!)1m52qMDJYMkvm=$aByV#Pp9ubp^2zafVfe{xYhf zm=o3b7({l^S&rDhX$fkSVyhBacfviTsH6@TggZ;IU#z|*w+3mRa~R~55WS|jBdQ6C zEy!RP;uJIRR{Yt&GY^J&VfvC{MX~h8VFvczxWlXrX3+V*QwM~_;fxwtszCDS&N8lH zH}6~L&6@NzLvgbb$D1~(%b!y0*6gM!@1sCVKA38bXGs}niqR4DMe6sM?c8F1Tm!~F z4w2_nI{n=(#FX^!J6kE{RTYT_q?o>ot0KG^i@UlBU%TSotetg04u$2X6j|>Lsh`ZC zKN(p(@)XxZ^@iexsPcA+`I=qR^~C%uqKuo76!(0}eUhXpGBL&Bf6$JL#QA@=WAZQ! z$gMp#ArW#SdHVVqq7HUFRxFj`Kb48>Hc8bymME%`DnUQaR~0Mft{0ssjv3{=bnG3) zU8#|8C~~%k*IFFLybQK^jYaN$<&Juv8bg!TVRXic}LGJw11eSw1qbiECP!%m(|Map&8rQIfcR=h{6~zIlik5?rhZL67$3yAk zFvVHv)*5Ovp9PGLAB zok%`sz+O_u{EgtP;9qPo$0CdR!~4HK5!E8G7E!#bi0#0O?H~>{o= z%Gflv3|Tu!8Pl>h$+i_SElbM3TZK3+p?$~D=CQ(r zv+)7Mc3D}zvulAlLDOAU+?lsKPXo!p0rMQzD)SWoDKWE%=K{+_*ebaMjmZ-9Z5|@m z4QE3o5j*BUHsEU)SMRJ8W1QELgzSLE`AbJ9>{S&{F~;#^A?9t;4Lu=$#SNATWZe~Y zEcFaB>220+t>vYKMv9An5)0ay1kObl`g!a__z zaCPF+6qY0|MSA}EE}i3S_1(2-nY5DH^jvl92rhM~9yExMwA0 z+_#c4?p;Y44`%Emj6m!msAB%0irJl^BlotHK=?kyn>{G;eTcV>NXM&G_!JaJ5|oYW zaV#Zd98F1?)K?u#^CgKP6XI6wGD6>y0XIA`#9MpfOq9Mz#d!#SYP1C@VHpHfoP(f> zGvNG<(qqJXfvelO803trg_zQ<0dk2b?vt|^L%b{&kR8saB8JQC5!yUEuFP}5IG_1H zCkVTz%Y~`A7~=K%1iih$)h&S-5*&P9=S}!j#a$MOyRgukh7e5GyKUQJUp&yEEHGT%O{_38tz_&d{m)}yJe|{9jZ=; z${e;ybtqAdP(1ma<*35@x^swy-zBOZ#FxP}py+Q+RTMWxHNFLr9rRuYBA5dSYLwzz zC9>{>dsk6Ox!V`+EX5_U`j*@pqdgCwyyZL0s%3ubaPiA#MSRBr%k);Y`7u~tQH5`Nb)_HR+ea%q3t;F$WO0xS? ziu0P?H035_x8#GV=6IHracM9*g1k>=7Gpn|S&aQ;Mofov=DPui8CBUzF}pj7mZg}! zi>typC*LBmjpEBJjCDX-h2^IdS?}SK*&$ljWbw#Tyb{$Lir1pb+a=~}c1_n4^MQzQ zGm_%gOLY{lsm5L zD()+Y>acp8uPRo|-6A?s95c$h(y@0GQ!cJBTTni^EM2+f~&O`FFn1 z@!W7F+~y12=LorZINWB*Lt>ArKx#{HT#_VY;+=Plc40Li?Y0s5p7h{DAO{b#oF_xZ zFhyr@EzWx$8M!cfk4|jkEGc4m<~yq3iZjTzds!MX6bFAdkGA7u5Z|gQiReyJvP)p$WM+swplP5JutsPvyv9>?&8>zCGf(~Mw)GI?y<0dn39 zb%2yb5{{~A^YzMt!iPYnjaPzlsN?W-kdAA+s3V@&E=16SYxv$b2XR4FhY*id)%<6c z^U;cHFw8<6Q`H*8O;ue&yjB&1;g!KuO^XFNY3W12EiwjX3C{vDrhQw3xT&g3h}Wv> zLI--ZBQp@^RJ9NBP*sfxhSlSIV`Y-{9)z$AX-YH^8tZ@tCKogIb(fkmKwKOee|Cn3q9p zNug)i1TIxy>=&S zU7$6|pQ(QG)Bu@&m?i%(giDY!Ss6>FE*7He^ZhBUI0JcQKdYpIO$^hUWm%+YOwwg0 zYYt7!jYl&D%rvgvWUU8NkZ{aoCCxK|Fig#iovfTUcj&b{Ssw**CP>Uv1#%>#V5U4- z_8*3D398~~t1cFz>+}67tvE?}WwxrMf=vw5n`PTb)2^h;Ox7JVF*hE~0We3ndXu#t z%%Oy1CM#*434~#4X6$6WMQ{7@99){L@q@5CgP+bae7BE1I-l}mfAv|V<$aZX^Mn+% zJ`CZKRwcYteJnuN>HAY!an|F?VW^S{HZc|6tZhUWnk8Lk@;61j^k~|E;qZEszaC7x zgkvT@X`Ts$VQOaV@a{m_M;a*!cHLc&>8GfRV~z9Ekb1NGE9DUHa1Ec%?;*Cx z2)!ADm>1PgD9(xM%|66aQT^oM2qstIPKhQ-bT35aWvT7T)QTaRvP4r4NAyh&C9{uf zcnNq9aYoYg&9+I?HyOmMaeu?1R~0%9xIpX>{NJUv*+s_)VexF2EjjgDUvzU7tbGaw3$JOcm#TNf}SYk}?k0 z`UrtoA3hA-$#(W|8Lz z@bSL%I)gWzc)ky>AiASR{h*q{Lk(B9pqhn>%bN4@mN(&=(wion{B8x?r%6M%NQN!*?bW0=5P%Y(%HsilzSrJOQ8i&m3Ht# zR4XMV<6*V9d%dL#JGi9_N=xVL^_DK|;Fc~ZEuFL1$8_a|Eaod~V?uw?BjXs-=loV} z6-^sDSmCibp8WNpQYb0}#XBjrTr)&1$Q;EfqDznOoI|X8znhG1Q9Mk=hR*Xgt=RJb zVGx~4^iU>#!NgA!-U~~}z#3+NR?&p5BJ&_hE3KlB1ldA(ySRq`i6f0N%}BYLbHyIe z`(pKzw?K2IIlG!;WvA?$I*9JoJr@VgwXkP9L<~*`;|&MnMmA`39wK+6B*c8j>oYks z#~AuN0@U4^Vo+F_oK0>U6lX#eo>h6);mTgxs^Wds-M=hd*p)0@P+B@?|FU#pSF&_L zY3ZE(E2b+i)-hjM8x#5qI~jM7K4<^pA?XefpQt`m4i#4B;@z0kT`mt%k4ia;JVusn zxo`0RRa8Gu>}Of>EDnVi|f|0vg^p3I*2+Y0b^XF zG)*26gVPFm!<_6&noQi}u2}!#uH_Ml4y4(4cL6z;pv}H}h^8A{!(!>|yD`e$cTYi) zLKT#DQw}nBq>?foZg=0cbYVBObU|t9oPF2Qh27NB1*N5P_T8ASyvf9TWo=C8Z%AZ3 zlfg3kZVNKohO19hA8PhJF5b;S8}{7=h&s=|rg-+A?K#SsQ@wh0x8h+kHgxvgxK9DX zAU2dJo+6G_4UmsUT!ZfyNXS49!`6yH*DA`}Dl(fYtvG+2AM-yAB#rR8q&A0FAs(tK z9_(&3^$29_1R`gev&A`9cFMk~gJ?$G&qCys2=5OaA_jLWhHp3+cgb5Exhs~MI3YVA z)SQ_uuH`Q*pF*Z_4O@x*xnfsbC?xKHs0xDy{+M zyrL5^giQ?dRcfKpd{t{ho(S^(pOOw>x+JIOm3AkZm_U!F7npurzex3%aO%PINjT<2 zK$?#Zp#$xc{hvxWEshbdI~VH$9ZAp4T27uCAZrh^EI$mHei$TG%CWvgM`X zFvK>dezx4S&av!5Ygt>LZAVpGwpRDh2@ayXKgIAEjPnbmnC3HwFe5#h<+~rQH+N$$ z;u^*+XybA7ZDSOf`_#k557%44+@&6Zwm#eTsj+g9yG!#eMFReRL1&bxip?li3P?ohR>4ePu+R_%PlI`2+Z zdzD(}-MMPRzxvC&OK4xEe%8Crn`>33*LicR%BFSR+$(8F7$<&C7s#OH-CNa$H1cjr zwE@e!Y1M}0@@`hO0n592)rOSwZc()X%e!UOhJoPSs%it4cN?k=!^68R)dno@c2pY% zjdy#h4OreCs5T5G?~YU(u)I4_Z5UwQovAipd3T}OFzmd$Qf!g$^j>-KZbh{(^Dz~M?w|s92>GN!cMAEULU#%I zrb2fMnP-Zkk478|cz7u4TA|~Sp{RSwQ~CYShvq3fyJay9T%Cd{57iW|K{W$$R#giS z7gePCNw^72;?rYAXnq7DQk)mn_yWXL zRmJlzgQg0r7&7xPgbwz_QHJ8|?&rx5%8GC{@e$-O7s!xWV}Pws8u z&XfCGRb78+*-baD&d)9m;pS4@nO`9MA|dSOhIVQbVnx^E9NLIwFqCMVL4O^YstAz_^Oh4-|)n^A2@Bk$%^8yI-EpxTgJ-Yuy%V0pKq+K_VIt*JI( zdAF(BFc7@kR&BuYZdbL%-(=x#U$p_tyF=B6LF3)AY6F&cr>YG@$-8sa1}yI`RT~DF zch{;7Sl->LHVixO?o}JGa);;HQ0So;8gbXG+JNOs6@z(a$QXazkr21jM^7)xONf^0(rb`B+}E_fhSffkFE+AMvA~m-&cwgF9j6McpiP3%C|_i;!0;bgPgz zD|B0scPn&zkhzc+`HrAFt-zf@zO2w)LB6ff-9hG2qsZ5UBLL47MO_GdvZ3;uf)hVcEp_;=rs1_kEscIGCnyR)SZmVh!BDdzibp+M1qRt?m ztLh5kwW{tQ-m8j5#M5e^XASXG8dNMHo<4)>p$ZC+DYz-9yIF{Hs#=7&q^ebjYpU9U zxUH%^i2JHKf_SW|Gl=J^x`KGEsym4Hs(Q&x>BkH&nJJ~=rDjTLc$rP5G<=rp49_@i zvWAUw%dhhNJq>g>uHi80d@1ROP~I7$9!#giXf_hkJQE1>R`E^6`Iggz{u1TouO3Wq za{fs3Od!li20aS(=X{eIKr2yR{_4RDCg+bd&jiA${T8SEaPFdbCaUpEh}WvRhuGg+ z{!|)%!4se9$UP=j!xWV}Pwp#0<;mUnmy#Ww*Z7X7SZ0Rqre#37Ecvnzu`0W7i=2RQ7Lx^omV+>l} zO{v!T^}+M;{vo}bM!sfnEzZOo^1}Rhv-7F!!gQoN4vRBGV{f0I)e7>rR*}be{?>z8 z1&@;q(tLCX`?85x!rB$S9rA8lwc*t}?{-xiJ~#7jU$x=GGVcym8$KcP?pU?qV=?be zRU1A-@$Ou;;k7sKE>&Cn)Qh`o)rM~syt`Fx_P0(0XmjZQ8x$OBCbW<66Dni-5TVr3f(s3y$anvp$ZC+0^Ch&1alByGE>UmOJ+)G;OhKRGn`c&m?u5BhArOt!rB?3 zyp_EkOc(f^=}nrC4q=Zg-uOCintKr`QC`pM!Sp5foHQRD!oFk?OBi$KUH2ebiSl}0 z4`wL2=cM`Qkbay{vbcu&qc|g~@mYvVs^WCvbqY-tR&3&x);q$Ip*Z+gmLGeAI>%Q0sfTcOxWwK4ds@cIYjxX-n4Qx|Bbb}jL-=ma zyH?eP@8-PgP;J28@($Z-$bQf^;;u!t&X@P+BwQg z)tRBOx6jY25BVFY%p)fOuJvI0!Q&)@G#?$pz6>FjFnhv_a^7WC8(x(2ZcMe|<1p{? zstuokc~?+v_~6UC8P$eQyS$rIZTN`Gy9L#Tm(;vlQf>IMz`GUIhEK4(TT^ZL*vh+2 zXiJ|}d9$s`^g3^LRoS%8n|&oMeyc@Yx3SJkY2;m6wIPkX>r`!E;9a+BLvnf7tJ;9& zUB7BW%6T`a+JNO{E z)dno@mQ@=Dn0KqH4Orf7s5T5c@3vGMu)Nz*Z72rb?Ws0kd3OM9sYG~l^d6LVCkjok z^XBY5DDN&6YQMY>psa@8D=*$Utpe zSLg;HXDW1A$ZsojdC1chx*5px6}kn;%N4p6$Qu>9O~^YHx?RWz6}m&nCl$I=$d?tm z=z$~klBb^a$K)wIb+sa`T%Cfd1FBA3gQ^E&uc`(h4yq~(F{i3LL~hN2YX+)WMJ+&F zRMiT^RaI?5+)~vp#649VLOfE{Da12XJybz2nPGPg^xU)H^JH=0Sot&jGjZB$;1zS2j(MnxYgDk=&pDk>@}Dk>@}0|pEjFkrxd z0Rsj^$bbO@BHEo<>$g_k{aYtFnFV!k^`j6wG()gj2`$uf7|kl)KFP+sQsU>?#l2hFQPunw-NmEUUxM->+5!X$%A>yW~u$AG8pdMwFHs|J@CHRJV zs~0MO>swE}RRR^j^{pq~DuD{%`qmR~l|Th>ed~$0N}vL`zV*agB~Sre-+JP$5~u*K z=!xdR&kx97?}@dgE|0&+^=-|H#hhH5a^G)?xNWL^5f4mtE8?B0dj8JO`3}gnDK|MP zVxp?=KZ&?(s!b91R5f`h;*qMpzZ3D^R4wuznQZ9yU5 z!x~r2*-<(KbNG-B!QA$1@hM!)aX}#z3nqG3A;f|SKT!y=VAk7prii6ShWZpjESUPa zbO`4EKp`}Z=!cth2>PQ#-*FKOAnoZ8wAASHkdbuAwhS%(z54F%lZbn!+86QKR5v2F z|9xuMA!47Y`b8WyRU+bqsnD6YBB*@{&fhQJP;d1@1#o@qiML9i0=T~Q#9Jj$0bJjD z;;j;>0IqL6@m2{`0N1ykc&h{|fa_aNyj21fz!g1l^wpnOkL&VSe#6%_^!bUsTdv^^ z--L(-Q_YGvXR2)xcT9CH;=QUSoBy8A^eu7?^aCOenrcGClBy=>MO;wT_d6o)n(A1@ zb5%`ViFmE5@7wTpLSI;X-yveBsYXRiOjQyQFG0eKx^+?EB}h=6hzc)3g6dIJc)j7g z;X9D2LX(8oq39o6?*#HFR|kS=>(!Fen=H)PLOKL=%lu9)a4 zg%ArSd`Tgc5oY~NA;f~&zf}maVCuVNu0m@fOk6Sla|)q%bLfZ7bO`$6{CUV(Is`4% ztZ&LF7C>_8kb(>?DkOopr>fGSh$F*zok#z035b@}Di6_!iXduMqGGRzeWpUWaXk^v zN4dVs{R#h_%QG3g)Bwg{k1K|%c)IA{Km_PPdFWTQw=#4u*YdszAGiXOfu;rob!w5~ zgv>c&7t|pZD6eY?T7WBs?PAN8EzAx&z@38n=>{w>o>4?qGlkA5TJIm0sRx7X!;e`p zmAHcD8-WZ;WrpPHWb}xNR!riYszH)131V?^HEil8|>a^yys@kyTS} zdQRLRlAwYcT+fB`(zr2%>y->$D}?r!Kh=;&s|&iIr1M+kIiTu+;6QtN8a<794l{?T z#ykfVrW$U83ZCIMs4)9zzM#U?;`$^hO#b=L?f)*f+_r@no+PY_azwfefmM_bqI{HV zMHw%pin3P<(a z#VM3^m>66gmtAlP`e4`P@OL@2~9vn#(C8EF;(dsCd^okv+0PcZn`gx_D2GPqI;gu$9j ztHJ<~_aN5@#(7GMX@2IA2dNBp3TM5}%ie_fuWWdyqQtY7y9+J~XjykRdh3ayDssMq z0%%)#Xl1O+(576yx1PXcps4}b7Y_$=bz2u8l*t8wp(f~1+yLaYZatVI;dA;DG~WmW zVWKjX7DPYZ*zEA_Y)#9HT9z2BNq;E}0C`hZ59TU;%0TmtKyWmy$r0f$3xIHbxF9gp z1g+Ca^h^3Gq#n$M@HuM-G~Wp1Kr*?sj3BOz>I=1X5r_T}RV5;xnkqiq!F{3Jd5Fec zWbPt!(@PU@_xwYMXslnvHB)u}!=FcQ<=T`RgS#EgZtOtB3sXIch)9Cr0VPal7=qf= z2*x>ragJb|BN*oh#yNuVw344|$tNJLYIf6zU|8pF8j0F;(pw^Acc$FGf@s_ynEL~B z)9v?_a6TzF&3Fb#4jrJW&LEsoO?8IDp~v8MAwo-qe^+T)R2w?C6ycXyb*2+zs4ARz z;=7`Vf06rhTPsn>W!+2Jbw~a}g;pbXK^1$;P((D~y-rvH@%kUbS}#3_c%7)~QN$-x zwdX&NcE~ln&hHYj*Hl9y4x6eVV#!pCA}*O~O~h?e9f){jsxuMKO%;~~IX`L6d5E3= zC=#4rm&7hK!Rbp8kyUuNyD4rEiSxQQC!8(D9Y@qELv0G7x%^WN>9M+?3)Xdhi#!KZ zJrLYzPfw$#G0$Pfg2ejGDvkKdAj9HdLM!OJ z!^{L46^12c3a=}PhqoOuRZzuD&O4DcsmYzrTzJ2a)q{l-n)~;* zuyC<(DoUah#pK^6)kswlB~a3ocfaaxGxLZS(8kzt2ioR|Kv+Aym$;xB{jii1Nf zma||of%b*rTA9My;JO86oWHwZ9J&^duEnF{1p~TUiLTt?=!rgA9AzEk0bMXNaSmlz zoI+U_PmtrX3obz)?7AHOE{DG>jUNRMOChETs+h@HFb`6bC%HN={T~TJZ~1bv?X>Fg zNpG&32|_1Dk3jm;S$YXVu?z}iIGtsPAjC2%kb<%hWP%`+^prs6(phE+LM;0NxtD9X zapGH%vJN*M8?s@Qbw?uO&ZDfOW)j|Gx%z8T1`lh2Fj$l6D01h$hHC`ly#0x3e&&#F z*?6#1IO}y=AejF!S1ntQqQtXSMH$cXu7D2Y8s4GA5DZn3^Gkn#&XtE&#)%A_$<=%5 z4@?G{8W22i-iRl+bpb+|To4#)f^NkPKwj(CgSitvr!PVCjX)44DpP4e^kcg|YB)c^ zuW8v_%Myb%>05*WAaBa*!L$mWGi9LpMj$vEj;+SL+5y7(;jSGp)C8S~8-Tots0VYJ zJ`te#Mj$tmN!u7+E+r86e+^aXM8u!#Wjao<$OBA%KmK5CG2r{=@ZJe_2*!C81*>zjdKuzlAq278&Y3``!t^NDN|SP(LOaL# zy6x=HbvR}JlMauL+Zl8@nZV`&* zse&qIa@x6FlJ1nN^PZ`LAoO6_EszPhhAC{@!p#h#s3;d?QQ(H9qKtc&>Do#TT~IPz zP(Du=9(SDRS{yp(!HA;^P3+M1d35}Di%U|okqO)xei-`w&*HLN!{6eFbAr{JSO>_p zh!3X9V3h&#YQ!0Qzd=F;oXLK!F7758^V9^LNgGu__;9Yh_1&e2=#KEOU_k7ZR<4-F z&Fngz6*5}{v$37CdBMsS0sU>0mw_xuc%L-={GEs$x@_tF@RC4KmT-`F3VKzoW{yRi z{T0^#%%+GrUH>y&jhSs3y*E^=+~ptY-Tn;U?ayq;-O8pus?Fd&9NSn36?gmCVuK2I z`^U10J9j3_lJkmIYO-4rL{~Wf(1~Nk?e)G6qEmB^*0ovih!C7L;CqyOQtM0q5DB=e zmPNcUnB5=FbV12<&gsc?duZ)iaA#)1~t^i-YvaR9F`+x(I0R0QbK5DDOZ*&~8L= z`8}%$<3V1HID_vuNG|8i$uo6vPqLV&Ca6uiwgSS3c5UVFIz_bZ{tg|8?yi`kzxSn! zD$2OS-AMLm{d|l)H03^m-`3B^m_4APa^=8n>*tjqhmypJF4TOhR03rR&oxM5Q`at? z*r!5prbLswf<|eb)622qiF;oMQLA>qB$~oHz#~F%Hb3t%Ki7IIK&KbDs~Rqz!XAmF zUn8PtzdnLcS%(F(AlJ}|;Wu=$@!}|{C~+Txlc}PNgJQaHY%yI>GM#h4FJ1JmZ77%@*x(4DRLzAb#X*LM5vk-GakGzz-A!jJy$l>V+L;|_Nt zSs@P}V-Mlz0>7=Fk1@M*z=7M=4;^qX16h|OwzYEkURj_hQ#jy|M2l_$v=i?L!LAZb zwhJ1ibq+YkiYM-U9YnY09!-(c4aXxwa5g{hF+bgU15XDWxT_j2-U?R4t=$yRpCTab8>Zl=7pgu za=sq`XhnIb8<%8gS+3sCynx9-Qv-4&9**Ve?!W+{OfCovH9;rh1|avRDs^B^1?#j6 zTzw-Dgo(;jS`ht+-=4UAS<~{`=9PB}4A!K-5e9&~DXRx_n?7Zr`9>hvu@7YDc4r45 zZ0jxv3^hTAbU^ge7iINej)c!yJD_=W$d$y9`wp+p6Ntx?P?gR^y!s2Ox)U+?7gZJC z7=Zgp^UOmu?jmy+nVWu;1MXRkd+b8QuI~}i*sX|rn#$Ofhd~U>r+j22I1Ulsxur8{jh0Jh-@M$oH`&2=}BR!^y-pHAf6S` zv!!bhFH5Sr7xBSVt<#@JyX6}G!tsEJgQiMEESPFe#CcOKi@0v8T@m+9bt2-Ksjfu4 zF;%<=Am;(iIS;X*s_9utY*!PUJ{Pe~xu^F;L?q$IbFsTY;T$&Z7&0P5qY9zv{#zGP zvZOKVD_YCnvR54Rf#YAV4bkASqXLX_CdE6Oyw7NHBjFMu6_aei`u zAnqiX8j$*kuY?f9ZaZfJ-3U{=)+ux@*C{CDeBE|-=sG;Q4v&u88FZZzUAZN@MaImQ zb#cIDT^z61&JKT{!{6ud_c{F3&frINL!-u2K@~GO?c66x56IQ|F=RhM==IBxK<4Ed zrm$@*k^V;%73G>Jal=wk#*2dK!gp9q7nDrreA~rz;X5p*3rePQzU^}8!VlCr**=es z-)?=9nw6$-|M+3@pZF|p%hmZYB&=4%IzXO8Y%`*`u#Qy*$g2@&@cjk}6=-1E+)Xs* zsR_EZwcNLb4|m#b-#v(k?g&4Igg7D{SmBSG*>$=sWVQ%qV>@T_f|V@-I<8*^vL@ke zYWn#W$+2Ho8-4$=K^2-A5cIBE&0LAN{EuV(&m4-_sq24+t1)vVqpf;tKhq=Pg{k;% zf962$_7C;xZ3g$@*v7&Q1@88-Ck7Sn_OE2Kb8b7fCFdQj)Z~yPh^}zHZF8)+z24VB zbYt$(x@gX(oJWM7nDrroSqI{pGOz|k_;!yr{{^(Y)DtnELP2+ z&f6>w(nnKaU3BXrpuGd!XW}F5K;Z5(qPYByRR+kb5ohrI1_>2tVA|Z1Eas^R>Xojo zfbgMDTlu>I5v{wwL!+R(E2il0Gil3;GVX9Ul2ckgA7c;US0LcG_46@icYZ4ZZd*U} zTalN6Tu2hvx=`~yQVEnPJl7zJLtVRcV&4eCtrAV12pXkzPA|ubC+>Y6L_OL8lV}R- z0FMa4+5Ei6{5@Wq=^)7bni(`wbE*(7?30Cq~Ru6VxJY zQ~}{btM=A+?IK!te}_gvcUMf&-viR$6=mGvZX`Rjem=$?!qEkOTR$ITcISWtx2+#K z;9dr@FG(EfLd}mz$fLy2@&T{T6NnwEqMyWc%22OD5{QGUdLgSJAxxAwfjFfq^3|ACNeCB|IDxpV zD)O}=LmLW7AnvM)toCH+NFfQtGgZBi)wvK}D{%txURC6)F{=k5Y@X4Mg4nJq^3|AC zhY6D>fgFqZo6}4}_41F17SXd_1Q37#Z zRph%dt4SfOL7V}yAS{a-9xa_E8TynCS(c%dbjYd5v^6+D(V- z$l|7;f!L`k z3a2rvE+Onw;soN5s>oMkR>ML#p~MNqlB&p8V^*_5IH$yPd|+tFAP`qoMd37NwI+mn zN}NEvQC0C)#LmBri6{350y&gxbMB9>bM)7+eH7>)U(FU#9h-;K+}6E(YLT=;%t0H! z=XgEas(c;4i1k#We3$#9@TH4{ikbMVj6!}TOO(m=i6}2E+K#O@j+Vb)_;Snhx_w@V z1)}x7u4n|~d|eUK{LCS!NY(0(x+`}l#Y6jg#j6K{W$07}G~Wp1Nh*Vt;#H;|3|6~S z8PI$qkXG3Vup>AbePa;pz`c@L$Oz(~s_2*;lA%e3BoNnCRooEq%vA9rEXmNUT>bOb zM}dC#)oc;fym<&G+_ro={E;@!?DcG`@^#Kz#JVWaRgSrR`GA>l&%Rf(M44Qlh;qfE z?btfzX!*STa?4M3`&yDGLnb9B^thK(Js7N0CnwOnI%H0A!YXuP`DzgCSE~|Jhy~)N zs_1mumZ2ksBoH4|ReTh&_qRC1i0DKhr*idACm#j+7NLK6TSRqk(Us2w@z-H~om1lV zY^(Bh{36y%iMetpv`MI#3HPLUB}K@r!Tj>uG{C0SRh*ObZP|S zYydIM&m4k^RIUE_bb6BFp?$rbydDgep;H;qygH;c+6ug!>cL>0Iyr&n)ghgd6IP)U z%U6S7zZ#U7LM#wRRYiwNB12OONg&Rv>V>Qpgm77j6Nu}oB43SJZ3yA65+@K3RYkrU zvpN#OGbK(SUa5+FHD+}!g!f9EK+Mgj-a0g9)hvYVN}NFKRu$#dm{pGu4k&Q~aYR+* zt1+ulA)Hj=1mc{k$X8=l6F)RnHurhCIy(f076ej0DOW^ZtokxNy&MUj`PbZa87SLyaeKCIHk zhvHkEe!101okGjS?G#jTHw9JPOhFa*Qc%UM6jX611y$TgK^6B=P{nN&RB;ytRop~D z757k3#ia?V=Q=1r-YWB>?FoC(TV>EY@vie$nYYSRDuAQvZJ()>Ba|V-4veB*$T{y6 z4?~xFE6~4nC-QxjuK72gZ(myET7I7F6uGNP*Dvxwm2Onzq)Jy3dA3ToB=V;!-MYvd zRk}Tq_p5X#BA-_2u0+1B(mja$Sfy*9`+T)k)Iw>tH2HBzV0a&bEaRoqQM6*p5* z#k~|%aVrH?+(|(dH&Rf=eH2u28wFL|ML`ueQBcJ_6jX6(f(jcqu5kwi$XjJ9#d)g? z_H^_Lu5Xn|s|@z)0ok*|Y8nzTF%{~FD~1ZX)BlowoL&!R;(1r!2&5#Le6oyIMBFeH z>WC|bwguvyob_NfpLg}@kUfdvG(8p!ooU*?+`1L{zDkEO;rdc`q1j`1&Vdtq`_pZO zd1?L2pKtb@f?=plAmwiE6}i7khv~%irR+jTvAYaW{`{;^7hIhr!hhn1QCyw>KLta$ zx`cT9Q$ZY7?iq+9s-k}|58Mbg)Cl69a+l!l-c(2&R}h(1tssqv{+}@rA&j3sqBY6d zQu}~{w1*u@8te^?$7;Mx-W`h;s3A$1FjpwgtgR^qs3VV zWJ!zs!?uV!rh-pgL2R@21BP(T0D(0oI%I&=G@-sJseQ@&SguaqF9SIc2eu^?5S}ge z0`kSRF{`5}sqibAHfo9(H37>(8`EZs;Y~}sy zqQKlMGj$t0*(O9sM?(-=&dibuv2b4rawqk$r0L&eM+|_t{{vqPa&AOoh|4o5yMawN zExQ(hbfj+_xJT$!2%U?7;2y&HpMw}eJp+h2qMm7s!u_4xAA83DV8%qt83_a87BCZN zKw?6*n{rfT4B13b@(n>UI3fs+hy|U_BA;9oUTpQZ<=XzH{Q29rV*4KrVuQzZPW&#Z z{{qBMs-j~NRu(lSmH`55b3}<^Xhmar7UCW{;8_=*0P5PphixUNzWh=HoSu#LqE>0px?lO)+&VCw0T%IR!*8Wf7@hgGY z{#T(Yc8S<)ssRy)OoiouE4aIqI}dR~Ri#}KZ%xJAR7V8aD^_m9VsJ#Msn~-uWDq(? zhXgV!*B@;KyQ19l2ID+_WQi)_8oLR%bTN5Q#gxvC9}~T2qW4Vn9+BWWA~_Z0>PG}L zu8moh#K(&InmH8l$W-uwt7C;BTr)ssBj4UWgSd7z7-}Uzs(Kqi;0nn07qRS%H45bI zdB7Z~C))E)Waw5Qw8}C-F2(vzS*S38G^cMBS7QC3EcD+|WPn@~3%!6rvgU}AMkau` z`(`H4qr}s#iPI!xfV7G=Heu&&+)oDaS}zX9!{F4INUzLSgA7XyBN_|chh>1kdNQ3Q z1EeI@i^`HfJW*BgRKzP&VTZx>#fVnLN0oc{z;*w52qL}Lh!cn%3woQ;DPo_g-~-ne zBWe~ORqo*fSA;RD;Uo}`{%H*wXk1~nt5)L&B3_#6TEu-NqW@fHSRfN>Rah0#xVcpu zvO-?)<^4UTpAr*pJ&-$!>D>9m5ms4Q#prl)tT30jW`Lk_Q&NAgf?pF;k~mPd@Cc8d zOSI<-lOk@K3OVBnqIn^#BDysd(6}~cH7kV6O8lOKevhDMHE6nZ1(5}BZ5S)sx^ z8Z_N?tjSOYNR9TcgJn-+q1&5v88S!o!~@8#vJhlLh5&JIk}`o1$Avl@LxWD}1dl<) z+&j;^M?!FFL=e$LHLR-Kqla+?v9Zt|ax6Y=ho_A>10)XDEows`Cvk*oS(P#r`Cbyu z>D18wVF$>g&ck=8B(8uoE6XcEI>kYkI{J%<0oM%~vXhwh1weL`g~Ht?mha&J*AszU zD@y`#_@C9=iBS>PO$7p6LA3JEz-oM5#6wdZiP*11a%JVs}3bDaD=p{!ODE8 zl|}eMR*6K0>36=90Ax~=pqdtlh1Mw?EGP?|=kqd@0kWzrbP|K5Mk53A(vIjnhXdPF zDCtGX#KNU_J=cMxxeGjZov|z6}4_mBEZ_tszPk(tnGLP z-1&|{&e0Gv%?T5nKY z*2VflSrUldi@0BznH2HBREHv-n=0-caGxu89-?uVn7hQ>sc|1E_ZY+xji?CjBU7aX zd8S0;5G}}Q5Lp4HIY?S~*TQK;KQPe`Ohn&3KM7H%ppg=YQ>vQT5b@qr4*gs33b za&JL4^7kO$(_E;xMk%BORtIWDy~S1qSna44^%h!VLR%z(c&Mrm4PJ_q_FwH?yZ!HL? z5q)H$k4*G2uH>2!?aQ^?Tab`UQ~=SET2V*N$q*bkUo&3`r2C&o`y~)pRQ2IR#IAn>NJWCfV!AgLpVh0};W zGSNpSqK=#rqEB)ycO+yZe-H9o&4oI0fkH}Pb*Wa#m54W{iYK=|B8!O5b|xwyqH}d$ zKtx7F-HuLN*2zvF-m2sB9;MMSO4L$}{av~0z86=m!%whVveB)0SZ7K-@ENg|<_TOeEH?_;J4EQ;VJ3f=J*L)=6j zgr{3WS{sU7<$&qb`f~%y(1}74h&}(JHK2(7s!B#g+*B1epl}{5cOIf~mmnHBDA&&o7}>e=b`e>Y8!)nSS^`!%fmS+8 zWQ+WL%;Yv82N2ifCW5$$JP4>;Lvk8WFr9*N-VLLFE)|kM?EaUu0jEUVG1ab!$EJ$& z0QZG*=OG$*iMdP6%?&7=C(1nraa1EJf_u+YagaAcU=hv2%Cep1i0JQf-3n2=`ugph zh(`2VCi-n05fe=_(KHj$1^}W?2_v*)4zi{D9_hkKQ|>)P1YWj`9hP>fmSN|cA#u?(W=ArXg7H7a6a zss#}{)!p={i1VgOi{M5h7=vi3l#q%M(Ym-7f=4ByCow=;{|KoO1lBbmIkB#S^oVLO zow!+sx)qY|6LHy8>mnYT3T0i^O6O752`wxA@Ez_f$Z5E4i z?zb^jP=U!dhTlFi>6E1gT>~;16+1j(HWm&OX@M?u z3!a8}sjBzaBHoyav!^n$y9OtAP71J`UdDyzAxl)o1P9Na=9M7(7Tt2`O$CT7oMcT1 zHjOCm&TLj(X>xxed0c2UXoCUdG#!GW^K=M?YB;(Q>vqk%fIF&5Q^lo#)wTLA@J$yz zRy$TPF??6u&BYLeHKpNE^#ECT9#T?BVNOJ|q6|Q6zU#57@)aiqLd4)44H&ZUDDNf7 zU{kK%Z(SJ^{^$DWPmBp~i6cbrbs+C@fBc8fMw1ETgp9oc)d^=(oE1Z8@$yDNEEiJ# zs{J>1bSscn-K2;m0|eG~mqaXpw5L15Pz{z2u?ECztVS@-S8_4U&m1x-mBIay(^P=i z^C8U=tY_0_sU$;ycvH{_#;I>i^D~E_uA5rC1Y+mPpQ)_8u$}gan3yVFlpxwxqCCXQ zKL*is?r(e+o8=l_Oty;HW~zP>bLwuoU&NBB(jwT<2*w~ zWr5YBSU2Uq62yI*(k!cGP_E@icC^5~ESri>*2{!k%ewea%oUEZn5wK223vu@eV%BV ziF7+OB3hIjQHhC491*Qk5OwJ0k{WakNJ~`g@EG4%I83AkI@G;x8sd?v-k*qgYAVj2 z%E;~-oY*cZ0F|-lc}O2Y672A6npcAC?@Sf&ZyJoYUGJZC8jkFoXW#}P z?&EgMlL_R+GZKaD{k#9bj0)Cy9KjGO<~)TlgcdY!9<;q-S31&I=!aQnGKAyTi6sLB z)^>A3u>kU@u@D49HCUd+8W3*=8o@ZT6w|yK1kZT5+i|7<5WCZ(;=y`SmY%~>kRd?4 z;x&SCDihPZ8Uz(t)U*?blmGIcsqA=RTbmMb^u35}M8^`>5wpF!q{36zM zi~00-w^k(9ZHqZ*^wB;nS08ubZ~?lkFp? zONS0KHZr% zVDag}v|%Ff>B+PKtDofFC^SQPdgN29X#*CY+D#iK4WBwq8?gA)ZQ3xE_|$9KfW@bN z(}oGgr$N&OEItjJHcUG{jhZ%K@oB=ep&9UL(zF4KPbJY-S_B{Fegws*1%q~N;lt98 zp!l?6P`;~tTaRz+F`P`Fx8b+-__+>m>#=gP(rTOa&-Z*hkRXpN*s!DG6VARcuWu*e z=XL&e66V5|&nMxCG|;GA%gM2NR;jGJ6di7f%DP+8;nt_DdlX%>9LZ%} zi^%O&x(<=Mt8_gg_gCo#L>{ivjfgx^r7MVxdy2B(S<&IjfgmE zDl`#J$3Q#Z{Aowv$VDiIn26~XnbGH;d1wLledbU;hI(`xBfyErY z%HEb(4=rZr3+~smt*Vvd7qK2$%;Br-eTntdVs^gZem&c&S~-3Z>xso2z81%)Gt-8z z#qsINv;li8d7WE+L5ojUrVR{OFSvd?-oGTvbE(&bT+6>nI+MDfKHl$?Udk@q%flU} z#kswYz5V>G9;ALxRdqxs;aU&oQFxqUfacX9$feoVNqDP_Ppzg6Z-L&DGRD9|* zZTQX8J`I{SywSy{Vbg|hG4W~CwBh?oe3~$A`I|}k zG%450*JAikGG*5mKFpc2WeXn`MEUuPlq>mk^CK-j-I+F&5uYAR8%mB(Po@pU)lYKv zfA-capIS{DN{&zMrVYIK)M?r<5%|+x+phO^}JI`5WF>9sz3TaTeSZ|m{rdp^FMgkkNz zorIM|`b8(hiMVd6Z4q}&h0eh>?w}C*TV*Q6d8!x^jv|HLnM=rrv4lK=bO5O^E?-t-YM;!EC4J1e#Ze>`4rGtL^1f4`x3- zC(yh)z|g5dAYQ797HVTwk3!h;ui-m9`X>ll zWvEXf$$*H%ri!+NT!#$xD1?X;87e7+N-;qYVwn@jlCluwlMJmXB!RfEs^Wo&kEV)~ zszJ1CRvoozh_G(TeFt$uiQYq;Qx*L`u^>W3p~}Cr z1uDc;QN~dxXof43ON~=l1QAYnVESi>fLvi+EzHxWGL!G%wfikE6B0Y`;o( zEHbFdxR|R~F#U23K@EyHVyZ;Mf~rao5kxRV3@eICAg+okgwP6k&0r8Wt6-3K4F++) z3Kl0B;)rtu9MG^$=jeny6V7vU7xQF*T#5BW0@ML#&-*iYp=>m?|!C4We1I0@1puUX2KOl+t}=fWX?4NH_^co{n8Ba( z50t?h;>>1s6J_TR-x4I@aA?*#B^LP^|O_KHQHT%GML0|YJ>jRoR? zs)~mq9-Atjq8da?W_9!xiI7K?`#9(fkZp;0*OEXrkc`tIDAc)HB@iD}ReTh&_21Iv z7e`ow=#q(=zXB2RxG?u|&>0}Gwj>f%!;+vSbR$0R%y)~VT%(5F0_oT4BoGU#Do%>H zVyZZ=8bpI;1)^C~y&4hn7)bY(0Rn4FBH<)xGJqa7-^(J_s3C@S)hdBFxvtA#R>U<^ z?TWZ>s<^BN!g(gw%DxGz1+jBCQ&^S+R6c}Y2#4Om1Uq;PTLH}A&)FTm%*x7Cf-i&^ z{vF@6np|tWOU;sGt5&kKE8?E1(ugjMD2ALw^>>GjHN`#LZbiP%>XxDJ4^AqeD0tc37!gqoI`M1TwFl2!f$yg-|dti{9Ze==a_c=#w}xXB5w>K-M%Kg6zxCK{^CO zCkmmgVu<&zq#uj9(NHjF0y$St1i{OeR%v*rB{D$z|J~0^cSNp%1>&5lit{2anJQjp zi3}AKl9WV*wG$!GQ)UJ9f~jI(+cLCM4}=cVn58^bVB9lih=-yo!yq3U4B|-@ERGvv zr)CyI&SmJL9tfotvy@{7W+`V5r%&b_V#~kxd3l#% zklRETnh0Wh6)eskV;yGpJcLq%b!R#YLo%>Xf#9G!-4P&N3L!@f83Wpg$qGX~N=)mI zA;bdf-gFj*WMH9E!9jnzBS88TLXH?R2DA~ARU(87N}ND^R8_J0-~ZgcEpm09rxpdh zCRg{x5I{NMDZk5%xxM$Bumic{|6KguSNo5--JpN391GzJ4x8nC+ z6QQ3x-N{g^c&~&QyLaP8-u;??0&ziARDM8)(;*`=G^G%VdQpZ}6p}!^P!;(GWH%kM zAw#DMA>R)&^r#Tp{V>$BiEc?C4yua6Ys?D7o$16wGL$GJfjFls3a2rv48-%|b6tHW z5S#x)6s*`LV!Ns0<+ULM2Xb}W6rd*om6uY??JY0Zf!tYMfPgwcVrIwcQUbY_Yg3L| z>`I0}TuCgZcC$sby0vNv#FDCLsvENcaeq4TfD9!Hp%I6SO9UGbVXbosVnLo zM6sg~>Ya6Bq29>=*%X!Dg#~qXdj}xY##wlPWa8P=+E9Dl$WU(U^M?2?_g8qY zV9-2+?ujY<#fx~>9Z=J=Am`w1mT)`e8r~g1oKh7XMzESt2<_t?GL*>mU2bu93m?pm zdJJ~mN=?U61_*M1BX?0S$oYnaLC(A)*nUmcnKB2&Qx=1qzX3BKPDW}ub3lJc{Skv4 zXC-m+Nv@$kAYQ1dcqQV!sp5tO(Y8XUWmaV9=K$G|SdgUKKmhG&PPE4Z0v=}v$^h9B z2bb!Iwr|96tPomS`@}-qcLvCzu+(sr0dgcP=p1+Zt_yUkiPPSUwrt(T&1wR1LRG~{ z5$8=6H!+CX6q1K%L?sYSDT>;nLxy^vhg1>A;eZ7Yw@JIjML}Ir?;wgHg;4MG5exNB z2FQT0)NqsmGAJylv)elWp*GIK10)mAh}MSM>yr#^%GEvk8RQ)OtHk7-BMykqkr?D0 z{oCT~P_AKXhxnu_I{IOCuMpbD4`k?0u9c%7AIy$=40gv#O-FwQ2y%cUcTq6NIr6{ke}WU3tz_e>QBm6M@)h2+_avlleNsEVjtiD)IlSAA9;LTJPk z&VWFM)i*%~W$23w2BLNKRpNrt@d+!7@L9;a+%hk@I(VimzupqHwZJJQGpSF(llt@kSkkynTc*ypO~f zXHmWm#N8rdSD8SWLZ<18T{+XokY`!keS~>3^jC(qaPH7?Cw69s62#{J1kd`#RuOwm zm55j{RU9_BI~9^=E83vgYK*ODpMe#E53>XDTvMYG!O9>nM0_GXjhOPh5y-uUN03_? z`r?@Y(U8tWiEB!|3M-57S%`a&SO*Up%{kk^@}%{mXdYz9(xi0*h&f7ym?MHp)GE(bv=zbXK&{3g zwy3WX6VZMOB6B~^R^#z%Vyg+Znn<%k?ZTk|ab5GEW`Hk)yb$q%_%vcFa|Xz&u&ikY z^bd}~!M;MsQ3lAaSl8~j&gVN0M6KE=(`-e1EUYYvXCd!$f1Pi98{l!CkutCxalPV( zL@BXyo#p93uvBcFClGDzQ5#=KIDmSG0%Q14h%wF%`#KPJzmHvI0y!abO{stkp+n&& zsS z#;jh9h}~1WI8DV?^qiQfgEG{RATKpJL>wpOo+2@*vEsxm8C^XavQuZmeU zF@)NJAsLdQN0o+HD3(Dv5@+>jq%8%f=8!^YuNs!2M6TXFV2p8&tO+rnQcnelh%fv? zfp5Lxc2eyq!h#F|;zbx^oCq_8!!twSIMi%KGm&X0cg`_Vv9HD=B&!U>458;r=O+%1 ziis$kS1YsIh8Y5S8Azs`$>|tL{?0kA-oI_DwVTN9TkV; zY%b0&PA%!|;!QaR<6TRD?Ms@UpX?hp7@%T>mf z<$vmeb-!#_mxU|FWSaX7d(;~wu59_UQ{8N;n9Q+a$g@XMrlX`07KhkTam3H=R^Ic6 zr;DkxVZ7zXI_7>J}F3#2b!Xdx^0x;(@7RB3K!O?wtTxf1YJA9fF~ibO?rO zIKt3wItw63-g)T($j_(ka$m%0f5!u&&BG?y3xs*u*(dGi}L~r1MpRqhj|| z^GtVXv@D&V9TmIJLc~^d1iTi6o?$Y*mH2Am(IahKhm7|C8E)|Di@l%Fm9uE#Xfi=w zW}Y(K9T6l`8<7O>=^PDU1hrWqI-@w;7l*mGTanofMkf} zSxBb(W&%0S|6H4A@1e3R%`BKqyHY8x;Msz;|JoZH?PzNT&u4Jp?l7+dE@owt9s@et41|LS$6JJ z9aU`Q-lw|C*wT64dmTu&+s~o-*EH&@mG8WI9$d zu+Rz0j-G{N$|(~l(-BLz3USC;+Aj+x)158*G3%#$R~y5 zS4A`{nrK)ptJN4=(Vhh>Bc}UcK<1P<)prd@Nvvm;g{B79Re8s=l>ri)IFD6Mi#jMK zqP#Qh5Lv8H{ynWu0-GQKe7WDvl75)kqyfa2VRB zT_Ww$h{-psEKjxSNVfvI%2yomog`(D51m5Tr^NK_Obsh*pL(q7@>Svpslky?jrqio zH41HesBMjz!H{J@%O-}nH)=7+*`H#F%hNBjHmI{l%>>A(La2NUAr?3oQI-r4as+FO zg;*FuEK?H0uEs(KDnn>n0Axd1#&(F9PES~Es?|7KQD?!*BBmEhfGjI zc%Sl8;be%I7Gs9zla~swvA2h`7@a2MnfaPljg*}urkRN$?lII5$k{Sto=gxrftlr5 zNT#eZY!@%ZlPPi9P&n}nO_2dY55w$;AelBCvSQ*4;bnkOshk5NQ_X38I8BjhGjq0v z40&X+!cE4R-UB2McmH#JvOEy+$W(FhL3FM}d5HUJHN!-7fP?5%iN+vWL?tGoJ3kPe zDA72?J&kCZiD>Dkd5LF5u5LUr z$l1YTNJbvoW@4Tiu9mcQ=&S-u4ajnoxU-4?*-%H+*$klr8W2=C9P{f!XvC>jfI2q^ zAT$Vthaq!BkRyrZN|Q_=ZvPj0_QiV;tS;4R45C@lVFW8U2>l2#_q;Dazu4+pgQjX= z=sq2CBSZB;9>uCgo_9=~!3ts2AkM(TkPju9kv*LmdNBf@y$boRU&JX>#k~VGpw7zc z6KjLa42o(*iDyPd+%;9~3j`Aip(!7bAtNTp5JAQgQCXgJetk_V1YaZ10!2*cR|d#r z#NzJr4S}4)Dduq?=+aLTSNK;@RzzGgRooV^S};f*R#m=Y;yEESVrnKpjHSrF$qIy3 zRG%2yl?hHM(hH->727qdDo;OrlciixQG8+{6;2Z&5> zy6C1QQ_ziBQRTTBbXYrgUd~O3gJSLs?!Ov@?l?JI+R0xFLX*jko`tv@aLkhll&Sq` z(ZsGYb#aE-raNMGL=dMxGgvVsLwE$)lP&f^w_2JyhEO#bLd^)sjXD~?C*SnN4Xkd} zYJ#okD>hhJQuMbD0XbLVRNplqr(%7kEOfI8>#Drtnacn{CSALDwn-ok{g+S`Cqz6p zRqP8y-Aa^)IHFdwOhm6(K$Ixa7{n)4eP|QTVdee+?sZc^+!R&$*R+r=7do#HLZ|v0 zhiJLXz@HJ(YfBJyDA5E&t8R&j=TA3=~fu3@)Z;J ziZx;gug8Z()u|IQ4Y6NU137UtFG|Up@_DmsHSW+!&cN6Z1sA+ znk5P3Pb4MG`U$Q%)5 zL1J0aB&kgnBZxb7G052)Vu;JLC(h8m&eUaq>=O$;OJsmx!Ch!=5{S9~3U|XFAhxQC zwki&#HDJ2?%XhgG2L}dg~pAwBjwA4yWL>oAWdX;Db z;((?$%|vu_3?fuGtRIL4<)(?PVKta;g`v@O$dC*f7t%y#ZP3108)W)QRB#ZUrS3)5tTm)Y zV4@Nem6(WHlZk#fqKJOD71fYNM0fB==|rF*d!&RgoPrz*y2>gp>#0DHpYwwGWgr*i zh_?C+5cCX^chAAPK$bY27~rV^K^!$E;ZYJtzqujDAm`fD-v&>)lnhRhK`u=VX|lF6}%C#H%Q1FUuxl4mPw6Iku3)fijR z@dvAYwHjwDdf^GHCAFee1jtl61Vi)bkdh3|D&+lwh>NC*3kbp*;Vp~xrm|25bwG}k zg<1eCR^U{~N;(UM))hkGuF8->@*AS6YNWVSK-Z|lwy+=rcg5EQsu54j<1Eb#kP`_x zw}+e4q$J{ksp49|>PD=?<3GeDwW7lnR-FnNV_&rHV0Ep&#vz(7>J(T#sui_C9gy2} z77W#JbT8H|ns;GVM5{4vy|6-w!U@AxRAX3G)tIfQ#;`J9MYf_Eqi1?FuVg^PVO4#A zn5c?oqFIIvLcSP6sWXJWU}+IY9U4nvgnZLXvi-HXBj3f+|ZE_TE$v{)HJc?0sG8NG*33y-W2-mO@@%l)-K z+`Q!NW>FUrCA}_aQ?9s^%i`Y)fijRWUzF z>>E}$>N^i{K&|M$4OX2B8S5oqG{PuzFN0TAX!2Zqr#XRKwA|SR179 zB&s$oMS)8}lf^_O5ZPo=+1Y9gRxRp&3}Uyc=nXRy6+vX~X(j;4DKXvix5^Mo;Jip= z2s!E^7Mk*5foy6lsgPNP?#Z8$q!4Zp8|XxtgxQ$ayI zsJt;X1j+6`9MYBkPQbkoOH z6Kq943}>rfu@(JR99C-5eE6J=@ALvd?ON?pPbYCkL|W1%&4Nsegp&Iv+mDgy*D+-O0QClRqEoQ(mi zzejh01mdQurng1hGgZ7`K-8y@Jj4xEm6(Y3z#2qDMijdrlp%xASq{jgvZO-R6rvID znkvmVtSaBUAye47U&kRNSeE~uL~Q8&OXRU#_@PQ{=KM1`Y*l0{I&g+0@k9$iWg8~Q zhY3+3v+xg_u`jx5dodyeTVt*j9Ehr0Z5*S)m2(27IJ}HFu z5eyj%If}d6*)$v#ThUJVieI$Q-9)4RQ66=_^E)X{wUHVmBcGQC6nYT;2wHk4$B zaB039azv{m0}D>T6J28o#EJhN4}c#gMJ$;r<_6J)66GNp(KHj$<_n^8B^ra+rtW8$ zh~5N%=uC;mAtp*xVj`OL8bmkBO;*=3WDq(Y0Lf`MsgMzcWQiEWW|d_M*{aCZp&bSJ zJ!mN?iCY;m$oof8HEUk97XV$OI%tS4Wg*{nK&)ESOYP#IGu;t}YQ)kb)`QAIUDGE+ z0}7$-11tuig^wX~L@e?8b~)*CnkQE`>W6YN4Hu2Cm8Q(BzETfBgU@-d6)a+KcxRK zC3ckwlquv4twP&|vjM~bW`MX4kId6Zf5j{rU1dqsNz75j0XW;5vj!X#6VX2JJQQcz z{4&fuEnE&K14{-7O|p{|`=;=mnz9vz)9A)a?qgr?a)0!;LB&O>`uu7eRF#j4m|=xx z+#)i}d0!W8-*{wNwi`N#$Eqrxig<6T_W$AY<5!PdodyT@wOZxbif+ANg)qVzfViSW zlx$;GOG0SG6wanV_S82)wq>YUOHo3ey{3w19#%$7%Rh#^%PsS&jX_RF0fK3CAUl%7 zv8LJJr0-KPraPqwRt(xyVPz2#q$2458l6Cc+T97rKptaab^G zBf1_Fh$U5(=0sdK)uD)Iri!}`+!G4PLp)H`G>DE>m4|q)Dr$OgCkh#ZxUZ@rbB{4M zwd-UcACwOSI^{Ktn7Ld;dqgl`i&+IBBX+BCeY%?s0IBDkRTVbPK{( zV{ApwXRt!>Re3yUYP4^_${;U9d@DYUnDT6qs&rU&;sUnH(7ZxQD8+`U(yWY_dI!XS zxOZbQ$mt$H&>s$@O#wsoCAw6#`5b*)}h<&KD`yqjY^!ra^8yCXa2pLA;g@-Fu` z_}h_~ClkntrzZ;8+u?yheVrX1L#VeiVGN-izCQ}aVHpz0s9c@z4>CY7_v^|+u>i7~ z4q20-8Y~#vNN4$K5X7)+u|T|56|DtWohgJiz ze*samLh=wNRrTuy5!XzWM)aiB8G~pMl{g|g%MlUsDX%ec+oJA^-69T{DlH;d`$Vx- zs}RCLSXOS4(C5xObQ5H3R~7VLP3T3|ZXj%4UeuHJ7& zVvKX%pNRRXdMZE!^Sj()^VYeHUl|VKwWun%xSPNavha_bTnZj`&cAztq2B*l&xd{y zM@$v_f>n<~@@z#L9jwgP7+cZ%D_A{gJ(3P_+pX?t(qMIOR&f#-sv?dd4`SV-j^1~Q zXi2>1BhFcAX3JS<$JrMeTX}DEV~lfFF@ze{X>&&v6TMzMv8N2dIKLWq zR1FbRxtQgvZCcMd$}%ZgFqukD_h?+148m6g+6LH^E@wCCpAT(`& ztUb@NkPgAnaykSoT;N4#7|jmVL2)N@oG&P9gb6vZ6VG z)xBDcu@${FgO!CtFHixwP~ueIH6UkVeXcBYM-J<%yyM=?06``lhj_7+Ks;1c@mRzY zQ^meO)Txj>#FDChJuBj>snUqr6*30VA}Vo2bdQRNkWaX`fY_zn#a66oriBUaX662Uh}INE=Kg)=PHniHa{n6QqpChK_ph0o{-a+sT(=U@ z83IU0Is`*q=@1OnaD<_LWto`}ane-r8S_(EJyO;SH-*CH_qpZB40G2s!)@;&J6MWW=*fO#9Nhgt4vR6tPpn+PQIJtB-6& z>z%Errn?fxiH1YxL?} zJ3oOqs;Uyif~sg1Ks2b3Jj4lA(V5hkRlHuDSDj9$J1Qok)^WBf=PBMnF*o&prq`16 zSlpDO+a2fM`*Bbl5&d$%DM#B%Q!WdNx#{0*b-pcY%4I<@_wTccZe5#lSx`(wJ^B+u zXqVzxUI~)vi(tChh{JR5D`Jp$58>%zJ7+yRs+Y0yHehC^O_3pVk~ZZ?^=ej3?5uWD zu@!A(4M8$gi*{pn^h*8TfTJuuk_FRP6XR%}*TXh}c%iD&rHD7CiZcb#fJQa|Sl!-bnW~%%pD%fp{ zo%=Vd;1D3^9sz!j)jyT!M20TXA!pekm&!sf!7)^$HEzZFPFV^NpG4*UmJ@>`|2y7m z(b@-OKq2{I5zUGw2Ude>HO5x7TfxeR=^hJ^E+tO&T?5h~)}6{iRfly|-tmIW06``N zb(BDyS5*n(lB#GLKs2S0Jj6v+(c*8+3Sn$0aRPDp2#r!46)`bYTp$o_Dp4My5tW#T z)*6V`m1qp&h`OI~rp7|sH$&*y0%TQL#x_JWVmdNmwWe0% zY(+B(D4Ajsrc9VHMC{|`O0PDDI2RqP8y zCrXruc&t`4Ohk`6AUaZ_F^ES>G|fbGW`XEXiN+yXY9%J3J_Qj96V5D%7s_3{67kkl zX*Gg%713$B6^5#O#l&Y~jTpk4scTWKYt24D+*4J7v#0GHoHg>oP)>J<1%;6BK^YoNhYS&9HW8IoYnH1;?-quMXlz1MOLBEyk~U_Ad}^eQ z!kKT{KNl%H+J#}gsu@h5ig;$KcxFDykXe=3iWVDNQ8?)14fRb^4#;jj5PJIu7IReC z5kezQwF1=p!G*9GgfhU8IU)#Zf2~O-5L^CF?A_B4+f+pb1<{=n0}5Zg7PX(pm05JV_UIB*~ql$++GhSgxY6^2IBAwx1`kPnHd?$qi7 z#AZ#kz^T$P1bw)(5o?3Y?u+V3iD!>R zwCc=uOQEdC=~x2isS;7@d*q8C2Lu^A5!Hnf)9r3!R!F%<#3;A1_&KfU@=F9C-G^-saAkGhZ_hDLg8V^ z91#S~JgP}15ZjM+d+!pl+f?z&1JQ^QjX^Y`5);wnfe2xQ%@pFia@UhbV^&GJFAPnk zLndUXKFF+C)rfeKi8ELsj2grlSQzr*Qo_N!I)6tMKDPzhl>2U1#0yi!?F2NS-bOCg z2ASCx)sYg<9E;egtviEYt()l{1DvNyL>;$Bz6f$akg*d{S?auzH)MsBYealTzIh`j z2<@Dh@&|#2DSr~NS!+zMQDAl3kX4nhxKXZ!(1>Xo05O&#M@&{Atg?!I--~asm77#b z(4wUv;>N5HMzyaf9t_zukZ%mt2oI}bP%}s%9;&K%EaI7|qG)m;T2V+IR;Q*)vszTh z7{onQePE(7a9Tuk^NNU&PdHj2PAWImtcKN4x)p|!bjYv_8Kg8Js&%z0LA31OBYR7g zPEl~y$ZJY`%&RX-y(B|(=@1OnV8M`OFwK)iw|-0Fb5(uQPMHC+Of0map+C(LZHt(L z4UL6L1;}na5ZWfeVvgSL2%!H{ zX{o`wifA<53PV-CV&X)s5kvS_HA|w}*Gf-AJXKYJv!^W|oHg=7*Q}-|0mvtX(2W3w zYOrAFL|O8uB0id`UGghvo_TcVlBwbvg6L9-iXiGzE8ctsU1b#$p9=(R;qQoa2%*iy zZ+Ir?Z<1UQ(GOUhYZ~DXAhIP!zc2^UwWit#igrJi1((7s{yM!^-VvS#gGxt zFflE6wkoj|t?g!sv`r(X!?T4Tba-NFYcvXWRLofT0U;(0`(#jI(rjC!h?!`HiDsCH z3brA6nR`loR3KAY9o=|QTj#gs%YsH&VVjG)V1*!5(|v&)sBc<)fSl9=q1Sp~F-L`C zAvEGtD?pu>fgm&pWq=`bL=dz>+y9H3gaqQCsy;v*Q5Dr3L|qEWLmX1oG(;n!nE_F! zT8%;MQB?_|5z!4Lh&t429Adw!QVRlT`1>*tYgi$S`Tw82_Y115?ec?mcQXlQFvBQ` z7}20XMMY&sR5Yk)NCp-4K=UQ%?T>tep55KN??+XWk_#$D)nE;iFjZJDRpA1wsDg{G z6c=1@!37swaDj@7ii!~x6%`c~4Js-sI_`5=zxC{Q{np;S&*{@W-EXCD_F_H1^;>_Q z_59g~Kdr z4&1ZK{SsoxHU@VfqTL2WGfFfGaZV$8%|vvK01=9wYzh$9m7C@|$7&(l3PUT|kVP2^ zkTP#p5qpEm_B04! z?R>C%E5rfv8iYei{CY*iP#tOnCW@ITW+G}$Ci?b4f<(&6@6B~fL<<_^x4eGn`hzSZ zwW@#@d>{Mdf6$?PxiG_B1G(d1f`*?wjM#a&XhRaJ-hNkL)&~eI+ z%4H(Xv;x#Qgb{gwPzD&v$pHO)tx1-mfA#6qXpyIL%YoI6T8*<6O$)4U)oOyRsB2(# zr&cf7iasEL)uCEZBLT9V4Z+Y}Hsrkw?I`4%eGw0W%B~g==7e`F)|bjc8PoxJRF(?n zwN>Yr8VAIo=0&Vd#K*b%qKHokGJYYdbT655T?r(FLkk8zbE<`Whc)lgzKF*`Wn4$F z>QTrz#8XvK0bvy@WP*KBtHWwetzNPfwK}W@)r!hq2c$Qf1w%QG`o(%wS;_|@h8ol4 z!3xPHClFgvjbW9lF#1&Qj)Z`Sw zN2H~pmB$bY2apqWM37|}T2siY4H0*P%7%xb5ZC#%Y&8xm`1;>Lpvz1#d%wKhq?ry^wN%P{a(O#knmGcGb~1#3NPx%oY$n zLn$acPLkU1UL1^`=yhpY#5ky|Z&wt7*vtTI4QI}W;NV!*314>LY!&Wh@!pu;O*=hn-!Pf-D;dfK^V7*{TAo;EQSu$bp7K z9eN}~#|n9KFJd63cT=D*)r#_D2!+=!Z8xLsS6UTuEvW2%46A;Hj6>W|6@>$fAkZ*<%%X_iz`ZuwUmBvIY1(j_iSamC899HF^%ChQE$OKzaBf(dXTD@c|x|Olj zBwNvsShCem*ouDY5?1Fr6Pe+Ba>$v)5FF700^~-+{TRsohgs_DEkvFZ-lg~qknvkl zwP=?V=}0D;V4@;T`Y7&0lTw#3gxU|wDX`Fc0%{o`G(TF}z4h*%QN z2Txf2v%w1Dm8xD}i+C4QcCP@@yh6qyUaBf)BH9CUh?WD9b-yG-0Yb+=Alu542{~7Y zMtmDoS-xTQBI@tnLZ+~*DL-Uc{UKy)=>6qUqymr0&&pb}MD-zW$@gB^iVmD*Nqk)k zK*TEqd9xv^5aAp4MR%>H5h2)|xyI05c3uS_@5OpIn*~ETjxcnfEVM~r=tLp3asWA2 z2<;;n3M}LZYkczG(hJ6dh>JmGdka=&g^aTmZH}-SQ>zKKq9kB7rB*N5icWM`wW!r3 z#CcU!n1~hxhL4Z(3%tDO?>*?%p7iDNYKp^&HuU(QhgEqi~N7TFUa7wJgaXhry?T^@6Bb|*g5|PM+1--(VzPb`rp1SPa%*K&x#4z z`;+;=gtF2Gf+5VC^VioIq795XJ67uwUk>r5Kpy0od=LP!$CIRaF7eoT|nlE~$#T72J_RCLqSDdd=Ju%uP$GO$bs2u&Dup!Z_OytOJC0 z6NbDV7T=R02~;>#gCb_43KLbBh|0=D@qk1U=Dq}RT7!(4o3ceAVC~clkX|8v5&b4_ zFx@7g>SlsjMHt=&(`W3Q1>FF|-8(E#A&?VKzX{pfV1U6qIUnU=C{&&%hat304Vhq^ z4aY7MCl=?^Cr8CZ^a+9E-cd0TeS^m7!{1#iTHYKE&0j+hy5c)6$ix(0q4}e&rqQxH z^G7NU`h$={|NoQo>%i=aUU`}WY0P&aE1DaQn11@)`R~`*sYMeJN+!C(0{r|zd6_d%Zuo@`37!z3V{lR+(<9mXbNpj1spX4Qf$6I z+!M}G%xTk^|0O|i|J{{)NRko6b5+rf1FQE68HZTUHet{FTR`DI~SRzPSc5m60n9y&b8djv)q@# z19>`&?<<4Y+Bg|G*Y08}=5E@jMRX%}B4YQAS^7PL>!?|u7P&k)kZ!}t0kQK8FSoRgVRfxm;}AF0sE-oFQ;%AtryL3J(SO;Fh) z!QF$pn}9f=?qZ08s-m~#NQQdlS?ylPW2*bU6LLwZ%1GuR1+#I2zN}_3%ua#|44s-V zt#S}`sufKEAhAN;!Plq~zk4s@Zcu#*LCR}{U|_Q=qvLTKv*aexp@S*$}|)TbB<^BJT0W^_Ku z3g}f0?;U0zQ~xZYDTmd3u(Dl&p~Y;-f(!xTopFs|ocpPz`NARStB3639m)_O?mOj4 zBOvEq3MXi&q$PL_QJ1ty+rg?9qP275#&-PimPsR>73y2di2t z*3QjurfHT*GS;J$--YX8jfk!PJ}v|_e>qkUfygfWM;VHgm@Zyl83ZL72pK_~ zQWc#buZ=8Hi}%2$C)-=vi`$6U*cJj+WNyppHWm|qzLh3YuRZKDKnSXFeBfmNGA z#vvZ4s&XRY!hZnzVeMB65}7jT~|itZg_GBl?Uy1jrn zK!^qT>?+GUG#ip}UX)?A9;|E=VrVlPvLQo&cvq4}FwVAaX})j>X5&DMM;i({1ly4_ zOP68|NOFzfbN{9hkaM2H3A!hV2MshIb}!o{eKG{AT8P%pjT_tV$6F@JSdUJA+Y;$+ zNCsQ*Sy0*ha;%QBt&U~rL?QHv%U1?Li5^2n5PSX-t{1dd!s=eF#vyK~Rb@xS@_z)P zN-W|`P_2r%7F2e!;I37wSCNg&05tj35OWU&;T+9P4$RI%8^`;Swb9b>cUpNGv@{m`)Lm5ng`1W$r2*^3z z;RG%6gY9cFy{Fk$Xp_N|W%m|3EM>{DV`Kh!%OoM|(aCX1B3(_VgX3^7t+YAjT5jiA zzL&urc{+{xl|fLb%a9So)(c!f=q3ZJbF~_WxTIEyod`yWhV^o zZq(fb#2$4QL+n)*-DK{Bpi>~#n+)V3)qURyd045+NaiX9vvGocRLx?T?FAJWB275v z8qg5{?wnZxWKw;-gZqB<^=^Rb{qDz_$GuERqUheyAwz=-q1y|H1B6(R&%Cm{L$e_n=UpCFQ^CqMA%@~?$g~Ur;$2A^ z!8qHxrTM}kn2jYZ9&IS-kSm4IKJZ?K07oCI6?O$U4sT13cHu>l6&zE zt6GTG&W#(}@5fsv$ykq0elwE9d`JdI-bPT_{Bo>TvaMESXiXvXiOW|8L5Yq-Mi6gR zMSCTz4iz#Ear!^eOUayw-T$eo`b6vxs!0*cL1iZk?#|TR1jJT#7ej1Q72Q)Vgy2!0 z)q4u$ZZWI=@CxJ}r79ztqZG`>3Hm-Yi($4FRA9IYDy{)-E8xzV6+i}rxb}8}0NSOz zHD!mXc}@A_&gN34Jg0u24T2ajQORd1cA65Eoh0WImwQR7U0Z1eB3d}Pvw(Y1QFPmQ z5TY)H(47Uu0YWV3`;Zs4F@`47J&N8$#%?>pawu(SdlrKud7xn#1jxJIG=g#NE|%sC zhoDoA^2)a?gDDW-Ue+1`Ij1|EphbSLeRZYxG}{X25<$wcdkY2z=$E~J$<$6U*qJj+=boRg>1m|qzLg?b+{f_SDXy2-$5Qz7FJM=$l-QWmlG zKT}nQh@C+-B;s&T*$IQYJ#{w$@m5ta#5+~dP3Ay`uH;$0$v|$AXsbWG0=ZR_DI=Mk z6wJm6`gS#oVYU!dU^odXt^pkZ;Le#9K)RIp9o#;h!jG%7Z3*su^^uzWqF5YLo&`M zF0kqeR<;Q-)RztEl_5a9D@h|5XIr;4UpNG_F{;I*4Fw&tqY&B$W@QMFNix=>lV86ifxSM-4_okbc78clrEIH7 z87eD;K5_ZVASlsl$Oz)Ts%Wo-)v`jyA@=^~dMOzc@g}J5MSKXVuK(i6pj)2K@4v&{ zhPs=8c&4ft;<>8mp0X`N$MUS+Qy|}{?)wPxtx}bd%!)+r{ZZ~!LSol zTm#xxz@0NIfIN!(+S>^NxDanO<)wUqn%9)}pa9*EBb)b9l$`o~HV9(CL?xf4*l9{s zc9NV=Tn;6v3vIX=h-l&D&I0ZcZ8*AZ90|d-649Ln!~sGq=#-EbwK0ae((Q=eM8CW9#u-(Jd%fSl7EPS7Gh*uJjw z!rYX>lx6o8IxJ<$vF|j^GD*mKbaHH$lMkmrEk|t4!!qcuiCoM6Jj($Y9F(Wim|qzL zg_;c+LEKOk-DF@DD`XsE`<32gxBeU4t17iAfj!P z+Y7k+bmHmW@m>f{l!$IGAPx{>K|U?&=pC93$vB_5!0J|gQxjt7J{xi;Lx6Z!l14Dj zwr**@a0q6jU1xcCy56QbgEfUmn_Q=tZE@z zJ2&pNrdcM*SdUJA58@AdeUcxx;9foYD8C%5&TOkL8R}LDed6+!K~SP{$Oz)1s;I|d zRZ_?}#9LKWqW|ibYA4{HJd+#9p@>I8buHpeP}y^HMmSgHS-oCB-c{ZA5#&9Mp^O+x z!tQ-g0{WbU0XY)pr~9vPZp*W#d@o-hohPKp2y~y%N=LWHp^ z!PYtkJ%x61+X$8?X-i9w!LvNjsSE<-o%oGloa5ZmeBltZ3fj?~hz{wa6o?OW^mbh! z=fHzKTBH^c`eaukal?#dFlE`jQ3fNScN+66gP>4@AtQ*>s-i6vR{aVYhj^~4%8iH{*H4p?9PaN$+zF~v5zm6k zmVH!+=HyvD+##>2?)y&2>!M4xal|kv?A~VwpwCGdkR4@y2j&%x``s#~LYGPqeGXq^ z5^RpI&jvvZp@1<8*s2ALF-zs3;`X3!oRK`2baLK8L`S4L;a*X66wk`gszT^M2XTN9 z3sO8$mUrk8G>G%U2dlkcWtRbl4zeNpG6aZsNH>CUHabi5g+nkKS5hJGnsp;%XhUb3 z9t|WpVE8CRM}wyj$T{L*kM>F8K?kkt3ZX4#Oom`p^KR|jkg)7N-ZDwXdUWzTl1NWO zGB^e9g32y~9ILBrt7{p$Q3$=4e`OGqsQbUc@mhj7qAJ=fVb!USafth>s+@?p@ZW;F zvMl0CQ0SrTic>Kzyu+YxN7W6)D*C%27Yxt6xHy@tV!JkYuf0^}X} zjbNPf+|qpEkQ1p4+R>eeO9t_Qe$xoZIq(n(TBH^c`eZ)67uiUGmR8yvb1jeZERSXIM4nD#eq|68D*Eqm0GA;4s*1KySUqSR z#vyL1Rb@}a=^JoYW<{I}s&x@Jg33-~3{5J84s;L)2(ci=HD!5+9zlaRFMP0C2v)XtFtn5nS(G6_yhFMX zjI+^MnlBuJ+1QZ^dDpBx8ABU7({yYg$;rw`;aMXf=ZHfbXrCk=bkLNp5ZYooWC&KZ z5UrgXH=Ol~>MujHn{LU?K_e$h7WuHl>ru^Oa_#h?B$?>y65Ce*tENYZ;M`td^j6DPu zw+eM;yP$j3>McZcM{p-XlY!@=Q*HVK8r|bjaj3rL!G@AcH%K z2yW(trq)^LJ+z(MZm=w+Eo}rCoX!JH${;}A)u0~Cl<+y{K4`uY2qqqr?M?)`A_eNF z|KNN_YEl=-IT&G&7O6#qJ{d^wS+*6>s42_-Eyt2$e~{Qe-ZDwZdUSG}mNaJ5>EI+; zODk=Txt2?Lmdi4@B2TAxzcL64br>>&c&#ehYGJjnka39R|4~o;84){gRn;S6Z%~bi zSPCjTVW;BeUY^xU0OSsFlDwGrLhjTU%82101nDv{TeZ6=+X z@^|0knUpRk$Ik{q3@B!@xKYX#ow*n@b`ezED%6>`l4pxry@iPGNG<_zH?JrAlG2aw-v|Ec>?{OO73j@Z&9$ zgsev=$6-lhES(Nch`F@V=9p_aoo5-#;EX(-{{G4!DAZndMjJBJ`aeCL(MdD4(X|wy z9Rb%s_@YHDpGD(#E@1aQZTFc$I}+ZmhFRVh@gS(Of;tt*^XQLmU5k8|(q-A@RD4s4 z5$Z-CBmq)@r2qs|>-^Rv92J0I4jq<#$>>O)PA4#gk_IHwS;>UtlnyKbLS1=46F|rI zl|b$_qi^g?qh#G0Zsj8&=(D7{w#}S^!}rHoy@)D*q1Ae;DYFvk*IeTP5hsHRRJTEu zMHGrg7dYgW18EZnA01A+5QRFvMG{!#&!V?B30Q>)n*n(d{rP9K@%D12HX0NG6OtUJ zBVrZirUY?Gh7!~cB_CtvLh>{{Lx$VCOfrTq6c*$B4USI(c@h2AZ&01Bt3n_rWUf3F zkRi0qjhPxd_an^bbeK=u7!G7#(Ba^t@X!^zN=%z0x}*Pp#%n!g&?!SJ@=PuaEmU-X zdeb0$v8?2@f5WaPZD+Ip#Gu~4{FHm2Jd=0I0TBm-Dl4clfjo~!wqlXzQo1a=oQiiz zF+$yFQUEEyQUHRfb&e-EDgeP8IxGW{(QtMrFoco@WJy^vAvvW3OMp;U4$=hB!kHGx zyv9Pe3Y2VHA#|A;zFs%zWKDL9Bf&Z>5Su-@ET1^n%4uJOKz=RpOkSzT7NXMrdb ztr5to`26T_)`Te3@hy_TB6n^TunI}gt)c;ld#l*tOzn$1byW!Dgv^zv0y2cQxl>bP=T?FFyb@?J z2p@bD9=f7W8-+GUbjO}TD1!|dYQ59XD)?3b(2js>R}XyAB9_h@D(v2;?d-Dn#GoAs zZ&$-C?~8a4R9Qit3Z#0gxEA>?rOUF*sraT8Bh-y11&{(P1t6GO=Xipn0uaoh!?G_K z9m&(_1cp%3fJ8bgnUI{)fh9obR&hWRKnv$eAorRP-6~MBZVi`i6?H(+XGwK!n>hss z@yA&`eO6(b+Pzi4U%%!W4~RG!R0#YwsO<6pQ79U1YXu-};^3phX&0hU$G1oVi`=})Q*TD`4}@7lBekzGTh#+f-!un zuo&lv{xlHx!eCt$0y!ab<*9%Sp>1x=)Y!Q)U_PhAeA>ovAp3$22OoupuGm##+8ogx zJ^xGQXBAyCG$>E^J0Q&m-Tc7a|N0bOn>=%482N#vDJ23e1UgPL;foVdCLd{>iFh7V zkwn;9BvRy9{q6}2kz!4k5qyvOqkij_p#qRFp}+i#^x;zjJim~9YwVAFN+#rlz@4>J z2V_i(7?(tx3o1+p=F#yrBxuZH?YIRV)99YTy~eV7FqsZ_&MH`i^y#c>0OFoi0}^1< zYm{7oY=xXV5h^>P^FjBqIv|*zV!q)smAYAl5r)t-hR~dGyD(V1~r1x~$BG)f;u!kPH=oVESG}zx)TtRYN@Ae>xuIgP@&N zQwL;53mDIexEfTLiZFw;kjjF_4A#zG;4y{nfjnX?lhYUeVCNjjunOtZf!qMZJ&;Qh zVAE@q9E!F=&Vh`|PV0Qofm{a!^Ha<>e5O*jOAte7o1_mHCDPDAC5Q)_M0_P;h$!Z2 zP@l~kZtp;53?IlAR>p6Eatx3dj)JGM7z_ovj7)xe?~mHiiSa6?8Zp zC_HqH?SAP&P{@V)rq@Cra40}I4ReV1EB zYzrzxIIOD7>L9P`;R`b)<{ik$Y)WIIxhcy~0SKngJ&+sXaSr5W@gN@r?W~$QAj?|7 zctymWpu$vy8Ki|YFKEnQ?d$~}Q|KPZ)5bD6ec=yw&VdZ8kUkyA4M5xjc~$~!dX17p z(N@SgkWtx1oew&Y>wsW>ius1mRO)tf!4TRe>B9|)G;~l2;<+XfKZ+P4in$upXKRMr zJCGT}2eQRDr`xB2xM!_(RS4vS%$27CGK99wZBt`sYr%Z(hxxRP;XwFspzzQYkscOw zAY)fpRtRM|NGMgU{#*UC)DdAZUj|U zP`d)De(-!O@?}bwWtUU&IVnb{8%+uz1y~9|FtyH(2}cDWm_vtUMKW5??gWNV(tw;R zOC}_zbYKY(>dIA`09rWv0y)uG=-cBc*@Hspu&D!rK1-@=+sr9Ah(FG%cE_;Z+=~bN zwd#V2+e91)Do~vU)tQJ`GS2=8?odbC=?XxuWEMU}gxA6ys{ID3hP>#%ID%Eks~M0N z(VycV_>ZK@spRdxgdt2@G7&vu6=tvmaXQT4iijck81swCbtbjla94l#8gSICsDnn?4>@&eQESS)BfjSVJ zi}lSp=C$kpz#BJ(*CIpn@~r)so$UdDI?^C~F{k9Tt;4Q8ZI?yFa=Ig8A2Q6u?fau!Gz)vbRakv>zi}T z>%K033U5<}+8&CXLfvRm04cyy0D`G?PAxbp0KptOEC-U&u{@nlUhss@yA)!?iJRX zd)a`$LCrND5-|=cP(21!BufQL#@X4x9qLGzjRKH%@%bqt>=5oy?Kem@TQU)oVijhv1aVD<5)`)2kbI2!#pF7ZI&8RW7Yox1-eqIV*g1!L z0}%HfVR;IHoOntmWbd*83`*`?HZX)KaEi(h+90P)Fb)eQ^jM${>h<7G*{9tD^kPIXC;WoGL)chsTE>W11;#Z-n`+i z9^ZhYgS;bs$=EqZXaf-Uw6;8jKu$c%CS>nO2L>f~PCE=?3Y?-cgpTwz6O6-x34IW# z19_C8(1k_j9P>IahmMovtPHIx9y z0;i}9p`-iQ1mmz^LUDFD5F97<%{k_EM^7FKZ(D|r6hcRLb0G_ldUUUexD!;gNF=P& z4~JI(G8r5}EUT(KEn*y0h;Tzy?>0p&5HwP)9@AignRj%f&^gofUg}T)f*Ey>?uK}r zqq|u=$Ol0?OP~(Oxpqr@A!4L67-K5Jq{cj{baWpJ5hk^EN`nHk>K@&@#xgml5d!R- zqZ?MCB6M^&0CA7*LkaM6lr1?vZPA>g8^sQ5nvU)|AegdZzTq=f4ZAC02+fsr>mBu3 z2`$$bS`WKUh$u!i(1K3qUmEV}F%396$UC}kjGc2-HUM!?Wy@0t?3Ipr7R`)^h#Dj+8zCa=RibYeMO+K2O%eBk>O(};X+=md^QM{u zcxTO=sx`}MhJ6(%Q9V}OTC&opi046dC1R^i8tqnn0vS^)y2)FJS7(cHidq0tk|3ru zm@+2!GN_Q%T~IxW7!swQ%lHv-+r{Ce)&K;(x~yfTUabRyd2==eW}%iV0700+5wWaF zCY$nn5iRiVcB~ta)48zEarItUav&HAJ^F5xc2LTpIabvrYn^$^7~W1L9j6!tAje`I z*6b^+*;^%k#cTGJ?OIr+N@gK z+7P{tZkAn=zIEqR#Cj`cg{t2;vj(T$tikRw%$jYj0+4gD?h)_Fjt#L_Rb_~XF+riR z5TdiyBeENf@S7pwEGhRlQzFgz=oT3(hv`Y|O8cZ3JyBSo-YA>h`MGT43 z{qIM_ZRgNQtpNynbwtZby;=tZ^X6;{%t9?!0D>@sBVrkoOt8PWcY{d-ayl3GIj&-1 z$$?<#MC<#mRnFG1gHjI7v8pav>&#om@U|Law4GD{vMknN&A!5#-BsdOyk_bC2dh-c zY&d&D2sU?)_YKIIW7y}oIu@232!?Jn%?eIQl;8Q>nyuck6?I0RG|#9!tM@<12hX1F ze93>m9UY2%ozmGVmW5+pp2<(wwr?Ga!HGO;$}hok+C*FJWE-s4-OaKqULEVPxFu%d zeQMS)lgPC?yY?UKHqtZM5NJ&puH>2QfZp61j?F78M(~{)q;p2UAiUyh`8-cI;k}PLB~c~ zR=OqD0l~aEeQ#OZRwx8QsBq>owMstNbKHAGJAsm8(iRa6x$e4!DHnu6^lL5fBe6V| zr<+alEUQb|y7ZPeJdPF#D;G2@3}G$5!djk@p=Z%6UdwcQgw+qqXJ>0xD8c8>`y7Fs zc?UzTyCq@D1!3^Lrdv4_5mVvZBCS=eF|3{2E!RTc@f^3twPDC}K{vYl;%R(ep5A9t zoq``yJN|1u7V{!%pXOymMEuu`EYb65v;fbCF)h*PuXJTHO=@cWTU?UtD1+UIW5>S` zj_hEUytP<&&Wnt-sxDS*<}F~h`;<|3o7r^|=`9Wk6^d=D&W~0wG5y$9zwuoy*dBF1 zPc_?(ICebMSS?7TC0ageko4YZXKh|Q9IK}ph$pHlLtK&GOYTYUMZ^?4 zS0_ZjqD0?Zig*`Pk0Q1!H~pakOH^G32nlB1USjQ%GFmgIvdyxZVPAAdWncAJEol`? zJ0cEf6-&b+&IFa6{Z+BrRU-O$$3nb1TZ~iG0+2lk;!uMrV{(Tyg)*`#1=SQKO7BxY zB5pf}PHGK6(5u&4eCpLYAec92Q(zWqxdIS`85|MItz_~j&*VnU{~z$Z0Xdxu`y5v- z(ttS-428w`Zbz)b4oW#R$Evzytut>K!&{#&t;~ROAU$Fo*6b^+*)b)4#cP({n_!hH znQiQn5Q5E}<4FT@<{0)lu3}-yfnaDw)2!f>+zBe116#dgE1HNiA&gqWyAtH(Ur^oX zs>lZ^osFPHIC_H0?+=tQlG>M+v_Zf(LswzVSdvY(r#td@js)UT@ zl<1pd5if%3TEvH-vKzc5si?F6?t$-3m(%1Vdpl zzFU*F4Ld01&>XAklC{pfWejf}y0kI_%7L_rby%~nux1C8_!X~NdVhjds${mYu?c|9 zo#P?#3Xn6$7|L-qCM-D+49#hp6`Yc5L1lAbt9NWg6LBDf=kl!n)Dq;G-;4LB@1t3f zH&Qwq!HsaV{T|ry`;*1E?@t!wH5p_0{izX*|NaD~9!;%(YhFsRs3qa|C$<}L?D$e` z?P}jAv<}^G9$L$4?W|#5Jwt|{I?_ASE^ayx^?(q2^5SGucHX5dwF8M{xXM=Ld(y^O`)9n-IixRh1!vJwai^2Dx*E zLROPX^v#Zlhe35B;$=|Tjo%Vg+XW%P%xfWQS1YeIbZg!`%cL&WW1&*jV>PCwE6s}- zNgpKdS8XB=1eGmtS*#Z1>DI)8yoy^)AtD#FD50##Gx@1MOm(X!QbulFLDfs?(p%P# zh}+JjlUf51bnKoMpWd?SfMDL7zPBuHD-;4DR5){)4kVuwdAj%TBLX=;{RM_xcW1(s z3&J3lXD#qKX=3cIZZ^%ctS)8i(p%o}_@MQ3N>d1QCk$aNzrtGX)V2JI*D}3*!RiO) zvn`M90etSfcZ=Tua+1SfuDgD-1-Y{ahDlAgGAkmc!uhE`YgMDRcCJ5L6Xy@&IR4m* z{*w%blvqW7nTa7pydmW{)(Vv%Ua9KswTSmYWw}9gqL6WjqpeTxlF8+~EaF;FWf2`J zQ5oW?swh>s2Q)d#Am&)@2_c}xtPaEqg>wFSQUM6UN|o7`;#?e|{7C_CMD-v~=Y{7| zhH{9T13_3hUBThLwn=_T5LC5A+mrs=`8puOfdzfP5>&Phk1}n+s=`*(_poYL;xeqJ zf@(>`;GXVlAPT8}5R&Zh{I@^a#8sDirr^GW0pUMis!`F+b zzngyevJhxmLY$GO_aE9bhChU|m}k+qwt<=pS(1QXM8D1d53O~T3j&i9GEX}-3q$Cd zJWp*vEI4o01?rr_fV|I!zY()@Q z-zW>+jTn;2a-}R25ZnGL++V1#ZUz0QR6f7?g^WYIR#kj2 z;$u+JE+IqP@=Wfrty>SquBI$x37UQN_~t;wi=aYW@RR(NRfq^R*JYq8lHx1{FoOW# z%{gC|#A;2$rg_2;l1^5fO~YA)t-tT7eY)hCK)OZj2`XD{Sam35oUN#fEsGP5v-K5I zF*mt)ZljKhiKx;}M9s3IAGTs*f)q-EHU}pON5$^xiu`FHFQVV#>zk`A;Qv|FoT#aY z?7IM@X%pB;V|quv&BFWO$6}m6Mg3_Y$)BR;E1q>#2vjKK0`o^@x6u?>NA8`Sd8kz^ z#N}C$U3pV?=hC)_?}N%x!D?M0<7`EnDhO|bRrHHbM@pMKlmFrs;-ILWNB{C7g9y{jCf=W3O+?*b6SFt02$naeV?qY(NzncqbS%~3QKpY9>##SMn2a#Of8(R#g84+hygjRBgk1o9}AiDb&0jJ`66?KdYQ=k2nXin-}{ zN?w&M%6?reqGnkY2&Vvq?uv~Tj6M%3^w}p_+3LKAmifa*3u=z5LM-(D$gwmBLKDM| z8i6#{qu#!1n9vz~}P2tQ$>-A1O7-a7>257z#$emQ?UY<@yUl|0=*ZE6N z@0>|S5I0p-c`xE#P+f?48C3Sf8k3jhq#|0gW1(uz=mOu+|?d&;a%g(J! zQQn6@xFhPPyUwFSRJkdfm}tG;sRx7XoyGvoR|2__%G}D+$>=MCp!qu6!`UO^wyNS? z5g&uf9yB28P{=sM_o{l$MD!5?i2BrO0%C}$0-^&&Rjx$54yvpmdlm8$;()5?{jFPu z5Qg))5g;SVLU~z8vN5#M_ZmuKKP^vpivg&d2f|=3)0A=Nt@K7P&bqKPUpNG1n+rAO z%^9GXJP-zRnP!CnAa5cX!8ld6G+#Ib3;ZzDn2&20bSf5Cd6u9BxOQBhvt{zCD9Xn` z#~o2W-EAHnqRLI-%tY(;PCXc8?=%Kzz7oitROViuPDWoD1kKm|%X(Zx+)-7$FJjAI z0~CGp0YqJDH4brCRj-+djx`VssMQ3-5K#q0M~bT4h*S#`? zFr4EWkTGSUyez~$uFGOSBTx6Z2534Dguz^<*tqjndLtNTU09kg9D=efgc|ea4A5L2 z2!pvy^TGg-HxZ3soGM$IFC2meejIAd$F&PO7mJ%bOV9#bJFYL;vU3aD3iiMn(rz&I z)7^*YxWN!rZVDGBTCaEN!6195F+lT`KpvzrkMeXf`pO_^zFs|uOAz-}6(5P%{?}$6 z*C6Uqt8s`2s(Q^tbgY4BSgj@?hKMR4I#pEVUc`r>va6|IhCt{XynvLIg(9>N_u!4i zeqNsL!3)rA9teZEOmoJaw`Lo`I2~?jzHkW2wj65A`yxP#c_0ktGA#)MK;A?&f^n*B zX})j>mg-rkF(14x=t?Z^^DIFNaP2s~Vav`fY!KMZ+=I7%x=1!hmkv?orf_Yd^?Iis z46=6`12kU=q(y4mss~WX?(JV01kKlxoe_q50tDiKs_5sG8nYS{!Z9T-LA+EIorJKO zRLD5QQ&rKM{k06;D1;^xL$}!w48Fvs4N|oS#H6pC=TG zkQ#-pi1=Cbrx-;lhESQE0lyqgo=2Y=+# z{h>w`KlGA{6K4>`J6! ztCy^zzuNUIqW>cFSwx0RG|4LZTXoMOLb26PSVhbDSwtwd`jf1phJF?iimhmAKa0LA zfU=ObsQoYhj{N(ge)oWS*+%aCbs|UgSFCIW(qB6Tb5v=Is_Z}lbVl2{4cghT zE#x!0YS#6vz=_`+2;F~d@d{*AsJ?|jgc#g?OJrguE^{Bc6j55c&w_* ziHH|L^&n#W2ij|s;Ji$M`$(Dc7c`Aku;f$3#lPFac5Ctn*|EJ>qR!i^-=o$4ze^$O}R(5%S_@=IK&IOHplfFk1 z51It^Ieet7Y&aYg<_5sV&7-T>~9o59?EoDT8P$PFQv7qPCuTtg~ z;}VS(@n%7uH;Zw-A*XpwpXMEX4T#HQL0&)>Q;5jflb0pdYkAgolY99B4O~;&{`}pr zT#>-`<@qf7nGI{h#QrRz9b`u!shpp0-5I+iXI^fNTkZ<|u{@teKedtX$3 zVPc%WFm6F!`&f+IJ|_}Lt~U$vyjhIv4Qc0kvmno##kk(iisWWNo;QneyUR259*|LQ%TK;D|@tvvyB1L#k${%NyDinOB zsTKi}Fm4lqGWSO;WeaMBt`8km{`vx;LJN zK+bi>@-zlHl2FgJ9CYJ3lOar?yFplxyVDdQx@ZLCc`HP8FW#_Doe!rl6s1?9J=Z=d zh<~NXao0Q$-x?fug+OhzxjRhF1MyknxGMzueMJH<1p56&m_7`07PrlFXrq~vp}J9nJDI1{s#4d{UmyH=|4Dw&$j9 zL0%0l#w98j@n%7uH;Zw-;RYM-)^w9?4#a(lu?Iu*Kuc1^U7c1sKelBEsk_Zu2=rc< zj@21`r*lV!P8C8&-jNK2c%08eEXbR9i*YCZq=+{Q^1NA$>kVn==4L^jH;Zw-ofXN= zf;?{)<9fR#Z*zRHECj;4d{20%?-g-As1`(A52_6jFM`T0tu`4-aXUm=RtO_`LxvT6 zI-kRKurEstNQ&4(`h_KxdKLsRIkAiwmSmOlPr?)ejS5pN&)*v@MD4%x><`hc9>AQy z%ff-c-Nv#YuR|@yC4!fA@#>tEfNUs)KJH(ZAwXPL7UacjF}XxJF(Z%*jhW7_9T@_| z-Qx>^b`6tLLqHBR9y$gNKg@D1kQ-&8tO`IL#X9;!?X^YYgj)d8Ce}THrC-FMpt7qH zR^192ht)t(Wm$D)Lok#I$FcyD@@*j)3M|y>7(&=d^@b&^F%6HVWm1NY1LRJ`$Dp#| z!0J#TH z&!goCRNIPMwp7uejE$%}`oUd5RszH_JO3*ktfqsNbv`6R!wR8pFUe3~p`V#804Wm- zIf?}`lO0O|2&`wbSuli&^1fpr)~NEch<@A&Q+k-~2#~#O2&_*71mdl#Dt97AT~Djo z`F0Mh&e`fdsOMB6stAN#|SiOjT`44X4i)*DSK?G%ji?;9u_-n@a0twcTHdqX{ zYZXcm`&3ow7jZbKED@|a0|ZtBL6v3I9UygBb%|9iU3}4_R3(U@tW^MCAgY=%zCeO* ztxCdN4jybiu?!t%LzZM{^$URPNeq|r{J}|Pb2~8L=gBc+F=Kz@(_)&Gr*mEufRu=Z zZW(Y;4vuC-oDV7+-l`1k1PH{Aze%@&E)jczs!znxpt9Vj!g-kr?%FFyU@E_9gzMHv*bWpDHi%pNdZWkumnf+qSj3i`ke{X11#<* zm4!gq?N_umC5VIFI4I?3fh>ElGiusp~PX;+2^)SXWYdKS?E za3?%%x=iTeRR^T=!z?+Fdx~Yo7OMc{L0Ez#+ASZABe!^kK#?RIoY8V<6-bZPhSoWX z4;FW8E(8KYj-084<-jAH0m zS?E>`$caM85r(c5Qi2%$%{bU9Eh4t6ihRN9UWurnwp7mjtpLQ?&YW)~6e21RAr-7c zO3 zuR{wgZ1=`+BwO&MZp9^tLw}1NXCoq(g38X|tq=?gB>7H5C(PoM&e}bSU7J$B%Yw9I zLok%X(kj+~c-`Fy#yOcR%@+>AtWIXv7ZA+kvxsI1)>GLmWf=m*n}S9#PJJ!S7Y;#P zXS8^NBu_+RA?{nB1v!hsLR_Ab)GgNfl^{kvT4h_(4MCr&6L)0XjCCI!^1K(r4X87SO*AAjfHqKJVu^~#zNegu^?xLEyU%Sm3Zbf zb6VB~Ah4d#W;v0ey8wYW^|xv(&5F1fRCYQ+^dLmlALxQSEoRT7--%UTd_GC!(zV-Y76mZ?2J4SjfJ?CwjgK5 zEX3uxlX&hmb6U&=Ah3SOX2A@_I_V{dtE!@jnUqauz4m7OG50h)Y#4{=_t;sp_x zgUS*O$+Oma}nev)h$OWBCn=&woM0QY(}2WUcwOid=MUX zl%;ej;#E*t-{&}e`x ziMSk8HYr$*38ea&3(QthI%~HrW4qbZM>2F1Al-k@QyM+;bkcy;tyon9f?2PaRdx2? zu#AmlQCITWmQpxw(QOf7JxX5{d4{x&z$5puX)nWTmS;=g=`iKt$%9BqBz)4N3_de zXip)ObOVrwv(a`;!Xb383VcXtSIJkn=Z%PCpzprr=Ifr)e($f%SbhOMCy*1~nj0XJ-JUKO52^ zLx8viWRO!p3u=kloldnV*WZ8yHJBYYh9(09;C?_01f^Yg+rZZu=QAefjUwNAN9(g(w534qXjKiuosO%EB6d$l^iT=#?Z){n^ zC#|(be77OaEC}eGxC^kr!J{}zes}v9XfZR$Sy=zLI$(n;0t15>0UR9MH5l@23CJXMCPYr1m2Z%hmU9XF3Q+>yX z_$a7s#31Swh}Toi!nBJI_;UVc_lQ7BIpH)5GirP};Y<7CsEg@r@y{xW^fToZ}3j6^)0^0SqD0>LFw^^$w;Jp?u7yzL25IYzT&K z1>&a4ASYD|a!zhQTK>ML4JUzgh}aoac0oQ$Xt1gl!JiG4QkTjiP6d_q)<;%l zSjB2ZTPUo?1kw^MT=DBnF;u^BfXmx}J{87~d%#5G{E^{Bft z!$D;?jBBy#P)M1rsEx-2T~aGL7%(&~5O-^~An*G$7UP`R1t4=0#$Jf{M8wmevej9T zp&f;kcSSr3DiECqRTj~PK>VEw?uwxn3vmJElnq00=QZ%B!uSPPl9UjUvsGg%Fb_^% z7)ni%osT*op<`$nU$@jqmXWE7}m zgWeR?xpLE42CJ(8xfk&vsO;pxD&?yINQ*cCi~F&l1^LNaR5H(eJz|h^%><}lv!|v4 zr0=63$QmqeYg&-knik`H-={2*uF5m{D;WRMU)udw?oa;0U;JbA-alo)?zC8tw=-Fc z`y*})awcWjgyeZ^7G}lxa>}_bkg#azaK+;3_y@48OOqm&gUT)%SPdy;99C07Wv$v} zsHBhz&~Z>%D?}E2Q4)Z3DN7>|SoaBw-{>+JKu#N2CTD5@8PSmAX%Ry$=)GV_Ah4>w z?pZVM6%hDTq8e_<&~`TDScXosAtwZ(KT~iakjreAD;ete2hq2c9ubFv z$|m_BR;}5PM}f2`gz8X|p>j54k|301ERfl3mQ@*A&xWiKgdFV(xmf)g_h!kYTYd2NsCis;caWcoS51nqW1X4T)uF zMj;e&0m!0QFJ-e7fUJr2dNxY|2{8m>XuPk=paxSq9p(q(b zKhb?Ajvlo7bnj&dIbsMo!mLc{?35sGtEzG!;?N(%w306nEvwZytj>c9V(&lkM3fYH zpkL$;A+PE>MTWzw&Q1nAmXv-1VhG|p1TplFBJ}Sdrh@2qg6MaG=+6owczg+u7aG?~ zh$)Y~j>lfdV{ewnF{Ph`7=n06GF{YQMk(Z(?Q7-~5X`{bQf*v1o7;z4ZWtc>!PN#dD>W#s&+}C7PVky6s%P@ z2WnU*Dn&vtqC_Q#ldAd#;=N2_^%eks$UG^U&ASS-X;*bN>#ENF<5<7Dm$J`mVBc{N z-+h?q+iM}ZP@->{=vzyKQniUyb)iD;S0-Ah#ms1~U9u`%CKE~A8^-^$=;sLKN`{;Z%9wpOi)_x0BH z>8>qn97eJ{Pl{(R1B}gRbme&yaI(3dMb>LgX&p|B<${vYXSD}1gmX1SzadkxEzdB5 zGNFCKNRJ#&{qhVWHZ=IX7XMx?Fm|Kiznzs}5U!gx>;OuB;=~5#{1A#`WlNA)+1!h9 z-y3sE?{+MBC6Kknt5~5A`{Ri&*~*Y#O|OP6A>3VXA{UFf_08n z%9rgd5C;ftiG30t8pKP~V%%@`mW60eQ!m+Y_GIW%AruZEVTYz;9FQ|*p$o!|4CS!k zd|TChE{2#odTCe1=LBQ2s+0F8h%>69k5FJWsgQAq!HPcVm=bg>&z9&nli#|rMFqiz za+e?;|B0t}hvcK}6A@2?$`UnZwIgm1<@r20(;=T~NHY*GQ!vP9BM5Wmy@a=`Vb1J} zcobANa>OvDM6a3X^#Kvli{pVrhiH@8y%5!v=0a`FR`I!@uQh1u31lCL=}J)t{8V?5C=5qx5FZ$oXHlCsW}WNG}n1h*(vG~HzVqf)-@ob3i&yv zEcl`~Rvt_I5?7xx( zTGpbJA->nxzvI}yL+o()ETY%AS>a5@-s!~NiP-n097&v=PVDrW0{(gNQ?;}Cd6*ta ztXC5(L+lq-LN!=~stD#iAL4d?2K+)&xsqpcxw#YZKB&4RDa^U^BA!Fk zE!NJ(305gzHVKB%O{ImxqXXPR+PkecS7&B(h+v&# zmGWh00K@@8{ctAXVb5^#v=Fx+VBaQ_=k&vv3}Fu4x?7OLgWJjKui+Fdt&2D~sw!Ix zSOo~ZN#9F=y~0+#6haHVZx7=(fObHcF@@6X#c3xhCDQZon{z2nSap4q)NDb1iYOOj`2G=qo(P3n})LcAGl z76xI2bwLefA>Ir&3xoZutjn|n@ljQA%Rl+F5iZHo`B)o7lWH{%F%VTiG^0e7MdGF_ z1h{9Edtz3^#h?OryK>Y2RJS4MZMC9Zdy^n^6FCvcowCq7bhpINtFaJE4?!pvlzTm! z1&~L9)HZUnLv730ozl>Ic=S&_O>l=iopZ8VhGrE)^Rz8PM+zxHjQ;5-2g!w?Rm8TS zG66@hx)Gw}E@mMS%)6AP1o1&t@uP^*82nT2Jp$=fE1s(lL&gNMpe#RyxT&fN#2r=r z6ylMpD#s#T1(i+Tx~tAR{H>|k6vzV;?W*&FK2a;$Lic3|aXDN1jX-Xdg^GwN=+vnw zK`g6^RuZf_6fzF6S5-8p-7++(5NcLfk1B*%24pBeh-J_~+}kXJoZq=(kn?*TQ{rw} zgQhYAGMf#7^?HCnT=-|OPAZEcE(MkC!VMt^Rxw*qSz)!O?i+z@i}ibDp;8op?27e; zJge&n^1U*@>XjPAS_@hvU^-W;ZyWYro`7mTH8v^UyY{-EOodgKP3supYY|QFX2yd0R1o2T-czL7Y()`D)B+RtOiBxCC)k zRphHNt2H6qR^k%GJynsf#;o>*@K}jU5YJUbz8bT-5W*WJEQM;W{yCg5 zC5TosM$9VH&ZakhXH0YU6Uc0Ka1%0 z3hPH@DM9R*cxtKSzix&&qN)vyuQ3Ni2J}@CBN*Mu#s} zH03uCPeoP3;S032^Iw=FOf*XZL6Vq`rdhQ~Y+>?fF=GfZBp9a=4|zvt!RGP zDrPI{rA0{sQ0JF|Fg+(>dhA+b2qnc3%77shE+DHCOLa4Vys7bh193YAgM1WVHjQ-| zg1NIjx6Ag{quX2w;(Jw5^04Yv$T-AcMad2ddQ`25c!(gxGAEFEWuZd=Lu(2lM+_lH zOJbeF!VqFvCKlSZR|rBI>yAL~{V51Qp9Uj#kV4k{z)~ojRSYL z>TVojaQB+sjle{i1T*%n9I-}|%G0-@_ zqgVif*=W}kVx+JZR5m=edd*f;!AJ;GzASMIL5O8eAoCg?uOk`C$pF>?LXMU`%)$_2 zK}Q{HLlERn9JTxejZGQV0qOWKOAh4T#Nsul#W>&nC;)j7PazoEJx~xpykPnz-I0*? ziioR0W&7+vhPriD=(lMKKn{iFBHIy$y3`TRtyn)O3$69L4@2$+(jtz$S^@K@o~Yyn zAg$t|T~nfX3qab$8Z+R<3rvT4qIe5H5GOo2?Ft70LXL3igmp|u=8S~7qv6tAzn3Af zc%Pn}2<9%(KrH_$>=17tPOGW}F;>-^1rgiJYG{`N+&!qf@hPziMD&*5L6Fz%i*~wh zu^NzPG8M2|3Mw06V^%%JSGB>cGq34j*QWu|>qG&_q*!B4l8X<-P}Mg`dRcu@$Lz>Z zm_fQw>)QqH%T?vpYJX;O<)GSK$;jNahTQ&TFEy-?CNAR+Q+a#FO%6o8gKe#4;&il{GwC z>KMw&fFa~476&;j3?Y^^VF`<(gf4x^&fq|Xjub+(TL5w>)~E9H8UUDM^+X#)0m!vj z-zp2mTL5w+)_2N6u@rz{ujzdCv>hcE4~UbhDsPIo9aOd%K~z@AIIMPqD$8nGArr9L z52`GyDTTa*)nQOss~#B|RtOcWSB7R4@(RSqL1l?y)%w$?8df_8a+~Oqx^Kn7lr%{Tqmw%;ft(5C;WS^@%wi36^6bmK63Y^s(})guf=wDpkA0h`6e; z7U2TNd*ON!{rS!b5+BZ9QJ`f2IZ+n695e@VAr3mjE@7+15ZaL#LR+1M)aEM76}ICV2w(JR zh;JbdiK>Rf7o!0OaV(9Sl`j?p4&r(mhXY_%dcEdkRleAiXEMDI&(gR%`6ALzc?%JJ z=xww zB3VNaO8Zozi8NrU@3}xO2LO3@~pMp&!VN^BLg6;+3=Dr`m7ffe?&q&giGAyo(YVB2%5 z(?u*)ogIN3$uoI_vW)`Bl|ty_PlnJN3?Qek)NS zf;jlkBgwZzBJKy3odXaJE73T_KDDZVXg8>`h=!DC0%9PFnTS>9u>>yvMj^DUYjz_^bTW9p)r~zrw#ONKO zIS@3{lscj#gdwy77($;Z9EgJ}byR|Q_Ag-lQzOIbQmw`zo~ji^466&Znt&L5Wkz_e zRxcq2Uz9q0J*w4Yw?sCq5z?M|CTPd1zaFbHeD$goH41!PYlID2*(Gu-gpvBD`D>9O zgz0QV7z%k4%Yd*9sv}CWIgoX6u&<7&w-`c=#1QJ53vtk1LF<!43oQT-*T2*!q zK-8v0;}G|isKP{)7l>MwXaeGa61`?3${s{5O7s$9AbP_@H0vOWlxPxSNG)cf%wj+4 zto{UIDE3<>qO;^d2w?5(?Hv+qp9Vc+rwlB;3MtQuI3HA5R$T#7hZVx|eiTXwb0UUy z@J&g<8ZjmB;apH^I<_j(VQf{To!F{K@2p65uH^Y5TIt-v7uP}AyM-_Ag0gc9Uqrfu zem*4PdQjQ9UKI*ZI-e0Rgw_v3Xst4YrpQ8S1+W3HOTfqSOx`jrWK)K=6+*8FDAu4> z=DT4k7JX<7E7Udl%$Tj{vzl88Bg_K*w<#cg)QEo$;!%x|{tzk90a96{B&f=4^_s0{ z`q=6XTTx%IRm@hjiNdN^Q~zdJ#I>NZv%X5H)2!og8_`3q1aVnaGb=?C|K za!*1GHHpC;Y7#RyH3_);mHQ_U!(6@v_lct3GB+K*eS!v|bNG%5WLk;&oRXm_g_IG_ zT2R?GhVN2<)M16NoWmDGIS~UAd{a`ep4adyTu^FYwtCH0)S7Hnr0LkINIPL=FX##{ zt%$f0RCcmpHKUMmi2JIl9Ev#b7P|)(2t=`3O+Y+Q)oUiAnt^CqtzJS5L~odg)-H&q zlxPxSNG)a}TBsmeQlg)5W$EM3vY_j;niZ=B^;NP{#>8cWv!+(`&Ihac0I9 zWLt&~1LXf_?`@ze-L~|seX2O8>4X?sQBhGznsi8lhV-R7Bux^Ma3e89H@6uXoD&?E zF`(*lZ)0E5!H5wf+O(-Cu}cpsDhetpYN@EGsHmu@sHkN`Efp0N6}41UR8;&~d-J|? zap!zDXVpH37)PhZsIlf=-!p&KTtDCXe)fjqwN-_Qy^li|D4$oB=C=6Z()2>JsCQyW z7?TCaF|_IEdF7{D!|g}9cxNI0z{e#}{KF95lGvNyz)AaDdwpi62Q?JOtSV%&IjvS0 z96(vmJwFVZw~%}4br}+JUx0K%n~r4e>7vg<6uB2r%)N(1?yGPzVeJY{_sH|gLL4xY z&|l1UDDGNS=)-v&+CW+F4Sv`(y$}-hRtyQfQGhH%n~r2}(8X&DQS^p@VsCgz^u`-F zIk9$CDYkr@lOtrYIjtl3cyA3$s}Mh2=K%c4l6q%`gxnV(Z=p>`GWT?GX(5W-3n=E^ zLn8OBNN}4aIt)9H$eGX%{l096;+$25K5R~_2L`Js>+^>nCd^xC2=xXH34K_A3_zQX zWFOMSsD&u{P(ZN{JtX>Y9!_3ayQ&nAtt#ZcIjt2Ke1o!{dw$q6Zz1>8TQ?-+z5sa* zZ90;88#5&2 zz5p48HXX^_)5Vm9C~_~Ln0pV2+^@jNrnRd|@tswL+&8DS4ueN1>$&HLWAherPrY43 zLhcKY9ca^$%spKkScoF`0*bl!kjVWxoZMQwsuTx)qT!m;oYpmbbir^v_x#Xp-a_uF z*J4P>eF0K|HXX^_(?y4cC~_~Ln0pV2+z-OZgte=aoNr`}_FeDC@n0 zcx6@L-N>##|Gtp}DAPR;iX&DP1}l+aAn6tFmT+6fL*fo2T}+v)D#dxL3f_s#J?7m* z!uu-p*UeRR6XH&;Lhh_s!=cxP%u?$nR~Zgr8;81nl7nid8)8qc@>=hqb!&zvhd{5P zd{+5`;Xw%FsG8;3MW-g7rBjP>J%Z$r!!31&+5(3ymG+g^Eq=;T$G_u2rX#m(it?bf zB#Z`TG>1LI@aRo^8=?;ehs|)9WurJW)fm~uq4yb~cw<#BTfckX=aVSK+g~(vWm@AD zv!NF>)cU(Qh+Ygs++MV*!N1^M96_1Bwm1s0nydU!V+5BL!8a)82xb|iFW3OoYx_DnENv3FihzR%n+wU`s05`6?PbNS+9)QOr-xur+qe6 z!+KMIbV8eZ0$f=Wq8}NZ`Cn^gVbK_aciD+=$PTUO6xg zo$lb45C>ga%ewuTtJV1-SF7_QZp}G-R{2`+_aV#;mfrh$=NIDpS}s&vcl8`ycae$j zEfpXf+n2DWeQo0?DY084as)IX6thO*dP;p`W*U~}P<~SRiO*ZV^LeXJK0R^Yq&<4-eucY;3s=+N^GbXC z+Rqw--$mKb?YaZSa6JUVhSq*)!6)MnC-cYvVTj_Ty5_XrqwO~+li@{dEc4zt494cP zIJ)o5*NZi5tdDGi9bU?cTC-6rY|Fh?{WR(I=GGkUGA!BMhE(bM%WK|e z$gAqSjX19pn;-oA>!i&zmf3QJ=sg|h-=7TU`w zKdyY<`swGb{K)?Jq%u{n_bc5T)X0hJg95~RQx`%{$Bcyh7wnxQ5-uP-B6t0}NZ&sTP3-K;jwf`meM`ux{hmuPWFLKol#F5`; zwk9F&=Bh)8ZGWjz-4M4|tm*>dWv=S{%kGc%piDvZLhQ>`e);P_lKN1pIp-Pi%yj_j z$CmS%VI)}O{5*HV8q)uu8`_Zb2i-7&T>p{Q4I<}0!OYB1&de7fst?AXzTDW1N7Q1r z4t4fZI(h%()&j=YBFcKD57KLg)~GAH6arnyOcNWAY&_dxX=bb}7$!!bwuA<08dbQmf-C#c3jM z10aF7DAO4#KDA^JghY?Nb#_`RKP@h8NOk;$_lwe(q0Zs)+9Lm5@ykIsILP#+H(Z## zUR&X3nY?wZ^ojDh6R*ZF8?$JP$cjf~c3Ys|XLiCcC&Ijm7xUVn-ECIF4JT^TQOdqJ zl@Gwcuo?QMpY&5W^hnEj=(Sl1GsPoneWN=2ug0(gFL1i3)v>zYZn_xuFOsgT1 zt%UnQ(MmvW;2@_Wtk@M~i9;j3O2JWZY&*5^MRICo!(RsJ$UQX>!kJ+>cNR{V0}O|T z(mD3)Ti#T?(i^K+`a#x(AbKpWDn+I#odm*zNgkUpwGgOB)GlHf>JPSdK0uG8B}hEk z{4k1J_LLFvSQ9brqSOx89VKo#8~~xWXO(z)UBVnXJ7Pu`Aa7yi9A$02<91*JC$?Ih z&%f78-o2U#=mK6U4=qD(vD0Xnp*%EbNElWgNqzWxLeM-@GtvYNe<7qh+M6n)L`vAE z38p~~2cN^CGzWIm#t>QjuE(yX%9z9iLrkMgc%SE^}B$Ch59lelXs}%rMtM) zY){Fbl@C}H-T9kEyxAg8c$ zhf=O59ulrDpnq+4UVPrl4>bNsB~_-i*5~#LO1x{4Iv~D|?jhX)%~7I3K6aTHHmno3 zV026^I7&(kihdx>fV$LtI_B4e0a$P!sQ{Tqs~$Y7@Llf_oxu;I_*g0pqqt}p|@w1p^(NBX4}~jW3d1^ft3f3;(V$-qFer96d(7=RKG(^Hz>8k3rC4m zx8QN%18=`9s?H@+*L8?slFk+fQsU40wN+f$8$OCWj zrIsRS!C4Z?EiB#_ap|@w1-yBAD3A69)h*TFK?_lM@Ya~9^ z9?>oTFp5`aGSydzsRdU{+TpdMM5;SrfZm=};%2Ud>2!8Pstb@YSeZttE*w20JZ(UI z6JkM|pEp!SrLg10PaCe9dr@jr9gY&?Wf%w> zr!F*}j`@0621Z>x;zm#b!rK53UJLV6+#@=JA4csVcsa$Fac~2rcF5Zyq(qnP!T`NJ ztNhlG#uDa@vm?fJ0m2vPs`esXmEzK0ZZGAnK|IY>=McMo+Nger3%P0);&HBe2eEV2 z6#F2a<*G}FJwIdAAjG9ywFdDtS6x6{{Qai*3gStwdIz!dl~H{VNB@9TO+lReE3IlC zV*g)dRU;7F)~u=<;&iTBggEdAjT(jcDpzenJkM2~fAzh>=4(@Y1Mz*Xs{A$gM~6|S z(J%pVJy-2QyvkK~5QqL+Ghc=HI#=yLyv$X%5Z`=miboJD>sHkP@#e3$s_wtxUfe;M zLfwVvUb7UtF%D`NoClRm}tCP8)VrifVCFDc^+TUt8q(^U!kmhgHg2+@8;+93Xy*WyRy^ENRQEGR4juNRpbB$A9{4Zgy zV27JBnIuBo#ObJ;qePN!5mN`YfZAPp@LylfNQor%0Ab_Q@79zsz0OXGc?D;GZW={1 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 AX8-^I literal 0 HcmV?d00001 From 7bbb5eac51b0cba5b11d3f28fbe39b085c7f5114 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 8 Feb 2023 17:41:50 +0100 Subject: [PATCH 065/424] Comment fixed --- android/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index e910255ab4..c7f80f319c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -177,9 +177,9 @@ android { 'normalOptimized', // for testing 'normalRelease', // for Google Play releases 'goldRelease', // for Google Play releases - 'vrDebug', // for VR debugging on Pico - 'vrOptimized', // for VR testing on Pico - 'vrRelease', // for VR releases on Pico + 'vrDebug', // for VR debugging + 'vrOptimized', // for VR testing + 'vrRelease', // for VR releases ] variant.setIgnore(!needed) } From a9a45481cc7c31e9ad1673f5836feb9e87510762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Feb 2023 21:54:15 +0100 Subject: [PATCH 066/424] Scale buttons by 1.5 instead of 2.0 on touch. Not sure if this should really be a setting. If you don't like the scaling at all, you can still choose the glow style. We should probably somehow make that one more obvious though. --- UI/GamepadEmu.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index e8262e5225..efb5b6bc3a 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -34,6 +34,8 @@ #include "Core/ControlMapper.h" #include "UI/GamepadEmu.h" +const float TOUCH_SCALE_FACTOR = 1.5f; + static uint32_t usedPointerMask = 0; static uint32_t analogPointerMask = 0; @@ -134,7 +136,7 @@ void MultiTouchButton::Draw(UIContext &dc) { if (g_Config.iTouchButtonStyle == 2) { opacity *= 1.35f; } else { - scale *= 2.0f; + scale *= TOUCH_SCALE_FACTOR; opacity *= 1.15f; } } @@ -384,8 +386,8 @@ void PSPDpad::Draw(UIContext &dc) { float y = bounds_.centerY() + yoff[i] * r; float x2 = bounds_.centerX() + xoff[i] * (r + 10.f * scale_); float y2 = bounds_.centerY() + yoff[i] * (r + 10.f * scale_); - float angle = i * M_PI / 2; - float imgScale = isDown ? scale_ * 2 : scale_; + float angle = i * (M_PI / 2.0f); + float imgScale = isDown ? scale_ * TOUCH_SCALE_FACTOR : scale_; float imgOpacity = opacity; if (isDown && g_Config.iTouchButtonStyle == 2) { From 85ee85102a5fc4857637476221c59c2122710a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Feb 2023 22:05:01 +0100 Subject: [PATCH 067/424] Just reorder some settings. --- UI/GameSettingsScreen.cpp | 41 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2f71c2ec55..2290b5192a 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -706,14 +706,33 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) layoutEditorChoice_->OnClick.Handle(this, &GameSettingsScreen::OnTouchControlLayout); layoutEditorChoice_->SetEnabledPtr(&g_Config.bShowTouchControls); - // Re-centers itself to the touch location on touch-down. - CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); - floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls); + Choice *gesture = controlsSettings->Add(new Choice(co->T("Gesture mapping"))); + gesture->OnClick.Add([=](EventParams &e) { + screenManager()->push(new GestureMappingScreen(gamePath_)); + return UI::EVENT_DONE; + }); + gesture->SetEnabledPtr(&g_Config.bShowTouchControls); + + static const char *touchControlStyles[] = { "Classic", "Thin borders", "Glowing borders" }; + View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), co->GetName(), screenManager())); + style->SetEnabledPtr(&g_Config.bShowTouchControls); + + PopupSliderChoice *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, co->T("Button Opacity"), screenManager(), "%")); + opacity->SetEnabledPtr(&g_Config.bShowTouchControls); + opacity->SetFormat("%i%%"); + PopupSliderChoice *autoHide = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonHideSeconds, 0, 300, co->T("Auto-hide buttons after seconds"), screenManager(), co->T("seconds, 0 : off"))); + autoHide->SetEnabledPtr(&g_Config.bShowTouchControls); + autoHide->SetFormat("%is"); + autoHide->SetZeroLabel(co->T("Off")); // Hide stick background, useful when increasing the size CheckBox *hideStickBackground = controlsSettings->Add(new CheckBox(&g_Config.bHideStickBackground, co->T("Hide touch analog stick background circle"))); hideStickBackground->SetEnabledPtr(&g_Config.bShowTouchControls); + // Re-centers itself to the touch location on touch-down. + CheckBox *floatingAnalog = controlsSettings->Add(new CheckBox(&g_Config.bAutoCenterTouchAnalog, co->T("Auto-centering analog stick"))); + floatingAnalog->SetEnabledPtr(&g_Config.bShowTouchControls); + if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { controlsSettings->Add(new CheckBox(&g_Config.bHapticFeedback, co->T("HapticFeedback", "Haptic Feedback (vibration)"))); } @@ -733,22 +752,6 @@ void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) CheckBox *disableDiags = controlsSettings->Add(new CheckBox(&g_Config.bDisableDpadDiagonals, co->T("Disable D-Pad diagonals (4-way touch)"))); disableDiags->SetEnabledPtr(&g_Config.bShowTouchControls); - PopupSliderChoice *opacity = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonOpacity, 0, 100, co->T("Button Opacity"), screenManager(), "%")); - opacity->SetEnabledPtr(&g_Config.bShowTouchControls); - opacity->SetFormat("%i%%"); - PopupSliderChoice *autoHide = controlsSettings->Add(new PopupSliderChoice(&g_Config.iTouchButtonHideSeconds, 0, 300, co->T("Auto-hide buttons after seconds"), screenManager(), co->T("seconds, 0 : off"))); - autoHide->SetEnabledPtr(&g_Config.bShowTouchControls); - autoHide->SetFormat("%is"); - autoHide->SetZeroLabel(co->T("Off")); - static const char *touchControlStyles[] = {"Classic", "Thin borders", "Glowing borders"}; - View *style = controlsSettings->Add(new PopupMultiChoice(&g_Config.iTouchButtonStyle, co->T("Button style"), touchControlStyles, 0, ARRAY_SIZE(touchControlStyles), co->GetName(), screenManager())); - style->SetEnabledPtr(&g_Config.bShowTouchControls); - Choice *gesture = controlsSettings->Add(new Choice(co->T("Gesture mapping"))); - gesture->OnClick.Add([=](EventParams &e) { - screenManager()->push(new GestureMappingScreen(gamePath_)); - return UI::EVENT_DONE; - }); - gesture->SetEnabledPtr(&g_Config.bShowTouchControls); } if (deviceType != DEVICE_TYPE_VR) { From aff0b46523023a0e58cdb5df35de067cd14ef292 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 8 Feb 2023 18:45:01 -0800 Subject: [PATCH 068/424] GPU: Skip depth resize when forcing 1x. --- GPU/Common/FramebufferManagerCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 68bb901968..1e2dcc11fa 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -485,7 +485,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer if (!resized && renderScaleFactor_ != 1 && vfb->renderScaleFactor == 1) { // Might be time to change this framebuffer - have we used depth? - if (vfb->usageFlags & FB_USAGE_COLOR_MIXED_DEPTH) { + if ((vfb->usageFlags & FB_USAGE_COLOR_MIXED_DEPTH) && !PSP_CoreParameter().compat.flags().ForceLowerResolutionForEffectsOn) { ResizeFramebufFBO(vfb, vfb->width, vfb->height, true); _assert_(vfb->renderScaleFactor != 1); } From fcc1abc7c3a31e5084a14131d4d4ec78c6cde8a8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 8 Feb 2023 19:02:37 -0800 Subject: [PATCH 069/424] Dialog: Update by button flag consistently. Always check for the flag to change in Update(). --- Core/Dialog/PSPDialog.cpp | 17 +++++++++++++++++ Core/Dialog/PSPDialog.h | 2 ++ Core/Dialog/PSPGamedataInstallDialog.cpp | 3 +++ Core/Dialog/PSPMsgDialog.cpp | 14 ++------------ Core/Dialog/PSPNetconfDialog.cpp | 13 ++----------- Core/Dialog/PSPNpSigninDialog.cpp | 13 ++----------- Core/Dialog/PSPPlaceholderDialog.cpp | 2 ++ Core/Dialog/PSPSaveDialog.cpp | 12 ++---------- Core/Dialog/PSPScreenshotDialog.cpp | 2 ++ 9 files changed, 34 insertions(+), 44 deletions(-) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 7fddd2c642..1ede717e24 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -39,6 +39,23 @@ PSPDialog::PSPDialog(UtilityDialogType type) : dialogType_(type) { PSPDialog::~PSPDialog() { } +void PSPDialog::InitCommon() { + UpdateCommon(); +} + +void PSPDialog::UpdateCommon() { + okButtonImg = ImageID("I_CIRCLE"); + cancelButtonImg = ImageID("I_CROSS"); + okButtonFlag = CTRL_CIRCLE; + cancelButtonFlag = CTRL_CROSS; + if (GetCommonParam() && GetCommonParam()->buttonSwap == 1) { + okButtonImg = ImageID("I_CROSS"); + cancelButtonImg = ImageID("I_CIRCLE"); + okButtonFlag = CTRL_CROSS; + cancelButtonFlag = CTRL_CIRCLE; + } +} + PSPDialog::DialogStatus PSPDialog::GetStatus() { if (pendingStatusTicks != 0 && CoreTiming::GetTicks() >= pendingStatusTicks) { bool changeAllowed = true; diff --git a/Core/Dialog/PSPDialog.h b/Core/Dialog/PSPDialog.h index 0489a0d2b8..641829c4d4 100644 --- a/Core/Dialog/PSPDialog.h +++ b/Core/Dialog/PSPDialog.h @@ -89,6 +89,8 @@ public: int FinishShutdown(); protected: + void InitCommon(); + void UpdateCommon(); PPGeStyle FadedStyle(PPGeAlign align, float scale); PPGeImageStyle FadedImageStyle(); void UpdateButtons(); diff --git a/Core/Dialog/PSPGamedataInstallDialog.cpp b/Core/Dialog/PSPGamedataInstallDialog.cpp index 22ef058313..0f43cfbc4d 100644 --- a/Core/Dialog/PSPGamedataInstallDialog.cpp +++ b/Core/Dialog/PSPGamedataInstallDialog.cpp @@ -97,6 +97,7 @@ int PSPGamedataInstallDialog::Init(u32 paramAddr) { memset(&request, 0, sizeof(request)); // Only copy the right size to support different request format Memory::Memcpy(&request, paramAddr, size, "sceGamedataInstallInitStart"); + InitCommon(); ChangeStatusInit(GAMEDATA_INIT_DELAY_US); return 0; @@ -114,6 +115,8 @@ int PSPGamedataInstallDialog::Update(int animSpeed) { return 0; } + UpdateCommon(); + // TODO: param->mode == 1 should show a prompt to confirm, then a progress bar. // Any other mode (i.e. 0 or negative) should proceed and show no UI. diff --git a/Core/Dialog/PSPMsgDialog.cpp b/Core/Dialog/PSPMsgDialog.cpp index b681319aab..cffce18219 100755 --- a/Core/Dialog/PSPMsgDialog.cpp +++ b/Core/Dialog/PSPMsgDialog.cpp @@ -140,6 +140,7 @@ int PSPMsgDialog::Init(unsigned int paramAddr) { ChangeStatusInit(MSG_INIT_DELAY_US); UpdateButtons(); + InitCommon(); StartFade(true); return 0; } @@ -282,20 +283,9 @@ int PSPMsgDialog::Update(int animSpeed) { ChangeStatus(SCE_UTILITY_STATUS_FINISHED, 0); } else { UpdateButtons(); + UpdateCommon(); UpdateFade(animSpeed); - okButtonImg = ImageID("I_CIRCLE"); - cancelButtonImg = ImageID("I_CROSS"); - okButtonFlag = CTRL_CIRCLE; - cancelButtonFlag = CTRL_CROSS; - if (messageDialog.common.buttonSwap == 1) - { - okButtonImg = ImageID("I_CROSS"); - cancelButtonImg = ImageID("I_CIRCLE"); - okButtonFlag = CTRL_CROSS; - cancelButtonFlag = CTRL_CIRCLE; - } - StartDraw(); // white -> RGB(168,173,189), black -> RGB(129,134,150) // (255 - a) + (x * a / 255) = 173, x * a / 255 = 134 diff --git a/Core/Dialog/PSPNetconfDialog.cpp b/Core/Dialog/PSPNetconfDialog.cpp index bb9340471c..72d7bf7667 100644 --- a/Core/Dialog/PSPNetconfDialog.cpp +++ b/Core/Dialog/PSPNetconfDialog.cpp @@ -73,18 +73,8 @@ int PSPNetconfDialog::Init(u32 paramAddr) { ChangeStatusInit(NET_INIT_DELAY_US); // Eat any keys pressed before the dialog inited. + InitCommon(); UpdateButtons(); - okButtonImg = ImageID("I_CIRCLE"); - cancelButtonImg = ImageID("I_CROSS"); - okButtonFlag = CTRL_CIRCLE; - cancelButtonFlag = CTRL_CROSS; - if (request.common.buttonSwap == 1) - { - okButtonImg = ImageID("I_CROSS"); - cancelButtonImg = ImageID("I_CIRCLE"); - okButtonFlag = CTRL_CROSS; - cancelButtonFlag = CTRL_CIRCLE; - } connResult = -1; scanInfosAddr = 0; @@ -247,6 +237,7 @@ int PSPNetconfDialog::Update(int animSpeed) { } UpdateButtons(); + UpdateCommon(); auto di = GetI18NCategory("Dialog"); auto err = GetI18NCategory("Error"); u64 now = (u64)(time_now_d() * 1000000.0); diff --git a/Core/Dialog/PSPNpSigninDialog.cpp b/Core/Dialog/PSPNpSigninDialog.cpp index 48245c2008..6667bf217f 100644 --- a/Core/Dialog/PSPNpSigninDialog.cpp +++ b/Core/Dialog/PSPNpSigninDialog.cpp @@ -67,17 +67,7 @@ int PSPNpSigninDialog::Init(u32 paramAddr) { // Eat any keys pressed before the dialog inited. UpdateButtons(); - okButtonImg = ImageID("I_CIRCLE"); - cancelButtonImg = ImageID("I_CROSS"); - okButtonFlag = CTRL_CIRCLE; - cancelButtonFlag = CTRL_CROSS; - if (request.common.buttonSwap == 1) - { - okButtonImg = ImageID("I_CROSS"); - cancelButtonImg = ImageID("I_CIRCLE"); - okButtonFlag = CTRL_CROSS; - cancelButtonFlag = CTRL_CIRCLE; - } + InitCommon(); //npSigninResult = -1; startTime = (u64)(time_now_d() * 1000000.0); @@ -244,6 +234,7 @@ int PSPNpSigninDialog::Update(int animSpeed) { } UpdateButtons(); + UpdateCommon(); auto di = GetI18NCategory("Dialog"); auto err = GetI18NCategory("Error"); u64 now = (u64)(time_now_d() * 1000000.0); diff --git a/Core/Dialog/PSPPlaceholderDialog.cpp b/Core/Dialog/PSPPlaceholderDialog.cpp index 2fc3fbe92f..e320449bd3 100644 --- a/Core/Dialog/PSPPlaceholderDialog.cpp +++ b/Core/Dialog/PSPPlaceholderDialog.cpp @@ -27,6 +27,7 @@ PSPPlaceholderDialog::~PSPPlaceholderDialog() { int PSPPlaceholderDialog::Init() { ChangeStatus(SCE_UTILITY_STATUS_INITIALIZE, 0); + InitCommon(); return 0; } @@ -38,6 +39,7 @@ int PSPPlaceholderDialog::Update(int animSpeed) { } else if (ReadStatus() == SCE_UTILITY_STATUS_FINISHED) { ChangeStatus(SCE_UTILITY_STATUS_SHUTDOWN, 0); } + UpdateCommon(); return 0; } diff --git a/Core/Dialog/PSPSaveDialog.cpp b/Core/Dialog/PSPSaveDialog.cpp index 9b21f5d770..9b153339d5 100755 --- a/Core/Dialog/PSPSaveDialog.cpp +++ b/Core/Dialog/PSPSaveDialog.cpp @@ -270,6 +270,7 @@ int PSPSaveDialog::Init(int paramAddr) } param.ClearCaches(); + InitCommon(); UpdateButtons(); StartFade(true); @@ -654,16 +655,7 @@ int PSPSaveDialog::Update(int animSpeed) UpdateButtons(); UpdateFade(animSpeed); - okButtonImg = ImageID("I_CIRCLE"); - cancelButtonImg = ImageID("I_CROSS"); - okButtonFlag = CTRL_CIRCLE; - cancelButtonFlag = CTRL_CROSS; - if (param.GetPspParam()->common.buttonSwap == 1) { - okButtonImg = ImageID("I_CROSS"); - cancelButtonImg = ImageID("I_CIRCLE"); - okButtonFlag = CTRL_CROSS; - cancelButtonFlag = CTRL_CIRCLE; - } + UpdateCommon(); auto di = GetI18NCategory("Dialog"); diff --git a/Core/Dialog/PSPScreenshotDialog.cpp b/Core/Dialog/PSPScreenshotDialog.cpp index 92e4a17a91..6615e84252 100644 --- a/Core/Dialog/PSPScreenshotDialog.cpp +++ b/Core/Dialog/PSPScreenshotDialog.cpp @@ -84,11 +84,13 @@ int PSPScreenshotDialog::Init(u32 paramAddr) { mode = params_->mode; ChangeStatus(SCE_UTILITY_STATUS_INITIALIZE, 0); + InitCommon(); return 0; } int PSPScreenshotDialog::Update(int animSpeed) { + UpdateCommon(); if (UseAutoStatus()) { if (ReadStatus() == SCE_UTILITY_STATUS_INITIALIZE) { ChangeStatus(SCE_UTILITY_STATUS_RUNNING, 0); From d7732f7fd75b257663351091bfce2bc4787fedf6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 8 Feb 2023 19:04:18 -0800 Subject: [PATCH 070/424] Dialog: Warn when ignoring the dialog language. --- Core/Dialog/PSPDialog.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/Dialog/PSPDialog.cpp b/Core/Dialog/PSPDialog.cpp index 1ede717e24..fa31a862a0 100644 --- a/Core/Dialog/PSPDialog.cpp +++ b/Core/Dialog/PSPDialog.cpp @@ -41,6 +41,10 @@ PSPDialog::~PSPDialog() { void PSPDialog::InitCommon() { UpdateCommon(); + + if (GetCommonParam() && GetCommonParam()->language != g_Config.iLanguage) { + WARN_LOG(SCEUTILITY, "Game requested language %d, ignoring and using user language", GetCommonParam()->language); + } } void PSPDialog::UpdateCommon() { From 4bc205b7bc8047d741e76b08ebcdcb6b9a435b3d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 8 Feb 2023 19:07:54 -0800 Subject: [PATCH 071/424] Impose: Log when ignoring requested language. --- Core/HLE/sceImpose.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceImpose.cpp b/Core/HLE/sceImpose.cpp index 6bebff1fde..c5ab64a24a 100644 --- a/Core/HLE/sceImpose.cpp +++ b/Core/HLE/sceImpose.cpp @@ -73,12 +73,13 @@ static u32 sceImposeGetBatteryIconStatus(u32 chargingPtr, u32 iconStatusPtr) return 0; } -static u32 sceImposeSetLanguageMode(u32 languageVal, u32 buttonVal) -{ - DEBUG_LOG(SCEUTILITY, "sceImposeSetLanguageMode(%08x, %08x)", languageVal, buttonVal); +static u32 sceImposeSetLanguageMode(u32 languageVal, u32 buttonVal) { language = languageVal; buttonValue = buttonVal; - return 0; + if (language != g_Config.iLanguage) { + return hleLogWarning(SCEUTILITY, 0, "ignoring requested language"); + } + return hleLogSuccessI(SCEUTILITY, 0); } static u32 sceImposeGetLanguageMode(u32 languagePtr, u32 btnPtr) @@ -116,7 +117,7 @@ static u32 sceImposeGetBacklightOffTime() { //OSD stuff? home button? const HLEFunction sceImpose[] = { - {0X36AA6E91, &WrapU_UU, "sceImposeSetLanguageMode", 'x', "xx"}, // Seen + {0X36AA6E91, &WrapU_UU, "sceImposeSetLanguageMode", 'i', "ii"}, {0X381BD9E7, nullptr, "sceImposeHomeButton", '?', "" }, {0X0F341BE4, nullptr, "sceImposeGetHomePopup", '?', "" }, {0X5595A71A, nullptr, "sceImposeSetHomePopup", '?', "" }, From 0bccdf336b4a269e67aa80ce44b5cb0fd8107fd0 Mon Sep 17 00:00:00 2001 From: Jaakko Saarikko <74954275+styxnix@users.noreply.github.com> Date: Thu, 9 Feb 2023 09:08:52 +0200 Subject: [PATCH 072/424] Update fi_FI.ini --- assets/lang/fi_FI.ini | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 59d55445d0..19b549c7f9 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -37,7 +37,7 @@ Calibrate = Calibrate Calibrated = Calibrated Calibration = Calibration Circular stick input = Circular stick input -Classic = Classic +Classic = Klassinen Confine Mouse = Trap mouse within window/display area Control Mapping = Control mapping Custom Key Setting = Custom Key Setting @@ -364,13 +364,13 @@ Game disc read error - ISO corrupt = Game disc read error: ISO corrupt. GenericAllStartupError = PPSSPP failed to start up with any graphics backend. Try upgrading your graphics and other drivers. GenericBackendSwitchCrash = PPSSPP crashed while starting.\n\nThis usually means a graphics driver problem. Try upgrading your graphics drivers.\n\nGraphics backend has been switched: GenericDirect3D9Error = Failed initializing graphics. Try upgrading your graphics drivers and DirectX 9 runtime.\n\nWould you like to try switching to OpenGL?\n\nError message: -GenericGraphicsError = Graphics Error +GenericGraphicsError = Grafiikkavirhe GenericOpenGLError = Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to DirectX 9?\n\nError message: GenericVulkanError = Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to OpenGL?\n\nError message: InsufficientOpenGLDriver = Insufficient OpenGL driver support detected!\n\nYour GPU reports that it does not support OpenGL 2.0. Would you like to try using DirectX instead?\n\nDirectX is currently compatible with less games, but on your GPU it may be the only choice.\n\nVisit the forums at https://forums.ppsspp.org for more information.\n\n Just a directory. = just a directory. Missing key = Missing key -MsgErrorCode = Error code: +MsgErrorCode = Virhekoodi: MsgErrorSavedataDataBroken = Save data was corrupt. MsgErrorSavedataMSFull = Memory Stick full. Check your storage space. MsgErrorSavedataNoData = Warning: no save data was found. @@ -532,12 +532,12 @@ Postprocessing shaders = Postprocessing shaders Recreate Activity = Recreate activity Render duplicate frames to 60hz = Render duplicate frames to 60 Hz RenderDuplicateFrames Tip = Can make framerate smoother in games that run at lower framerates -Rendering Mode = Rendering mode -Rendering Resolution = Rendering resolution -RenderingMode NonBuffered Tip = Faster, but nothing may draw in some games -Rotation = Rotation -Safe = Safe -Screen Scaling Filter = Screen scaling filter +Rendering Mode = Renderöinti tapa +Rendering Resolution = Renderöinti resoluutio +RenderingMode NonBuffered Tip = Nopeampi, mutta mitään ei välttämättä piirry joissakin peleissä +Rotation = Kierto +Safe = Turvallinen +Screen Scaling Filter = Näytön skaalauksen suodatin Show Debug Statistics = Näytä virheenkorjaustilastot Show FPS Counter = Näytä FPS-laskuri Skip GPU Readbacks = Skip GPU Readbacks @@ -545,22 +545,22 @@ Software Rendering = Ohjelmistopohjainen renderointi (kokeellinen) Software Skinning = Software skinning SoftwareSkinning Tip = Combine skinned model draws on the CPU, faster in most games Speed = Nopeus -Speed Hacks = Speed Hacks (can cause rendering errors!) +Speed Hacks = Nopeus kikkoja (saattaa aiheuttaa renderöinti virheitä!) Stereo display shader = Stereo display shader -Stereo rendering = Stereo rendering +Stereo rendering = Stereo renderöinti Stretch = Venytä Texture Filter = Tekstuurisuodatin Texture Filtering = Tekstuurin suodatus Texture Scaling = Tekstuurin skaalaus -Texture Shader = Texture shader +Texture Shader = Tekstuurin varjostin Turn off Hardware Tessellation - unsupported = Turn off "hardware tessellation": unsupported -Unlimited = Unlimited -Up to 1 = Up to 1 -Up to 2 = Up to 2 -Upscale Level = Upscale level -Upscale Type = Upscale type -UpscaleLevel Tip = CPU heavy - some scaling may be delayed to avoid stutter -Use all displays = Use all displays +Unlimited = Rajoittamaton +Up to 1 = 1 asti +Up to 2 = 2 asti +Upscale Level = Ylösskaalauksen taso +Upscale Type = Ylösskaalauksen tapa +UpscaleLevel Tip = Prosessorille raskas - joillekkin skaalauksille voidaan antaa viivettä nykimisen välttämiseksi +Use all displays = Käytä kaikkia näyttöjä Vertex Cache = Verteksivälimuisti VertexCache Tip = Nopeampi, mutta voi välillä aiheuttaa vilkkumista VSync = VSync From c52db636cea7741d8633556ee9276bddd3d0e8ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 12 Jan 2023 22:34:44 +0100 Subject: [PATCH 073/424] Optimize tag formatting --- Core/HLE/ReplaceTables.cpp | 32 ++++++++++++++++++-------------- Core/HLE/sceDmac.cpp | 5 +++-- Core/HLE/sceKernelInterrupt.cpp | 7 ++++--- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 446df7826c..93ac83c079 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -159,12 +159,13 @@ static int Replace_memcpy() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = GetMemWriteTagAt("ReplaceMemcpy/", srcPtr, bytes); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); // It's pretty common that games will copy video data. - if (tag == "ReplaceMemcpy/VideoDecode" || tag == "ReplaceMemcpy/VideoDecodeRange") { + if (!strcmp(tagData, "ReplaceMemcpy/VideoDecode") || !strcmp(tagData, "ReplaceMemcpy/VideoDecodeRange")) { if (bytes == 512 * 272 * 4) { gpu->PerformWriteFormattedFromMemory(destPtr, bytes, 512, GE_FORMAT_8888); } @@ -211,12 +212,13 @@ static int Replace_memcpy_jak() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = GetMemWriteTagAt("ReplaceMemcpy/", srcPtr, bytes); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); // It's pretty common that games will copy video data. - if (tag == "ReplaceMemcpy/VideoDecode" || tag == "ReplaceMemcpy/VideoDecodeRange") { + if (!strcmp(tagData, "ReplaceMemcpy/VideoDecode") || !strcmp(tagData, "ReplaceMemcpy/VideoDecodeRange")) { if (bytes == 512 * 272 * 4) { gpu->PerformWriteFormattedFromMemory(destPtr, bytes, 512, GE_FORMAT_8888); } @@ -250,9 +252,10 @@ static int Replace_memcpy16() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = GetMemWriteTagAt("ReplaceMemcpy16/", srcPtr, bytes); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpy16/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); } return 10 + bytes / 4; // approximation @@ -322,9 +325,10 @@ static int Replace_memmove() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = GetMemWriteTagAt("ReplaceMemmove/", srcPtr, bytes); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemmove/", srcPtr, bytes); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tagData, tagSize); } return 10 + bytes / 4; // approximation diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 3735eb2a84..f7bcf0d0f6 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -52,8 +52,9 @@ static int __DmacMemcpy(u32 dst, u32 src, u32 size) { if (!skip && size != 0) { currentMIPS->InvalidateICache(src, size); if (MemBlockInfoDetailed(size)) { - const std::string tag = GetMemWriteTagAt("DmacMemcpy/", src, size); - Memory::Memcpy(dst, src, size, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "DmacMemcpy/", src, size); + Memory::Memcpy(dst, src, size, tagData, tagSize); } else { Memory::Memcpy(dst, src, size, "DmacMemcpy"); } diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 569c1cf746..2168df3eed 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -657,9 +657,10 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) } if (MemBlockInfoDetailed(size)) { - const std::string tag = GetMemWriteTagAt("KernelMemcpy/", src, size); - NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "KernelMemcpy/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tagData, tagSize); } return dst; From dc74778dea88dc2ba8032b5ce67dbbbfe3e540a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Feb 2023 10:27:29 +0100 Subject: [PATCH 074/424] Do the last ones too --- Core/Debugger/MemBlockInfo.cpp | 11 ----------- Core/Debugger/MemBlockInfo.h | 2 -- Core/HLE/ReplaceTables.cpp | 7 ++++--- Core/HLE/sceAtrac.cpp | 7 ++++--- Core/HLE/sceDeflt.cpp | 7 ++++--- Core/HLE/sceKernelInterrupt.cpp | 14 ++++++++------ 6 files changed, 20 insertions(+), 28 deletions(-) diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index 909803b797..050a2968a0 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -548,17 +548,6 @@ static const char *FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint3 return nullptr; } -std::string GetMemWriteTagAt(const char *prefix, uint32_t start, uint32_t size) { - const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size); - if (tag && strcmp(tag, "MemInit") != 0) - return std::string(prefix) + tag; - // Fall back to alloc and texture, especially for VRAM. We prefer write above. - tag = FindWriteTagByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size); - if (tag) - return std::string(prefix) + tag; - return StringFromFormat("%s%08x_size_%08x", prefix, start, size); -} - size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size) { const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size); if (tag && strcmp(tag, "MemInit") != 0) { diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index 839249f3a2..108423d53f 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -68,8 +68,6 @@ inline void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, co std::vector FindMemInfo(uint32_t start, uint32_t size); std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size); -std::string GetMemWriteTagAt(const char *prefix, uint32_t start, uint32_t size); -// Same as above but allocation-free. size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size); void MemBlockInfoInit(); diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 93ac83c079..ea49f5855a 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -294,9 +294,10 @@ static int Replace_memcpy_swizzled() { RETURN(0); if (MemBlockInfoDetailed(pitch * h)) { - const std::string tag = GetMemWriteTagAt("ReplaceMemcpySwizzle/", srcPtr, pitch * h); - NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "ReplaceMemcpySwizzle/", srcPtr, pitch * h); + NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, tagData, tagSize); } return 10 + (pitch * h) / 4; // approximation diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index f336d8713b..dac70d4b27 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1271,9 +1271,10 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 if (outbufPtr != 0) { u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); if (packetAddr != 0 && MemBlockInfoDetailed()) { - const std::string tag = GetMemWriteTagAt("AtracDecode/", packetAddr, packetSize); - NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "AtracDecode/", packetAddr, packetSize); + NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tagData, tagSize); } else { NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, "AtracDecode"); } diff --git a/Core/HLE/sceDeflt.cpp b/Core/HLE/sceDeflt.cpp index 985b89d543..d1a6da33e1 100644 --- a/Core/HLE/sceDeflt.cpp +++ b/Core/HLE/sceDeflt.cpp @@ -59,9 +59,10 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength, } if (MemBlockInfoDetailed(stream.total_in, stream.total_out)) { - const std::string tag = GetMemWriteTagAt("sceDeflt/", InBuffer, stream.total_in); - NotifyMemInfo(MemBlockFlags::READ, InBuffer, stream.total_in, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, stream.total_out, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "sceDeflt/", InBuffer, stream.total_in); + NotifyMemInfo(MemBlockFlags::READ, InBuffer, stream.total_in, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, stream.total_out, tagData, tagSize); } return hleLogSuccessI(HLE, stream.total_out); diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 2168df3eed..ec4b452a64 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -693,9 +693,10 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) { memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); } if (MemBlockInfoDetailed(size)) { - const std::string tag = GetMemWriteTagAt("KernelMemcpy/", src, size); - NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "KernelMemcpy/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tagData, tagSize); } return dst; } @@ -796,9 +797,10 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) { memmove(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); } if (MemBlockInfoDetailed(size)) { - const std::string tag = GetMemWriteTagAt("KernelMemmove/", src, size); - NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); + char tagData[128]; + size_t tagSize = FormatMemWriteTagAt(tagData, sizeof(tagData), "KernelMemmove/", src, size); + NotifyMemInfo(MemBlockFlags::READ, src, size, tagData, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tagData, tagSize); } return 0; } From d426ce511801472f729d13628e771822569d2623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 00:42:46 +0100 Subject: [PATCH 075/424] Clear depth buffers after changing depth rounding mode. And thus change of depth buffer scale/offset. Previously, old depth buffers with values that now are out of range could stick around, causing #16941. This clears them to the expected 0 value, which helps Outrun. Ideally we should convert depth buffers to the new format, but if we can get away without that, that's also nice. This is enough for #16941. --- GPU/Common/FramebufferManagerCommon.cpp | 15 ++++++++++++++- GPU/Common/FramebufferManagerCommon.h | 5 +++++ GPU/D3D11/GPU_D3D11.cpp | 3 ++- GPU/Directx9/GPU_DX9.cpp | 3 ++- GPU/GLES/GPU_GLES.cpp | 3 ++- GPU/Vulkan/GPU_Vulkan.cpp | 5 ++++- 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 1e2dcc11fa..a5332d934c 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1059,7 +1059,14 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe if (useBufferedRendering_) { if (vfb->fbo) { shaderManager_->DirtyLastShader(); - draw_->BindFramebufferAsRenderTarget(vfb->fbo, {Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP}, "FBSwitch"); + Draw::RPAction depthAction = Draw::RPAction::KEEP; + float clearDepth = 0.0f; + if (vfb->usageFlags & FB_USAGE_INVALIDATE_DEPTH) { + depthAction = Draw::RPAction::CLEAR; + clearDepth = GetDepthScaleFactors().offset; + vfb->usageFlags &= ~FB_USAGE_INVALIDATE_DEPTH; + } + draw_->BindFramebufferAsRenderTarget(vfb->fbo, {Draw::RPAction::KEEP, depthAction, Draw::RPAction::KEEP, 0, clearDepth}, "FBSwitch"); } else { // This should only happen very briefly when toggling useBufferedRendering_. ResizeFramebufFBO(vfb, vfb->width, vfb->height, true); @@ -2573,6 +2580,12 @@ void FramebufferManagerCommon::ShowScreenResolution() { INFO_LOG(SYSTEM, "%s", messageStream.str().c_str()); } +void FramebufferManagerCommon::ClearAllDepthBuffers() { + for (auto vfb : vfbs_) { + vfb->usageFlags |= FB_USAGE_INVALIDATE_DEPTH; + } +} + // We might also want to implement an asynchronous callback-style version of this. Would probably // only be possible to implement optimally on Vulkan, but on GL and D3D11 we could do pixel buffers // and read on the next frame, then call the callback. diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 37650a57ba..df33d549b4 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -46,6 +46,7 @@ enum { FB_USAGE_FIRST_FRAME_SAVED = 128, FB_USAGE_RENDER_DEPTH = 256, FB_USAGE_COLOR_MIXED_DEPTH = 512, + FB_USAGE_INVALIDATE_DEPTH = 1024, // used to clear depth buffers. }; enum { @@ -317,6 +318,10 @@ public: void ApplyClearToMemory(int x1, int y1, int x2, int y2, u32 clearColor); bool PerformWriteStencilFromMemory(u32 addr, int size, WriteStencil flags); + // We changed our depth mode, gotta start over. + // Ideally, we should convert depth buffers here, not just clear them. + void ClearAllDepthBuffers(); + // Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it. // In that case we hardly need to actually copy the bytes in VRAM, they will be wrong anyway (unless // read framebuffers is on, in which case this should always return false). diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 342f033738..5706c45fca 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -161,8 +161,9 @@ void GPU_D3D11::BeginFrame() { if (gstate_c.useFlagsChanged) { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. - WARN_LOG(G3D, "Shader use flags changed, clearing all shaders"); + WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); shaderManagerD3D11_->ClearShaders(); + framebufferManager_->ClearAllDepthBuffers(); drawEngine_.ClearInputLayoutMap(); gstate_c.useFlagsChanged = false; } diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index a7398018e9..af8d80e327 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -159,8 +159,9 @@ void GPU_DX9::BeginFrame() { if (gstate_c.useFlagsChanged) { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. - WARN_LOG(G3D, "Shader use flags changed, clearing all shaders"); + WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); shaderManagerDX9_->ClearCache(true); + framebufferManager_->ClearAllDepthBuffers(); gstate_c.useFlagsChanged = false; } } diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 034e8bd660..3646fc802c 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -283,8 +283,9 @@ void GPU_GLES::BeginHostFrame() { if (gstate_c.useFlagsChanged) { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. - WARN_LOG(G3D, "Shader use flags changed, clearing all shaders"); + WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); shaderManagerGL_->ClearCache(true); + framebufferManager_->ClearAllDepthBuffers(); gstate_c.useFlagsChanged = false; } } diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 5543c15e37..8e1ad1e2d1 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -310,9 +310,12 @@ void GPU_Vulkan::BeginHostFrame() { if (gstate_c.useFlagsChanged) { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. - WARN_LOG(G3D, "Shader use flags changed, clearing all shaders"); + WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); + // TODO: Not all shaders need to be recompiled. In fact, quite few? Of course, depends on + // the use flag change.. This is a major frame rate hitch in the start of a race in Outrun. shaderManagerVulkan_->ClearShaders(); pipelineManager_->Clear(); + framebufferManager_->ClearAllDepthBuffers(); gstate_c.useFlagsChanged = false; } From d65dae71856a5b441d7b0ad4e63d42ebff711500 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 14:07:45 +0100 Subject: [PATCH 076/424] Depth scale functions: Clean up the naming, add a failing test --- GPU/Common/DepalettizeShaderCommon.cpp | 14 +++---- GPU/Common/DepthBufferCommon.cpp | 6 +-- GPU/Common/DepthBufferCommon.h | 1 + GPU/Common/Draw2D.cpp | 8 ++-- GPU/Common/FragmentShaderGenerator.cpp | 4 +- GPU/Common/FramebufferManagerCommon.cpp | 2 +- GPU/Common/GPUStateUtils.cpp | 54 ++++++++++++------------- GPU/Common/GPUStateUtils.h | 33 ++++++++++----- GPU/Common/ShaderUniforms.cpp | 2 +- GPU/Common/SoftwareTransformCommon.cpp | 2 +- GPU/Directx9/FramebufferManagerDX9.cpp | 4 +- GPU/Directx9/ShaderManagerDX9.cpp | 2 +- GPU/GPUState.h | 6 ++- Windows/GEDebugger/GEDebugger.cpp | 12 +++--- ext/armips | 2 +- unittest/UnitTest.cpp | 40 ++++++++++++++++++ 16 files changed, 123 insertions(+), 69 deletions(-) create mode 100644 GPU/Common/DepthBufferCommon.h diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index c15bd4075a..d1cd9149af 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -55,9 +55,9 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { // NOTE: This swizzle can be made to work with any power-of-2 resolution scaleFactor by shifting // the bits around, but not sure how to handle 3x scaling. For now this is 1x-only (rough edges at higher resolutions). if (config.bufferFormat == GE_FORMAT_DEPTH16) { - DepthScaleFactors factors = GetDepthScaleFactors(); - writer.ConstFloat("z_scale", factors.scale); - writer.ConstFloat("z_offset", factors.offset); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); + writer.ConstFloat("z_scale", factors.ScaleU16()); + writer.ConstFloat("z_offset", factors.Offset()); if (config.depthUpperBits == 0x2) { writer.C(R"( int x = int((texcoord.x / scaleFactor) * texSize.x); @@ -116,7 +116,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { writer.C(" int index = (a << 15) | (b << 10) | (g << 5) | (r);\n"); break; case GE_FORMAT_DEPTH16: - // Remap depth buffer. + // Decode depth buffer. writer.C(" float depth = (color.x - z_offset) * z_scale;\n"); if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) { @@ -161,9 +161,9 @@ void GenerateDepalShaderFloat(ShaderWriter &writer, const DepalConfig &config) { const int mask = config.mask; if (config.bufferFormat == GE_FORMAT_DEPTH16) { - DepthScaleFactors factors = GetDepthScaleFactors(); - writer.ConstFloat("z_scale", factors.scale); - writer.ConstFloat("z_offset", factors.offset); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); + writer.ConstFloat("z_scale", factors.ScaleU16()); + writer.ConstFloat("z_offset", factors.Offset()); } writer.C(" vec4 index = ").SampleTexture2D("tex", "v_texcoord").C(";\n"); diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 2e69260410..5d118a4e10 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -227,7 +227,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x ub.u_depthFactor[0] = 0.0f; ub.u_depthFactor[1] = fudgeFactor; } else { - const float factor = DepthSliceFactor(); + const float factor = DepthSliceFactor(gstate_c.UseFlags()); ub.u_depthFactor[0] = -0.5f * (factor - 1.0f) * (1.0f / factor); ub.u_depthFactor[1] = factor * fudgeFactor; } @@ -276,10 +276,10 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x // We downloaded float values directly in this case. uint16_t *dest = pixels; const float *packedf = (float *)convBuf_; - DepthScaleFactors depthScale = GetDepthScaleFactors(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); for (int yp = 0; yp < destH; ++yp) { for (int xp = 0; xp < destW; ++xp) { - float scaled = depthScale.Apply(packedf[xp]); + float scaled = depthScale.DecodeToU16(packedf[xp]); if (scaled <= 0.0f) { dest[xp] = 0; } else if (scaled >= 65535.0f) { diff --git a/GPU/Common/DepthBufferCommon.h b/GPU/Common/DepthBufferCommon.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/GPU/Common/DepthBufferCommon.h @@ -0,0 +1 @@ +#pragma once diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 6a37cb2c0d..61911b2a81 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -108,10 +108,10 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) { writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); // Unlike when just copying a depth buffer, here we're generating new depth values so we'll // have to apply the scaling. - DepthScaleFactors factors = GetDepthScaleFactors(); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); writer.C(" vec3 rgb = ").SampleTexture2D("tex", "v_texcoord.xy").C(".xyz;\n"); writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n"); - writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale, factors.offset); + writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ @@ -128,7 +128,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); // Unlike when just copying a depth buffer, here we're generating new depth values so we'll // have to apply the scaling. - DepthScaleFactors factors = GetDepthScaleFactors(); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); writer.C(" vec2 tsize = texSize;\n"); writer.C(" vec2 coord = v_texcoord * tsize;\n"); writer.F(" float strip = 4.0 * scaleFactor;\n"); @@ -137,7 +137,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { writer.C(" coord /= tsize;\n"); writer.C(" vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n"); writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n"); - writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.scale, factors.offset); + writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index d45f8391e7..c6ee43f9ea 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -1185,13 +1185,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } if (gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { - const double scale = DepthSliceFactor() * 65535.0; + const double scale = DepthSliceFactor(gstate_c.UseFlags()) * 65535.0; WRITE(p, " highp float z = gl_FragCoord.z;\n"); if (gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { // We center the depth with an offset, but only its fraction matters. // When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0. - if (((int)(DepthSliceFactor() - 1.0f) & 1) == 1) { + if (((int)(DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) & 1) == 1) { WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale); } else { WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index a5332d934c..24627f8c72 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1063,7 +1063,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe float clearDepth = 0.0f; if (vfb->usageFlags & FB_USAGE_INVALIDATE_DEPTH) { depthAction = Draw::RPAction::CLEAR; - clearDepth = GetDepthScaleFactors().offset; + clearDepth = GetDepthScaleFactors(gstate_c.UseFlags()).Offset(); vfb->usageFlags &= ~FB_USAGE_INVALIDATE_DEPTH; } draw_->BindFramebufferAsRenderTarget(vfb->fbo, {Draw::RPAction::KEEP, depthAction, Draw::RPAction::KEEP, 0, clearDepth}, "FBSwitch"); diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index ef6fdc9e25..23d156fae2 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -502,25 +502,28 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) { static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f; static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f; -float DepthSliceFactor() { - if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { +float DepthSliceFactor(u32 useFlags) { + if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { + return 1.0f; + } + if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { return DEPTH_SLICE_FACTOR_16BIT; } - if (gstate_c.Use(GPU_USE_DEPTH_CLAMP)) { + if (useFlags & GPU_USE_DEPTH_CLAMP) { return 1.0f; } return DEPTH_SLICE_FACTOR_HIGH; } -// This is used for float values which might not be integers, but are in the integer scale of 65535. -float ToScaledDepthFromIntegerScale(float z) { - if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { +// This is used for float values which might not be integers, but are in the integer scale of 0-65535. +float ToScaledDepthFromIntegerScale(u32 useFlags, float z) { + if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { return z * (1.0f / 65535.0f); } - const float depthSliceFactor = DepthSliceFactor(); - if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) { - const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor); + const float depthSliceFactor = DepthSliceFactor(useFlags); + const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor); + if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). return (float)((double)z * (1.0 / 16777215.0) + doffset); } else { @@ -529,20 +532,15 @@ float ToScaledDepthFromIntegerScale(float z) { } } -// See struct DepthScaleFactors for how to apply. -DepthScaleFactors GetDepthScaleFactors() { - DepthScaleFactors factors; - if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { - factors.offset = 0; - factors.scale = 65535.0f; - return factors; +// See class DepthScaleFactors for how to apply. +DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { + if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { + return DepthScaleFactors(0.0f, 65535.0f); } - const float depthSliceFactor = DepthSliceFactor(); + const float depthSliceFactor = DepthSliceFactor(useFlags); const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - factors.scale = depthSliceFactor * 65535.0f; - factors.offset = offset; - return factors; + return DepthScaleFactors(offset, depthSliceFactor * 65535.0f); } void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { @@ -608,8 +606,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo out.viewportY = renderY * renderHeightFactor + displayOffsetY; out.viewportW = curRTWidth * renderWidthFactor; out.viewportH = curRTHeight * renderHeightFactor; - out.depthRangeMin = ToScaledDepthFromIntegerScale(0); - out.depthRangeMax = ToScaledDepthFromIntegerScale(65536); + out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 0.0f); + out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 65536.0f); } else { // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. float vpXScale = gstate.getViewportXScale(); @@ -723,7 +721,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // Here, we should "clamp." But clamping per fragment would be slow. // So, instead, we just increase the available range and hope. // If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction. - float fullDepthRange = 65535.0f * (DepthSliceFactor() - 1.0f) * (1.0f / 2.0f); + float fullDepthRange = 65535.0f * (DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) * (1.0f / 2.0f); if (minz == 0) { minz -= fullDepthRange; } @@ -734,7 +732,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // This means clamp isn't enabled, but we still want to allow values up to 65535.99. // If DepthSliceFactor() is 1.0, though, this would make out.depthRangeMax exceed 1. // Since that would clamp, it would make Z=1234 not match between draws when maxz changes. - if (DepthSliceFactor() > 1.0f) + if (DepthSliceFactor(gstate_c.UseFlags()) > 1.0f) maxz = 65535.99f; } // Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz. @@ -746,11 +744,11 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { out.depthScale = 1.0f; out.zOffset = 0.0f; - out.depthRangeMin = ToScaledDepthFromIntegerScale(vpZCenter - vpZScale); - out.depthRangeMax = ToScaledDepthFromIntegerScale(vpZCenter + vpZScale); + out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter - vpZScale); + out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter + vpZScale); } else { - out.depthRangeMin = ToScaledDepthFromIntegerScale(minz); - out.depthRangeMax = ToScaledDepthFromIntegerScale(maxz); + out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), minz); + out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), maxz); } // OpenGL will clamp these for us anyway, and Direct3D will error if not clamped. diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index ab524f6c3f..8164967a0f 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -86,25 +86,38 @@ struct ViewportAndScissor { float zOffset; bool throughMode; }; + void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out); void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor); -float ToScaledDepthFromIntegerScale(float z); -struct DepthScaleFactors { - float offset; - float scale; +class DepthScaleFactors { +public: + // This should only be used from GetDepthScaleFactors. + DepthScaleFactors(float offset, float scale) : offset_(offset), scale_(scale) {} - float Apply(float z) const { - return (z - offset) * scale; + // Decodes a value from a depth buffer to a value of range 0..65536 + float DecodeToU16(float z) const { + return (z - offset_) * scale_; } - float ApplyInverse(float z) const { - return (z / scale) + offset; + // Encodes a value from the range 0..65536 to a normalized depth value (0-1), in the + // range that we write to the depth buffer. + float EncodeFromU16(float z_u16) const { + return (z_u16 / scale_) + offset_; } + + float Offset() const { return offset_; } + float ScaleU16() const { return scale_; } + // float Scale() const { return scale_ / 65535.0f; } + +private: + float offset_; + float scale_; }; -DepthScaleFactors GetDepthScaleFactors(); -float DepthSliceFactor(); +DepthScaleFactors GetDepthScaleFactors(u32 useFlags); +float ToScaledDepthFromIntegerScale(u32 useFlags, float z); +float DepthSliceFactor(u32 useFlags); // These are common to all modern APIs and can be easily converted with a lookup table. enum class BlendFactor : uint8_t { diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 8cfa0c3c55..02533b85aa 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -255,7 +255,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f; + float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 7270cd9b2a..f05117160a 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -454,7 +454,7 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt if (matchingComponents && stencilNotMasked) { result->color = transformed[1].color0_32; // Need to rescale from a [0, 1] float. This is the final transformed value. - result->depth = ToScaledDepthFromIntegerScale((int)(transformed[1].z * 65535.0f)); + result->depth = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), (int)(transformed[1].z * 65535.0f)); result->action = SW_CLEAR; gpuStats.numClears++; return; diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 364bafbdf8..58d92756f0 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -74,13 +74,13 @@ bool FramebufferManagerDX9::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, i const u32 *packed = (const u32 *)locked.pBits; u16 *depth = (u16 *)pixels; - DepthScaleFactors depthScale = GetDepthScaleFactors(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); // TODO: Optimize. for (int yp = 0; yp < h; ++yp) { for (int xp = 0; xp < w; ++xp) { const int offset = (yp + y) * pixelsStride + x + xp; - float scaled = depthScale.Apply((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f)); + float scaled = depthScale.DecodeToU16((packed[offset] & 0x00FFFFFF) * (1.0f / 16777215.0f)); if (scaled <= 0.0f) { depth[offset] = 0; } else if (scaled >= 65535.0f) { diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index e6dc013922..ea341103a9 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -466,7 +466,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor() / 256.0f) * 0.5f; + float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale); float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 839f52f181..9f7e46432e 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -524,8 +524,10 @@ enum class SubmitType { }; struct GPUStateCache { - bool Use(u32 flags) { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true. - bool UseAll(u32 flags) { return (useFlags_ & flags) == flags; } // Return true if ALL flags are true. + bool Use(u32 flags) const { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true. + bool UseAll(u32 flags) const { return (useFlags_ & flags) == flags; } // Return true if ALL flags are true. + + u32 UseFlags() const { return useFlags_; } uint64_t GetDirtyUniforms() { return dirty & DIRTY_ALL_UNIFORMS; } void Dirty(u64 what) { diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index f9496f13f9..ae35d85ab6 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -839,9 +839,9 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, case GPU_DBG_FORMAT_24BIT_8X: { - DepthScaleFactors depthScale = GetDepthScaleFactors(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); // These are only ever going to be depth values, so let's also show scaled to 16 bit. - snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.Apply((pix & 0x00FFFFFF) * (1.0f / 16777215.0f))); + snprintf(desc, 256, "%d,%d: %d / %f / %f", x, y, pix & 0x00FFFFFF, (pix & 0x00FFFFFF) * (1.0f / 16777215.0f), depthScale.DecodeToU16((pix & 0x00FFFFFF) * (1.0f / 16777215.0f))); break; } @@ -860,8 +860,8 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, case GPU_DBG_FORMAT_FLOAT: { float pixf = *(float *)&pix; - DepthScaleFactors depthScale = GetDepthScaleFactors(); - snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.Apply(pixf)); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + snprintf(desc, 256, "%d,%d: %f / %f", x, y, pixf, depthScale.DecodeToU16(pixf)); break; } @@ -870,11 +870,11 @@ void CGEDebugger::DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, double z = *(float *)&pix; int z24 = (int)(z * 16777215.0); - DepthScaleFactors factors = GetDepthScaleFactors(); + DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); // TODO: Use GetDepthScaleFactors here too, verify it's the same. int z16 = z24 - 0x800000 + 0x8000; - int z16_2 = factors.Apply(z); + int z16_2 = factors.DecodeToU16(z); snprintf(desc, 256, "%d,%d: %d / %f", x, y, z16, (z - 0.5 + (1.0 / 512.0)) * 256.0); } diff --git a/ext/armips b/ext/armips index 7bd1ec93d4..6719edebaa 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 7bd1ec93d4586985ba1ef420b43b5e620f68695e +Subproject commit 6719edebaae03330ee5441d9b28280672edf00d5 diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 05d2d35475..2212b5af65 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -61,6 +61,7 @@ #include "Core/MemMap.h" #include "Core/MIPS/MIPSVFPUUtils.h" #include "GPU/Common/TextureDecoder.h" +#include "GPU/Common/GPUStateUtils.h" #include "android/jni/AndroidContentURI.h" @@ -795,6 +796,44 @@ static bool TestSmallDataConvert() { return true; } +static bool TestDepthMath() { + // Flag combinations that can happen: + // 0 + // GPU_USE_ACCURATE_DEPTH + // GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT + // What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH? + + // These are in normalized space. + static const float testValues[] = { 0.0f * 65535.0f, 0.1f * 65535.0f, 0.9f * 65535.0f, 1.0f * 65535.0f }; + + static const u32 useFlagsArray[] = { + 0, + GPU_USE_ACCURATE_DEPTH, + GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, + }; + static const float expectedScale[] = { 65535.0f, 262140.0f, -1.0f }; + static const float expectedOffset[] = { 0.0f, 0.375f, -2.0f }; + + for (int j = 0; j < ARRAY_SIZE(useFlagsArray); j++) { + u32 useFlags = useFlagsArray[j]; + printf("j: %d useflags: %d\n", j, useFlags); + DepthScaleFactors factors = GetDepthScaleFactors(useFlags); + + EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); + EXPECT_EQ_FLOAT(factors.Offset(), expectedOffset[j]); + EXPECT_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f); + + for (int i = 0; i < ARRAY_SIZE(testValues); i++) { + float encoded = factors.EncodeFromU16(testValues[i]); + float decodedU16 = factors.DecodeToU16(encoded); + EXPECT_EQ_FLOAT(decodedU16, testValues[i]); + EXPECT_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValues[i])); + } + } + + return true; +} + typedef bool (*TestFunc)(); struct TestItem { const char *name; @@ -846,6 +885,7 @@ TestItem availableTests[] = { TEST_ITEM(WrapText), TEST_ITEM(TinySet), TEST_ITEM(SmallDataConvert), + TEST_ITEM(DepthMath), }; int main(int argc, const char *argv[]) { From 8d40684833a3303ddfd4e86b3e95c0d0f4ff6b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 14:34:33 +0100 Subject: [PATCH 077/424] Make the test pass, add some commented-out failing ones --- GPU/Common/GPUStateUtils.cpp | 6 +++--- GPU/Common/GPUStateUtils.h | 10 +++++----- unittest/UnitTest.cpp | 24 ++++++++++++++++-------- unittest/UnitTest.h | 17 ++++++++++++++++- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 23d156fae2..b7c3bb65ae 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -522,13 +522,13 @@ float ToScaledDepthFromIntegerScale(u32 useFlags, float z) { } const float depthSliceFactor = DepthSliceFactor(useFlags); - const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor); if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { + const double doffset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). return (float)((double)z * (1.0 / 16777215.0) + doffset); } else { - const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - return z * (1.0f / depthSliceFactor) * (1.0f / 65535.0f) + offset; + const float offset = 0.5f * (depthSliceFactor - 1.0f) / depthSliceFactor; + return z / depthSliceFactor * (1.0f / 65535.0f) + offset; } } diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 8164967a0f..5d4406ac5a 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -93,7 +93,7 @@ void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor); class DepthScaleFactors { public: // This should only be used from GetDepthScaleFactors. - DepthScaleFactors(float offset, float scale) : offset_(offset), scale_(scale) {} + DepthScaleFactors(double offset, double scale) : offset_(offset), scale_(scale) {} // Decodes a value from a depth buffer to a value of range 0..65536 float DecodeToU16(float z) const { @@ -106,13 +106,13 @@ public: return (z_u16 / scale_) + offset_; } - float Offset() const { return offset_; } - float ScaleU16() const { return scale_; } + float Offset() const { return (float)offset_; } + float ScaleU16() const { return (float)scale_; } // float Scale() const { return scale_ / 65535.0f; } private: - float offset_; - float scale_; + double offset_; + double scale_; }; DepthScaleFactors GetDepthScaleFactors(u32 useFlags); diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 2212b5af65..9d5027b1ec 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -29,6 +29,7 @@ #include "ppsspp_config.h" +#include #include #include #include @@ -801,18 +802,23 @@ static bool TestDepthMath() { // 0 // GPU_USE_ACCURATE_DEPTH // GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT - // What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH? + // + // TODO: What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH? // These are in normalized space. - static const float testValues[] = { 0.0f * 65535.0f, 0.1f * 65535.0f, 0.9f * 65535.0f, 1.0f * 65535.0f }; + static const volatile float testValues[] = { 0.0f, 0.1f, 0.5f, 0.9f, 1.0f }; static const u32 useFlagsArray[] = { 0, GPU_USE_ACCURATE_DEPTH, GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, + // GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH, fails + // GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, fails }; - static const float expectedScale[] = { 65535.0f, 262140.0f, -1.0f }; - static const float expectedOffset[] = { 0.0f, 0.375f, -2.0f }; + static const float expectedScale[] = { 65535.0f, 262140.0f, 16776960.0f }; + static const float expectedOffset[] = { 0.0f, 0.375f, 0.498047f }; + + EXPECT_REL_EQ_FLOAT(100000.0f, 100001.0f, 0.00001f); for (int j = 0; j < ARRAY_SIZE(useFlagsArray); j++) { u32 useFlags = useFlagsArray[j]; @@ -820,14 +826,16 @@ static bool TestDepthMath() { DepthScaleFactors factors = GetDepthScaleFactors(useFlags); EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); - EXPECT_EQ_FLOAT(factors.Offset(), expectedOffset[j]); + EXPECT_REL_EQ_FLOAT(factors.Offset(), expectedOffset[j], 0.00001f); EXPECT_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f); for (int i = 0; i < ARRAY_SIZE(testValues); i++) { - float encoded = factors.EncodeFromU16(testValues[i]); + float testValue = testValues[i] * 65535.0f; + + float encoded = factors.EncodeFromU16(testValue); float decodedU16 = factors.DecodeToU16(encoded); - EXPECT_EQ_FLOAT(decodedU16, testValues[i]); - EXPECT_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValues[i])); + EXPECT_REL_EQ_FLOAT(decodedU16, testValue, 0.0001f); + EXPECT_REL_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValue), 0.00001f); } } diff --git a/unittest/UnitTest.h b/unittest/UnitTest.h index 2267a7a87f..37c02b091c 100644 --- a/unittest/UnitTest.h +++ b/unittest/UnitTest.h @@ -1,11 +1,26 @@ #pragma once +#include +#include + +inline bool rel_equal(float a, float b, float precision) { + float diff = fabsf(a - b); + if (diff == 0.0f) { + return true; + } + float range = std::max(fabsf(a), fabsf(b)); + float quot = diff / range; + return quot < precision; +} + + #define EXPECT_TRUE(a) if (!(a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; } #define EXPECT_FALSE(a) if ((a)) { printf("%s:%i: Test Fail\n", __FUNCTION__, __LINE__); return false; } #define EXPECT_EQ_INT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%d\nvs\n%d\n", __FUNCTION__, __LINE__, (int)(a), (int)(b)); return false; } #define EXPECT_EQ_HEX(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%x\nvs\n%x\n", __FUNCTION__, __LINE__, a, b); return false; } -#define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); return false; } +#define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%0.7f\nvs\n%0.7f\n", __FUNCTION__, __LINE__, a, b); return false; } #define EXPECT_APPROX_EQ_FLOAT(a, b) if (fabsf((a)-(b))>0.00001f) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } +#define EXPECT_REL_EQ_FLOAT(a, b, precision) if (!rel_equal(a, b, precision)) { printf("%s:%i: Test Fail\n%0.7f\nvs\n%0.7f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } #define EXPECT_EQ_STR(a, b) if (a != b) { printf("%s: Test Fail\n%s\nvs\n%s\n", __FUNCTION__, a.c_str(), b.c_str()); return false; } #define RET(a) if (!(a)) { return false; } From 28a7912ae6058d30c1a336f757678d821c038c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 01:11:02 +0100 Subject: [PATCH 078/424] Add comments, re-enable remaining tests (they do work, just forgot to add expected values) --- GPU/Common/GPUStateUtils.cpp | 39 +++++++++++++++++++++++++++++++++--- GPU/Common/GPUStateUtils.h | 8 ++++++-- unittest/UnitTest.cpp | 12 +++++------ unittest/UnitTest.h | 2 +- 4 files changed, 49 insertions(+), 12 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index b7c3bb65ae..de56c4517a 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -502,22 +502,55 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) { static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f; static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f; +// The supported flag combinations +// +// 0 - "Old"-style GL depth. +// Or "Non-accurate depth" : effectively ignore minz / maxz. Map Z values based on viewport, which clamps. +// This skews depth in many instances. Depth can be inverted in this mode if viewport says. +// This is completely wrong, but works in some cases (probably because some game devs assumed it was how it worked) +// and avoids some depth clamp issues. +// +// GPU_USE_ACCURATE_DEPTH: +// Accurate depth: Z in the framebuffer matches the range of Z used on the PSP linearly in some way. We choose +// a centered range, to simulate clamping by letting otherwise out-of-range pixels survive the 0 and 1 cutoffs. +// Clip depth based on minz/maxz, and viewport is just a means to scale and center the value, not clipping or mapping to stored values. +// +// GPU_USE_ACCURATE_DEPTH | GPU_USE_DEPTH_CLAMP: +// Variant of GPU_USE_ACCURATE_DEPTH, just the range is the nice and convenient 0-1 since we can use +// hardware depth clamp. only viable in accurate depth mode, clamps depth and therefore uses the full 0-1 range. Using the full 0-1 range is not what accurate means, it's implied by depth clamp (which also means we're clamping.) +// +// GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT: +// GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT | GPU_USE_DEPTH_CLAMP: +// Only viable in accurate depth mode, means to use a range of the 24-bit depth values available +// from the GPU to represent the 16-bit values the PSP had, to try to make everything round and +// z-fight (close to) the same way as on hardware, cheaply (cheaper than rounding depth in fragment shader). +// We automatically switch to this if Z tests for equality are used. +// Depth clamp has no noticeable effect here if set. +// +// Any other combinations of these particular flags are bogus (like for example a lonely GPU_USE_DEPTH_CLAMP). + float DepthSliceFactor(u32 useFlags) { if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { + // Old style depth. return 1.0f; } if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { + // Accurate depth but 16-bit resolution, so squish. return DEPTH_SLICE_FACTOR_16BIT; } if (useFlags & GPU_USE_DEPTH_CLAMP) { + // Accurate depth, but we can use the full range since clamping is available. return 1.0f; } + + // Standard accurate depth. return DEPTH_SLICE_FACTOR_HIGH; } // This is used for float values which might not be integers, but are in the integer scale of 0-65535. float ToScaledDepthFromIntegerScale(u32 useFlags, float z) { if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { + // Old style depth, shortcut. return z * (1.0f / 65535.0f); } @@ -538,9 +571,9 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { return DepthScaleFactors(0.0f, 65535.0f); } - const float depthSliceFactor = DepthSliceFactor(useFlags); - const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - return DepthScaleFactors(offset, depthSliceFactor * 65535.0f); + const double depthSliceFactor = DepthSliceFactor(useFlags); + const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); + return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); } void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 5d4406ac5a..f3a7338401 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -90,6 +90,7 @@ struct ViewportAndScissor { void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out); void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor); +// NOTE: See the .cpp file for detailed comment about how the use flags are interpreted. class DepthScaleFactors { public: // This should only be used from GetDepthScaleFactors. @@ -97,13 +98,13 @@ public: // Decodes a value from a depth buffer to a value of range 0..65536 float DecodeToU16(float z) const { - return (z - offset_) * scale_; + return (float)((z - offset_) * scale_); } // Encodes a value from the range 0..65536 to a normalized depth value (0-1), in the // range that we write to the depth buffer. float EncodeFromU16(float z_u16) const { - return (z_u16 / scale_) + offset_; + return (float)(((double)z_u16 / scale_) + offset_); } float Offset() const { return (float)offset_; } @@ -111,11 +112,14 @@ public: // float Scale() const { return scale_ / 65535.0f; } private: + // Doubles hardly cost anything these days, and precision matters here. double offset_; double scale_; }; DepthScaleFactors GetDepthScaleFactors(u32 useFlags); + +// These two will be replaced with just DepthScaleFactors. float ToScaledDepthFromIntegerScale(u32 useFlags, float z); float DepthSliceFactor(u32 useFlags); diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 9d5027b1ec..08c01bf677 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -806,17 +806,17 @@ static bool TestDepthMath() { // TODO: What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH? // These are in normalized space. - static const volatile float testValues[] = { 0.0f, 0.1f, 0.5f, 0.9f, 1.0f }; + static const volatile float testValues[] = { 0.0f, 0.1f, 0.5f, M_PI / 4.0f, 0.9f, 1.0f }; static const u32 useFlagsArray[] = { 0, GPU_USE_ACCURATE_DEPTH, GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, - // GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH, fails - // GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, fails + GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH, + GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, // Here, GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT should take precedence over USE_DEPTH_CLAMP. }; - static const float expectedScale[] = { 65535.0f, 262140.0f, 16776960.0f }; - static const float expectedOffset[] = { 0.0f, 0.375f, 0.498047f }; + static const float expectedScale[] = { 65535.0f, 262140.0f, 16776960.0f, 65535.0f, 16776960.0f, }; + static const float expectedOffset[] = { 0.0f, 0.375f, 0.498047f, 0.0f, 0.498047f, }; EXPECT_REL_EQ_FLOAT(100000.0f, 100001.0f, 0.00001f); @@ -835,7 +835,7 @@ static bool TestDepthMath() { float encoded = factors.EncodeFromU16(testValue); float decodedU16 = factors.DecodeToU16(encoded); EXPECT_REL_EQ_FLOAT(decodedU16, testValue, 0.0001f); - EXPECT_REL_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValue), 0.00001f); + EXPECT_REL_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValue), 0.000001f); } } diff --git a/unittest/UnitTest.h b/unittest/UnitTest.h index 37c02b091c..42bd8b3665 100644 --- a/unittest/UnitTest.h +++ b/unittest/UnitTest.h @@ -20,7 +20,7 @@ inline bool rel_equal(float a, float b, float precision) { #define EXPECT_EQ_HEX(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%x\nvs\n%x\n", __FUNCTION__, __LINE__, a, b); return false; } #define EXPECT_EQ_FLOAT(a, b) if ((a) != (b)) { printf("%s:%i: Test Fail\n%0.7f\nvs\n%0.7f\n", __FUNCTION__, __LINE__, a, b); return false; } #define EXPECT_APPROX_EQ_FLOAT(a, b) if (fabsf((a)-(b))>0.00001f) { printf("%s:%i: Test Fail\n%f\nvs\n%f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } -#define EXPECT_REL_EQ_FLOAT(a, b, precision) if (!rel_equal(a, b, precision)) { printf("%s:%i: Test Fail\n%0.7f\nvs\n%0.7f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } +#define EXPECT_REL_EQ_FLOAT(a, b, precision) if (!rel_equal(a, b, precision)) { printf("%s:%i: Test Fail\n%0.9f\nvs\n%0.9f\n", __FUNCTION__, __LINE__, a, b); /*return false;*/ } #define EXPECT_EQ_STR(a, b) if (a != b) { printf("%s: Test Fail\n%s\nvs\n%s\n", __FUNCTION__, a.c_str(), b.c_str()); return false; } #define RET(a) if (!(a)) { return false; } From 639ca318141840384aba56e3eaaec353599fd547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:23:00 +0100 Subject: [PATCH 079/424] Address feedback --- GPU/Common/DepthBufferCommon.h | 1 - GPU/Common/GPUStateUtils.cpp | 5 +++-- unittest/UnitTest.cpp | 9 ++------- 3 files changed, 5 insertions(+), 10 deletions(-) delete mode 100644 GPU/Common/DepthBufferCommon.h diff --git a/GPU/Common/DepthBufferCommon.h b/GPU/Common/DepthBufferCommon.h deleted file mode 100644 index 6f70f09bee..0000000000 --- a/GPU/Common/DepthBufferCommon.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index de56c4517a..8bbac0b9a2 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -502,7 +502,7 @@ ReplaceBlendType ReplaceBlendWithShader(GEBufferFormat bufferFormat) { static const float DEPTH_SLICE_FACTOR_HIGH = 4.0f; static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f; -// The supported flag combinations +// The supported flag combinations. TODO: Maybe they should be distilled down into an enum. // // 0 - "Old"-style GL depth. // Or "Non-accurate depth" : effectively ignore minz / maxz. Map Z values based on viewport, which clamps. @@ -525,7 +525,8 @@ static const float DEPTH_SLICE_FACTOR_16BIT = 256.0f; // from the GPU to represent the 16-bit values the PSP had, to try to make everything round and // z-fight (close to) the same way as on hardware, cheaply (cheaper than rounding depth in fragment shader). // We automatically switch to this if Z tests for equality are used. -// Depth clamp has no noticeable effect here if set. +// Depth clamp has no effect on the depth scaling here if set, though will still be enabled +// and clamp wildly out of line values. // // Any other combinations of these particular flags are bogus (like for example a lonely GPU_USE_DEPTH_CLAMP). diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 08c01bf677..e7fe46e52b 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -798,16 +798,11 @@ static bool TestSmallDataConvert() { } static bool TestDepthMath() { - // Flag combinations that can happen: - // 0 - // GPU_USE_ACCURATE_DEPTH - // GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT - // - // TODO: What about GPU_USE_DEPTH_CLAMP? It basically overrides GPU_USE_ACCURATE_DEPTH? - // These are in normalized space. static const volatile float testValues[] = { 0.0f, 0.1f, 0.5f, M_PI / 4.0f, 0.9f, 1.0f }; + // Flag combinations that can happen (any combination not included here is invalid, see comment + // over in GPUStateUtils.cpp): static const u32 useFlagsArray[] = { 0, GPU_USE_ACCURATE_DEPTH, From 116b3ba8cc1d02dd8a15b371a669a1ceddbad8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:24:02 +0100 Subject: [PATCH 080/424] Increase precision of GetDepthScaleFactors to match ToScaledDepthFromIntegerScale --- GPU/Common/GPUStateUtils.cpp | 10 ++++++++-- unittest/UnitTest.cpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 8bbac0b9a2..c4e43bdd5c 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -573,8 +573,14 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { } const double depthSliceFactor = DepthSliceFactor(useFlags); - const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); + if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { + const double offset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; + const double scale = 16777215.0; + return DepthScaleFactors(offset, scale); + } else { + const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); + return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); + } } void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index e7fe46e52b..1236349da5 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -810,7 +810,7 @@ static bool TestDepthMath() { GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH, GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH | GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT, // Here, GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT should take precedence over USE_DEPTH_CLAMP. }; - static const float expectedScale[] = { 65535.0f, 262140.0f, 16776960.0f, 65535.0f, 16776960.0f, }; + static const float expectedScale[] = { 65535.0f, 262140.0f, 16777215.0f, 65535.0f, 16777215.0f, }; static const float expectedOffset[] = { 0.0f, 0.375f, 0.498047f, 0.0f, 0.498047f, }; EXPECT_REL_EQ_FLOAT(100000.0f, 100001.0f, 0.00001f); @@ -822,7 +822,7 @@ static bool TestDepthMath() { EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); EXPECT_REL_EQ_FLOAT(factors.Offset(), expectedOffset[j], 0.00001f); - EXPECT_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f); + EXPECT_REL_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f, 0.0001f); for (int i = 0; i < ARRAY_SIZE(testValues); i++) { float testValue = testValues[i] * 65535.0f; From 9053d8ccc7c99ec3f87a71d7140aa32affabc12b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:25:02 +0100 Subject: [PATCH 081/424] Flip a sign for consistency --- GPU/Common/DepthBufferCommon.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 5d118a4e10..6be46fb107 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -62,7 +62,7 @@ void GenerateDepthDownloadFs(ShaderWriter &writer) { writer.BeginFSMain(depthUniforms, varyings); writer.C(" float depth = ").SampleTexture2D("tex", "v_texcoord").C(".r; \n"); // At this point, clamped maps [0, 1] to [0, 65535]. - writer.C(" float clamped = clamp((depth + u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);\n"); + writer.C(" float clamped = clamp((depth - u_depthFactor.x) * u_depthFactor.y, 0.0, 1.0);\n"); writer.C(" vec4 enc = u_depthShift * clamped;\n"); writer.C(" enc = floor(mod(enc, 256.0)) * u_depthTo8;\n"); writer.C(" vec4 outColor = enc.yzww;\n"); // Let's ignore the bits outside 16 bit precision. @@ -228,9 +228,11 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x ub.u_depthFactor[1] = fudgeFactor; } else { const float factor = DepthSliceFactor(gstate_c.UseFlags()); - ub.u_depthFactor[0] = -0.5f * (factor - 1.0f) * (1.0f / factor); + ub.u_depthFactor[0] = 0.5f * (factor - 1.0f) * (1.0f / factor); ub.u_depthFactor[1] = factor * fudgeFactor; } + + // These are for packing a float in u8x4 colors. We should support more suitable readback formats on APIs that can do it. static constexpr float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f }; memcpy(ub.u_depthShift, shifts, sizeof(shifts)); static constexpr float to8[] = { 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f, 1.0f / 255.0f }; From 805591e49335196f286248060c4036a9c8d8b409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:44:10 +0100 Subject: [PATCH 082/424] Replace all uses of ToScaledDepthFromIntegerScale. --- GPU/Common/GPUStateUtils.cpp | 15 +++++++++------ GPU/Common/SoftwareTransformCommon.cpp | 3 ++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index c4e43bdd5c..0d77d5f2f5 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -575,6 +575,7 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { const double depthSliceFactor = DepthSliceFactor(useFlags); if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { const double offset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; + // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). const double scale = 16777215.0; return DepthScaleFactors(offset, scale); } else { @@ -638,6 +639,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo float offsetX = gstate.getOffsetX(); float offsetY = gstate.getOffsetY(); + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + if (out.throughMode) { // If renderX/renderY are offset to compensate for a split framebuffer, // applying the offset to the viewport isn't enough, since the viewport clips. @@ -646,8 +649,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo out.viewportY = renderY * renderHeightFactor + displayOffsetY; out.viewportW = curRTWidth * renderWidthFactor; out.viewportH = curRTHeight * renderHeightFactor; - out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 0.0f); - out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), 65536.0f); + out.depthRangeMin = depthScale.EncodeFromU16(0.0f); + out.depthRangeMax = depthScale.EncodeFromU16(65536.0f); } else { // These we can turn into a glViewport call, offset by offsetX and offsetY. Math after. float vpXScale = gstate.getViewportXScale(); @@ -784,11 +787,11 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { out.depthScale = 1.0f; out.zOffset = 0.0f; - out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter - vpZScale); - out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), vpZCenter + vpZScale); + out.depthRangeMin = depthScale.EncodeFromU16(vpZCenter - vpZScale); + out.depthRangeMax = depthScale.EncodeFromU16(vpZCenter + vpZScale); } else { - out.depthRangeMin = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), minz); - out.depthRangeMax = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), maxz); + out.depthRangeMin = depthScale.EncodeFromU16(minz); + out.depthRangeMax = depthScale.EncodeFromU16(maxz); } // OpenGL will clamp these for us anyway, and Direct3D will error if not clamped. diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index f05117160a..9aff2c301e 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -452,9 +452,10 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt bool matchingComponents = params_.allowSeparateAlphaClear || (alphaMatchesColor && depthMatchesStencil); bool stencilNotMasked = !gstate.isClearModeAlphaMask() || gstate.getStencilWriteMask() == 0x00; if (matchingComponents && stencilNotMasked) { + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); result->color = transformed[1].color0_32; // Need to rescale from a [0, 1] float. This is the final transformed value. - result->depth = ToScaledDepthFromIntegerScale(gstate_c.UseFlags(), (int)(transformed[1].z * 65535.0f)); + result->depth = depthScale.EncodeFromU16((float)(int)(transformed[1].z * 65535.0f)); result->action = SW_CLEAR; gpuStats.numClears++; return; From d40aa17198240f6add2161a0963bb32bc9193606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 11:45:27 +0100 Subject: [PATCH 083/424] Remove ToScaledDepthFromIntegerScale --- GPU/Common/GPUStateUtils.cpp | 18 ------------------ GPU/Common/GPUStateUtils.h | 3 +-- unittest/UnitTest.cpp | 1 - 3 files changed, 1 insertion(+), 21 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 0d77d5f2f5..54daaf855c 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -548,24 +548,6 @@ float DepthSliceFactor(u32 useFlags) { return DEPTH_SLICE_FACTOR_HIGH; } -// This is used for float values which might not be integers, but are in the integer scale of 0-65535. -float ToScaledDepthFromIntegerScale(u32 useFlags, float z) { - if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { - // Old style depth, shortcut. - return z * (1.0f / 65535.0f); - } - - const float depthSliceFactor = DepthSliceFactor(useFlags); - if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { - const double doffset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; - // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). - return (float)((double)z * (1.0 / 16777215.0) + doffset); - } else { - const float offset = 0.5f * (depthSliceFactor - 1.0f) / depthSliceFactor; - return z / depthSliceFactor * (1.0f / 65535.0f) + offset; - } -} - // See class DepthScaleFactors for how to apply. DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { if (!(useFlags & GPU_USE_ACCURATE_DEPTH)) { diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index f3a7338401..ae1abf3be8 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -119,8 +119,7 @@ private: DepthScaleFactors GetDepthScaleFactors(u32 useFlags); -// These two will be replaced with just DepthScaleFactors. -float ToScaledDepthFromIntegerScale(u32 useFlags, float z); +// This will be replaced with just DepthScaleFactors. float DepthSliceFactor(u32 useFlags); // These are common to all modern APIs and can be easily converted with a lookup table. diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 1236349da5..bfe752bb4a 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -830,7 +830,6 @@ static bool TestDepthMath() { float encoded = factors.EncodeFromU16(testValue); float decodedU16 = factors.DecodeToU16(encoded); EXPECT_REL_EQ_FLOAT(decodedU16, testValue, 0.0001f); - EXPECT_REL_EQ_FLOAT(encoded, ToScaledDepthFromIntegerScale(useFlags, testValue), 0.000001f); } } From a2c9491a06c9c0329e36569f0e97e3ebb4d61c02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 12:23:51 +0100 Subject: [PATCH 084/424] Remove a division by 0 that I hadn't noticed before. --- GPU/Common/ShaderUniforms.cpp | 5 +++-- GPU/Directx9/ShaderManagerDX9.cpp | 2 +- GPU/GLES/ShaderManagerGLES.cpp | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 02533b85aa..54d83874a5 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -251,11 +251,12 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView float vpZCenter = gstate.getViewportZCenter(); // These are just the reverse of the formulas in GPUStateUtils. - float halfActualZRange = vpZScale / gstate_c.vpDepthScale; + float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; + float halfDepthPixel = (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; + float viewZCenter = minz + halfDepthPixel; ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index ea341103a9..cb9c1e33b0 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -462,7 +462,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float vpZCenter = gstate.getViewportZCenter(); // These are just the reverse of the formulas in GPUStateUtils. - float halfActualZRange = vpZScale / gstate_c.vpDepthScale; + float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; // Account for the half pixel offset. diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index c7d4d1a7f6..9df5b7f28d 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -588,7 +588,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin float vpZCenter = gstate.getViewportZCenter(); // These are just the reverse of the formulas in GPUStateUtils. - float halfActualZRange = vpZScale / gstate_c.vpDepthScale; + float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange; float viewZCenter = minz + halfActualZRange; From 5bdbe6984c531aebb963d281b31a7d8192c1d94f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 13:34:08 +0100 Subject: [PATCH 085/424] Simplify GetDepthScaleFactors --- GPU/Common/GPUStateUtils.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 54daaf855c..e4c095d65a 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -554,15 +554,16 @@ DepthScaleFactors GetDepthScaleFactors(u32 useFlags) { return DepthScaleFactors(0.0f, 65535.0f); } - const double depthSliceFactor = DepthSliceFactor(useFlags); if (useFlags & GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT) { - const double offset = 0.5 * (depthSliceFactor - 1.0) / depthSliceFactor; + const double offset = 0.5 * (DEPTH_SLICE_FACTOR_16BIT - 1.0) / DEPTH_SLICE_FACTOR_16BIT; // Use one bit for each value, rather than 1.0 / (65535.0 * 256.0). const double scale = 16777215.0; return DepthScaleFactors(offset, scale); + } else if (useFlags & GPU_USE_DEPTH_CLAMP) { + return DepthScaleFactors(0.0f, 65535.0f); } else { - const double offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor); - return DepthScaleFactors(offset, (float)(depthSliceFactor * 65535.0)); + const double offset = 0.5f * (DEPTH_SLICE_FACTOR_HIGH - 1.0f) * (1.0f / DEPTH_SLICE_FACTOR_HIGH); + return DepthScaleFactors(offset, (float)(DEPTH_SLICE_FACTOR_HIGH * 65535.0)); } } From 241f8e75bc14e446329851770d5fb11de76a939f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 14:37:48 +0100 Subject: [PATCH 086/424] Replace some uses of DepthSliceFactor --- GPU/Common/DepthBufferCommon.cpp | 13 +++---------- GPU/Common/GPUStateUtils.cpp | 5 +++-- GPU/Common/GPUStateUtils.h | 3 ++- unittest/UnitTest.cpp | 2 +- 4 files changed, 9 insertions(+), 14 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 6be46fb107..3c78362352 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -221,16 +221,9 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x // Setting this to 0.95f eliminates flickering lights with delayed readback in Syphon Filter. // That's pretty ugly though! But we'll need to do that if we're gonna enable delayed readback in those games. const float fudgeFactor = 1.0f; - - if (!gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { - // Don't scale anything, since we're not using factors outside accurate mode. - ub.u_depthFactor[0] = 0.0f; - ub.u_depthFactor[1] = fudgeFactor; - } else { - const float factor = DepthSliceFactor(gstate_c.UseFlags()); - ub.u_depthFactor[0] = 0.5f * (factor - 1.0f) * (1.0f / factor); - ub.u_depthFactor[1] = factor * fudgeFactor; - } + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + ub.u_depthFactor[0] = depthScale.Offset(); + ub.u_depthFactor[1] = depthScale.Scale(); // These are for packing a float in u8x4 colors. We should support more suitable readback formats on APIs that can do it. static constexpr float shifts[] = { 16777215.0f, 16777215.0f / 256.0f, 16777215.0f / 65536.0f, 16777215.0f / 16777216.0f }; diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index e4c095d65a..d223283e3f 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -747,7 +747,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // Here, we should "clamp." But clamping per fragment would be slow. // So, instead, we just increase the available range and hope. // If depthSliceFactor is 4, it means (75% / 2) of the depth lies in each direction. - float fullDepthRange = 65535.0f * (DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) * (1.0f / 2.0f); + float fullDepthRange = 65535.0f * (depthScale.Scale() - 1.0f) * (1.0f / 2.0f); if (minz == 0) { minz -= fullDepthRange; } @@ -758,9 +758,10 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo // This means clamp isn't enabled, but we still want to allow values up to 65535.99. // If DepthSliceFactor() is 1.0, though, this would make out.depthRangeMax exceed 1. // Since that would clamp, it would make Z=1234 not match between draws when maxz changes. - if (DepthSliceFactor(gstate_c.UseFlags()) > 1.0f) + if (depthScale.Scale() > 1.0f) maxz = 65535.99f; } + // Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz. float halfActualZRange = (maxz - minz) * (1.0f / 2.0f); out.depthScale = halfActualZRange < std::numeric_limits::epsilon() ? 1.0f : vpZScale / halfActualZRange; diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index ae1abf3be8..ed021bbb83 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -108,8 +108,9 @@ public: } float Offset() const { return (float)offset_; } + float ScaleU16() const { return (float)scale_; } - // float Scale() const { return scale_ / 65535.0f; } + float Scale() const { return (float)(scale_ / 65535.0); } private: // Doubles hardly cost anything these days, and precision matters here. diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index bfe752bb4a..5e5f6e8d63 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -822,7 +822,7 @@ static bool TestDepthMath() { EXPECT_EQ_FLOAT(factors.ScaleU16(), expectedScale[j]); EXPECT_REL_EQ_FLOAT(factors.Offset(), expectedOffset[j], 0.00001f); - EXPECT_REL_EQ_FLOAT(factors.ScaleU16(), DepthSliceFactor(useFlags) * 65535.0f, 0.0001f); + EXPECT_REL_EQ_FLOAT(factors.Scale(), DepthSliceFactor(useFlags), 0.0001f); for (int i = 0; i < ARRAY_SIZE(testValues); i++) { float testValue = testValues[i] * 65535.0f; From 99e6fd62f750c97c99db483feaa500dfca7bc428 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 14:41:25 +0100 Subject: [PATCH 087/424] Remove a baffling depth offset I don't quite get --- GPU/Common/ShaderUniforms.cpp | 4 +--- GPU/Directx9/ShaderManagerDX9.cpp | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 54d83874a5..011d09a49b 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -254,9 +254,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; - // Account for the half pixel offset. - float halfDepthPixel = (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; - float viewZCenter = minz + halfDepthPixel; + float viewZCenter = minz; ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index cb9c1e33b0..1571d517bd 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -465,8 +465,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; - // Account for the half pixel offset. - float viewZCenter = minz + (DepthSliceFactor(gstate_c.UseFlags()) / 256.0f) * 0.5f; + float viewZCenter = minz; float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale); float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f; From 547ecec0741892a98949c52a6e02088b0a7ddabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 14:45:01 +0100 Subject: [PATCH 088/424] Replace the rest of the uses of DepthSliceFactor --- GPU/Common/FragmentShaderGenerator.cpp | 6 ++++-- GPU/Common/GPUStateUtils.h | 3 --- unittest/UnitTest.cpp | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index c6ee43f9ea..4cd163feab 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -1185,13 +1185,15 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } if (gstate_c.Use(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { - const double scale = DepthSliceFactor(gstate_c.UseFlags()) * 65535.0; + DepthScaleFactors depthScale = GetDepthScaleFactors(gstate_c.UseFlags()); + + const double scale = depthScale.ScaleU16(); WRITE(p, " highp float z = gl_FragCoord.z;\n"); if (gstate_c.Use(GPU_USE_ACCURATE_DEPTH)) { // We center the depth with an offset, but only its fraction matters. // When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0. - if (((int)(DepthSliceFactor(gstate_c.UseFlags()) - 1.0f) & 1) == 1) { + if (((int)(depthScale.Scale() - 1.0f) & 1) == 1) { WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale); } else { WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale); diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index ed021bbb83..a786190f60 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -120,9 +120,6 @@ private: DepthScaleFactors GetDepthScaleFactors(u32 useFlags); -// This will be replaced with just DepthScaleFactors. -float DepthSliceFactor(u32 useFlags); - // These are common to all modern APIs and can be easily converted with a lookup table. enum class BlendFactor : uint8_t { ZERO, diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 5e5f6e8d63..fcbe56f282 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -797,6 +797,8 @@ static bool TestSmallDataConvert() { return true; } +float DepthSliceFactor(u32 useFlags); + static bool TestDepthMath() { // These are in normalized space. static const volatile float testValues[] = { 0.0f, 0.1f, 0.5f, M_PI / 4.0f, 0.9f, 1.0f }; From a083a65f77727fbc1cde3c6004fce507826be3ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 00:17:49 +0100 Subject: [PATCH 089/424] Depal: Get depth scale factors dynamically --- GPU/Common/DepalettizeShaderCommon.cpp | 5 +---- GPU/Common/Draw2D.cpp | 19 ++++++++++++++----- GPU/Common/Draw2D.h | 6 +++--- GPU/Common/FramebufferManagerCommon.cpp | 6 +++--- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index d1cd9149af..bca9e5c8dd 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -51,13 +51,10 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { writer.C(" vec2 texcoord = v_texcoord;\n"); // Implement the swizzle we need to simulate, if a game uses 8888 framebuffers and any other mode than "6" to access depth textures. - // This implements the "2" mode swizzle (it fixes up the Y direction but not X. See comments on issue #15898) + // This implements the "2" mode swizzle (it fixes up the Y direction but not X. See comments on issue #15898, Tantalus games) // NOTE: This swizzle can be made to work with any power-of-2 resolution scaleFactor by shifting // the bits around, but not sure how to handle 3x scaling. For now this is 1x-only (rough edges at higher resolutions). if (config.bufferFormat == GE_FORMAT_DEPTH16) { - DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); - writer.ConstFloat("z_scale", factors.ScaleU16()); - writer.ConstFloat("z_offset", factors.Offset()); if (config.depthUpperBits == 0x2) { writer.C(R"( int x = int((texcoord.x / scaleFactor) * texSize.x); diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 61911b2a81..0ffb2a0722 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -39,23 +39,28 @@ static const SamplerDef samplers[1] = { { 0, "tex", SamplerFlags::ARRAY_ON_VULKAN }, }; -const UniformDef g_draw2Duniforms[2] = { +const UniformDef g_draw2Duniforms[4] = { { "vec2", "texSize", 0 }, { "float", "scaleFactor", 1}, + { "float", "z_scale", 2 }, + { "float", "z_offset", 3 }, }; struct Draw2DUB { float texSizeX; float texSizeY; float scaleFactor; + float zScale; + float zOffset; }; const UniformBufferDesc draw2DUBDesc{ sizeof(Draw2DUB), { { "texSize", -1, 0, UniformType::FLOAT2, 0 }, { "scaleFactor", -1, 1, UniformType::FLOAT1, 8 }, + { "z_scale", -1, 1, UniformType::FLOAT1, 12 }, + { "z_offset", -1, 1, UniformType::FLOAT1, 16 }, } }; - Draw2DPipelineInfo GenerateDraw2DCopyColorFs(ShaderWriter &writer) { writer.DeclareSamplers(samplers); writer.BeginFSMain(Slice::empty(), varyings); @@ -95,8 +100,8 @@ Draw2DPipelineInfo GenerateDraw2DCopyDepthFs(ShaderWriter &writer) { writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ - "draw2d_copy_depth", - RASTER_DEPTH, + "draw2d_copy_r16_to_depth", + RASTER_DEPTH, // Unused in this case, I think. RASTER_DEPTH, }; } @@ -319,6 +324,10 @@ void Draw2D::DrawStrip2D(Draw::Texture *tex, const Draw2DVertex *verts, int vert ub.texSizeY = tex ? tex->Height() : texH; ub.scaleFactor = (float)scaleFactor; + DepthScaleFactors zScaleFactors = GetDepthScaleFactors(gstate_c.UseFlags()); + ub.zScale = zScaleFactors.Scale(); + ub.zOffset = zScaleFactors.Offset(); + draw_->BindPipeline(pipeline->pipeline); draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub)); @@ -356,7 +365,7 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) { pipeline = draw2DPipelineColorRect2Lin_; break; - case DRAW2D_COPY_DEPTH: + case DRAW2D_COPY_R16_TO_DEPTH: if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { // Can't do it return nullptr; diff --git a/GPU/Common/Draw2D.h b/GPU/Common/Draw2D.h index 4d7d728404..4302a3fa2e 100644 --- a/GPU/Common/Draw2D.h +++ b/GPU/Common/Draw2D.h @@ -13,7 +13,7 @@ struct Draw2DVertex { enum Draw2DShader { DRAW2D_COPY_COLOR, - DRAW2D_COPY_DEPTH, + DRAW2D_COPY_R16_TO_DEPTH, DRAW2D_565_TO_DEPTH, DRAW2D_565_TO_DEPTH_DESWIZZLE, DRAW2D_COPY_COLOR_RECT2LIN, @@ -21,7 +21,7 @@ enum Draw2DShader { inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) { switch (shader) { - case DRAW2D_COPY_DEPTH: + case DRAW2D_COPY_R16_TO_DEPTH: return RASTER_DEPTH; case DRAW2D_COPY_COLOR: case DRAW2D_565_TO_DEPTH: @@ -38,7 +38,7 @@ struct Draw2DPipelineInfo { Slice samplers; }; -extern const UniformDef g_draw2Duniforms[2]; +extern const UniformDef g_draw2Duniforms[4]; struct Draw2DPipeline { Draw::Pipeline *pipeline; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 24627f8c72..9768449970 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -974,7 +974,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir // Some GPUs can copy depth but only if stencil gets to come along for the ride. We only want to use this if there is no blit functionality. if (useRaster) { - BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster"); + BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_R16_TO_DEPTH), "BlitDepthRaster"); } else if (useCopy) { draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "CopyFramebufferDepth"); RebindFramebuffer("After BlitFramebufferDepth"); @@ -3036,7 +3036,7 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa // Rearrange to strip form. std::swap(coord[2], coord[3]); - draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_DEPTH : DRAW2D_COPY_COLOR)); + draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_R16_TO_DEPTH : DRAW2D_COPY_COLOR)); gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); } @@ -3135,7 +3135,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag); } else { - Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_DEPTH); + Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_R16_TO_DEPTH); Draw::Framebuffer *srcFBO = src->fbo; if (src == dst) { Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::BLIT, src->renderWidth, src->renderHeight); From 1938fa44d4de1eb3bc661bccdc1e1e29f9b958d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Feb 2023 09:41:18 +0100 Subject: [PATCH 090/424] Split the depth copy shader into depth copy and depth encode, dynamic depth scale in Draw2D --- GPU/Common/DepalettizeShaderCommon.cpp | 2 +- GPU/Common/Draw2D.cpp | 73 ++++++++++++++++++------- GPU/Common/Draw2D.h | 8 ++- GPU/Common/FramebufferManagerCommon.cpp | 11 ++-- GPU/Common/FramebufferManagerCommon.h | 5 +- 5 files changed, 68 insertions(+), 31 deletions(-) diff --git a/GPU/Common/DepalettizeShaderCommon.cpp b/GPU/Common/DepalettizeShaderCommon.cpp index bca9e5c8dd..1d3630919c 100644 --- a/GPU/Common/DepalettizeShaderCommon.cpp +++ b/GPU/Common/DepalettizeShaderCommon.cpp @@ -114,7 +114,7 @@ void GenerateDepalShader300(ShaderWriter &writer, const DepalConfig &config) { break; case GE_FORMAT_DEPTH16: // Decode depth buffer. - writer.C(" float depth = (color.x - z_offset) * z_scale;\n"); + writer.C(" float depth = (color.x - z_offset) * z_scale * 65535.0f;\n"); if (config.bufferFormat == GE_FORMAT_DEPTH16 && config.textureFormat == GE_TFMT_5650) { // Convert depth to 565, without going through a CLUT. diff --git a/GPU/Common/Draw2D.cpp b/GPU/Common/Draw2D.cpp index 0ffb2a0722..4f19277956 100644 --- a/GPU/Common/Draw2D.cpp +++ b/GPU/Common/Draw2D.cpp @@ -39,11 +39,12 @@ static const SamplerDef samplers[1] = { { 0, "tex", SamplerFlags::ARRAY_ON_VULKAN }, }; -const UniformDef g_draw2Duniforms[4] = { +const UniformDef g_draw2Duniforms[5] = { { "vec2", "texSize", 0 }, { "float", "scaleFactor", 1}, { "float", "z_scale", 2 }, - { "float", "z_offset", 3 }, + { "float", "z_scale_inv", 3 }, + { "float", "z_offset", 4 }, }; struct Draw2DUB { @@ -51,6 +52,7 @@ struct Draw2DUB { float texSizeY; float scaleFactor; float zScale; + float zScaleInv; float zOffset; }; @@ -58,7 +60,8 @@ const UniformBufferDesc draw2DUBDesc{ sizeof(Draw2DUB), { { "texSize", -1, 0, UniformType::FLOAT2, 0 }, { "scaleFactor", -1, 1, UniformType::FLOAT1, 8 }, { "z_scale", -1, 1, UniformType::FLOAT1, 12 }, - { "z_offset", -1, 1, UniformType::FLOAT1, 16 }, + { "z_scale_inv", -1, 1, UniformType::FLOAT1, 16 }, + { "z_offset", -1, 1, UniformType::FLOAT1, 20 }, } }; Draw2DPipelineInfo GenerateDraw2DCopyColorFs(ShaderWriter &writer) { @@ -100,23 +103,41 @@ Draw2DPipelineInfo GenerateDraw2DCopyDepthFs(ShaderWriter &writer) { writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ - "draw2d_copy_r16_to_depth", + "draw2d_copy_depth", RASTER_DEPTH, // Unused in this case, I think. RASTER_DEPTH, }; } +Draw2DPipelineInfo GenerateDraw2DEncodeDepthFs(ShaderWriter &writer) { + writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH); + writer.HighPrecisionFloat(); + writer.DeclareSamplers(samplers); + writer.BeginFSMain(g_draw2Duniforms, varyings); + writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); + writer.C(" float depthValue = ").SampleTexture2D("tex", "v_texcoord.xy").C(".x;\n"); + writer.C(" gl_FragDepth = (depthValue * z_scale_inv) + z_offset;\n"); + writer.EndFSMain("outColor"); + + return Draw2DPipelineInfo{ + "draw2d_copy_r16_to_depth", + RASTER_COLOR, + RASTER_DEPTH, + }; +} + Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) { writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH); + writer.HighPrecisionFloat(); writer.DeclareSamplers(samplers); - writer.BeginFSMain(Slice::empty(), varyings); + writer.BeginFSMain(g_draw2Duniforms, varyings); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); // Unlike when just copying a depth buffer, here we're generating new depth values so we'll // have to apply the scaling. DepthScaleFactors factors = GetDepthScaleFactors(gstate_c.UseFlags()); writer.C(" vec3 rgb = ").SampleTexture2D("tex", "v_texcoord.xy").C(".xyz;\n"); - writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n"); - writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); + writer.F(" float depthValue = ((floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0)) / 65535.0; \n"); + writer.C(" gl_FragDepth = (depthValue * z_scale_inv) + z_offset;\n"); writer.EndFSMain("outColor"); return Draw2DPipelineInfo{ @@ -128,6 +149,7 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthFs(ShaderWriter &writer) { Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { writer.SetFlags(ShaderWriterFlags::FS_WRITE_DEPTH); + writer.HighPrecisionFloat(); writer.DeclareSamplers(samplers); writer.BeginFSMain(g_draw2Duniforms, varyings); writer.C(" vec4 outColor = vec4(0.0, 0.0, 0.0, 0.0);\n"); @@ -140,11 +162,11 @@ Draw2DPipelineInfo GenerateDraw2D565ToDepthDeswizzleFs(ShaderWriter &writer) { writer.C(" float in_strip = mod(coord.y, strip);\n"); writer.C(" coord.y = coord.y - in_strip + strip - in_strip;\n"); writer.C(" coord /= tsize;\n"); - writer.C(" vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n"); - writer.F(" highp float depthValue = (floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0); \n"); - writer.F(" gl_FragDepth = (depthValue / %f) + %f;\n", factors.ScaleU16(), factors.Offset()); + writer.C(" highp vec3 rgb = ").SampleTexture2D("tex", "coord").C(".xyz;\n"); + writer.F(" highp float depthValue = floor(rgb.x * 31.99) + floor(rgb.y * 63.99) * 32.0 + floor(rgb.z * 31.99) * 2048.0; \n"); + writer.C(" gl_FragDepth = z_offset + ((depthValue / 65535.0) * z_scale_inv);\n"); writer.EndFSMain("outColor"); - + return Draw2DPipelineInfo{ "draw2d_565_to_depth_deswizzle", RASTER_COLOR, @@ -253,7 +275,7 @@ Draw2DPipeline *Draw2D::Create2DPipeline(std::functionCreateInputLayout(desc); - BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0 }); + BlendState *blend = draw_->CreateBlendState({ false, info.writeChannel == RASTER_COLOR ? 0xF : 0x0 }); DepthStencilStateDesc dsDesc{}; if (info.writeChannel == RASTER_DEPTH) { @@ -326,6 +348,7 @@ void Draw2D::DrawStrip2D(Draw::Texture *tex, const Draw2DVertex *verts, int vert DepthScaleFactors zScaleFactors = GetDepthScaleFactors(gstate_c.UseFlags()); ub.zScale = zScaleFactors.Scale(); + ub.zScaleInv = 1.0f / ub.zScale; ub.zOffset = zScaleFactors.Offset(); draw_->BindPipeline(pipeline->pipeline); @@ -352,10 +375,10 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) { switch (shader) { case DRAW2D_COPY_COLOR: - if (!draw2DPipelineColor_) { - draw2DPipelineColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs); + if (!draw2DPipelineCopyColor_) { + draw2DPipelineCopyColor_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyColorFs); } - pipeline = draw2DPipelineColor_; + pipeline = draw2DPipelineCopyColor_; break; case DRAW2D_COPY_COLOR_RECT2LIN: @@ -364,16 +387,26 @@ Draw2DPipeline *FramebufferManagerCommon::Get2DPipeline(Draw2DShader shader) { } pipeline = draw2DPipelineColorRect2Lin_; break; - - case DRAW2D_COPY_R16_TO_DEPTH: + case DRAW2D_COPY_DEPTH: if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { // Can't do it return nullptr; } - if (!draw2DPipelineDepth_) { - draw2DPipelineDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs); + if (!draw2DPipelineCopyDepth_) { + draw2DPipelineCopyDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DCopyDepthFs); } - pipeline = draw2DPipelineDepth_; + pipeline = draw2DPipelineCopyDepth_; + break; + + case DRAW2D_ENCODE_R16_TO_DEPTH: + if (!draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) { + // Can't do it + return nullptr; + } + if (!draw2DPipelineEncodeDepth_) { + draw2DPipelineEncodeDepth_ = draw2D_.Create2DPipeline(&GenerateDraw2DEncodeDepthFs); + } + pipeline = draw2DPipelineEncodeDepth_; break; case DRAW2D_565_TO_DEPTH: diff --git a/GPU/Common/Draw2D.h b/GPU/Common/Draw2D.h index 4302a3fa2e..5df67f7493 100644 --- a/GPU/Common/Draw2D.h +++ b/GPU/Common/Draw2D.h @@ -13,7 +13,8 @@ struct Draw2DVertex { enum Draw2DShader { DRAW2D_COPY_COLOR, - DRAW2D_COPY_R16_TO_DEPTH, + DRAW2D_COPY_DEPTH, + DRAW2D_ENCODE_R16_TO_DEPTH, DRAW2D_565_TO_DEPTH, DRAW2D_565_TO_DEPTH_DESWIZZLE, DRAW2D_COPY_COLOR_RECT2LIN, @@ -21,9 +22,10 @@ enum Draw2DShader { inline RasterChannel Draw2DSourceChannel(Draw2DShader shader) { switch (shader) { - case DRAW2D_COPY_R16_TO_DEPTH: + case DRAW2D_COPY_DEPTH: return RASTER_DEPTH; case DRAW2D_COPY_COLOR: + case DRAW2D_ENCODE_R16_TO_DEPTH: case DRAW2D_565_TO_DEPTH: case DRAW2D_565_TO_DEPTH_DESWIZZLE: default: @@ -38,7 +40,7 @@ struct Draw2DPipelineInfo { Slice samplers; }; -extern const UniformDef g_draw2Duniforms[4]; +extern const UniformDef g_draw2Duniforms[5]; struct Draw2DPipeline { Draw::Pipeline *pipeline; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9768449970..05289365e8 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -974,7 +974,7 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir // Some GPUs can copy depth but only if stencil gets to come along for the ride. We only want to use this if there is no blit functionality. if (useRaster) { - BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_R16_TO_DEPTH), "BlitDepthRaster"); + BlitUsingRaster(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, false, dst->renderScaleFactor, Get2DPipeline(Draw2DShader::DRAW2D_COPY_DEPTH), "BlitDepthRaster"); } else if (useCopy) { draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, w, h, 1, Draw::FB_DEPTH_BIT, "CopyFramebufferDepth"); RebindFramebuffer("After BlitFramebufferDepth"); @@ -2964,9 +2964,10 @@ void FramebufferManagerCommon::ReleasePipelines() { DoRelease(stencilReadbackPipeline_); DoRelease(depthReadbackSampler_); DoRelease(depthReadbackPipeline_); - DoRelease(draw2DPipelineColor_); + DoRelease(draw2DPipelineCopyColor_); DoRelease(draw2DPipelineColorRect2Lin_); - DoRelease(draw2DPipelineDepth_); + DoRelease(draw2DPipelineCopyDepth_); + DoRelease(draw2DPipelineEncodeDepth_); DoRelease(draw2DPipeline565ToDepth_); DoRelease(draw2DPipeline565ToDepthDeswizzle_); } @@ -3036,7 +3037,7 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa // Rearrange to strip form. std::swap(coord[2], coord[3]); - draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_COPY_R16_TO_DEPTH : DRAW2D_COPY_COLOR)); + draw2D_.DrawStrip2D(nullptr, coord, 4, (flags & DRAWTEX_LINEAR) != 0, Get2DPipeline((flags & DRAWTEX_DEPTH) ? DRAW2D_ENCODE_R16_TO_DEPTH : DRAW2D_COPY_COLOR)); gstate_c.Dirty(DIRTY_ALL_RENDER_STATE); } @@ -3135,7 +3136,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, channel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST, tag); } else { - Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_R16_TO_DEPTH); + Draw2DPipeline *pipeline = Get2DPipeline(channel == RASTER_COLOR ? DRAW2D_COPY_COLOR : DRAW2D_COPY_DEPTH); Draw::Framebuffer *srcFBO = src->fbo; if (src == dst) { Draw::Framebuffer *tempFBO = GetTempFBO(TempFBO::BLIT, src->renderWidth, src->renderHeight); diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index df33d549b4..ea4565e6c0 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -605,9 +605,10 @@ protected: Draw::SamplerState *depthReadbackSampler_ = nullptr; // Draw2D pipelines - Draw2DPipeline *draw2DPipelineColor_ = nullptr; + Draw2DPipeline *draw2DPipelineCopyColor_ = nullptr; Draw2DPipeline *draw2DPipelineColorRect2Lin_ = nullptr; - Draw2DPipeline *draw2DPipelineDepth_ = nullptr; + Draw2DPipeline *draw2DPipelineCopyDepth_ = nullptr; + Draw2DPipeline *draw2DPipelineEncodeDepth_ = nullptr; Draw2DPipeline *draw2DPipeline565ToDepth_ = nullptr; Draw2DPipeline *draw2DPipeline565ToDepthDeswizzle_ = nullptr; From 66bd9cde142e50789ad961419793c194d6b8ba79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 19:39:25 +0100 Subject: [PATCH 091/424] Revert accidental armips change --- ext/armips | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/armips b/ext/armips index 6719edebaa..7bd1ec93d4 160000 --- a/ext/armips +++ b/ext/armips @@ -1 +1 @@ -Subproject commit 6719edebaae03330ee5441d9b28280672edf00d5 +Subproject commit 7bd1ec93d4586985ba1ef420b43b5e620f68695e From 7d40ed6ba12d0b446d3754904ab1ef16ecd36110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Feb 2023 23:42:55 +0100 Subject: [PATCH 092/424] Tilt control: Split the deadzone parameter since it needs to be different for different types. Can at least share the string without problems. Also rearrange the settings a little bit. --- Core/Config.cpp | 3 ++- Core/Config.h | 13 +++++++------ Core/TiltEventProcessor.cpp | 34 ++++++++++++++++----------------- Core/TiltEventProcessor.h | 2 +- UI/EmuScreen.cpp | 21 -------------------- UI/NativeApp.cpp | 2 +- UI/TiltAnalogSettingsScreen.cpp | 14 +++++++++----- 7 files changed, 37 insertions(+), 52 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index a280c1946f..9e4aff034b 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -977,7 +977,8 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("TiltInvertY", &g_Config.bInvertTiltY, false, true, true), ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 70, true, true), ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 70, true, true), - ConfigSetting("DeadzoneRadius", &g_Config.fDeadzoneRadius, 0.0f, true, true), + ConfigSetting("TiltAnalogDeadzoneRadius", &g_Config.fTiltAnalogDeadzoneRadius, 0.0f, true, true), + ConfigSetting("TiltDigitalDeadzoneRadius", &g_Config.fTiltDigitalDeadzoneRadius, 0.15f, true, true), ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, true, true), #endif diff --git a/Core/Config.h b/Core/Config.h index b88e37520f..552f99299c 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -287,14 +287,15 @@ public: // This is the held base angle, that we compute the tilt relative from. float fTiltBaseAngleY; // whether the x axes and y axes should invert directions (left becomes right, top becomes bottom.) - // TODO: Do we really need these? - bool bInvertTiltX, bInvertTiltY; - //the sensitivity of the tilt in the x direction + bool bInvertTiltX; + bool bInvertTiltY; + // The sensitivity of the tilt in the X and Y directions, separately. int iTiltSensitivityX; - //the sensitivity of the tilt in the Y direction int iTiltSensitivityY; - //the deadzone radius of the tilt - float fDeadzoneRadius; + // The deadzone radius of the tilt. + // Separate settings for analog vs digital since the usable ranges differ. + float fTiltAnalogDeadzoneRadius; + float fTiltDigitalDeadzoneRadius; //type of tilt input currently selected: Defined in TiltEventProcessor.h //0 - no tilt, 1 - analog stick, 2 - D-Pad, 3 - Action Buttons (Tri, Cross, Square, Circle) int iTiltInputType; diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 8f1f3d4303..536c8b90d8 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -28,7 +28,7 @@ void GenerateTriggerButtonEvent(const Tilt &tilt); // deadzone is normalized - 0 to 1 // sensitivity controls how fast the deadzone reaches max value -inline float tiltInputCurve(float x, float deadzone, float sensitivity) { +inline float TiltInputCurve(float x, float deadzone, float sensitivity) { const float factor = sensitivity * 1.0f / (1.0f - deadzone); if (x > deadzone) { @@ -41,28 +41,26 @@ inline float tiltInputCurve(float x, float deadzone, float sensitivity) { } // dampen the tilt according to the given deadzone amount. -inline Tilt dampTilt(const Tilt &tilt, float deadzone, float xSensitivity, float ySensitivity) { +inline Tilt DampenTilt(const Tilt &tilt, float deadzone, float xSensitivity, float ySensitivity) { //multiply sensitivity by 2 so that "overshoot" is possible. I personally prefer a //sensitivity >1 for kingdom hearts and < 1 for Gods Eater. so yes, overshoot is nice //to have. - return Tilt(tiltInputCurve(tilt.x_, deadzone, 2.0f * xSensitivity), tiltInputCurve(tilt.y_, deadzone, 2.0f * ySensitivity)); + return Tilt( + TiltInputCurve(tilt.x_, deadzone, 2.0f * xSensitivity), + TiltInputCurve(tilt.y_, deadzone, 2.0f * ySensitivity) + ); } -inline float clamp(float f) { - if (f > 1.0f) return 1.0f; - if (f < -1.0f) return -1.0f; - return f; -} - -Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity) { +Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity) { if (landscape) { std::swap(x, y); } else { x *= -1.0f; } - Lin::Vec3 down(x, y, z); - down.normalize(); + float deadzone = g_Config.iTiltInputType > 1 ? g_Config.fTiltDigitalDeadzoneRadius : g_Config.fTiltAnalogDeadzoneRadius; + + Lin::Vec3 down = Lin::Vec3(x, y, z).normalized(); float angleAroundX = atan2(down.z, down.y); float yAngle = angleAroundX - calibrationAngle; @@ -79,12 +77,8 @@ Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, transformedTilt.y_ *= -1.0f; } - // For the button mappings to work, we need a minimum deadzone. - // Analog stick though is better off with a zero one but any can work. - float actualDeadzone = g_Config.iTiltInputType == TILT_ANALOG ? deadzone : std::max(0.2f, deadzone); - // finally, dampen the tilt according to our curve. - return dampTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); + return DampenTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); } void TranslateTiltToInput(const Tilt &tilt) { @@ -113,6 +107,12 @@ void TranslateTiltToInput(const Tilt &tilt) { } } +inline float clamp(float f) { + if (f > 1.0f) return 1.0f; + if (f < -1.0f) return -1.0f; + return f; +} + void GenerateAnalogStickEvent(const Tilt &tilt) { __CtrlSetAnalogXY(CTRL_STICK_LEFT, clamp(tilt.x_), clamp(tilt.y_)); } diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index 9504dc90e5..fb7156b9a2 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -11,7 +11,7 @@ struct Tilt { // generates a tilt in the correct coordinate system based on // calibration. x, y, z is the current accelerometer reading (with no conversion). -Tilt GenTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float deadzone, float xSensitivity, float ySensitivity); +Tilt GenTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity); void TranslateTiltToInput(const Tilt &tilt); void ResetTiltEvents(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index fbc6a7bfb3..28287cc786 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -542,27 +542,6 @@ void EmuScreen::sendMessage(const char *message, const char *value) { } } -//tiltInputCurve implements a smooth deadzone as described here: -//http://www.gamasutra.com/blogs/JoshSutphin/20130416/190541/Doing_Thumbstick_Dead_Zones_Right.php -inline float tiltInputCurve(float x) { - const float deadzone = g_Config.fDeadzoneRadius; - const float factor = 1.0f / (1.0f - deadzone); - - if (x > deadzone) { - return (x - deadzone) * (x - deadzone) * factor; - } else if (x < -deadzone) { - return -(x + deadzone) * (x + deadzone) * factor; - } else { - return 0.0f; - } -} - -inline float clamp1(float x) { - if (x > 1.0f) return 1.0f; - if (x < -1.0f) return -1.0f; - return x; -} - void EmuScreen::touch(const TouchInput &touch) { Core_NotifyActivity(); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 2de45b8861..bd3a062f82 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1405,7 +1405,7 @@ void NativeAxis(const AxisInput &axis) { bool landscape = dp_yres < dp_xres; // now transform out current tilt to the calibrated coordinate system Tilt trueTilt = GenTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, - g_Config.bInvertTiltX, g_Config.bInvertTiltY, g_Config.fDeadzoneRadius, + g_Config.bInvertTiltX, g_Config.bInvertTiltY, xSensitivity, ySensitivity); TranslateTiltToInput(trueTilt); diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index a79317e85a..ff0bc965f2 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -120,15 +120,19 @@ void TiltAnalogSettingsScreen::CreateViews() { calibrate->SetEnabledFunc(enabledFunc); settings->Add(calibrate); + settings->Add(new ItemHeader(co->T("Sensitivity"))); + if (g_Config.iTiltInputType > 1) { + settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltDigitalDeadzoneRadius, 0.05f, 0.5f, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); + } else { + settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltAnalogDeadzoneRadius, 0.0f, 0.8f, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); + } + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); + settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); + settings->Add(new ItemHeader(co->T("Invert Axes"))); settings->Add(new CheckBox(&g_Config.bInvertTiltX, co->T("Invert Tilt along X axis")))->SetEnabledFunc(enabledFunc); settings->Add(new CheckBox(&g_Config.bInvertTiltY, co->T("Invert Tilt along Y axis")))->SetEnabledFunc(enabledFunc); - settings->Add(new ItemHeader(co->T("Sensitivity"))); - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); - settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityY, 0, 100, co->T("Tilt Sensitivity along Y axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); - settings->Add(new PopupSliderChoiceFloat(&g_Config.fDeadzoneRadius, 0.0, 1.0, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); - settings->Add(new BorderView(BORDER_BOTTOM, BorderStyle::HEADER_FG, 2.0f, new LayoutParams(FILL_PARENT, 40.0f))); settings->Add(new Choice(di->T("Back")))->OnClick.Handle(this, &UIScreen::OnBack); } From c8daec9f4057f65ade42dd8c2e0472644ce561b0 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 12 Feb 2023 09:28:02 +0100 Subject: [PATCH 093/424] OpenXR - Do not block stereo if world unit is not specified --- Common/VR/PPSSPPVR.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index d30511ad20..20a54ab678 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -637,10 +637,8 @@ bool StartVRRender() { // Get 6DoF scale float scale = 1.0f; - bool hasUnitScale = false; if (PSP_CoreParameter().compat.vrCompat().UnitsPerMeter > 0) { scale = PSP_CoreParameter().compat.vrCompat().UnitsPerMeter; - hasUnitScale = true; } // Update matrices @@ -739,7 +737,7 @@ bool StartVRRender() { M[11] += side.z; } // Stereoscopy - if (hasUnitScale && (matrix == VR_VIEW_MATRIX_RIGHT_EYE)) { + if (matrix == VR_VIEW_MATRIX_RIGHT_EYE) { float dx = fabs(invViewTransform[1].position.x - invViewTransform[0].position.x); float dy = fabs(invViewTransform[1].position.y - invViewTransform[0].position.y); float dz = fabs(invViewTransform[1].position.z - invViewTransform[0].position.z); @@ -758,15 +756,14 @@ bool StartVRRender() { } // Decide if the scene is 3D or not - bool stereo = hasUnitScale && g_Config.bEnableStereo; bool vrIncompatibleGame = PSP_CoreParameter().compat.vrCompat().ForceFlatScreen; bool vrScene = !vrFlatForced && (g_Config.bManualForceVR || (vr3DGeometryCount > 15)); VR_SetConfigFloat(VR_CONFIG_CANVAS_ASPECT, 480.0f / 272.0f); if (g_Config.bEnableVR && !vrIncompatibleGame && (appMode == VR_GAME_MODE) && vrScene) { - VR_SetConfig(VR_CONFIG_MODE, stereo ? VR_MODE_STEREO_6DOF : VR_MODE_MONO_6DOF); + VR_SetConfig(VR_CONFIG_MODE, g_Config.bEnableStereo ? VR_MODE_STEREO_6DOF : VR_MODE_MONO_6DOF); vrFlatGame = false; } else { - VR_SetConfig(VR_CONFIG_MODE, stereo ? VR_MODE_STEREO_SCREEN : VR_MODE_MONO_SCREEN); + VR_SetConfig(VR_CONFIG_MODE, g_Config.bEnableStereo ? VR_MODE_STEREO_SCREEN : VR_MODE_MONO_SCREEN); if (IsGameVRScene()) { vrFlatGame = true; } From b569c635f3bc28adf30d272591d6c07a100fa467 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 12 Feb 2023 09:36:59 +0100 Subject: [PATCH 094/424] OpenXR - Remove redundant compat values --- assets/compatvr.ini | 619 -------------------------------------------- 1 file changed, 619 deletions(-) diff --git a/assets/compatvr.ini b/assets/compatvr.ini index cb2cc9a972..7159a0b650 100644 --- a/assets/compatvr.ini +++ b/assets/compatvr.ini @@ -108,37 +108,6 @@ ELF000000 = 10.0 ULES00766 = 0.95 ULUS10241 = 0.95 -# 50 Cent: Bulletproof G Unit Edition -ULES00451 = 1.0 -ULES00452 = 1.0 -ULUS10128 = 1.0 - -# 7 Wonders of the Ancient World -ULES01037 = 1.0 -ULUS10227 = 1.0 - -# Ace Combat X: Skies of Deception -UCAS40120 = 1.0 -UCAS40169 = 1.0 -UCES00423 = 1.0 -UCKS45038 = 1.0 -UCKS45067 = 1.0 -ULJS00086 = 1.0 -ULJS19018 = 1.0 -ULUS10176 = 1.0 - -# Activision Hits Remixed -ULES00640 = 1.0 -ULUS10186 = 1.0 - -# Age of Zombies -NPEZ00044 = 1.0 -NPUZ00024 = 1.0 - -# Alien Syndrome -ULES00772 = 1.0 -ULUS10245 = 1.0 - # Ape Escape Academy NPJG00048 = 100.0 UCAS40007 = 100.0 @@ -165,10 +134,6 @@ UCKS45007 = 10.0 ULES00011 = 10.0 ULUS10017 = 10.0 -# Are You Alice? -AAPP11042 = 1.0 -ULJM05848 = 1.0 - # Army of Two: The 40th Day NPEH90028 = 128.0 NPUH90067 = 128.0 @@ -178,85 +143,9 @@ ULJM05643 = 128.0 ULJM05849 = 128.0 ULUS10472 = 128.0 -# Armored Core 3 Portable -NPEH00045 = 1.0 -NPUH10023 = 1.0 -UCAS40268 = 1.0 -ULJM05492 = 1.0 -ULKS46210 = 1.0 - -# Armored Core: Formula Front - Extreme Battle -NPJH50041 = 1.0 -UCAS40004 = 1.0 -UCAS40036 = 1.0 -ULES00219 = 1.0 -ULJS00003 = 1.0 -ULJS19001 = 1.0 -ULKS46003 = 1.0 -ULUS10034 = 1.0 - -# Armored Core: Last Raven Portable -NPEH00046 = 1.0 -NPUH10024 = 1.0 -ULJM05611 = 1.0 -UCAS40302 = 1.0 -UCKS45148 = 1.0 - -# Assassin's Creed: Bloodlines -NPEH00029 = 1.0 -NPUH10032 = 1.0 -ULES01367 = 1.0 -ULKS46231 = 1.0 -ULJM05571 = 1.0 -ULJM05720 = 1.0 -ULUS10455 = 1.0 - -# Astonishia Story -ULES00363 = 1.0 -ULJM05176 = 1.0 -ULKS46021 = 1.0 -ULUS10083 = 1.0 - -# Atari Classics Evolved -ULUS10325 = 1.0 - -# ATV Offroad Fury Pro -UCES00786 = 1.0 -UCUS98648 = 1.0 -UCUS98681 = 1.0 - # Audition Portable ULKS46122 = 32.0 -# B-Boy -UCED00432 = 1.0 -UCES00249 = 1.0 -ULUS10363 = 1.0 - -# Battle Poker -NPUZ00020 = 1.0 - -# BattleZone -ULES00522 = 1.0 -ULET00456 = 1.0 -ULUS10156 = 1.0 - -# Beam 'em up -NPEZ00081 = 1.0 - -# Beaterator -ULES01023 = 1.0 -ULUS10405 = 1.0 - -# Beats -NPEG00001 = 1.0 -NPHG00002 = 1.0 -NPJG00001 = 1.0 -NPUG80060 = 1.0 - -# Big head snooker -NPEZ00104 = 1.0 - # Black Rock Shooter: The Game JRPG00001 = 80.0 JRPG00002 = 80.0 @@ -265,29 +154,6 @@ NPJH50448 = 80.0 NPUH10126 = 80.0 ULJM05859 = 80.0 -# Blast Off -NPEZ00041 = 1.0 -NPUZ00021 = 1.0 - -# BlazBlue: Calamity Trigger Portable -NPJH50180 = 1.0 -UCAS40299 = 1.0 -ULJM05613 = 1.0 -ULJM05970 = 1.0 -ULUS10519 = 1.0 - -# BlazBlue: Continuum Shift II -NPJH50401 = 1.0 -UCKS45170 = 1.0 -ULES01526 = 1.0 -ULJM05850 = 1.0 -ULUS10579 = 1.0 - -# Bleach: Heat the Soul 1 -UCAS40011 = 1.0 -UCJS18005 = 1.0 -UCJS10008 = 1.0 - # Bleach: Heat the Soul 2 UCAS40024 = 0.98 UCAS40130 = 0.98 @@ -325,26 +191,6 @@ UCJS10110 = 0.96 UCJS18057 = 0.96 UCKS45158 = 0.96 -# Bleach: Soul Carnival 1 -NPJG00008 = 1.0 -UCAS40227 = 1.0 -UCAS40234 = 1.0 -UCAS40296 = 1.0 -UCJS10085 = 1.0 -UCJS18038 = 1.0 -UCKS45102 = 1.0 -ULJS10085 = 1.0 - -# Bleach: Soul Carnival 2 -NPJG00070 = 1.0 -UCJS10106 = 1.0 -UCAS40291 = 1.0 -UCAS40297 = 1.0 - -# Bloons -NPEZ00045 = 1.0 -NPUZ00010 = 1.0 - # Bomberman Land Portable NPJH50142 = 10.0 ULAS42097 = 10.0 @@ -353,22 +199,11 @@ ULJM05181 = 10.0 ULJM05319 = 10.0 ULUS10319 = 10.0 -# Bowling 3D -NPUZ00002 = 1.0 - # Brain Challenge NPEH00003 = 30.0 NPJH00002 = 30.0 NPUH10006 = 30.0 -# BreakQuest -NPEZ00011 = 1.0 -NPUZ00031 = 1.0 - -# Bubble Trubble -NPEZ00023 = 1.0 -NPUZ00007 = 1.0 - # Burnout Legends ULES00125 = 2.0 ULUS10025 = 2.0 @@ -378,27 +213,11 @@ ULJM05049 = 2.0 ULKS46027 = 2.0 ULAS42019 = 2.0 -# Bust-A-Move Deluxe -NPJH50087 = 1.0 -ULES00233 = 1.0 -ULUS10057 = 1.0 -ULJM05116 = 1.0 - -# Cabela's African Safari -ULUS10175 = 1.0 - # Call of Duty: Roads to Victory ULES00643 = 1.05 ULES00644 = 1.05 ULUS10218 = 1.05 -# Capcom Classics Collection Reloaded -ULAS42072 = 1.0 -ULES00377 = 1.0 -ULJM05104 = 1.0 -ULJM05280 = 1.0 -ULUS10134 = 1.0 - # Castlevania: The Dracula X Chronicles NPJH50028 = 100.0 ULES00841 = 100.0 @@ -406,61 +225,18 @@ ULJM05287 = 100.0 ULKS46155 = 100.0 ULUS10277 = 100.0 -# Championship Manager -ULES00174 = 1.0 - -# Charge! Tank Squad -NPEX00005 = 1.0 -NPJG00103 = 1.0 -NPUX80433 = 1.0 - -# Chessmaster: The Art of Learning -ULES01013 = 1.0 -ULUS10335 = 1.0 - -# Circles, Circles, Circles -NPEZ00007 = 1.0 -NPUZ00028 = 1.0 - -# Coded Arms: Contagion -ULAS42099 = 1.0 -ULES00718 = 1.0 -ULJM05243 = 1.0 -ULKS46139 = 1.0 -ULUS10184 = 1.0 - # Coded Soul: Uketsugareshi Idea NPJG00043 = 9.5 UCAS40180 = 9.5 UCJS10061 = 9.5 UCKS45071 = 9.5 -# Crash Tag Team Racing -ULES00168 = 1.0 -ULES00169 = 1.0 -ULES00170 = 1.0 -ULES00171 = 1.0 -ULES00172 = 1.0 -ULJM05036 = 1.0 -ULUS10044 = 1.0 - # Crazy Taxi: Fare Wars NPJH50490 = 10.0 ULES00811 = 10.0 ULJM05340 = 10.0 ULUS10273 = 10.0 -# Creature Defense -NPEH00027 = 1.0 -NPJH00006 = 1.0 -NPUH10034 = 1.0 - -# Crimson Gem Saga -UCAS40212 = 1.0 -ULJM05369 = 1.0 -ULKS46142 = 1.0 -ULUS10400 = 1.0 - # Crimson Room Reverse NPJH50046 = 32.0 NPUH10037 = 32.0 @@ -480,26 +256,11 @@ ULJM05275 = 100.0 ULJM05517 = 100.0 ULUS10336 = 100.0 -# Crush -ULES00765 = 1.0 -ULUS10238 = 1.0 - -# Crystal Defenders -NPEH00017 = 1.0 -NPJH00005 = 1.0 -NPJH90066 = 1.0 -NPUH10026 = 1.0 -NPUH90048 = 1.0 - # Cube ULES00722 = 10.0 ULJS00108 = 10.0 ULUS10223 = 10.0 -# Cubixx -NPEZ00101 = 1.0 -NPUZ00080 = 1.0 - # D-Cube Planet NPEZ00008 = 20.0 NPUZ00027 = 20.0 @@ -527,67 +288,6 @@ ULJM08046 = 0.8 ULKS46246 = 0.8 ULUS10521 = 0.8 -# Death Jr. -ULES00144 = 1.0 -ULUS10027 = 1.0 - -# Deflector -NPEZ00127 = 1.0 -NPUZ00040 = 1.0 - -# Diamond and the Sound of a Gunshot -UCJS10092 = 1.0 -UCKS45120 = 1.0 - -# Dissidia 012: Duodecim Final Fantasy -NPJH50377 = 1.0 -UCAS40333 = 1.0 -UCAS40329 = 1.0 -UCAS40335 = 1.0 -UCKS45166 = 1.0 -ULES01505 = 1.0 -ULJM05814 = 1.0 -ULJM06121 = 1.0 -ULUS10566 = 1.0 - -# Dissidia: Final Fantasy -NPEH90014 = 1.0 -NPJH50065 = 1.0 -NPJH50330 = 1.0 -NPUH90029 = 1.0 -UCAS40322 = 1.0 -ULES01270 = 1.0 -ULJM05262 = 1.0 -ULJM05405 = 1.0 -ULJM05550 = 1.0 -ULJM05760 = 1.0 -ULJM05761 = 1.0 -ULUS10437 = 1.0 - -# Disney G-Force -ULES01238 = 1.0 -ULES01239 = 1.0 -ULES01240 = 1.0 -ULUS10439 = 1.0 - -# Disney Hannah Montana: Rock Out the Show -ULES01303 = 1.0 -ULUS10431 = 1.0 - -# Disney/Pixar Cars -UCKS45018 = 1.0 -ULES00319 = 1.0 -ULES00320 = 1.0 -ULES00321 = 1.0 -ULES00322 = 1.0 -ULES00323 = 1.0 -ULES00324 = 1.0 -ULES00325 = 1.0 -ULES00326 = 1.0 -ULES00327 = 1.0 -ULJM05149 = 1.0 -ULUS10073 = 1.0 - # Disney/Pixar Ratatouille UCKS45050 = 10.0 ULES00734 = 10.0 @@ -606,32 +306,6 @@ ULES00748 = 10.0 ULES00749 = 10.0 ULUS10247 = 10.0 -# DJ Max Fever -NPEH00030 = 1.0 -ULUS10403 = 1.0 - -# DJ Max Portable 2 -ULKS46116 = 1.0 - -# DJ Max Portable 3 -NPJH50471 = 1.0 -ULKS46236 = 1.0 -ULJM05836 = 1.0 -ULJM06033 = 1.0 -ULUS10538 = 1.0 - -# DJ Max Portable: Black Square -NPJH50559 = 1.0 -ULJM06034 = 1.0 -ULKS46189 = 1.0 - -# DJ Max Portable: Clazziquai Edition -ULKS46190 = 1.0 -ULKS46191 = 1.0 - -# DJ Max Portable Hot Tunes -ULKS46240 = 1.0 - # DreamWorks Shrek the Third ULES00812 = 0.5 ULES00813 = 0.5 @@ -654,21 +328,11 @@ ULES00474 = 0.1 ULES00475 = 0.1 ULUS10146 = 0.1 -# Evangelion Shin Gekijoban: 3nd Impact -ULAS42293 = 1.0 -ULJS00408 = 1.0 -NPJH50457 = 1.0 - # F1 Grand Prix UCAS40026 = 0.1 UCES00004 = 0.1 UCJS10019 = 0.1 -# Family Guy -ULES00567 = 1.0 -ULES00601 = 1.0 -ULUS10185 = 1.0 - # Fat Princess: Fistful of Cake NPHG00025 = 80.0 NPJG00045 = 80.0 @@ -686,14 +350,6 @@ ULJM05241 = 6.8 ULJM05514 = 6.8 ULUS10251 = 6.8 -# Final Fantasy II -NPJH50407 = 1.0 -UCAS40152 = 1.0 -ULJM05245 = 1.0 -ULJM05515 = 1.0 -ULES00987 = 1.0 -ULUS10263 = 1.0 - # Final Fantasy III NPEH00134 = 8.0 NPHH00351 = 8.0 @@ -701,23 +357,6 @@ NPJH50626 = 8.0 NPUH10125 = 8.0 ULJM06133 = 8.0 -# Final Fantasy IV -NPJH50414 = 1.0 -UCAS40334 = 1.0 -UCAS40342 = 1.0 -ULES01521 = 1.0 -ULJM05855 = 1.0 -ULJM06122 = 1.0 -ULUS10560 = 1.0 - -# Final Fantasy Tactics: The War of the Lions -NPJH50408 = 1.0 -UCAS40148 = 1.0 -ULES00850 = 1.0 -ULJM05194 = 1.0 -ULJM05516 = 1.0 -ULUS10297 = 1.0 - # Final Fantasy Type-0 NPJH50443 = 100.0 NPJH50444 = 100.0 @@ -730,9 +369,6 @@ NPEG00003 = 1000.0 NPJG00004 = 1000.0 NPUG80086 = 1000.0 -# Free Running -ULES00704 = 1.0 - # Ghost in the Shell: Stand Alone Complex UCAS40025 = 83.0 UCJS10018 = 83.0 @@ -762,44 +398,6 @@ ULJS19081 = 100.0 ULKS46263 = 100.0 ULUS10563 = 100.0 -# God of War: Ghost of Sparta -NPEG00044 = 1.0 -NPHG00092 = 1.0 -NPJG00120 = 1.0 -UCAS40323 = 1.0 -UCES01401 = 1.0 -UCES01473 = 1.0 -UCJS10114 = 1.0 -UCKS45161 = 1.0 -UCUS98737 = 1.0 - -# God of War: Chains of Olympus -NPEG00023 = 1.0 -NPUG80325 = 1.0 -UCAS40191 = 1.0 -UCAS40198 = 1.0 -UCED00970 = 1.0 -UCED00971 = 1.0 -UCES00842 = 1.0 -ULJM05348 = 1.0 -UCKS45084 = 1.0 -UCUS98653 = 1.0 -UCUS98705 = 1.0 -UCUS98713 = 1.0 - -# Gran Turismo: The Real Driving Simulator -NPJG00027 = 1.0 -UCAS40265 = 1.0 -UCES01245 = 1.0 -UCJS10100 = 1.0 -UCUS98632 = 1.0 - -# Grand Theft Auto: Chinatown Wars -NPJH00138 = 1.0 -ULES01347 = 1.0 -ULJM05604 = 1.0 -ULUS10490 = 1.0 - # Grand Theft Auto: Liberty City Stories NPJH50825 = 0.5 ULES00051 = 0.5 @@ -811,32 +409,6 @@ ULJM05359 = 0.5 ULJM05885 = 0.5 ULUS10041 = 0.5 -# Grand Theft Auto: Vice City Stories -NPJH50827 = 1.0 -ULES00502 = 1.0 -ULES00503 = 1.0 -ULJM05297 = 1.0 -ULJM05395 = 1.0 -ULJM05884 = 1.0 -ULUS10160 = 1.0 - -# Gun Showdown -ULES00484 = 1.0 -ULUS10158 = 1.0 - -# Gungnir -NPEH00135 = 1.0 -NPJH50397 = 1.0 -ULJM05779 = 1.0 -ULUS10592 = 1.0 - -# Harry Potter and the Goblet of Fire -ULES00210 = 1.0 -ULES00214 = 1.0 -ULES00215 = 1.0 -ULES00216 = 1.0 -ULUS10032 = 1.0 - # Hatsune Miku: Project Diva NPJH50494 = 3.6 UCKS45123 = 3.6 @@ -849,19 +421,10 @@ NPJH50475 = 4.0 ULJM05681 = 4.0 ULJM05952 = 4.0 -# Indiana Jones and the Staff of Kings -ULES00939 = 1.0 -ULUS10316 = 1.0 - # Iron Man 2 ULES01422 = 1.000999 ULUS10497 = 1.000999 -# James Cameron's Avatar: The Game -NPEH00031 = 1.0 -ULES01357 = 1.0 -ULUS10451 = 1.0 - # Jeanne d'Arc NPJG00032 = 7.0 UCAS40129 = 7.0 @@ -873,19 +436,6 @@ UCUS98700 = 7.0 UCUS98706 = 7.0 ULAS40129 = 7.0 -# Kingdom Hearts: Birth by Sleep -UCAS40295 = 1.0 -UCAS40317 = 1.0 -UCAS40326 = 1.0 -UCKS45143 = 1.0 -UCKS45168 = 1.0 -ULES01441 = 1.0 -ULJM05600 = 1.0 -ULJM05775 = 1.0 -ULJM06213 = 1.0 -ULJM06214 = 1.0 -ULUS10505 = 1.0 - # Kingdom of Paradise 1 UCAS40018 = 9.0 UCAS40023 = 9.0 @@ -903,11 +453,6 @@ UCAS40156 = 9.0 UCJS10047 = 9.0 UCKS45034 = 9.0 -# LEGO Batman: The Videogame -NPUH90019 = 1.0 -ULES01151 = 1.0 -ULUS10380 = 1.0 - # LEGO Indiana Jones 1: The Original Adventures ULES01086 = 47.0 ULUS10365 = 47.0 @@ -916,10 +461,6 @@ ULUS10365 = 47.0 ULES01370 = 47.0 ULUS10487 = 47.0 -# LEGO Star Wars II: The Original Trilogy -ULES00479 = 1.0 -ULUS10155 = 1.0 - # LEGO Star Wars III: The Clone Wars ULES01446 = 3.0 ULUS10531 = 3.0 @@ -933,34 +474,6 @@ UCJS10028 = 5.0 UCUS98647 = 5.0 UCUS98671 = 5.0 -# LocoRoco -NPJG00057 = 1.0 -UCAS40063 = 1.0 -UCAS40157 = 1.0 -UCED90007 = 1.0 -UCES00304 = 1.0 -UCET00357 = 1.0 -UCJB98011 = 1.0 -UCJS10041 = 1.0 -UCJS18041 = 1.0 -UCKS45020 = 1.0 -UCKS45055 = 1.0 -UCUS98662 = 1.0 - -# Macross Ace Frontier -ULJS00158 = 1.0 -ULJS19029 = 1.0 - -# Me & My Katamari -NPJH50141 = 1.0 -UCAS40049 = 1.0 -UCKS45022 = 1.0 -ULAS40155 = 1.0 -ULES00339 = 1.0 -ULJS00033 = 1.0 -ULJS19009 = 1.0 -ULUS10094 = 1.0 - # Mega Man Powered Up NPJH50183 = 10.0 UCAS40208 = 10.0 @@ -986,12 +499,6 @@ ULJM08011 = 930.0 ULKS46065 = 930.0 ULUS10077 = 930.0 -# Metal Gear Solid: Digital Graphic Novel -NPJH50128 = 1.0 -ULES00382 = 1.0 -ULJM05150 = 1.0 -ULUS10108 = 1.0 - # Metal Gear Solid: Peace Walker NPEH90023 = 1000.0 NPJH50045 = 1000.0 @@ -1044,11 +551,6 @@ NPJH55800 = 100.0 ULJM05800 = 100.0 ULJM08058 = 100.0 -# Nayuta no Kiseki -NPJH50625 = 1.0 -ULJM06113 = 1.0 -ULJM08069 = 1.0 - # OutRun 2006: Coast 2 Coast ULES00262 = 10.0 ULKS46087 = 10.0 @@ -1091,20 +593,6 @@ UCUS98751 = 100.0 # Petz: Dogz Family ULUS10463 = 3.28 -# Prince of Persia Revelations -ULES00223 = 1.0 -ULUS10063 = 1.0 - -# Ratchet & Clank: Size Matters -NPJG00015 = 1.0 -UCAS40145 = 1.0 -UCES00420 = 1.0 -UCJS10052 = 1.0 -UCJS18030 = 1.0 -UCJS18047 = 1.0 -UCKS45048 = 1.0 -UCUS98633 = 1.0 - # Ridge Racer 2 NPJH50366 = 1000.0 UCAS40113 = 1000.0 @@ -1114,98 +602,22 @@ UCES00422 = 1000.0 UCKS45032 = 1000.0 ULJS00080 = 1000.0 -# Sega Rally Revo -ULAS42119 = 1.0 -ULES00910 = 1.0 -ULET00919 = 1.0 -ULJM05302 = 1.0 -ULJM05417 = 1.0 -ULUS10311 = 1.0 - -# Shin Megami Tensei: Persona 3 Portable -NPJH50040 = 1.0 -UCAS40288 = 1.0 -UCKS45140 = 1.0 -UCKS45175 = 1.0 -ULES01523 = 1.0 -ULJM05489 = 1.0 -ULJM08044 = 1.0 -ULUS10512 = 1.0 - -# Silent Hill: Origins -NPJH50051 = 1.0 -ULAS42117 = 1.0 -ULES00869 = 1.0 -ULJM05281 = 1.0 -ULKS46161 = 1.0 -ULUS10285 = 1.0 - -# Silent Hill: Shattered Memories -NPJH50148 = 1.0 -ULAS42189 = 1.0 -ULES01352 = 1.0 -ULJM05564 = 1.0 -ULJM05828 = 1.0 -ULUS10450 = 1.0 - -# SoulCalibur: Broken Destiny -NPJH50034 = 1.0 -UCKS45126 = 1.0 -ULES01298 = 1.0 -ULJS00202 = 1.0 -ULJS19055 = 1.0 -ULUS10457 = 1.0 - -# Spectral vs Generation -UCAS40102 = 1.0 -ULES00757 = 1.0 -ULJM05162 = 1.0 -ULJM05599 = 1.0 -ULUS10076 = 1.0 - # Split/Second NPJH50371 = 10.0 ULES01402 = 10.0 ULJM05812 = 10.0 ULUS10513 = 10.0 -# Spot the Differences! -NPEZ00107 = 1.0 -NPEZ00108 = 1.0 -NPUZ00034 = 1.0 - -# Star Soldier -NPJH50261 = 1.0 -ULJM05026 = 1.0 -ULJM05235 = 1.0 - # Star Trek: Tactical Assault ULES00623 = 0.01 ULUS10150 = 0.01 -# Star Wars: Battlefront II -ULAS42037 = 1.0 -ULES00183 = 1.0 -ULJM05060 = 1.0 -ULUS10053 = 1.0 - # Star Wars: The Force Unleashed ULES00981 = 100.0 ULES00982 = 100.0 ULKS46143 = 100.0 ULUS10345 = 100.0 -# Street Fighter Alpha 3 MAX -ULES00235 = 1.0 -ULJM05082 = 1.0 -ULJM05225 = 1.0 -ULUS10062 = 1.0 - -# Sword Art Online: Infinity Moment -NPJH50701 = 1.0 -ULJS00557 = 1.0 -ULJS00558 = 1.0 - # Tekken: Dark Resurrection NPJH50137 = 1000.0 UCAS40095 = 1000.0 @@ -1257,19 +669,6 @@ ULJM05798 = 100.0 ULJM06008 = 100.0 ULUS10567 = 100.0 -# The Simpsons Game -ULAS42115 = 1.0 -ULES00975 = 1.0 -ULES00976 = 1.0 -ULES00977 = 1.0 -ULES00978 = 1.0 -ULES00979 = 1.0 -ULUS10295 = 1.0 - -# The Terminator -NPEZ00140 = 1.0 -NPUZ00056 = 1.0 - # Tomb Raider: Legend ULES00283 = 256.0 ULJM05180 = 256.0 @@ -1302,24 +701,6 @@ ULJM05079 = 10.0 ULKS46023 = 10.0 ULUS10037 = 10.0 -# Wipeout Pulse -NPEG90003 = 1.0 -NPUG70008 = 1.0 -UCAS40179 = 1.0 -UCES00465 = 1.0 -UCET00713 = 1.0 -UCKS45078 = 1.0 -UCUS98712 = 1.0 - -# Wipeout Pure -NPJG00059 = 1.0 -UCAS40012 = 1.0 -UCES00001 = 1.0 -ULJM05105 = 1.0 -UCJS10007 = 1.0 -UCKS45008 = 1.0 -UCUS98612 = 1.0 - # WWE SmackDown! vs. Raw 2006 ULES00227 = 10.0 ULJM05103 = 10.0 From 3397703bb7bc2700e8822b996a03581358ee514e Mon Sep 17 00:00:00 2001 From: iota97 Date: Sun, 12 Feb 2023 11:40:50 +0100 Subject: [PATCH 095/424] Minor fix --- UI/GameSettingsScreen.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2290b5192a..1636e1bdff 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1830,8 +1830,6 @@ void DeveloperToolsScreen::CreateViews() { Draw::DrawContext *draw = screenManager()->getDrawContext(); // Experimental, will move to main graphics settings later. - list->Add(new ItemHeader(gr->T("Stereo rendering"))); - bool multiViewSupported = draw->GetDeviceCaps().multiViewSupported; auto enableStereo = [=]() -> bool { @@ -1839,6 +1837,7 @@ void DeveloperToolsScreen::CreateViews() { }; if (draw->GetDeviceCaps().multiViewSupported) { + list->Add(new ItemHeader(gr->T("Stereo rendering"))); list->Add(new CheckBox(&g_Config.bStereoRendering, gr->T("Stereo rendering"))); std::vector stereoShaderNames; From 0532b35538a5628c5c2ce79663b7215abe02ed71 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 10:06:53 -0800 Subject: [PATCH 096/424] Osk: Update by button flag consistently. --- Core/Dialog/PSPOskDialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index 9e74569cfa..e6e1ccafc4 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -350,6 +350,7 @@ int PSPOskDialog::Init(u32 oskPtr) { // Eat any keys pressed before the dialog inited. UpdateButtons(); + InitCommon(); std::lock_guard guard(nativeMutex_); nativeStatus_ = PSPOskNativeStatus::IDLE; @@ -954,6 +955,7 @@ int PSPOskDialog::Update(int animSpeed) { const int framesHeldRepeatRate = 5; UpdateButtons(); + UpdateCommon(); int selectedRow = selectedChar / numKeyCols[currentKeyboard]; int selectedExtra = selectedChar % numKeyCols[currentKeyboard]; From 89c18d8077a0dbf3d1ab975a17b5d0d72f288086 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 12:10:29 -0800 Subject: [PATCH 097/424] riscv: Cleanup missing Poison, Crash. --- Common/CommonFuncs.h | 2 ++ Common/RiscVEmitter.cpp | 12 ++++++++++++ Common/RiscVEmitter.h | 5 ++++- Core/MIPS/JitCommon/JitBlockCache.cpp | 2 +- Core/MIPS/JitCommon/JitState.cpp | 2 +- GPU/Software/RasterizerRegCache.cpp | 2 ++ GPU/Software/RasterizerRegCache.h | 7 +++++++ 7 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Common/CommonFuncs.h b/Common/CommonFuncs.h index 848a3eae83..2b2d46f91a 100644 --- a/Common/CommonFuncs.h +++ b/Common/CommonFuncs.h @@ -36,6 +36,8 @@ #define Crash() {asm ("bkpt #0");} #elif PPSSPP_ARCH(ARM64) #define Crash() {asm ("brk #0");} +#elif PPSSPP_ARCH(RISCV64) +#define Crash() {asm ("ebreak");} #else #include #define Crash() {kill(getpid(), SIGINT);} diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index bbac844fdc..6f4ad8ac79 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -4278,4 +4278,16 @@ void RiscVEmitter::C_SDSP(RiscVReg rs2, u32 uimm9) { Write16(EncodeCSS(Opcode16::C2, rs2, imm5_4_3_8_7_6, Funct3::C_SDSP)); } +void RiscVCodeBlock::PoisonMemory(int offset) { + // So we can adjust region to writable space. Might be zero. + ptrdiff_t writable = writable_ - code_; + + u32 *ptr = (u32 *)(region + offset + writable); + u32 *maxptr = (u32 *)(region + region_size - offset + writable); + // This will only write an even multiple of u32, but not much else to do. + // RiscV: 0x00100073 = EBREAK + while (ptr < maxptr) + *ptr++ = 0x00100073; +} + }; diff --git a/Common/RiscVEmitter.h b/Common/RiscVEmitter.h index 5e9b0b9f16..221a47f7a3 100644 --- a/Common/RiscVEmitter.h +++ b/Common/RiscVEmitter.h @@ -47,6 +47,8 @@ enum RiscVReg { V8, V9, V10, V11, V12, V13, V14, V15, V16, V17, V18, V19, V20, V21, V22, V23, V24, V25, V26, V27, V28, V29, V30, V31, + + INVALID_REG = 0xFFFFFFFF, }; enum class FixupBranchType { @@ -1024,13 +1026,14 @@ private: writable_ += 2; } +protected: const u8 *code_ = nullptr; u8 *writable_ = nullptr; const u8 *lastCacheFlushEnd_ = nullptr; bool autoCompress_ = false; }; -class MIPSCodeBlock : public CodeBlock { +class RiscVCodeBlock : public CodeBlock { private: void PoisonMemory(int offset) override; }; diff --git a/Core/MIPS/JitCommon/JitBlockCache.cpp b/Core/MIPS/JitCommon/JitBlockCache.cpp index 6ed9bc6427..d1498e4731 100644 --- a/Core/MIPS/JitCommon/JitBlockCache.cpp +++ b/Core/MIPS/JitCommon/JitBlockCache.cpp @@ -698,7 +698,7 @@ JitBlockDebugInfo JitBlockCache::GetBlockDebugInfo(int blockNum) const { debugInfo.targetDisasm = DisassembleArm64(block->normalEntry, block->codeSize); #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) debugInfo.targetDisasm = DisassembleX86(block->normalEntry, block->codeSize); -#elif PPSSPP_ARCH(ARM64) +#elif PPSSPP_ARCH(RISCV64) debugInfo.targetDisasm = DisassembleRV64(block->normalEntry, block->codeSize); #endif diff --git a/Core/MIPS/JitCommon/JitState.cpp b/Core/MIPS/JitCommon/JitState.cpp index 0326519245..00e87913a0 100644 --- a/Core/MIPS/JitCommon/JitState.cpp +++ b/Core/MIPS/JitCommon/JitState.cpp @@ -60,7 +60,7 @@ namespace MIPSComp { useStaticAlloc = false; enablePointerify = false; -#if PPSSPP_ARCH(ARM64) +#if PPSSPP_ARCH(ARM64) || PPSSPP_ARCH(RISCV64) useStaticAlloc = !Disabled(JitDisable::STATIC_ALLOC); // iOS/etc. may disable at runtime if Memory::base is not nicely aligned. enablePointerify = !Disabled(JitDisable::POINTERIFY); diff --git a/GPU/Software/RasterizerRegCache.cpp b/GPU/Software/RasterizerRegCache.cpp index 7806b43e03..851f6d1ceb 100644 --- a/GPU/Software/RasterizerRegCache.cpp +++ b/GPU/Software/RasterizerRegCache.cpp @@ -145,6 +145,8 @@ void RegCache::SetupABI(const std::vector &args, bool forceRetain) { for (Reg r : vecTemps) Add(r, VEC_INVALID); #endif +#elif PPSSPP_ARCH(RISCV64) + _assert_msg_(false, "Not yet implemented (no vector calling standard yet)"); #elif PPSSPP_ARCH(MIPS) _assert_msg_(false, "Not yet implemented"); #else diff --git a/GPU/Software/RasterizerRegCache.h b/GPU/Software/RasterizerRegCache.h index 546273d2ec..4b8ada5007 100644 --- a/GPU/Software/RasterizerRegCache.h +++ b/GPU/Software/RasterizerRegCache.h @@ -44,6 +44,8 @@ #include "Common/x64Emitter.h" #elif PPSSPP_ARCH(MIPS) #include "Common/MipsEmitter.h" +#elif PPSSPP_ARCH(RISCV64) +#include "Common/RiscVEmitter.h" #else #include "Common/FakeEmitter.h" #endif @@ -60,6 +62,8 @@ typedef Arm64Gen::ARM64CodeBlock BaseCodeBlock; typedef Gen::XCodeBlock BaseCodeBlock; #elif PPSSPP_ARCH(MIPS) typedef MIPSGen::MIPSCodeBlock BaseCodeBlock; +#elif PPSSPP_ARCH(RISCV64) +typedef RiscVGen::RiscVCodeBlock BaseCodeBlock; #else typedef FakeGen::FakeXCodeBlock BaseCodeBlock; #endif @@ -169,6 +173,9 @@ struct RegCache { #elif PPSSPP_ARCH(MIPS) typedef MIPSGen::MIPSReg Reg; static constexpr Reg REG_INVALID_VALUE = MIPSGen::INVALID_REG; +#elif PPSSPP_ARCH(RISCV64) + typedef RiscVGen::RiscVReg Reg; + static constexpr Reg REG_INVALID_VALUE = RiscVGen::INVALID_REG; #else typedef int Reg; static constexpr Reg REG_INVALID_VALUE = -1; From 0b05d20c0a4994fe0e340f850f5bb724416fc29e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 13:01:30 -0800 Subject: [PATCH 098/424] riscv: Fix poison with compressed instructions. --- Common/RiscVEmitter.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index 6f4ad8ac79..b061486f37 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -1021,8 +1021,12 @@ void RiscVEmitter::ReserveCodeSpace(u32 bytes) { _assert_msg_((bytes & 3) == 0 || SupportsCompressed(), "Code space should be aligned (no compressed)"); for (u32 i = 0; i < bytes / 4; i++) EBREAK(); - if (bytes & 2) - Write16(0); + if (bytes & 2) { + if (SupportsCompressed()) + C_EBREAK(); + else + Write16(0); + } } const u8 *RiscVEmitter::AlignCode16() { @@ -4285,9 +4289,11 @@ void RiscVCodeBlock::PoisonMemory(int offset) { u32 *ptr = (u32 *)(region + offset + writable); u32 *maxptr = (u32 *)(region + region_size - offset + writable); // This will only write an even multiple of u32, but not much else to do. - // RiscV: 0x00100073 = EBREAK - while (ptr < maxptr) + // RiscV: 0x00100073 = EBREAK, 0x9002 = C.EBREAK + while (ptr + 1 <= maxptr) *ptr++ = 0x00100073; + if (SupportsCompressed() && ptr < maxptr && (intptr_t)maxptr - (intptr_t)ptr >= 2) + *(u16 *)ptr = 0x9002; } }; From 219e0db4e5baf13adfd20424a22af861f63c3b7d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 13:31:39 -0800 Subject: [PATCH 099/424] riscv: Initial vertexjit. --- CMakeLists.txt | 4 + GPU/Common/VertexDecoderCommon.h | 4 + GPU/Common/VertexDecoderRiscV.cpp | 152 ++++++++++++++++++++++++++++++ GPU/GPU.vcxproj | 1 + GPU/GPU.vcxproj.filters | 3 + 5 files changed, 164 insertions(+) create mode 100644 GPU/Common/VertexDecoderRiscV.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a344e03c74..4b0206f664 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1485,6 +1485,10 @@ list(APPEND CoreExtra Core/MIPS/MIPS/MipsJit.h ) +list(APPEND CoreExtra + GPU/Common/VertexDecoderRiscV.cpp +) + if(NOT MOBILE_DEVICE) set(CoreExtra ${CoreExtra} Core/AVIDump.cpp diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 70bd18795d..7de309b406 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -37,6 +37,8 @@ #include "Common/Arm64Emitter.h" #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #include "Common/x64Emitter.h" +#elif PPSSPP_ARCH(RISCV64) +#include "Common/RiscVEmitter.h" #else #include "Common/FakeEmitter.h" #endif @@ -489,6 +491,8 @@ public: #define VERTEXDECODER_JIT_BACKEND Arm64Gen::ARM64CodeBlock #elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) #define VERTEXDECODER_JIT_BACKEND Gen::XCodeBlock +#elif PPSSPP_ARCH(RISCV64) +#define VERTEXDECODER_JIT_BACKEND RiscVGen::RiscVCodeBlock #endif diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp new file mode 100644 index 0000000000..58dfee0c9b --- /dev/null +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2023- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "ppsspp_config.h" +#if PPSSPP_ARCH(RISCV64) + +#include "Common/CPUDetect.h" +#include "Common/Log.h" +#include "Common/RiscVEmitter.h" +#include "Core/MIPS/JitCommon/JitCommon.h" +#include "GPU/GPUState.h" +#include "GPU/Common/VertexDecoderCommon.h" + +using namespace RiscVGen; + +static const RiscVReg srcReg = X10; +static const RiscVReg dstReg = X11; +static const RiscVReg counterReg = X12; + +static const RiscVReg tempReg1 = X13; +static const RiscVReg tempReg2 = X14; +static const RiscVReg tempReg3 = X15; +static const RiscVReg scratchReg = X16; + +static const RiscVReg fullAlphaReg = X17; +static const RiscVReg boundsMinUReg = X28; +static const RiscVReg boundsMinVReg = X29; +static const RiscVReg boundsMaxUReg = X30; +static const RiscVReg boundsMaxVReg = X31; + +static const RiscVReg fpScratchReg1 = F10; +static const RiscVReg fpScratchReg2 = F11; +static const RiscVReg fpScratchReg3 = F12; +static const RiscVReg fpScratchReg4 = F13; + +static const JitLookup jitLookup[] = { + {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, +}; + +JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) { + dec_ = &dec; + + BeginWrite(4096); + const u8 *start = AlignCode16(); + SetAutoCompress(true); + + bool log = false; + + if (dec.col) { + // Or LDB and skip the conditional? This is probably cheaper. + LI(fullAlphaReg, 0xFF); + } + + if (dec.tc && dec.throughmode) { + // TODO: Smarter, only when doing bounds. + LI(tempReg1, &gstate_c.vertBounds.minU); + LH(boundsMinUReg, tempReg1, offsetof(KnownVertexBounds, minU)); + LH(boundsMaxUReg, tempReg1, offsetof(KnownVertexBounds, maxU)); + LH(boundsMinVReg, tempReg1, offsetof(KnownVertexBounds, minV)); + LH(boundsMaxVReg, tempReg1, offsetof(KnownVertexBounds, maxV)); + } + + // TODO: Skipping, prescale. + + const u8 *loopStart = GetCodePtr(); + for (int i = 0; i < dec.numSteps_; i++) { + if (!CompileStep(dec, i)) { + EndWrite(); + // Reset the code ptr (effectively undoing what we generated) and return zero to indicate that we failed. + ResetCodePtr(GetOffset(start)); + char temp[1024]{}; + dec.ToString(temp); + ERROR_LOG(G3D, "Could not compile vertex decoder, failed at step %d: %s", i, temp); + return nullptr; + } + } + + ADDI(srcReg, srcReg, dec.VertexSize()); + ADDI(dstReg, dstReg, dec.decFmt.stride); + ADDI(counterReg, counterReg, -1); + BLT(R_ZERO, counterReg, loopStart); + + if (dec.col) { + LI(tempReg1, &gstate_c.vertexFullAlpha); + FixupBranch skip = BNE(R_ZERO, fullAlphaReg); + SB(fullAlphaReg, tempReg1, 0); + SetJumpTarget(skip); + } + + if (dec.tc && dec.throughmode) { + // TODO: Smarter, only when doing bounds. + LI(tempReg1, &gstate_c.vertBounds.minU); + SH(boundsMinUReg, tempReg1, offsetof(KnownVertexBounds, minU)); + SH(boundsMaxUReg, tempReg1, offsetof(KnownVertexBounds, maxU)); + SH(boundsMinVReg, tempReg1, offsetof(KnownVertexBounds, minV)); + SH(boundsMaxVReg, tempReg1, offsetof(KnownVertexBounds, maxV)); + } + + RET(); + + FlushIcache(); + + if (log) { + char temp[1024]{}; + dec.ToString(temp); + INFO_LOG(JIT, "=== %s (%d bytes) ===", temp, (int)(GetCodePtr() - start)); + std::vector lines = DisassembleRV64(start, (int)(GetCodePtr() - start)); + for (auto line : lines) { + INFO_LOG(JIT, "%s", line.c_str()); + } + INFO_LOG(JIT, "=========="); + } + + *jittedSize = (int)(GetCodePtr() - start); + EndWrite(); + return (JittedVertexDecoder)start; +} + +bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { + // See if we find a matching JIT function. + for (size_t i = 0; i < ARRAY_SIZE(jitLookup); i++) { + if (dec.steps_[step] == jitLookup[i].func) { + ((*this).*jitLookup[i].jitFunc)(); + return true; + } + } + return false; +} + +void VertexDecoderJitCache::Jit_TcFloat() { + // Just copy 64 bits. Might be nice if we could detect misaligned load perf. + LW(tempReg1, srcReg, dec_->tcoff); + LW(tempReg2, srcReg, dec_->tcoff + 4); + SW(tempReg1, dstReg, dec_->decFmt.uvoff); + SW(tempReg2, dstReg, dec_->decFmt.uvoff + 4); +} + +#endif // PPSSPP_ARCH(RISCV64) diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 0f8711b03b..625bfb112c 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -498,6 +498,7 @@ true + true true diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index 828e4c5265..e30366acb3 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -521,6 +521,9 @@ GLES + + Common + From ee10fae04e3d6238fd4a771ea795b785122cae9a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 14:45:48 -0800 Subject: [PATCH 100/424] riscv: Add basic steps to vertex decode. --- GPU/Common/VertexDecoderArm64.cpp | 2 +- GPU/Common/VertexDecoderRiscV.cpp | 232 +++++++++++++++++++++++++++++- 2 files changed, 232 insertions(+), 2 deletions(-) diff --git a/GPU/Common/VertexDecoderArm64.cpp b/GPU/Common/VertexDecoderArm64.cpp index 9743b3dc52..837e0ec830 100644 --- a/GPU/Common/VertexDecoderArm64.cpp +++ b/GPU/Common/VertexDecoderArm64.cpp @@ -722,7 +722,7 @@ void VertexDecoderJitCache::Jit_NormalS16() { void VertexDecoderJitCache::Jit_NormalFloat() { // Only need to copy 12 bytes, but copying 16 should be okay (and is faster.) - if ((dec_->posoff & 7) == 0 && (dec_->decFmt.posoff & 7) == 0) { + if ((dec_->nrmoff & 7) == 0 && (dec_->decFmt.nrmoff & 7) == 0) { LDP(INDEX_SIGNED, EncodeRegTo64(tempReg1), EncodeRegTo64(tempReg2), srcReg, dec_->nrmoff); STP(INDEX_SIGNED, EncodeRegTo64(tempReg1), EncodeRegTo64(tempReg2), dstReg, dec_->decFmt.nrmoff); } else { diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 58dfee0c9b..7d37f8ce44 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -25,6 +25,11 @@ #include "GPU/GPUState.h" #include "GPU/Common/VertexDecoderCommon.h" +static const float by128 = 1.0f / 128.0f; +static const float by16384 = 1.0f / 16384.0f; +static const float by32768 = 1.0f / 32768.0f; +static const float const65535 = 65535.0f; + using namespace RiscVGen; static const RiscVReg srcReg = X10; @@ -45,10 +50,30 @@ static const RiscVReg boundsMaxVReg = X31; static const RiscVReg fpScratchReg1 = F10; static const RiscVReg fpScratchReg2 = F11; static const RiscVReg fpScratchReg3 = F12; -static const RiscVReg fpScratchReg4 = F13; +static const RiscVReg fpSrc[3] = { F13, F14, F15 }; + +// TODO: Use vector, where supported. static const JitLookup jitLookup[] = { + {&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat}, + {&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat}, {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, + + {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, + + {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, + {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, + {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, + + {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, + {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, + {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, + + {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, + {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, + {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloatThrough}, + + {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, }; JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) { @@ -141,6 +166,18 @@ bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { return false; } +void VertexDecoderJitCache::Jit_TcU8ToFloat() { + Jit_AnyU8ToFloat(dec_->tcoff, 16); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU16ToFloat() { + Jit_AnyU16ToFloat(dec_->tcoff, 32); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + void VertexDecoderJitCache::Jit_TcFloat() { // Just copy 64 bits. Might be nice if we could detect misaligned load perf. LW(tempReg1, srcReg, dec_->tcoff); @@ -149,4 +186,197 @@ void VertexDecoderJitCache::Jit_TcFloat() { SW(tempReg2, dstReg, dec_->decFmt.uvoff + 4); } +void VertexDecoderJitCache::Jit_TcFloatThrough() { + // Just copy 64 bits. Might be nice if we could detect misaligned load perf. + LW(tempReg1, srcReg, dec_->tcoff); + LW(tempReg2, srcReg, dec_->tcoff + 4); + SW(tempReg1, dstReg, dec_->decFmt.uvoff); + SW(tempReg2, dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_NormalS8() { + LB(tempReg1, srcReg, dec_->nrmoff); + LB(tempReg2, srcReg, dec_->nrmoff + 1); + LB(tempReg3, srcReg, dec_->nrmoff + 2); + SB(tempReg1, dstReg, dec_->decFmt.nrmoff); + SB(tempReg2, dstReg, dec_->decFmt.nrmoff + 1); + SB(tempReg3, dstReg, dec_->decFmt.nrmoff + 2); + SB(R_ZERO, dstReg, dec_->decFmt.nrmoff + 3); +} + +void VertexDecoderJitCache::Jit_NormalS16() { + LH(tempReg1, srcReg, dec_->nrmoff); + LH(tempReg2, srcReg, dec_->nrmoff + 2); + LH(tempReg3, srcReg, dec_->nrmoff + 4); + SH(tempReg1, dstReg, dec_->decFmt.nrmoff); + SH(tempReg2, dstReg, dec_->decFmt.nrmoff + 2); + SH(tempReg3, dstReg, dec_->decFmt.nrmoff + 4); + SH(R_ZERO, dstReg, dec_->decFmt.nrmoff + 6); +} + +void VertexDecoderJitCache::Jit_NormalFloat() { + // Just copy 12 bytes, play with over read/write later. + LW(tempReg1, srcReg, dec_->nrmoff); + LW(tempReg2, srcReg, dec_->nrmoff + 4); + LW(tempReg3, srcReg, dec_->nrmoff + 8); + SW(tempReg1, dstReg, dec_->decFmt.nrmoff); + SW(tempReg2, dstReg, dec_->decFmt.nrmoff + 4); + SW(tempReg3, dstReg, dec_->decFmt.nrmoff + 8); +} + +void VertexDecoderJitCache::Jit_PosS8() { + Jit_AnyS8ToFloat(dec_->posoff); + FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); + FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); +} + +void VertexDecoderJitCache::Jit_PosS16() { + Jit_AnyS16ToFloat(dec_->posoff); + FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); + FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); +} + +void VertexDecoderJitCache::Jit_PosFloat() { + // Just copy 12 bytes, play with over read/write later. + LW(tempReg1, srcReg, dec_->posoff); + LW(tempReg2, srcReg, dec_->posoff + 4); + LW(tempReg3, srcReg, dec_->posoff + 8); + SW(tempReg1, dstReg, dec_->decFmt.posoff); + SW(tempReg2, dstReg, dec_->decFmt.posoff + 4); + SW(tempReg3, dstReg, dec_->decFmt.posoff + 8); +} + +void VertexDecoderJitCache::Jit_PosS8Through() { + // 8-bit positions in throughmode always decode to 0, depth included. + SW(R_ZERO, dstReg, dec_->decFmt.posoff); + SW(R_ZERO, dstReg, dec_->decFmt.posoff + 4); + SW(R_ZERO, dstReg, dec_->decFmt.posoff + 8); +} + +void VertexDecoderJitCache::Jit_PosS16Through() { + // Start with X and Y (which are signed.) + LH(tempReg1, srcReg, dec_->posoff + 0); + LH(tempReg2, srcReg, dec_->posoff + 2); + // This one, Z, has to be unsigned. + LHU(tempReg3, srcReg, dec_->posoff + 4); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); + FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); + FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); +} + +void VertexDecoderJitCache::Jit_PosFloatThrough() { + // Start by copying 8 bytes, then handle Z separately to clamp it. + LW(tempReg1, srcReg, dec_->posoff); + LW(tempReg2, srcReg, dec_->posoff + 4); + FL(32, fpSrc[2], srcReg, dec_->posoff + 8); + SW(tempReg1, dstReg, dec_->decFmt.posoff); + SW(tempReg2, dstReg, dec_->decFmt.posoff + 4); + + // Load the constants to clamp. Maybe could static alloc this constant in a reg. + LI(scratchReg, const65535); + FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + + FMAX(32, fpSrc[2], fpSrc[2], fpScratchReg1); + FMIN(32, fpSrc[2], fpSrc[2], fpScratchReg2); + FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); +} + +void VertexDecoderJitCache::Jit_Color8888() { + LW(tempReg1, srcReg, dec_->coloff); + + // Set tempReg2=-1 if full alpha, 0 otherwise. + SRLI(tempReg2, tempReg1, 24); + SLTIU(tempReg2, tempReg2, 0xFF); + ADDI(tempReg2, tempReg2, -1); + + // Now use that as a mask to set/clear fullAlpha. + AND(fullAlphaReg, fullAlphaReg, tempReg2); + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { + LB(tempReg1, srcReg, srcoff + 0); + LB(tempReg2, srcReg, srcoff + 1); + LB(tempReg3, srcReg, srcoff + 2); + // TODO: Could maybe static alloc? + LI(scratchReg, by128); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[2], tempReg3, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); +} + +void VertexDecoderJitCache::Jit_AnyS16ToFloat(int srcoff) { + LH(tempReg1, srcReg, srcoff + 0); + LH(tempReg2, srcReg, srcoff + 2); + LH(tempReg3, srcReg, srcoff + 4); + // TODO: Could maybe static alloc? + LI(scratchReg, by32768); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[2], tempReg3, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); +} + +void VertexDecoderJitCache::Jit_AnyU8ToFloat(int srcoff, u32 bits) { + _dbg_assert_msg_((bits & ~(16 | 8)) == 0, "Bits must be a multiple of 8."); + _dbg_assert_msg_(bits >= 8 && bits <= 24, "Bits must be a between 8 and 24."); + + LBU(tempReg1, srcReg, srcoff + 0); + if (bits >= 16) + LBU(tempReg2, srcReg, srcoff + 1); + if (bits >= 24) + LBU(tempReg3, srcReg, srcoff + 2); + // TODO: Could maybe static alloc? + LI(scratchReg, by128); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + if (bits >= 16) + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + if (bits >= 24) + FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); + if (bits >= 16) + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); + if (bits >= 24) + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); +} + +void VertexDecoderJitCache::Jit_AnyU16ToFloat(int srcoff, u32 bits) { + _dbg_assert_msg_((bits & ~(32 | 16)) == 0, "Bits must be a multiple of 16."); + _dbg_assert_msg_(bits >= 16 && bits <= 48, "Bits must be a between 16 and 48."); + + LHU(tempReg1, srcReg, srcoff + 0); + if (bits >= 32) + LHU(tempReg2, srcReg, srcoff + 2); + if (bits >= 48) + LHU(tempReg3, srcReg, srcoff + 4); + // TODO: Could maybe static alloc? + LI(scratchReg, by32768); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + if (bits >= 32) + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + if (bits >= 48) + FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); + if (bits >= 32) + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); + if (bits >= 48) + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); +} + #endif // PPSSPP_ARCH(RISCV64) From 77b2e63876b1b68d7aecf60761fe34f781d89928 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 19:19:12 -0800 Subject: [PATCH 101/424] riscv: Add colors to vertexjit. This don't feel very efficient, but they overall beat non-jit. --- Common/RiscVEmitter.h | 2 +- GPU/Common/VertexDecoderRiscV.cpp | 142 +++++++++++++++++++++++++++++- 2 files changed, 142 insertions(+), 2 deletions(-) diff --git a/Common/RiscVEmitter.h b/Common/RiscVEmitter.h index 221a47f7a3..7fd0ac0597 100644 --- a/Common/RiscVEmitter.h +++ b/Common/RiscVEmitter.h @@ -304,7 +304,7 @@ public: void ECALL(); void EBREAK(); - // 64-bit instructions - oens ending in W sign extend result to 32 bits. + // 64-bit instructions - ones ending in W sign extend result to 32 bits. void LWU(RiscVReg rd, RiscVReg addr, s32 simm12); void LD(RiscVReg rd, RiscVReg addr, s32 simm12); void SD(RiscVReg rs2, RiscVReg addr, s32 simm12); diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 7d37f8ce44..d72a9c3903 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -59,6 +59,7 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat}, {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, + {&VertexDecoder::Step_TcU16ThroughToFloat, &VertexDecoderJitCache::Jit_TcU16ThroughToFloat}, {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, @@ -74,6 +75,9 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloatThrough}, {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, + {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, + {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, + {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, }; JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) { @@ -186,6 +190,34 @@ void VertexDecoderJitCache::Jit_TcFloat() { SW(tempReg2, dstReg, dec_->decFmt.uvoff + 4); } +void VertexDecoderJitCache::Jit_TcU16ThroughToFloat() { + LHU(tempReg1, srcReg, dec_->tcoff + 0); + LHU(tempReg2, srcReg, dec_->tcoff + 2); + + if (cpu_info.RiscV_B) { + MINU(boundsMinUReg, boundsMinUReg, tempReg1); + MAXU(boundsMaxUReg, boundsMaxUReg, tempReg1); + MINU(boundsMinVReg, boundsMinVReg, tempReg2); + MAXU(boundsMaxVReg, boundsMaxVReg, tempReg2); + } else { + auto updateSide = [&](RiscVReg src, bool greater, RiscVReg dst) { + FixupBranch skip = BLT(greater ? dst : src, greater ? src : dst); + MV(dst, src); + SetJumpTarget(skip); + }; + + updateSide(tempReg1, false, boundsMinUReg); + updateSide(tempReg1, true, boundsMaxUReg); + updateSide(tempReg2, false, boundsMinVReg); + updateSide(tempReg2, true, boundsMaxVReg); + } + + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + void VertexDecoderJitCache::Jit_TcFloatThrough() { // Just copy 64 bits. Might be nice if we could detect misaligned load perf. LW(tempReg1, srcReg, dec_->tcoff); @@ -295,12 +327,120 @@ void VertexDecoderJitCache::Jit_Color8888() { SLTIU(tempReg2, tempReg2, 0xFF); ADDI(tempReg2, tempReg2, -1); - // Now use that as a mask to set/clear fullAlpha. + // Now use that as a mask to clear fullAlpha. AND(fullAlphaReg, fullAlphaReg, tempReg2); SW(tempReg1, dstReg, dec_->decFmt.c0off); } +void VertexDecoderJitCache::Jit_Color4444() { + LHU(tempReg1, srcReg, dec_->coloff); + + // Red... + ANDI(tempReg2, tempReg1, 0x0F); + // Move green left to position 8. + ANDI(tempReg3, tempReg1, 0xF0); + SLLI(tempReg3, tempReg3, 4); + OR(tempReg2, tempReg2, tempReg3); + // For blue, we modify tempReg1 since immediates are sign extended after 11 bits. + SRLI(tempReg1, tempReg1, 8); + ANDI(tempReg3, tempReg1, 0x0F); + SLLI(tempReg3, tempReg3, 16); + OR(tempReg2, tempReg2, tempReg3); + // And now alpha, moves 20 to get to 24. + ANDI(tempReg3, tempReg1, 0xF0); + SLLI(tempReg3, tempReg3, 20); + OR(tempReg2, tempReg2, tempReg3); + + // Now we swizzle. + SLLI(tempReg3, tempReg2, 4); + OR(tempReg2, tempReg2, tempReg3); + + // Color is down, now let's say the fullAlphaReg flag from tempReg1 (still has alpha.) + // Set tempReg1=-1 if full alpha, 0 otherwise. + SLTIU(tempReg1, tempReg1, 0xF0); + ADDI(tempReg1, tempReg1, -1); + + // Now use that as a mask to clear fullAlpha. + AND(fullAlphaReg, fullAlphaReg, tempReg1); + + SW(tempReg2, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color565() { + LHU(tempReg1, srcReg, dec_->coloff); + + // Start by extracting green. + SRLI(tempReg2, tempReg1, 5); + ANDI(tempReg2, tempReg2, 0x3F); + // And now swizzle 6 -> 8, using a wall to clear bits. + SRLI(tempReg3, tempReg2, 4); + SLLI(tempReg3, tempReg3, 8); + SLLI(tempReg2, tempReg2, 2 + 8); + OR(tempReg2, tempReg2, tempReg3); + + // Now pull blue out using a wall to isolate it. + SRLI(tempReg3, tempReg1, 11); + // And now isolate red and combine them. + ANDI(tempReg1, tempReg1, 0x1F); + SLLI(tempReg3, tempReg3, 16); + OR(tempReg1, tempReg1, tempReg3); + // Now we swizzle them together. + SRLI(tempReg3, tempReg1, 2); + SLLI(tempReg1, tempReg1, 3); + OR(tempReg1, tempReg1, tempReg3); + // But we have to clear the bits now which is annoying. + LI(tempReg3, 0x00FF00FF); + AND(tempReg1, tempReg1, tempReg3); + + // Now add green back in, and then make an alpha FF and add it too. + OR(tempReg1, tempReg1, tempReg2); + LI(tempReg3, (s32)0xFF000000); + OR(tempReg1, tempReg1, tempReg3); + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color5551() { + LHU(tempReg1, srcReg, dec_->coloff); + + // Separate each color. + SRLI(tempReg2, tempReg1, 5); + SRLI(tempReg3, tempReg1, 10); + + // Set tempReg3 to -1 if the alpha bit is set. + SLLIW(scratchReg, tempReg1, 16); + SRAIW(scratchReg, scratchReg, 31); + // Now we can mask the flag. + AND(fullAlphaReg, fullAlphaReg, scratchReg); + + // Let's move alpha into position. + SLLI(scratchReg, scratchReg, 24); + + // Mask each. + ANDI(tempReg1, tempReg1, 0x1F); + ANDI(tempReg2, tempReg2, 0x1F); + ANDI(tempReg3, tempReg3, 0x1F); + // And shift into position. + SLLI(tempReg2, tempReg2, 8); + SLLI(tempReg3, tempReg3, 16); + // Combine RGB together. + OR(tempReg1, tempReg1, tempReg2); + OR(tempReg1, tempReg1, tempReg3); + // Swizzle our 5 -> 8 + SRLI(tempReg2, tempReg1, 2); + SLLI(tempReg1, tempReg1, 3); + // Mask out the overflow in tempReg2 and combine. + LI(tempReg3, 0x00070707); + AND(tempReg2, tempReg2, tempReg3); + OR(tempReg1, tempReg1, tempReg2); + + // Add in alpha and we're done. + OR(tempReg1, tempReg1, scratchReg); + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { LB(tempReg1, srcReg, srcoff + 0); LB(tempReg2, srcReg, srcoff + 1); From dc4136d547e1b322a309dc60f5ad4455287be873 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Feb 2023 22:20:14 -0800 Subject: [PATCH 102/424] riscv: Add prescale to vertexjit. --- GPU/Common/VertexDecoderRiscV.cpp | 82 +++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index d72a9c3903..7995ac311a 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -52,6 +52,19 @@ static const RiscVReg fpScratchReg2 = F11; static const RiscVReg fpScratchReg3 = F12; static const RiscVReg fpSrc[3] = { F13, F14, F15 }; +struct UVScaleRegs { + struct { + RiscVReg u; + RiscVReg v; + } scale; + struct { + RiscVReg u; + RiscVReg v; + } offset; +}; + +static const UVScaleRegs prescaleRegs = { { F0, F1 }, { F2, F3 } }; + // TODO: Use vector, where supported. static const JitLookup jitLookup[] = { @@ -62,6 +75,10 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_TcU16ThroughToFloat, &VertexDecoderJitCache::Jit_TcU16ThroughToFloat}, {&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough}, + {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, + {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, + {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, + {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, @@ -88,6 +105,40 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int SetAutoCompress(true); bool log = false; + bool prescaleStep = false; + + // Look for prescaled texcoord steps + for (int i = 0; i < dec.numSteps_; i++) { + if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { + prescaleStep = true; + } + } + + // Keep the scale/offset in a few fp registers if we need it. + if (prescaleStep) { + LI(tempReg1, &gstate_c.uv); + FL(32, prescaleRegs.scale.u, tempReg1, 0); + FL(32, prescaleRegs.scale.v, tempReg1, 4); + FL(32, prescaleRegs.offset.u, tempReg1, 8); + FL(32, prescaleRegs.offset.v, tempReg1, 12); + if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { + LI(scratchReg, by128); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, fpScratchReg1); + FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, fpScratchReg1); + FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, fpScratchReg1); + FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, fpScratchReg1); + } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { + LI(scratchReg, by32768); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, fpScratchReg1); + FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, fpScratchReg1); + FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, fpScratchReg1); + FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, fpScratchReg1); + } + } if (dec.col) { // Or LDB and skip the conditional? This is probably cheaper. @@ -226,6 +277,37 @@ void VertexDecoderJitCache::Jit_TcFloatThrough() { SW(tempReg2, dstReg, dec_->decFmt.uvoff + 4); } +void VertexDecoderJitCache::Jit_TcU8Prescale() { + LBU(tempReg1, srcReg, dec_->tcoff + 0); + LBU(tempReg2, srcReg, dec_->tcoff + 1); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FMADD(32, fpSrc[0], fpSrc[0], prescaleRegs.scale.u, prescaleRegs.offset.u); + FMADD(32, fpSrc[1], fpSrc[1], prescaleRegs.scale.v, prescaleRegs.offset.v); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU16Prescale() { + LHU(tempReg1, srcReg, dec_->tcoff + 0); + LHU(tempReg2, srcReg, dec_->tcoff + 2); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FMADD(32, fpSrc[0], fpSrc[0], prescaleRegs.scale.u, prescaleRegs.offset.u); + FMADD(32, fpSrc[1], fpSrc[1], prescaleRegs.scale.v, prescaleRegs.offset.v); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcFloatPrescale() { + FL(32, fpSrc[0], srcReg, dec_->tcoff + 0); + FL(32, fpSrc[1], srcReg, dec_->tcoff + 4); + FMADD(32, fpSrc[0], fpSrc[0], prescaleRegs.scale.u, prescaleRegs.offset.u); + FMADD(32, fpSrc[1], fpSrc[1], prescaleRegs.scale.v, prescaleRegs.offset.v); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + void VertexDecoderJitCache::Jit_NormalS8() { LB(tempReg1, srcReg, dec_->nrmoff); LB(tempReg2, srcReg, dec_->nrmoff + 1); From 991c596490a9705eacd21427393d48e287feb4b0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 13 Feb 2023 16:57:13 -0800 Subject: [PATCH 103/424] riscv: Set constants once in vertexjit. --- GPU/Common/VertexDecoderRiscV.cpp | 86 +++++++++++++++---------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 7995ac311a..165dbab2e7 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -26,7 +26,6 @@ #include "GPU/Common/VertexDecoderCommon.h" static const float by128 = 1.0f / 128.0f; -static const float by16384 = 1.0f / 16384.0f; static const float by32768 = 1.0f / 32768.0f; static const float const65535 = 65535.0f; @@ -64,6 +63,10 @@ struct UVScaleRegs { }; static const UVScaleRegs prescaleRegs = { { F0, F1 }, { F2, F3 } }; +static const RiscVReg by128Reg = F4; +static const RiscVReg by32768Reg = F5; +// Warning: usually not valid. +static const RiscVReg const65535Reg = F6; // TODO: Use vector, where supported. @@ -106,6 +109,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int bool log = false; bool prescaleStep = false; + bool posThroughStep = false; // Look for prescaled texcoord steps for (int i = 0; i < dec.numSteps_; i++) { @@ -114,6 +118,19 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { prescaleStep = true; } + if (dec.steps_[i] == &VertexDecoder::Step_PosFloatThrough) { + posThroughStep = true; + } + } + + // TODO: Only load these when needed? + LI(scratchReg, by128); + FMV(FMv::W, FMv::X, by128Reg, scratchReg); + LI(scratchReg, by32768); + FMV(FMv::W, FMv::X, by32768Reg, scratchReg); + if (posThroughStep) { + LI(scratchReg, const65535); + FMV(FMv::W, FMv::X, const65535Reg, scratchReg); } // Keep the scale/offset in a few fp registers if we need it. @@ -124,24 +141,20 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int FL(32, prescaleRegs.offset.u, tempReg1, 8); FL(32, prescaleRegs.offset.v, tempReg1, 12); if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { - LI(scratchReg, by128); - FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); - FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, fpScratchReg1); - FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, fpScratchReg1); - FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, fpScratchReg1); - FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, fpScratchReg1); + FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, by128Reg); + FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, by128Reg); + FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, by128Reg); + FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, by128Reg); } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { - LI(scratchReg, by32768); - FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); - FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, fpScratchReg1); - FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, fpScratchReg1); - FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, fpScratchReg1); - FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, fpScratchReg1); + FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, by32768Reg); + FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, by32768Reg); + FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, by32768Reg); + FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, by32768Reg); } } if (dec.col) { - // Or LDB and skip the conditional? This is probably cheaper. + // Or LB and skip the conditional? This is probably cheaper. LI(fullAlphaReg, 0xFF); } @@ -154,7 +167,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int LH(boundsMaxVReg, tempReg1, offsetof(KnownVertexBounds, maxV)); } - // TODO: Skipping, prescale. + // TODO: Skinning. const u8 *loopStart = GetCodePtr(); for (int i = 0; i < dec.numSteps_; i++) { @@ -391,13 +404,10 @@ void VertexDecoderJitCache::Jit_PosFloatThrough() { SW(tempReg1, dstReg, dec_->decFmt.posoff); SW(tempReg2, dstReg, dec_->decFmt.posoff + 4); - // Load the constants to clamp. Maybe could static alloc this constant in a reg. - LI(scratchReg, const65535); + // Load the constant zero and clamp. Maybe could static alloc zero, but fairly cheap... FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); - FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); - FMAX(32, fpSrc[2], fpSrc[2], fpScratchReg1); - FMIN(32, fpSrc[2], fpSrc[2], fpScratchReg2); + FMIN(32, fpSrc[2], fpSrc[2], const65535Reg); FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); } @@ -527,30 +537,24 @@ void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { LB(tempReg1, srcReg, srcoff + 0); LB(tempReg2, srcReg, srcoff + 1); LB(tempReg3, srcReg, srcoff + 2); - // TODO: Could maybe static alloc? - LI(scratchReg, by128); - FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); FCVT(FConv::S, FConv::W, fpSrc[2], tempReg3, Round::TOZERO); - FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); - FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); - FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); + FMUL(32, fpSrc[0], fpSrc[0], by128Reg); + FMUL(32, fpSrc[1], fpSrc[1], by128Reg); + FMUL(32, fpSrc[2], fpSrc[2], by128Reg); } void VertexDecoderJitCache::Jit_AnyS16ToFloat(int srcoff) { LH(tempReg1, srcReg, srcoff + 0); LH(tempReg2, srcReg, srcoff + 2); LH(tempReg3, srcReg, srcoff + 4); - // TODO: Could maybe static alloc? - LI(scratchReg, by32768); - FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); FCVT(FConv::S, FConv::W, fpSrc[2], tempReg3, Round::TOZERO); - FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); - FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); - FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); + FMUL(32, fpSrc[0], fpSrc[0], by32768Reg); + FMUL(32, fpSrc[1], fpSrc[1], by32768Reg); + FMUL(32, fpSrc[2], fpSrc[2], by32768Reg); } void VertexDecoderJitCache::Jit_AnyU8ToFloat(int srcoff, u32 bits) { @@ -562,19 +566,16 @@ void VertexDecoderJitCache::Jit_AnyU8ToFloat(int srcoff, u32 bits) { LBU(tempReg2, srcReg, srcoff + 1); if (bits >= 24) LBU(tempReg3, srcReg, srcoff + 2); - // TODO: Could maybe static alloc? - LI(scratchReg, by128); - FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); if (bits >= 16) FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); if (bits >= 24) FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); - FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); + FMUL(32, fpSrc[0], fpSrc[0], by128Reg); if (bits >= 16) - FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); + FMUL(32, fpSrc[1], fpSrc[1], by128Reg); if (bits >= 24) - FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); + FMUL(32, fpSrc[2], fpSrc[2], by128Reg); } void VertexDecoderJitCache::Jit_AnyU16ToFloat(int srcoff, u32 bits) { @@ -586,19 +587,16 @@ void VertexDecoderJitCache::Jit_AnyU16ToFloat(int srcoff, u32 bits) { LHU(tempReg2, srcReg, srcoff + 2); if (bits >= 48) LHU(tempReg3, srcReg, srcoff + 4); - // TODO: Could maybe static alloc? - LI(scratchReg, by32768); - FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); if (bits >= 32) FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); if (bits >= 48) FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); - FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg1); + FMUL(32, fpSrc[0], fpSrc[0], by32768Reg); if (bits >= 32) - FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg1); + FMUL(32, fpSrc[1], fpSrc[1], by32768Reg); if (bits >= 48) - FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg1); + FMUL(32, fpSrc[2], fpSrc[2], by32768Reg); } #endif // PPSSPP_ARCH(RISCV64) From e1c391b1c80a9ad0410187e4281c37a28335213a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 13 Feb 2023 17:15:49 -0800 Subject: [PATCH 104/424] riscv: Use vertexjit for hardware skinned verts. --- GPU/Common/VertexDecoderRiscV.cpp | 43 +++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 165dbab2e7..27f3a13cec 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -71,6 +71,10 @@ static const RiscVReg const65535Reg = F6; // TODO: Use vector, where supported. static const JitLookup jitLookup[] = { + {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, + {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, + {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, + {&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat}, {&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat}, {&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat}, @@ -234,6 +238,45 @@ bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) { return false; } +void VertexDecoderJitCache::Jit_WeightsU8() { + // Just copy a byte at a time. Would be nice if we knew if misaligned access was fast. + // If it's not fast, it can crash or hit a software trap (100x slower.) + int j; + for (j = 0; j < dec_->nweights; j++) { + LB(tempReg1, srcReg, dec_->weightoff + j); + SB(tempReg1, dstReg, dec_->decFmt.w0off + j); + } + // We zero out any weights up to a multiple of 4. + while (j & 3) { + SB(R_ZERO, dstReg, dec_->decFmt.w0off + j); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsU16() { + int j; + for (j = 0; j < dec_->nweights; j++) { + LH(tempReg1, srcReg, dec_->weightoff + j * 2); + SH(tempReg1, dstReg, dec_->decFmt.w0off + j * 2); + } + while (j & 3) { + SH(R_ZERO, dstReg, dec_->decFmt.w0off + j * 2); + j++; + } +} + +void VertexDecoderJitCache::Jit_WeightsFloat() { + int j; + for (j = 0; j < dec_->nweights; j++) { + LW(tempReg1, srcReg, dec_->weightoff + j * 4); + SW(tempReg1, dstReg, dec_->decFmt.w0off + j * 4); + } + while (j & 3) { + SW(R_ZERO, dstReg, dec_->decFmt.w0off + j * 4); + j++; + } +} + void VertexDecoderJitCache::Jit_TcU8ToFloat() { Jit_AnyU8ToFloat(dec_->tcoff, 16); FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); From ada6aa77e014902717e054ca4a2bdb78a76036af Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Mon, 13 Feb 2023 17:16:27 -0800 Subject: [PATCH 105/424] riscv: Correct offset prescale in vertexjit. Also implement doubling while here. --- GPU/Common/VertexDecoderRiscV.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 27f3a13cec..b29e835318 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -21,6 +21,7 @@ #include "Common/CPUDetect.h" #include "Common/Log.h" #include "Common/RiscVEmitter.h" +#include "Core/HDRemaster.h" #include "Core/MIPS/JitCommon/JitCommon.h" #include "GPU/GPUState.h" #include "GPU/Common/VertexDecoderCommon.h" @@ -84,6 +85,8 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_TcU8Prescale, &VertexDecoderJitCache::Jit_TcU8Prescale}, {&VertexDecoder::Step_TcU16Prescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, + // We use the same jit code whether doubling or not. + {&VertexDecoder::Step_TcU16DoublePrescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, @@ -119,6 +122,7 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int for (int i = 0; i < dec.numSteps_; i++) { if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || + dec.steps_[i] == &VertexDecoder::Step_TcU16DoublePrescale || dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { prescaleStep = true; } @@ -147,13 +151,13 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_8BIT) { FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, by128Reg); FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, by128Reg); - FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, by128Reg); - FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, by128Reg); } else if ((dec.VertexType() & GE_VTYPE_TC_MASK) == GE_VTYPE_TC_16BIT) { - FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, by32768Reg); - FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, by32768Reg); - FMUL(32, prescaleRegs.offset.u, prescaleRegs.offset.u, by32768Reg); - FMUL(32, prescaleRegs.offset.v, prescaleRegs.offset.v, by32768Reg); + RiscVReg multipler = g_DoubleTextureCoordinates ? fpScratchReg1 : by32768Reg; + if (g_DoubleTextureCoordinates) { + FADD(32, fpScratchReg1, by32768Reg, by32768Reg); + } + FMUL(32, prescaleRegs.scale.u, prescaleRegs.scale.u, multipler); + FMUL(32, prescaleRegs.scale.v, prescaleRegs.scale.v, multipler); } } From a7baa3580b9c7ce40491ec4c411e89ccba2a8321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Feb 2023 10:56:09 +0100 Subject: [PATCH 106/424] Some code cleanups around rewind. --- Common/Serialize/Serializer.h | 52 +++++++++++++++++++++++------------ Core/SaveState.cpp | 52 +++++++++++++++++++++-------------- libretro/libretro.cpp | 9 +++--- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/Common/Serialize/Serializer.h b/Common/Serialize/Serializer.h index d91b9dfb2f..ba8f753c83 100644 --- a/Common/Serialize/Serializer.h +++ b/Common/Serialize/Serializer.h @@ -192,21 +192,8 @@ public: return (size_t)ptr; } - // Expects ptr to have at least MeasurePtr bytes at ptr. - template - static Error SavePtr(u8 *ptr, T &_class, size_t expected_size) - { - const u8 *expected_end = ptr + expected_size; - PointerWrap p(&ptr, PointerWrap::MODE_WRITE); - _class.DoState(p); - - if (p.error != PointerWrap::ERROR_FAILURE && (expected_end == ptr || expected_size == 0)) { - return ERROR_NONE; - } else { - return ERROR_BROKEN_STATE; - } - } - + // If *saved is null, will allocate storage using malloc. + // If it's not null, it will be used, but only hope can save you from overruns at the end. For libretro. template static Error MeasureAndSavePtr(T &_class, u8 **saved, size_t *savedSize) { @@ -216,9 +203,14 @@ public: _assert_(p.error == PointerWrap::ERROR_NONE); size_t measuredSize = p.Offset(); - u8 *data = (u8 *)malloc(measuredSize); - if (!data) - return ERROR_BAD_ALLOC; + u8 *data; + if (*saved) { + data = *saved; + } else { + data = (u8 *)malloc(measuredSize); + if (!data) + return ERROR_BAD_ALLOC; + } p.RewindForWrite(data); _class.DoState(p); @@ -233,6 +225,30 @@ public: } } + // Duplicate of the above but takes and modifies a vector. Less invasive + // than modifying the rewind manager to keep things in something else than vectors. + template + static Error MeasureAndSavePtr(T &_class, std::vector *saved) + { + u8 *ptr = nullptr; + PointerWrap p(&ptr, PointerWrap::MODE_MEASURE); + _class.DoState(p); + _assert_(p.error == PointerWrap::ERROR_NONE); + + size_t measuredSize = p.Offset(); + saved->resize(measuredSize); + u8 *data = saved->data(); + p.RewindForWrite(data); + _class.DoState(p); + if (p.CheckAfterWrite()) { + return ERROR_NONE; + } else { + saved->clear(); + return ERROR_BROKEN_STATE; + } + } + + // Load file template template static Error Load(const Path &filename, std::string *gitVersion, T& _class, std::string *failureReason) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index c28cb190a1..c3c2d8a5b2 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -91,10 +91,7 @@ namespace SaveState CChunkFileReader::Error SaveToRam(std::vector &data) { SaveStart state; - size_t sz = CChunkFileReader::MeasurePtr(state); - if (data.size() < sz) - data.resize(sz); - return CChunkFileReader::SavePtr(&data[0], state, sz); + return CChunkFileReader::MeasureAndSavePtr(state, &data); } CChunkFileReader::Error LoadFromRam(std::vector &data, std::string *errorString) { @@ -102,14 +99,24 @@ namespace SaveState return CChunkFileReader::LoadPtr(&data[0], state, errorString); } - struct StateRingbuffer - { - StateRingbuffer(int size) : first_(0), next_(0), size_(size), base_(-1) - { + // This ring buffer of states is for rewind save states, which are kept in RAM. + // Save states are compressed against one of two reference saves (bases_), and the reference + // is switched to a fresh save every N saves, where N is BASE_USAGE_INTERVAL. + // The compression is a simple block based scheme where 0 means to copy a block from the base, + // and 1 means that the following bytes are the next block. See Compress/LockedDecompress. + class StateRingbuffer { + public: + StateRingbuffer(int size) : size_(size) { states_.resize(size); baseMapping_.resize(size); } + ~StateRingbuffer() { + if (compressThread_.joinable()) { + compressThread_.join(); + } + } + CChunkFileReader::Error Save() { std::lock_guard guard(lock_); @@ -118,8 +125,7 @@ namespace SaveState if ((next_ % size_) == first_) ++first_; - static std::vector buffer; - std::vector *compressBuffer = &buffer; + std::vector *compressBuffer = &buffer_; CChunkFileReader::Error err; if (base_ == -1 || ++baseUsage_ > BASE_USAGE_INTERVAL) @@ -131,12 +137,13 @@ namespace SaveState compressBuffer = &bases_[base_]; } else - err = SaveToRam(buffer); + err = SaveToRam(buffer_); if (err == CChunkFileReader::ERROR_NONE) ScheduleCompress(&states_[n], compressBuffer, &bases_[base_]); else states_[n].clear(); + baseMapping_[n] = base_; return err; } @@ -177,18 +184,23 @@ namespace SaveState if (first_ == 0 && next_ == 0) return; + double start_time = time_now_d(); result.clear(); + result.reserve(512 * 1024); for (size_t i = 0; i < state.size(); i += BLOCK_SIZE) { int blockSize = std::min(BLOCK_SIZE, (int)(state.size() - i)); if (i + blockSize > base.size() || memcmp(&state[i], &base[i], blockSize) != 0) { result.push_back(1); - result.insert(result.end(), state.begin() + i, state.begin() +i + blockSize); + result.insert(result.end(), state.begin() + i, state.begin() + i + blockSize); } else result.push_back(0); } + + double taken_s = time_now_d() - start_time; + DEBUG_LOG(SAVESTATE, "Rewind: Compressed save from %d bytes to %d in %0.2f ms.", (int)state.size(), (int)result.size(), taken_s * 1000.0); } void LockedDecompress(std::vector &result, const std::vector &compressed, const std::vector &base) @@ -232,14 +244,15 @@ namespace SaveState return next_ == first_; } - static const int BLOCK_SIZE; + private: + static const int BLOCK_SIZE = 8192; // TODO: Instead, based on size of compressed state? - static const int BASE_USAGE_INTERVAL; + static const int BASE_USAGE_INTERVAL = 15; typedef std::vector StateBuffer; - int first_; - int next_; + int first_ = 0; + int next_ = 0; int size_; std::vector states_; @@ -247,9 +260,10 @@ namespace SaveState std::vector baseMapping_; std::mutex lock_; std::thread compressThread_; + std::vector buffer_; - int base_; - int baseUsage_; + int base_ = -1; + int baseUsage_ = 0; }; static bool needsProcess = false; @@ -273,8 +287,6 @@ namespace SaveState // TODO: Any reason for this to be configurable? const static float rewindMaxWallFrequency = 1.0f; static double rewindLastTime = 0.0f; - const int StateRingbuffer::BLOCK_SIZE = 8192; - const int StateRingbuffer::BASE_USAGE_INTERVAL = 15; void SaveStart::DoState(PointerWrap &p) { diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 8d9811dfdc..72db7aa22b 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1652,8 +1652,8 @@ size_t retro_serialize_size(void) if (useEmuThread) EmuThreadPause(); - return (CChunkFileReader::MeasurePtr(state) + 0x800000) - & ~0x7FFFFF; // We don't unpause intentionally + return (CChunkFileReader::MeasurePtr(state) + 0x800000) & ~0x7FFFFF; + // We don't unpause intentionally } bool retro_serialize(void *data, size_t size) @@ -1668,9 +1668,8 @@ bool retro_serialize(void *data, size_t size) if (useEmuThread) EmuThreadPause(); // Does nothing if already paused - size_t measured = CChunkFileReader::MeasurePtr(state); - assert(measured <= size); - auto err = CChunkFileReader::SavePtr((u8 *)data, state, measured); + size_t measuredSize; + auto err = CChunkFileReader::MeasureAndSavePtr(state, (u8 **)&data, &measuredSize); retVal = err == CChunkFileReader::ERROR_NONE; if (useEmuThread) From 5418be738bd6b2a242d5576bd9d972840d0f007e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Feb 2023 11:17:03 +0100 Subject: [PATCH 107/424] Make the rewind snapshot interval wall-time based instead of frame-based. --- Core/Config.cpp | 2 +- Core/Config.h | 2 +- Core/SaveState.cpp | 63 ++++++++++++++++++++---------------- UI/GameSettingsScreen.cpp | 4 +-- UI/PauseScreen.cpp | 2 +- assets/lang/ar_AE.ini | 2 +- assets/lang/az_AZ.ini | 2 +- assets/lang/bg_BG.ini | 2 +- assets/lang/ca_ES.ini | 2 +- assets/lang/cz_CZ.ini | 2 +- assets/lang/da_DK.ini | 2 +- assets/lang/de_DE.ini | 2 +- assets/lang/dr_ID.ini | 2 +- assets/lang/en_US.ini | 2 +- assets/lang/es_ES.ini | 2 +- assets/lang/es_LA.ini | 2 +- assets/lang/fa_IR.ini | 2 +- assets/lang/fi_FI.ini | 2 +- assets/lang/fr_FR.ini | 2 +- assets/lang/gl_ES.ini | 2 +- assets/lang/gr_EL.ini | 2 +- assets/lang/he_IL.ini | 2 +- assets/lang/he_IL_invert.ini | 2 +- assets/lang/hr_HR.ini | 2 +- assets/lang/hu_HU.ini | 2 +- assets/lang/id_ID.ini | 2 +- assets/lang/it_IT.ini | 2 +- assets/lang/ja_JP.ini | 2 +- assets/lang/jv_ID.ini | 2 +- assets/lang/ko_KR.ini | 2 +- assets/lang/lo_LA.ini | 2 +- assets/lang/lt-LT.ini | 2 +- assets/lang/ms_MY.ini | 2 +- assets/lang/nl_NL.ini | 2 +- assets/lang/no_NO.ini | 2 +- assets/lang/pl_PL.ini | 2 +- assets/lang/pt_BR.ini | 2 +- assets/lang/pt_PT.ini | 2 +- assets/lang/ro_RO.ini | 2 +- assets/lang/ru_RU.ini | 2 +- assets/lang/sv_SE.ini | 2 +- assets/lang/tg_PH.ini | 2 +- assets/lang/th_TH.ini | 2 +- assets/lang/tr_TR.ini | 2 +- assets/lang/uk_UA.ini | 2 +- assets/lang/vi_VN.ini | 2 +- assets/lang/zh_CN.ini | 2 +- assets/lang/zh_TW.ini | 2 +- 48 files changed, 84 insertions(+), 75 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 9e4aff034b..ff957a4a72 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -537,7 +537,7 @@ static const ConfigSetting generalSettings[] = { ConfigSetting("StateLoadUndoGame", &g_Config.sStateLoadUndoGame, "NA", true, false), ConfigSetting("StateUndoLastSaveGame", &g_Config.sStateUndoLastSaveGame, "NA", true, false), ConfigSetting("StateUndoLastSaveSlot", &g_Config.iStateUndoLastSaveSlot, -5, true, false), // Start with an "invalid" value - ConfigSetting("RewindFlipFrequency", &g_Config.iRewindFlipFrequency, 0, true, true), + ConfigSetting("RewindSnapshotInterval", &g_Config.iRewindSnapshotInterval, 0, true, true), ConfigSetting("ShowOnScreenMessage", &g_Config.bShowOnScreenMessages, true, true, false), ConfigSetting("ShowRegionOnGameIcon", &g_Config.bShowRegionOnGameIcon, false), diff --git a/Core/Config.h b/Core/Config.h index 552f99299c..7d90f6de8f 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -224,7 +224,7 @@ public: int iAnalogFpsMode; // 0 = auto, 1 = single direction, 2 = mapped to opposite int iMaxRecent; int iCurrentStateSlot; - int iRewindFlipFrequency; + int iRewindSnapshotInterval; bool bUISound; bool bEnableStateUndo; std::string sStateLoadUndoGame; diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index c3c2d8a5b2..50b3dad39d 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -106,9 +106,10 @@ namespace SaveState // and 1 means that the following bytes are the next block. See Compress/LockedDecompress. class StateRingbuffer { public: - StateRingbuffer(int size) : size_(size) { - states_.resize(size); - baseMapping_.resize(size); + StateRingbuffer() { + size_ = REWIND_NUM_STATES; + states_.resize(size_); + baseMapping_.resize(size_); } ~StateRingbuffer() { @@ -119,6 +120,8 @@ namespace SaveState CChunkFileReader::Error Save() { + rewindLastTime = time_now_d(); + std::lock_guard guard(lock_); int n = next_++ % size_; @@ -162,7 +165,9 @@ namespace SaveState static std::vector buffer; LockedDecompress(buffer, states_[n], bases_[baseMapping_[n]]); - return LoadFromRam(buffer, errorString); + CChunkFileReader::Error error = LoadFromRam(buffer, errorString); + rewindLastTime = time_now_d(); + return error; } void ScheduleCompress(std::vector *result, const std::vector *state, const std::vector *base) @@ -244,8 +249,29 @@ namespace SaveState return next_ == first_; } + void Process() { + if (g_Config.iRewindSnapshotInterval <= 0) { + return; + } + + // For fast-forwarding, otherwise they may be useless and too close. + double now = time_now_d(); + double diff = now - rewindLastTime; + if (diff < g_Config.iRewindSnapshotInterval) + return; + + DEBUG_LOG(SAVESTATE, "Saving rewind state"); + Save(); + } + + void NotifyState() { + // Prevent saving snapshots immediately after loading or saving a state. + rewindLastTime = time_now_d(); + } + private: static const int BLOCK_SIZE = 8192; + static const int REWIND_NUM_STATES = 20; // TODO: Instead, based on size of compressed state? static const int BASE_USAGE_INTERVAL = 15; @@ -264,6 +290,8 @@ namespace SaveState int base_ = -1; int baseUsage_ = 0; + + double rewindLastTime = 0.0f; }; static bool needsProcess = false; @@ -281,12 +309,8 @@ namespace SaveState static std::string saveStateInitialGitVersion = ""; // TODO: Should this be configurable? - static const int REWIND_NUM_STATES = 20; static const int SCREENSHOT_FAILURE_RETRIES = 15; - static StateRingbuffer rewindStates(REWIND_NUM_STATES); - // TODO: Any reason for this to be configurable? - const static float rewindMaxWallFrequency = 1.0f; - static double rewindLastTime = 0.0f; + static StateRingbuffer rewindStates; void SaveStart::DoState(PointerWrap &p) { @@ -357,6 +381,7 @@ namespace SaveState void Load(const Path &filename, int slot, Callback callback, void *cbUserData) { + rewindStates.NotifyState(); if (coreState == CoreState::CORE_RUNTIME_ERROR) Core_EnableStepping(true, "savestate.load", 0); Enqueue(Operation(SAVESTATE_LOAD, filename, slot, callback, cbUserData)); @@ -364,6 +389,7 @@ namespace SaveState void Save(const Path &filename, int slot, Callback callback, void *cbUserData) { + rewindStates.NotifyState(); if (coreState == CoreState::CORE_RUNTIME_ERROR) Core_EnableStepping(true, "savestate.save", 0); Enqueue(Operation(SAVESTATE_SAVE, filename, slot, callback, cbUserData)); @@ -778,22 +804,6 @@ namespace SaveState return false; } - static inline void CheckRewindState() - { - if (gpuStats.numFlips % g_Config.iRewindFlipFrequency != 0) - return; - - // For fast-forwarding, otherwise they may be useless and too close. - double now = time_now_d(); - float diff = now - rewindLastTime; - if (diff < rewindMaxWallFrequency) - return; - - rewindLastTime = now; - DEBUG_LOG(BOOT, "Saving rewind state"); - rewindStates.Save(); - } - bool HasLoadedState() { return hasLoadedState; } @@ -850,8 +860,7 @@ namespace SaveState void Process() { - if (g_Config.iRewindFlipFrequency != 0 && gpuStats.numFlips != 0) - CheckRewindState(); + rewindStates.Process(); if (!needsProcess) return; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 1636e1bdff..c3a17ce7e9 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1054,8 +1054,8 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { return UI::EVENT_CONTINUE; }); lockedMhz->SetZeroLabel(sy->T("Auto")); - PopupSliderChoice *rewindFreq = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindFlipFrequency, 0, 1800, sy->T("Rewind Snapshot Frequency", "Rewind Snapshot Frequency (mem hog)"), screenManager(), sy->T("frames, 0:off"))); - rewindFreq->SetZeroLabel(sy->T("Off")); + PopupSliderChoice *rewindInterval = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindSnapshotInterval, 0, 30, sy->T("Rewind Snapshot Interval"), screenManager(), sy->T("seconds, 0:off"))); + rewindInterval->SetZeroLabel(sy->T("Off")); systemSettings->Add(new ItemHeader(sy->T("General"))); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index d76824d9b1..4738e425d9 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -302,7 +302,7 @@ void GamePauseScreen::CreateViews() { saveUndoButton->OnClick.Handle(this, &GamePauseScreen::OnLastSaveUndo); } - if (g_Config.iRewindFlipFrequency > 0) { + if (g_Config.iRewindSnapshotInterval > 0) { UI::Choice *rewindButton = buttonRow->Add(new Choice(pa->T("Rewind"))); rewindButton->SetEnabled(SaveState::CanRewind()); rewindButton->OnClick.Handle(this, &GamePauseScreen::OnRewind); diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 091a2856be..699e53ef3d 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -1138,7 +1138,7 @@ Failed to save state. Error in the file system. = ‎فشل في حفظ الحا Fast (lag on slow storage) = ‎سريع (بطي علي الذواكر البطئيه) Fast Memory = ‎الذاكرة السريعة (غير ثابت) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = إطارات, 0 = ‎مُغلق +seconds, 0:off = إطارات, 0 = ‎مُغلق Games list settings = Games list settings General = ‎العام Grid icon size = Grid icon size diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 659165a6db..b030b67e94 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Sürətli Yaddaş (qərarsız) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = General Grid icon size = Grid icon size diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index b53040462f..8dbf12e598 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Бърза памет (нестабилно) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = Основни Grid icon size = Grid icon size diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 1fc5d21d19..64b19aba26 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Memòria ràpida (inestable) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = General Grid icon size = Grid icon size diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 1c4bd4f103..da88a9b085 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Rychlá (zasekává se na pomalém úložišti) Fast Memory = Rychlá paměť (nestabilní) Force real clock sync (slower, less lag) = Vynutit skutečný soulad hodin (pomalejší, méně sekání) -frames, 0:off = snímky, 0 = vypnuto +seconds, 0:off = sekundy, 0 = vypnuto Games list settings = Games list settings General = Obecné Grid icon size = Grid icon size diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 9c1da40995..b94cc282b7 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Hurtig (forsinkelser på langsomt lager) Fast Memory = Hurtig hukommelse (ustabil) Force real clock sync (slower, less lag) = Tving rigtig clock sync (langsommere, færre forsinkelser) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = Generel Grid icon size = Grid icon size diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index 6b91074989..2ac1e3b203 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Speichern des Standes ist fehl Fast (lag on slow storage) = Schnell (Lag bei langsamen Speicher) Fast Memory = Schneller Speicher (instabil) Force real clock sync (slower, less lag) = Erzwinge echte Taktsync (langsamer, weniger lag) -frames, 0:off = Frames, 0 = Aus +seconds, 0:off = seconds, 0 = Aus Games list settings = Games list settings General = Allgemein Grid icon size = Grid icon size diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index f6addd09f8..ed04d0f8aa 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Memori malassi (tang stabil) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = Yato biasa Grid icon size = Grid icon size diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 362ffc0a03..a896053141 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -1143,7 +1143,7 @@ Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Fast memory (unstable) Floating symbols = Floating symbols Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Game crashed = Game crashed Games list settings = Games list settings General = General diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 67364fc79d..93920a9973 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1131,7 +1131,7 @@ Failed to save state. Error in the file system. = Error al guardar estado. Error Fast (lag on slow storage) = Rápido (lag en almac. lento) Fast Memory = Memoria rápida (inestable) Force real clock sync (slower, less lag) = Forzar sinc. real de reloj (lento, menos lag) -frames, 0:off = cuadros, 0 = no +seconds, 0:off = segundos, 0 = no Games list settings = Ajsutes de la lista de juegos General = General Grid icon size = Tamaño de iconos de cuadrícula diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 9945e3c650..85ff013e98 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Falló al guardar el estado. H Fast (lag on slow storage) = Rápido (lag en almac. lento) Fast Memory = Memoria Rápida (inestable) Force real clock sync (slower, less lag) = Forzar sinc. real de reloj (lento, menos lag) -frames, 0:off = frames, 0 = No +seconds, 0:off = seconds, 0 = No Games list settings = Configuración de la lista de juegos General = General Grid icon size = Tamaño de icono de cuadrícula diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 01ba71f2f5..1e26d0e635 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = ‎سریع (در حافظه های کند باعث لگ میشود) Fast Memory = ‎(مموری سریع (ناپایدار Force real clock sync (slower, less lag) = ‎واقعی (کندتر، لگ کمتر) CPU اجبار به همگام سازی سرعت -frames, 0:off = ‎تعداد فریم، 0 : خاموش +seconds, 0:off = ‎تعداد فریم، 0 : ثانیه Games list settings = لیست تنظیمات بازی General = ‎عمومی Grid icon size = Grid icon size diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 19b549c7f9..cb4a69e71e 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Nopea muisti (epävakaa) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = General Grid icon size = Grid icon size diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index faf713b89f..084c9d650d 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1121,7 +1121,7 @@ Failed to save state. Error in the file system. = Échec de la sauvegarde de l' Fast (lag on slow storage) = Rapide (lag sur stockage lent) Fast Memory = Mémoire rapide (instable) Force real clock sync (slower, less lag) = Forcer synchronisation temps réel (+ lent, - de décalage) -frames, 0:off = images, 0 = off +seconds, 0:off = images, 0 = off Games list settings = Paramètres des listes de jeux General = Général Grid icon size = Taille des icônes diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 366d7a51e0..cfc7d3987f 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Rápido (lag en almacenamento lento) Fast Memory = Memoria rápida (inestable) Force real clock sync (slower, less lag) = Forzar sinc. real de reloxo (lento, menos lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = Xeral Grid icon size = Grid icon size diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 05e6b30145..c4ac45e86b 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Σφάλμα αποθήκευ Fast (lag on slow storage) = Γρήγορος (καθυστερήσεις σε αργά μέσα αποθήκευσης) Fast Memory = Γρήγορη Μνήμη (ασταθής) Force real clock sync (slower, less lag) = Εξαναγκασμός συγχρονισμού πραγματικού χρόνου (πιο αργό αλλά λιγότερες καθυστερήσεις) -frames, 0:off = καρέ, 0 = off +seconds, 0:off = δευτερόλεπτα, 0 = off Games list settings = Games list settings General = Γενικά Grid icon size = Grid icon size diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index 32210508a9..c2f1943fb7 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = עיבוד מהיר של זיכרון (לא יציב) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = כללי Grid icon size = Grid icon size diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index b076e61772..6f50014db9 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = )ביצי אל( ןורכיז לש ריהמ דוביע Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = יללכ Grid icon size = Grid icon size diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 87186065cf..6c3cb6a9ac 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Neuspješno spremanje state-a. Fast (lag on slow storage) = Brzo (štekanje na malom prostoru) Fast Memory = Brza memorija (nestabilno) Force real clock sync (slower, less lag) = Prisili pravo-satno sinkroniziranje (sporije, manje šteka) -frames, 0:off = frame-ova, 0 = isključeno +seconds, 0:off = sekundi, 0 = isključeno Games list settings = Games list settings General = Generalno Grid icon size = Veličina ikona na mreži diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index d9d9801e81..401245991b 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Állapotmentés készítése s Fast (lag on slow storage) = Gyors (lassú tárolón akadozik) Fast Memory = Gyors memória elérés (instabil) Force real clock sync (slower, less lag) = Valós idejű óra szinkron kényszerítése (lassabb, kevesebb lag) -frames, 0:off = képkocka, 0 = ki +seconds, 0:off = másodpercig, 0 = ki Games list settings = Játéklista beállításai General = Általános Grid icon size = Ikonok mérete rácsnézetben diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 0c5febe0a9..e93b4b551e 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Gagal menyimpan status/keadaan Fast (lag on slow storage) = Cepat (telat di penyimpanan yang lambat) Fast Memory = Memori cepat (tidak stabil) Force real clock sync (slower, less lag) = Paksa sinkronisasi pewaktu nyata (lambat, namun lebih tepat) -frames, 0:off = bingkai, 0 = mati +seconds, 0:off = detik, 0 = mati Games list settings = Daftar pengaturan permainan General = Umum Grid icon size = Ukuran ikon kisi diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 56111fc258..9e01656cce 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1141,7 +1141,7 @@ Show Memory Stick folder = Mostra cartella Memory Stick Theme = Tema Transparent UI background = Transparent UI background UI = Interfaccia -frames, 0:off = frames, 0 = spento +seconds, 0:off = secondi, 0 = spento Games list settings = Impostazioni Lista giochi General = Generali Grid icon size = Dimensioni delle icone diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 6f04fbb432..81910315c6 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = ステートのセーブに失 Fast (lag on slow storage) = 高速 (遅いストレージだとラグあり) Fast Memory = 高速メモリ (不安定) Force real clock sync (slower, less lag) = リアルクロックへの同期を強制する (低速化, ラグ減少) -frames, 0:off = フレーム, 0 = オフ +seconds, 0:off = 秒, 0 = オフ Games list settings = ゲームリストの設定 General = 全般 Grid icon size = グリッド表示時のアイコンサイズ diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 6d01a10515..90993b2ef8 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Cepet (lag on slow storage) Fast Memory = Memory cepet (ora stabil) Force real clock sync (slower, less lag) = Pasukan jam nyata sink (alon, kurang lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = detik, 0 = off Games list settings = Games list settings General = Umum Grid icon size = Grid icon size diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 4215f116af..ce40dbb90d 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1119,7 +1119,7 @@ Fast (lag on slow storage) = 빠름 (저속 저장 시 지연) Fast Memory = 빠른 메모리 (불안정) Floating symbols = 부동 기호 Force real clock sync (slower, less lag) = 실제 클럭 동기화 강제 실행(느림, 지연 감소) -frames, 0:off = 프레임, 0 = 끔 +seconds, 0:off = 초, 0 = 끔 Game crashed = 게임 충돌 Games list settings = 게임 목록 설정 General = 일반 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 86d1265ba1..e821e31861 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = ໄວ (ອາດແລັກຫາກບ່ອນເກັບຂໍ້ມູນອ່ານຊ້າ) Fast Memory = ໜ່ວຍຄວາມຈຳເຮັດວຽກໄວຂຶ້ນ (ໃຊ້ໄດ້ກັບບາງອຸປະກອນ) Force real clock sync (slower, less lag) = ບັງຄັບການຊິງສັນຍານຄວາມຖີ່ (ຊ້າກວ່າ, ແລັກໜ້ອຍກວ່າ) -frames, 0:off = ເຟຣມ, 0 = ປິດ +seconds, 0:off = ວິນາທີ, 0 = ປິດ Games list settings = Games list settings General = ທົ່ວໄປ Grid icon size = Grid icon size diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 646ab7494e..3079809344 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Greita atmintis (nestabili) Force real clock sync (slower, less lag) = Priversti tikro greičio sinchronizaciją (lėtesnis, mažiau striginėjimų) -frames, 0:off = frames, 0 = off +seconds, 0:off = sekundžių, 0 = off Games list settings = Games list settings General = Pagrindiniai Grid icon size = Grid icon size diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 2778e76e94..932dc4ce79 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Memori dilajukan (Tak stabil) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = Umum Grid icon size = Grid icon size diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 3ca5034f52..17931d0d2b 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Kon de savestate niet opslaan. Fast (lag on slow storage) = Snel (lagt bij traag geheugen) Fast Memory = Snel geheugen (instabiel) Force real clock sync (slower, less lag) = Kloksnelheid gelijkzetten (trager, minder lag) -frames, 0:off = frames, 0 = uit +seconds, 0:off = seconds, 0 = uit Games list settings = Games list settings General = Algemeen Grid icon size = Grid icon size diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 635c60bf81..78564c313c 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Fast (lag on slow storage) Fast Memory = Turbo minne (ikke stabilt) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = General Grid icon size = Grid icon size diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 757c58c37c..482bea9be3 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Nie można zapisać stanu. Bł Fast (lag on slow storage) = Szybka (zacina na wolnych dyskach) Fast Memory = Szybka pamięć (niestabilne) Force real clock sync (slower, less lag) = Wymuś rzeczywistą synchr. zegara (wolniej, mniej zacina) -frames, 0:off = klatki, 0 = wył. +seconds, 0:off = sekundy, 0 = wył. Games list settings = Games list settings General = Ogólne Grid icon size = Grid icon size diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 145a306ee3..61a97a6d42 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -1143,7 +1143,7 @@ Fast (lag on slow storage) = Rápido (atraso na armazenagem lenta) Fast Memory = Memória rápida (instável) Floating symbols = Símbolos flutuantes Force real clock sync (slower, less lag) = Forçar sincronização com o relógio real (mais lento, menos atrasos) -frames, 0:off = frames, 0 = Desligado +seconds, 0:off = seconds, 0 = Desligado Game crashed = O jogo teve um crash Games list settings = Configurações da lista de jogos General = Geral diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 072e9c6ff1..a3f2984a78 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -1146,7 +1146,7 @@ Fast (lag on slow storage) = Rápido (mais lento no armazenamento lento) Fast Memory = Memória Rápida (instável) Floating symbols = Símbolos flutuantes Force real clock sync (slower, less lag) = Forçar sincronização com o relógio real (mais lento, menos atrasos) -frames, 0:off = quadros, 0 = Desligado +seconds, 0:off = segundos, 0 = Desligado Games list settings = Definições da lista de jogos General = Geral Grid icon size = Tamanho do ícone da grade diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 75025f5fe9..a7c1e774f1 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Failed to save state. Error in Fast (lag on slow storage) = Rapid (lent pe stocare lentă) Fast Memory = Memorie rapidă (instabil) Force real clock sync (slower, less lag) = Forțează sincronizare cu ceas real (lent, mai puțină latență) -frames, 0:off = frames, 0 = off +seconds, 0:off = secunde, 0 = off Games list settings = Games list settings General = General Grid icon size = Grid icon size diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 05a99f929e..a33f26ff75 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1130,7 +1130,7 @@ Fast (lag on slow storage) = Быстрый Fast Memory = Быстрая память (нестабильно) Floating symbols = Парящие символы Force real clock sync (slower, less lag) = Принудительная синхронизация реальной частоты ЦП (медленнее, меньше лагов) -frames, 0:off = кадров, 0 = откл. +seconds, 0:off = секунды, 0 = откл. Games list settings = Настройки списка игр General = Основные Grid icon size = Размер ярлыков в режиме сетки diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 02f9e5c157..b9768f7c40 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1129,7 +1129,7 @@ Failed to save state. Error in the file system. = Kunde inte spara state - filsy Fast (lag on slow storage) = Snabbt (lag on slow storage) Fast Memory = Snabbt minne (instabilt) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = avstängt +seconds, 0:off = seconds, 0 = avstängt Games list settings = Inställningar för spel-listan General = Blandat Grid icon size = Ikonstorlek i rutnät diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index 7c8f3d374a..472813cd6b 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Pumalya sa save state. Nagka e Fast (lag on slow storage) = Mabilis (mabagal naman sa mahinang storage) Fast Memory = Mabilis na memorya (hindi stable) Force real clock sync (slower, less lag) = Force real clock sync (slower, less lag) -frames, 0:off = frames, 0 = off +seconds, 0:off = seconds, 0 = off Games list settings = Games list settings General = Pangkalahatan Grid icon size = Grid icon size diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index a0083d8ed8..7f626c743c 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1132,7 +1132,7 @@ Fast (lag on slow storage) = เร็ว (อาจแล็ก หากที Fast Memory = หน่วยความจำทำงานได้เร็วขึ้น (ไม่เสถียร) Floating symbols = สัญลักษณ์ปุ่มจอยลอยไปมา Force real clock sync (slower, less lag) = บังคับการซิงค์สัญญาณความถี่ (ช้ากว่า, เเล็กน้อยลง) -frames, 0:off = เฟรม, 0 = ปิด +seconds, 0:off = วินาที, 0 = ปิด Game crashed = Game crashed Games list settings = การตั้งค่าในรายการเกม General = ทั่วไป diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 0948a6cd6b..ae7edf0cf8 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1131,7 +1131,7 @@ Failed to save state. Error in the file system. = Durum kaydedilemedi. Dosya sis Fast (lag on slow storage) = Hızlı (Yavaş depolamada gecikme yapabilir) Fast Memory = Hızlı Bellek (Kararsız) Force real clock sync (slower, less lag) = Gerçek sayaç senkronizasyonuna zorla (daha yavaş, daha az kasma) -frames, 0:off = frames, 0 = off +seconds, 0:off = saniye, 0 = off Games list settings = Oyun listesi ayarları General = Genel Grid icon size = Izgara simge boyutu diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index b034407cf5..c4ec4fc6ca 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Не вдалося збере Fast (lag on slow storage) = Швидко (лаги при повільній шв. карти пам'яті) Fast Memory = Швидка пам'ять (нестабільно) Force real clock sync (slower, less lag) = Синхронизація в реальному часі (повільніше, можливі лаги) -frames, 0:off = кадри, 0 = вимк. +seconds, 0:off = секунд, 0 = вимк. Games list settings = Налаштування списку ігор General = Загальні Grid icon size = Розмір піктограми сітки diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index 14ef9e8c3c..e521a0d4be 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1130,7 +1130,7 @@ Failed to save state. Error in the file system. = Save thất bại. Lỗi nằm Fast (lag on slow storage) = Nhanh (lag trên bộ nhớ thấp) Fast Memory = Bộ nhớ nhanh (không ổn định) Force real clock sync (slower, less lag) = Buộc đồng bộ tốc độ xung nhịp (chậm hơn, giảm lag hơn) -frames, 0:off = Khung, 0 = tắt +seconds, 0:off = giây, 0 = tắt Games list settings = Games list settings General = Linh tinh Grid icon size = Grid icon size diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index cb3aef28c6..12b0227052 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1124,7 +1124,7 @@ Failed to save state. Error in the file system. = 无法保存即时存档。文 Fast (lag on slow storage) = 快速模式(存储低速时有延迟) Fast Memory = 快速内存(不稳定) Force real clock sync (slower, less lag) = 强制同步实际时钟(降低延迟,很慢) -frames, 0:off = 每几帧, 0=关 +seconds, 0:off = 秒, 0=关 Games list settings = 游戏列表设置 General = 常规设置 Grid icon size = 图标方格尺寸 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 7919506b93..6915f757ee 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1121,7 +1121,7 @@ Fast (lag on slow storage) = 快速 (慢速儲存體延遲) Fast Memory = 快速記憶體 (不穩定) Floating symbols = 浮動符號 Force real clock sync (slower, less lag) = 強制真實時脈同步 (更慢,減少延遲) -frames, 0:off = 影格,0 = 關閉 +seconds, 0:off = 秒,0 = 關閉 Games list settings = 遊戲清單設定 General = 一般 Grid icon size = 格狀圖示大小 From 2243ec5b31dd3d14ebf3043f2037448b727194f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Feb 2023 15:41:32 +0100 Subject: [PATCH 108/424] Clearing fixes, fix out-of-bounds iterator --- Core/SaveState.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 50b3dad39d..a8fc0dae14 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -228,7 +228,11 @@ namespace SaveState int blockSize = std::min(BLOCK_SIZE, (int)(compressed.size() - i)); result.insert(result.end(), compressed.begin() + i, compressed.begin() + i + blockSize); i += blockSize; - basePos += blockSize; + // This check is to avoid advancing basePos out of range, which MSVC catches. + // When this happens, we're at the end of decoding anyway. + if (base.end() - basePos >= blockSize) { + basePos += blockSize; + } } } } @@ -242,6 +246,18 @@ namespace SaveState std::lock_guard guard(lock_); first_ = 0; next_ = 0; + for (auto &b : bases_) { + b.clear(); + } + baseMapping_.clear(); + baseMapping_.resize(size_); + for (auto &s : states_) { + s.clear(); + } + buffer_.clear(); + base_ = -1; + baseUsage_ = 0; + rewindLastTime = time_now_d(); } bool Empty() const From cebb885e84a3cc386c402b07b6faac17d4e1fd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Feb 2023 10:09:22 +0100 Subject: [PATCH 109/424] Address feedback --- Common/Serialize/Serializer.h | 4 +++- Core/SaveState.cpp | 17 +++++++++++------ UI/GameSettingsScreen.cpp | 2 +- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Common/Serialize/Serializer.h b/Common/Serialize/Serializer.h index ba8f753c83..5c1f813199 100644 --- a/Common/Serialize/Serializer.h +++ b/Common/Serialize/Serializer.h @@ -220,7 +220,9 @@ public: *savedSize = measuredSize; return ERROR_NONE; } else { - free(data); + if (!*saved) { + free(data); + } return ERROR_BROKEN_STATE; } } diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index a8fc0dae14..54a6a4355b 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -120,7 +120,12 @@ namespace SaveState CChunkFileReader::Error Save() { - rewindLastTime = time_now_d(); + rewindLastTime_ = time_now_d(); + + // Make sure we're not processing a previous save. That'll cause a hitch though, but at least won't + // crash due to contention over buffer_. + if (compressThread_.joinable()) + compressThread_.join(); std::lock_guard guard(lock_); @@ -166,7 +171,7 @@ namespace SaveState static std::vector buffer; LockedDecompress(buffer, states_[n], bases_[baseMapping_[n]]); CChunkFileReader::Error error = LoadFromRam(buffer, errorString); - rewindLastTime = time_now_d(); + rewindLastTime_ = time_now_d(); return error; } @@ -257,7 +262,7 @@ namespace SaveState buffer_.clear(); base_ = -1; baseUsage_ = 0; - rewindLastTime = time_now_d(); + rewindLastTime_ = time_now_d(); } bool Empty() const @@ -272,7 +277,7 @@ namespace SaveState // For fast-forwarding, otherwise they may be useless and too close. double now = time_now_d(); - double diff = now - rewindLastTime; + double diff = now - rewindLastTime_; if (diff < g_Config.iRewindSnapshotInterval) return; @@ -282,7 +287,7 @@ namespace SaveState void NotifyState() { // Prevent saving snapshots immediately after loading or saving a state. - rewindLastTime = time_now_d(); + rewindLastTime_ = time_now_d(); } private: @@ -307,7 +312,7 @@ namespace SaveState int base_ = -1; int baseUsage_ = 0; - double rewindLastTime = 0.0f; + double rewindLastTime_ = 0.0f; }; static bool needsProcess = false; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index c3a17ce7e9..9e4bb43a6f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1054,7 +1054,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { return UI::EVENT_CONTINUE; }); lockedMhz->SetZeroLabel(sy->T("Auto")); - PopupSliderChoice *rewindInterval = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindSnapshotInterval, 0, 30, sy->T("Rewind Snapshot Interval"), screenManager(), sy->T("seconds, 0:off"))); + PopupSliderChoice *rewindInterval = systemSettings->Add(new PopupSliderChoice(&g_Config.iRewindSnapshotInterval, 0, 60, sy->T("Rewind Snapshot Interval"), screenManager(), sy->T("seconds, 0:off"))); rewindInterval->SetZeroLabel(sy->T("Off")); systemSettings->Add(new ItemHeader(sy->T("General"))); From 718cb9ee4abbdb31087c5d053800f889bab5b9a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Feb 2023 16:43:22 +0100 Subject: [PATCH 110/424] Reorder savestates to put memory before CoreTiming. Also, don't clear the JIT for rounding after saving, only after loading. --- Core/MIPS/x86/Jit.cpp | 4 +++- Core/SaveState.cpp | 12 +++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index ec74bcfb5d..2755a1ac5d 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -135,7 +135,9 @@ void Jit::DoState(PointerWrap &p) { Do(p, js.startDefaultPrefix); if (s >= 2) { Do(p, js.hasSetRounding); - js.lastSetRounding = 0; + if (p.mode == PointerWrap::MODE_READ) { + js.lastSetRounding = 0; + } } else { js.hasSetRounding = 1; } diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 54a6a4355b..db33309642 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -335,7 +335,7 @@ namespace SaveState void SaveStart::DoState(PointerWrap &p) { - auto s = p.Section("SaveStart", 1, 2); + auto s = p.Section("SaveStart", 1, 3); if (!s) return; @@ -357,8 +357,10 @@ namespace SaveState saveDataGeneration = 0; } - // Gotta do CoreTiming first since we'll restore into it. - CoreTiming::DoState(p); + // Gotta do CoreTiming before HLE, but from v3 we've moved it after the memory stuff. + if (s <= 2) { + CoreTiming::DoState(p); + } // Memory is a bit tricky when jit is enabled, since there's emuhacks in it. auto savedReplacements = SaveAndClearReplacements(); @@ -376,6 +378,10 @@ namespace SaveState Memory::DoState(p); } + if (s >= 3) { + CoreTiming::DoState(p); + } + // Don't bother restoring if reading, we'll deal with that in KernelModuleDoState. // In theory, different functions might have been runtime loaded in the state. if (p.mode != p.MODE_READ) From 78f3d450fff71ee9e240173dc64e2e599d62f347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Feb 2023 20:14:49 +0100 Subject: [PATCH 111/424] Eat some CPU cycles in sceUtilityOskUpdate. Works around timing bug in Ghost Recon Predator. The bug is in the game, it uses the wrong vblank wait, but it only works because the dialog processing takes so much time that it misses the vblank period anyway. Fixes #12044, and hopefully won't break anything else. --- Core/HLE/sceUtility.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 5cffd414af..1ff229a9ca 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -641,6 +641,9 @@ static int sceUtilityOskUpdate(int animSpeed) { return hleLogWarning(SCEUTILITY, SCE_ERROR_UTILITY_WRONG_TYPE, "wrong dialog type"); } + // This is the vblank period, plus a little slack. Needed to fix timing bug in Ghost Recon: Predator. + // See issue #12044. + hleEatCycles(msToCycles(0.7315 + 0.1)); return hleLogSuccessX(SCEUTILITY, oskDialog->Update(animSpeed)); } From 132e8eeccdcb2f7389f79381f667448ef357de66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Feb 2023 22:46:32 +0100 Subject: [PATCH 112/424] Now these variables need to be initialized --- Common/Serialize/Serializer.h | 4 ++-- Core/SaveState.cpp | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Common/Serialize/Serializer.h b/Common/Serialize/Serializer.h index 5c1f813199..a7fa964a0c 100644 --- a/Common/Serialize/Serializer.h +++ b/Common/Serialize/Serializer.h @@ -275,8 +275,8 @@ public: template static Error Save(const Path &filename, const std::string &title, const char *gitVersion, T& _class) { - u8 *buffer; - size_t sz; + u8 *buffer = nullptr; + size_t sz = 0; Error error = MeasureAndSavePtr(_class, &buffer, &sz); // SaveFile takes ownership of buffer (malloc/free) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 54a6a4355b..836236e660 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -806,6 +806,8 @@ namespace SaveState bool HandleLoadFailure() { + WARN_LOG(SAVESTATE, "HandleLoadFailure - trying a rewind state."); + // Okay, first, let's give the rewind state a shot - maybe we can at least not reset entirely. // Even if this was a rewind, maybe we can still load a previous one. CChunkFileReader::Error result; From 1ec33ddc04df8dee74583de5b95da473d5083b2e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 14 Feb 2023 19:59:42 -0800 Subject: [PATCH 113/424] riscv: Use __riscv_flush_icache() on Linux. This seems to perhaps clear icache on all harts. Otherwise crashing is seen. Not sure what to do on other platforms. --- Common/RiscVEmitter.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index b061486f37..9c99961656 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -18,6 +18,9 @@ #include "ppsspp_config.h" #include #include +#if PPSSPP_ARCH(RISCV64) && PPSSPP_PLATFORM(LINUX) +#include +#endif #include "Common/BitScan.h" #include "Common/CPUDetect.h" #include "Common/RiscVEmitter.h" @@ -1051,8 +1054,13 @@ void RiscVEmitter::FlushIcache() { void RiscVEmitter::FlushIcacheSection(const u8 *start, const u8 *end) { #if PPSSPP_ARCH(RISCV64) +#if PPSSPP_PLATFORM(LINUX) + __riscv_flush_icache((char *)start, (char *)end, 0); +#else + // TODO: This might only correspond to a local hart icache clear, which is no good. __builtin___clear_cache((char *)start, (char *)end); #endif +#endif } FixupBranch::~FixupBranch() { From 684aa753886b0fbc86d3c36b954e923d925aec8b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 14 Feb 2023 20:20:55 -0800 Subject: [PATCH 114/424] riscv: Include morph in vertexjit. --- Common/RiscVEmitter.cpp | 4 + GPU/Common/VertexDecoderRiscV.cpp | 670 +++++++++++++++++++++++++++++- 2 files changed, 665 insertions(+), 9 deletions(-) diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index 9c99961656..b5b7a29a42 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -1687,6 +1687,10 @@ void RiscVEmitter::EBREAK() { } void RiscVEmitter::LWU(RiscVReg rd, RiscVReg rs1, s32 simm12) { + if (BitsSupported() == 32) { + LW(rd, rs1, simm12); + return; + } _assert_msg_(BitsSupported() >= 64, "%s is only valid with R64I", __func__); Write32(EncodeGI(Opcode32::LOAD, rd, Funct3::LS_WU, rs1, simm12)); } diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index b29e835318..2263437e2a 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -41,6 +41,8 @@ static const RiscVReg tempReg2 = X14; static const RiscVReg tempReg3 = X15; static const RiscVReg scratchReg = X16; +static const RiscVReg morphBaseReg = X5; + static const RiscVReg fullAlphaReg = X17; static const RiscVReg boundsMinUReg = X28; static const RiscVReg boundsMinVReg = X29; @@ -50,7 +52,9 @@ static const RiscVReg boundsMaxVReg = X31; static const RiscVReg fpScratchReg1 = F10; static const RiscVReg fpScratchReg2 = F11; static const RiscVReg fpScratchReg3 = F12; -static const RiscVReg fpSrc[3] = { F13, F14, F15 }; +// We want most of these within 8-15, to be compressible. +static const RiscVReg fpSrc[4] = { F13, F14, F15, F16 }; +static const RiscVReg fpScratchReg4 = F17; struct UVScaleRegs { struct { @@ -69,6 +73,50 @@ static const RiscVReg by32768Reg = F5; // Warning: usually not valid. static const RiscVReg const65535Reg = F6; +struct MorphValues { + float by128[8]; + float by32768[8]; + float asFloat[8]; + float color4[8]; + float color5[8]; + float color6[8]; +}; +enum class MorphValuesIndex { + BY_128 = 0, + BY_32768 = 1, + AS_FLOAT = 2, + COLOR_4 = 3, + COLOR_5 = 4, + COLOR_6 = 5, +}; +static MorphValues morphValues; + +static uint32_t GetMorphValueUsage(uint32_t vtype) { + uint32_t morphFlags = 0; + switch (vtype & GE_VTYPE_TC_MASK) { + case GE_VTYPE_TC_8BIT: morphFlags |= 1 << (int)MorphValuesIndex::BY_128; break; + case GE_VTYPE_TC_16BIT: morphFlags |= 1 << (int)MorphValuesIndex::BY_32768; break; + case GE_VTYPE_TC_FLOAT: morphFlags |= 1 << (int)MorphValuesIndex::AS_FLOAT; break; + } + switch (vtype & GE_VTYPE_COL_MASK) { + case GE_VTYPE_COL_565: morphFlags |= (1 << (int)MorphValuesIndex::COLOR_5) | (1 << (int)MorphValuesIndex::COLOR_6); break; + case GE_VTYPE_COL_5551: morphFlags |= 1 << (int)MorphValuesIndex::COLOR_5; break; + case GE_VTYPE_COL_4444: morphFlags |= 1 << (int)MorphValuesIndex::COLOR_4; break; + case GE_VTYPE_COL_8888: morphFlags |= 1 << (int)MorphValuesIndex::AS_FLOAT; break; + } + switch (vtype & GE_VTYPE_NRM_MASK) { + case GE_VTYPE_NRM_8BIT: morphFlags |= 1 << (int)MorphValuesIndex::BY_128; break; + case GE_VTYPE_NRM_16BIT: morphFlags |= 1 << (int)MorphValuesIndex::BY_32768; break; + case GE_VTYPE_NRM_FLOAT: morphFlags |= 1 << (int)MorphValuesIndex::AS_FLOAT; break; + } + switch (vtype & GE_VTYPE_POS_MASK) { + case GE_VTYPE_POS_8BIT: morphFlags |= 1 << (int)MorphValuesIndex::BY_128; break; + case GE_VTYPE_POS_16BIT: morphFlags |= 1 << (int)MorphValuesIndex::BY_32768; break; + case GE_VTYPE_POS_FLOAT: morphFlags |= 1 << (int)MorphValuesIndex::AS_FLOAT; break; + } + return morphFlags; +} + // TODO: Use vector, where supported. static const JitLookup jitLookup[] = { @@ -89,10 +137,22 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_TcU16DoublePrescale, &VertexDecoderJitCache::Jit_TcU16Prescale}, {&VertexDecoder::Step_TcFloatPrescale, &VertexDecoderJitCache::Jit_TcFloatPrescale}, + {&VertexDecoder::Step_TcU8MorphToFloat, &VertexDecoderJitCache::Jit_TcU8MorphToFloat}, + {&VertexDecoder::Step_TcU16MorphToFloat, &VertexDecoderJitCache::Jit_TcU16MorphToFloat}, + {&VertexDecoder::Step_TcFloatMorph, &VertexDecoderJitCache::Jit_TcFloatMorph}, + {&VertexDecoder::Step_TcU8PrescaleMorph, &VertexDecoderJitCache::Jit_TcU8PrescaleMorph}, + {&VertexDecoder::Step_TcU16PrescaleMorph, &VertexDecoderJitCache::Jit_TcU16PrescaleMorph}, + {&VertexDecoder::Step_TcU16DoublePrescaleMorph, &VertexDecoderJitCache::Jit_TcU16PrescaleMorph}, + {&VertexDecoder::Step_TcFloatPrescaleMorph, &VertexDecoderJitCache::Jit_TcFloatPrescaleMorph}, + {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, + {&VertexDecoder::Step_NormalS8Morph, &VertexDecoderJitCache::Jit_NormalS8Morph}, + {&VertexDecoder::Step_NormalS16Morph, &VertexDecoderJitCache::Jit_NormalS16Morph}, + {&VertexDecoder::Step_NormalFloatMorph, &VertexDecoderJitCache::Jit_NormalFloatMorph}, + {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, @@ -101,10 +161,19 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, {&VertexDecoder::Step_PosFloatThrough, &VertexDecoderJitCache::Jit_PosFloatThrough}, + {&VertexDecoder::Step_PosS8Morph, &VertexDecoderJitCache::Jit_PosS8Morph}, + {&VertexDecoder::Step_PosS16Morph, &VertexDecoderJitCache::Jit_PosS16Morph}, + {&VertexDecoder::Step_PosFloatMorph, &VertexDecoderJitCache::Jit_PosFloatMorph}, + {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, {&VertexDecoder::Step_Color565, &VertexDecoderJitCache::Jit_Color565}, {&VertexDecoder::Step_Color5551, &VertexDecoderJitCache::Jit_Color5551}, + + {&VertexDecoder::Step_Color8888Morph, &VertexDecoderJitCache::Jit_Color8888Morph}, + {&VertexDecoder::Step_Color4444Morph, &VertexDecoderJitCache::Jit_Color4444Morph}, + {&VertexDecoder::Step_Color565Morph, &VertexDecoderJitCache::Jit_Color565Morph}, + {&VertexDecoder::Step_Color5551Morph, &VertexDecoderJitCache::Jit_Color5551Morph}, }; JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) { @@ -123,7 +192,11 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int if (dec.steps_[i] == &VertexDecoder::Step_TcU8Prescale || dec.steps_[i] == &VertexDecoder::Step_TcU16Prescale || dec.steps_[i] == &VertexDecoder::Step_TcU16DoublePrescale || - dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale) { + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescale || + dec.steps_[i] == &VertexDecoder::Step_TcU8PrescaleMorph || + dec.steps_[i] == &VertexDecoder::Step_TcU16PrescaleMorph || + dec.steps_[i] == &VertexDecoder::Step_TcU16DoublePrescaleMorph || + dec.steps_[i] == &VertexDecoder::Step_TcFloatPrescaleMorph) { prescaleStep = true; } if (dec.steps_[i] == &VertexDecoder::Step_PosFloatThrough) { @@ -161,6 +234,49 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int } } + if (dec_->morphcount > 1) { + uint32_t morphFlags = GetMorphValueUsage(dec.VertexType()); + + auto storePremultiply = [&](RiscVReg factorReg, MorphValuesIndex index, int n) { + FMUL(32, fpScratchReg2, fpScratchReg1, factorReg); + FS(32, fpScratchReg2, morphBaseReg, ((int)index * 8 + n) * 4); + }; + + LI(morphBaseReg, &morphValues); + LI(tempReg1, &gstate_c.morphWeights[0]); + + if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_4)) != 0) { + LI(scratchReg, 255.0f / 15.0f); + FMV(FMv::W, FMv::X, fpScratchReg1, scratchReg); + } + if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_5)) != 0) { + LI(scratchReg, 255.0f / 31.0f); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + } + if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_6)) != 0) { + LI(scratchReg, 255.0f / 63.0f); + FMV(FMv::W, FMv::X, fpScratchReg3, scratchReg); + } + + // Premultiply the values we need and store them so we can reuse. + for (int n = 0; n < dec_->morphcount; n++) { + FL(32, fpScratchReg1, tempReg1, n * 4); + + if ((morphFlags & (1 << (int)MorphValuesIndex::BY_128)) != 0) + storePremultiply(by128Reg, MorphValuesIndex::BY_128, n); + if ((morphFlags & (1 << (int)MorphValuesIndex::BY_32768)) != 0) + storePremultiply(by32768Reg, MorphValuesIndex::BY_32768, n); + if ((morphFlags & (1 << (int)MorphValuesIndex::AS_FLOAT)) != 0) + FS(32, fpScratchReg1, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_4)) != 0) + storePremultiply(fpScratchReg1, MorphValuesIndex::COLOR_4, n); + if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_5)) != 0) + storePremultiply(fpScratchReg2, MorphValuesIndex::COLOR_5, n); + if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_6)) != 0) + storePremultiply(fpScratchReg3, MorphValuesIndex::COLOR_6, n); + } + } + if (dec.col) { // Or LB and skip the conditional? This is probably cheaper. LI(fullAlphaReg, 0xFF); @@ -368,21 +484,159 @@ void VertexDecoderJitCache::Jit_TcFloatPrescale() { FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); } +void VertexDecoderJitCache::Jit_TcU8MorphToFloat() { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_128 * 8 + 0) * 4); + LBU(tempReg1, srcReg, dec_->tcoff + 0); + LBU(tempReg2, srcReg, dec_->tcoff + 1); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_128 * 8 + n) * 4); + LBU(tempReg1, srcReg, dec_->onesize_ * n + dec_->tcoff + 0); + LBU(tempReg2, srcReg, dec_->onesize_ * n + dec_->tcoff + 1); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpScratchReg2, tempReg2, Round::TOZERO); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + } + + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU16MorphToFloat() { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_32768 * 8 + 0) * 4); + LHU(tempReg1, srcReg, dec_->tcoff + 0); + LHU(tempReg2, srcReg, dec_->tcoff + 2); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_32768 * 8 + n) * 4); + LHU(tempReg1, srcReg, dec_->onesize_ * n + dec_->tcoff + 0); + LHU(tempReg2, srcReg, dec_->onesize_ * n + dec_->tcoff + 2); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpScratchReg2, tempReg2, Round::TOZERO); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + } + + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcFloatMorph() { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + FL(32, fpSrc[0], srcReg, dec_->tcoff + 0); + FL(32, fpSrc[1], srcReg, dec_->tcoff + 4); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + FL(32, fpScratchReg1, srcReg, dec_->onesize_ * n + dec_->tcoff + 0); + FL(32, fpScratchReg2, srcReg, dec_->onesize_ * n + dec_->tcoff + 4); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + } + + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU8PrescaleMorph() { + // We use AS_FLOAT since by128 is already baked into precale. + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + LBU(tempReg1, srcReg, dec_->tcoff + 0); + LBU(tempReg2, srcReg, dec_->tcoff + 1); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + LBU(tempReg1, srcReg, dec_->onesize_ * n + dec_->tcoff + 0); + LBU(tempReg2, srcReg, dec_->onesize_ * n + dec_->tcoff + 1); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpScratchReg2, tempReg2, Round::TOZERO); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + } + + FMADD(32, fpSrc[0], fpSrc[0], prescaleRegs.scale.u, prescaleRegs.offset.u); + FMADD(32, fpSrc[1], fpSrc[1], prescaleRegs.scale.v, prescaleRegs.offset.v); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcU16PrescaleMorph() { + // We use AS_FLOAT since by32768 is already baked into precale. + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + LHU(tempReg1, srcReg, dec_->tcoff + 0); + LHU(tempReg2, srcReg, dec_->tcoff + 2); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + LHU(tempReg1, srcReg, dec_->onesize_ * n + dec_->tcoff + 0); + LHU(tempReg2, srcReg, dec_->onesize_ * n + dec_->tcoff + 2); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::WU, fpScratchReg2, tempReg2, Round::TOZERO); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + } + + FMADD(32, fpSrc[0], fpSrc[0], prescaleRegs.scale.u, prescaleRegs.offset.u); + FMADD(32, fpSrc[1], fpSrc[1], prescaleRegs.scale.v, prescaleRegs.offset.v); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + +void VertexDecoderJitCache::Jit_TcFloatPrescaleMorph() { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + FL(32, fpSrc[0], srcReg, dec_->tcoff + 0); + FL(32, fpSrc[1], srcReg, dec_->tcoff + 4); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + FL(32, fpScratchReg1, srcReg, dec_->onesize_ * n + dec_->tcoff + 0); + FL(32, fpScratchReg2, srcReg, dec_->onesize_ * n + dec_->tcoff + 4); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + } + + FMADD(32, fpSrc[0], fpSrc[0], prescaleRegs.scale.u, prescaleRegs.offset.u); + FMADD(32, fpSrc[1], fpSrc[1], prescaleRegs.scale.v, prescaleRegs.offset.v); + FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); + FS(32, fpSrc[1], dstReg, dec_->decFmt.uvoff + 4); +} + void VertexDecoderJitCache::Jit_NormalS8() { - LB(tempReg1, srcReg, dec_->nrmoff); + LB(tempReg1, srcReg, dec_->nrmoff + 0); LB(tempReg2, srcReg, dec_->nrmoff + 1); LB(tempReg3, srcReg, dec_->nrmoff + 2); - SB(tempReg1, dstReg, dec_->decFmt.nrmoff); + SB(tempReg1, dstReg, dec_->decFmt.nrmoff + 0); SB(tempReg2, dstReg, dec_->decFmt.nrmoff + 1); SB(tempReg3, dstReg, dec_->decFmt.nrmoff + 2); SB(R_ZERO, dstReg, dec_->decFmt.nrmoff + 3); } void VertexDecoderJitCache::Jit_NormalS16() { - LH(tempReg1, srcReg, dec_->nrmoff); + LH(tempReg1, srcReg, dec_->nrmoff + 0); LH(tempReg2, srcReg, dec_->nrmoff + 2); LH(tempReg3, srcReg, dec_->nrmoff + 4); - SH(tempReg1, dstReg, dec_->decFmt.nrmoff); + SH(tempReg1, dstReg, dec_->decFmt.nrmoff + 0); SH(tempReg2, dstReg, dec_->decFmt.nrmoff + 2); SH(tempReg3, dstReg, dec_->decFmt.nrmoff + 4); SH(R_ZERO, dstReg, dec_->decFmt.nrmoff + 6); @@ -390,14 +644,26 @@ void VertexDecoderJitCache::Jit_NormalS16() { void VertexDecoderJitCache::Jit_NormalFloat() { // Just copy 12 bytes, play with over read/write later. - LW(tempReg1, srcReg, dec_->nrmoff); + LW(tempReg1, srcReg, dec_->nrmoff + 0); LW(tempReg2, srcReg, dec_->nrmoff + 4); LW(tempReg3, srcReg, dec_->nrmoff + 8); - SW(tempReg1, dstReg, dec_->decFmt.nrmoff); + SW(tempReg1, dstReg, dec_->decFmt.nrmoff + 0); SW(tempReg2, dstReg, dec_->decFmt.nrmoff + 4); SW(tempReg3, dstReg, dec_->decFmt.nrmoff + 8); } +void VertexDecoderJitCache::Jit_NormalS8Morph() { + Jit_AnyS8Morph(dec_->nrmoff, dec_->decFmt.nrmoff); +} + +void VertexDecoderJitCache::Jit_NormalS16Morph() { + Jit_AnyS16Morph(dec_->nrmoff, dec_->decFmt.nrmoff); +} + +void VertexDecoderJitCache::Jit_NormalFloatMorph() { + Jit_AnyFloatMorph(dec_->nrmoff, dec_->decFmt.nrmoff); +} + void VertexDecoderJitCache::Jit_PosS8() { Jit_AnyS8ToFloat(dec_->posoff); FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); @@ -458,8 +724,20 @@ void VertexDecoderJitCache::Jit_PosFloatThrough() { FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); } +void VertexDecoderJitCache::Jit_PosS8Morph() { + Jit_AnyS8Morph(dec_->posoff, dec_->decFmt.posoff); +} + +void VertexDecoderJitCache::Jit_PosS16Morph() { + Jit_AnyS16Morph(dec_->posoff, dec_->decFmt.posoff); +} + +void VertexDecoderJitCache::Jit_PosFloatMorph() { + Jit_AnyFloatMorph(dec_->posoff, dec_->decFmt.posoff); +} + void VertexDecoderJitCache::Jit_Color8888() { - LW(tempReg1, srcReg, dec_->coloff); + LWU(tempReg1, srcReg, dec_->coloff); // Set tempReg2=-1 if full alpha, 0 otherwise. SRLI(tempReg2, tempReg1, 24); @@ -580,6 +858,296 @@ void VertexDecoderJitCache::Jit_Color5551() { SW(tempReg1, dstReg, dec_->decFmt.c0off); } +void VertexDecoderJitCache::Jit_Color8888Morph() { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + LWU(tempReg1, srcReg, dec_->coloff); + for (int i = 0; i < 3; ++i) { + ANDI(tempReg2, tempReg1, 0xFF); + FCVT(FConv::S, FConv::WU, fpSrc[i], tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 8); + FMUL(32, fpSrc[i], fpSrc[i], fpScratchReg4); + } + FCVT(FConv::S, FConv::WU, fpSrc[3], tempReg1, Round::TOZERO); + FMUL(32, fpSrc[3], fpSrc[3], fpScratchReg4); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + LWU(tempReg1, srcReg, dec_->onesize_ * n + dec_->coloff); + for (int i = 0; i < 3; ++i) { + ANDI(tempReg2, tempReg1, 0xFF); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 8); + FMADD(32, fpSrc[i], fpScratchReg1, fpScratchReg4, fpSrc[i]); + } + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FMADD(32, fpSrc[3], fpScratchReg1, fpScratchReg4, fpSrc[3]); + } + + if (cpu_info.RiscV_B) { + LI(scratchReg, 0xFF); + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + MAX(tempReg1, tempReg1, R_ZERO); + MIN(tempReg1, tempReg1, scratchReg); + for (int i = 1; i < 4; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + MAX(tempReg2, tempReg2, R_ZERO); + MIN(tempReg2, tempReg2, scratchReg); + // If it's alpha, set tempReg3 as a flag. + if (i == 3) + SLTIU(tempReg3, tempReg2, 0xFF); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + } else { + // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... + LI(scratchReg, 255.0f); + FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + for (int i = 0; i < 4; ++i) { + FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); + FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); + } + + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + for (int i = 1; i < 4; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + // If it's alpha, set tempReg3 as a flag. + if (i == 3) + SLTIU(tempReg3, tempReg2, 0xFF); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + } + + // Now use the flag we set earlier to update fullAlphaReg. + // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. + ADDI(tempReg3, tempReg3, -1); + AND(fullAlphaReg, fullAlphaReg, tempReg3); + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color4444Morph() { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::COLOR_4 * 8 + 0) * 4); + LHU(tempReg1, srcReg, dec_->coloff); + for (int i = 0; i < 3; ++i) { + ANDI(tempReg2, tempReg1, 0xF); + FCVT(FConv::S, FConv::WU, fpSrc[i], tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 4); + FMUL(32, fpSrc[i], fpSrc[i], fpScratchReg4, Round::TOZERO); + } + FCVT(FConv::S, FConv::WU, fpSrc[3], tempReg1, Round::TOZERO); + FMUL(32, fpSrc[3], fpSrc[3], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::COLOR_4 * 8 + n) * 4); + LHU(tempReg1, srcReg, dec_->onesize_ * n + dec_->coloff); + for (int i = 0; i < 3; ++i) { + ANDI(tempReg2, tempReg1, 0xF); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 4); + FMADD(32, fpSrc[i], fpScratchReg1, fpScratchReg4, fpSrc[i]); + } + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FMADD(32, fpSrc[3], fpScratchReg1, fpScratchReg4, fpSrc[3]); + } + + if (cpu_info.RiscV_B) { + LI(scratchReg, 0xFF); + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + MAX(tempReg1, tempReg1, R_ZERO); + MIN(tempReg1, tempReg1, scratchReg); + for (int i = 1; i < 4; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + MAX(tempReg2, tempReg2, R_ZERO); + MIN(tempReg2, tempReg2, scratchReg); + // If it's alpha, set tempReg3 as a flag. + if (i == 3) + SLTIU(tempReg3, tempReg2, 0xFF); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + } else { + // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... + LI(scratchReg, 255.0f); + FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + for (int i = 0; i < 4; ++i) { + FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); + FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); + } + + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + for (int i = 1; i < 4; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + // If it's alpha, set tempReg3 as a flag. + if (i == 3) + SLTIU(tempReg3, tempReg2, 0xFF); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + } + + // Now use the flag we set earlier to update fullAlphaReg. + // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. + ADDI(tempReg3, tempReg3, -1); + AND(fullAlphaReg, fullAlphaReg, tempReg3); + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color565Morph() { + FL(32, fpScratchReg3, morphBaseReg, ((int)MorphValuesIndex::COLOR_5 * 8 + 0) * 4); + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::COLOR_6 * 8 + 0) * 4); + LHU(tempReg1, srcReg, dec_->coloff); + + ANDI(tempReg2, tempReg1, 0x1F); + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 5); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg3, Round::TOZERO); + + ANDI(tempReg2, tempReg1, 0x3F); + FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 6); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + + FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg3, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg3, morphBaseReg, ((int)MorphValuesIndex::COLOR_5 * 8 + n) * 4); + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::COLOR_6 * 8 + n) * 4); + LHU(tempReg1, srcReg, dec_->onesize_ * n + dec_->coloff); + + ANDI(tempReg2, tempReg1, 0x1F); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 5); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg3, fpSrc[0]); + + ANDI(tempReg2, tempReg1, 0x3F); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 6); + FMADD(32, fpSrc[1], fpScratchReg1, fpScratchReg4, fpSrc[1]); + + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FMADD(32, fpSrc[2], fpScratchReg1, fpScratchReg3, fpSrc[2]); + } + + if (cpu_info.RiscV_B) { + LI(scratchReg, 0xFF); + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + MAX(tempReg1, tempReg1, R_ZERO); + MIN(tempReg1, tempReg1, scratchReg); + for (int i = 1; i < 3; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + MAX(tempReg2, tempReg2, R_ZERO); + MIN(tempReg2, tempReg2, scratchReg); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + + SLLI(scratchReg, scratchReg, 24); + OR(tempReg1, tempReg1, scratchReg); + } else { + // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... + LI(scratchReg, 255.0f); + FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + for (int i = 0; i < 3; ++i) { + FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); + FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); + } + + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + for (int i = 1; i < 3; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + + LI(scratchReg, (s32)0xFF000000); + OR(tempReg1, tempReg1, scratchReg); + } + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + +void VertexDecoderJitCache::Jit_Color5551Morph() { + FL(32, fpScratchReg3, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::COLOR_5 * 8 + 0) * 4); + LHU(tempReg1, srcReg, dec_->coloff); + for (int i = 0; i < 3; ++i) { + ANDI(tempReg2, tempReg1, 0x1F); + FCVT(FConv::S, FConv::WU, fpSrc[i], tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 5); + FMUL(32, fpSrc[i], fpSrc[i], fpScratchReg4, Round::TOZERO); + } + + // We accumulate alpha to [0, 1] and then scale up to 255 later. + FCVT(FConv::S, FConv::WU, fpSrc[3], tempReg1, Round::TOZERO); + FMUL(32, fpSrc[3], fpSrc[3], fpScratchReg3, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg3, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::COLOR_5 * 8 + n) * 4); + LHU(tempReg1, srcReg, dec_->onesize_ * n + dec_->coloff); + for (int i = 0; i < 3; ++i) { + ANDI(tempReg2, tempReg1, 0x1F); + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg2, Round::TOZERO); + SRLI(tempReg1, tempReg1, 5); + FMADD(32, fpSrc[i], fpScratchReg1, fpScratchReg4, fpSrc[i]); + } + FCVT(FConv::S, FConv::WU, fpScratchReg1, tempReg1, Round::TOZERO); + FMADD(32, fpSrc[3], fpScratchReg1, fpScratchReg3, fpSrc[3]); + } + + LI(scratchReg, 255.0f); + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + FMUL(32, fpSrc[3], fpSrc[3], fpScratchReg2, Round::TOZERO); + + if (cpu_info.RiscV_B) { + LI(scratchReg, 0xFF); + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + MAX(tempReg1, tempReg1, R_ZERO); + MIN(tempReg1, tempReg1, scratchReg); + for (int i = 1; i < 4; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + MAX(tempReg2, tempReg2, R_ZERO); + MIN(tempReg2, tempReg2, scratchReg); + // If it's alpha, set tempReg3 as a flag. + if (i == 3) + SLTIU(tempReg3, tempReg2, 0xFF); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + } else { + // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... + // We still have 255.0f in fpScratchReg2. + FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); + for (int i = 0; i < 4; ++i) { + FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); + FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); + } + + FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); + for (int i = 1; i < 4; ++i) { + FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); + // If it's alpha, set tempReg3 as a flag. + if (i == 3) + SLTIU(tempReg3, tempReg2, 0xFF); + SLLI(tempReg2, tempReg2, i * 8); + OR(tempReg1, tempReg1, tempReg2); + } + } + + // Now use the flag we set earlier to update fullAlphaReg. + // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. + ADDI(tempReg3, tempReg3, -1); + AND(fullAlphaReg, fullAlphaReg, tempReg3); + + SW(tempReg1, dstReg, dec_->decFmt.c0off); +} + void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { LB(tempReg1, srcReg, srcoff + 0); LB(tempReg2, srcReg, srcoff + 1); @@ -646,4 +1214,88 @@ void VertexDecoderJitCache::Jit_AnyU16ToFloat(int srcoff, u32 bits) { FMUL(32, fpSrc[2], fpSrc[2], by32768Reg); } +void VertexDecoderJitCache::Jit_AnyS8Morph(int srcoff, int dstoff) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_128 * 8 + 0) * 4); + LB(tempReg1, srcReg, srcoff + 0); + LB(tempReg2, srcReg, srcoff + 1); + LB(tempReg3, srcReg, srcoff + 2); + FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[2], tempReg3, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_128 * 8 + n) * 4); + LB(tempReg1, srcReg, dec_->onesize_ * n + srcoff + 0); + LB(tempReg2, srcReg, dec_->onesize_ * n + srcoff + 1); + LB(tempReg3, srcReg, dec_->onesize_ * n + srcoff + 2); + FCVT(FConv::S, FConv::W, fpScratchReg1, tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpScratchReg2, tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpScratchReg3, tempReg3, Round::TOZERO); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + FMADD(32, fpSrc[2], fpScratchReg3, fpScratchReg4, fpSrc[2]); + } + + FS(32, fpSrc[0], dstReg, dstoff + 0); + FS(32, fpSrc[1], dstReg, dstoff + 4); + FS(32, fpSrc[2], dstReg, dstoff + 8); +} + +void VertexDecoderJitCache::Jit_AnyS16Morph(int srcoff, int dstoff) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_32768 * 8 + 0) * 4); + LH(tempReg1, srcReg, srcoff + 0); + LH(tempReg2, srcReg, srcoff + 2); + LH(tempReg3, srcReg, srcoff + 4); + FCVT(FConv::S, FConv::W, fpSrc[0], tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[1], tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpSrc[2], tempReg3, Round::TOZERO); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::BY_32768 * 8 + n) * 4); + LH(tempReg1, srcReg, dec_->onesize_ * n + srcoff + 0); + LH(tempReg2, srcReg, dec_->onesize_ * n + srcoff + 2); + LH(tempReg3, srcReg, dec_->onesize_ * n + srcoff + 4); + FCVT(FConv::S, FConv::W, fpScratchReg1, tempReg1, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpScratchReg2, tempReg2, Round::TOZERO); + FCVT(FConv::S, FConv::W, fpScratchReg3, tempReg3, Round::TOZERO); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + FMADD(32, fpSrc[2], fpScratchReg3, fpScratchReg4, fpSrc[2]); + } + + FS(32, fpSrc[0], dstReg, dstoff + 0); + FS(32, fpSrc[1], dstReg, dstoff + 4); + FS(32, fpSrc[2], dstReg, dstoff + 8); +} + +void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + 0) * 4); + FL(32, fpSrc[0], srcReg, srcoff + 0); + FL(32, fpSrc[1], srcReg, srcoff + 4); + FL(32, fpSrc[2], srcReg, srcoff + 8); + FMUL(32, fpSrc[0], fpSrc[0], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[1], fpSrc[1], fpScratchReg4, Round::TOZERO); + FMUL(32, fpSrc[2], fpSrc[2], fpScratchReg4, Round::TOZERO); + + for (int n = 1; n < dec_->morphcount; n++) { + FL(32, fpScratchReg4, morphBaseReg, ((int)MorphValuesIndex::AS_FLOAT * 8 + n) * 4); + FL(32, fpScratchReg1, srcReg, dec_->onesize_ * n + srcoff + 0); + FL(32, fpScratchReg2, srcReg, dec_->onesize_ * n + srcoff + 4); + FL(32, fpScratchReg3, srcReg, dec_->onesize_ * n + srcoff + 8); + FMADD(32, fpSrc[0], fpScratchReg1, fpScratchReg4, fpSrc[0]); + FMADD(32, fpSrc[1], fpScratchReg2, fpScratchReg4, fpSrc[1]); + FMADD(32, fpSrc[2], fpScratchReg3, fpScratchReg4, fpSrc[2]); + } + + FS(32, fpSrc[0], dstReg, dstoff + 0); + FS(32, fpSrc[1], dstReg, dstoff + 4); + FS(32, fpSrc[2], dstReg, dstoff + 8); +} + #endif // PPSSPP_ARCH(RISCV64) From 9f4301000436790345ee8e15f5366f1a492afa38 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 14 Feb 2023 20:38:46 -0800 Subject: [PATCH 115/424] riscv: Reuse some color morphing code. Small optimization loss in 5551, but fairly minimal and I think it's worth it. --- GPU/Common/VertexDecoderRiscV.cpp | 161 ++++++------------------------ 1 file changed, 31 insertions(+), 130 deletions(-) diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 2263437e2a..9a052242b1 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -883,48 +883,7 @@ void VertexDecoderJitCache::Jit_Color8888Morph() { FMADD(32, fpSrc[3], fpScratchReg1, fpScratchReg4, fpSrc[3]); } - if (cpu_info.RiscV_B) { - LI(scratchReg, 0xFF); - FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - MAX(tempReg1, tempReg1, R_ZERO); - MIN(tempReg1, tempReg1, scratchReg); - for (int i = 1; i < 4; ++i) { - FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); - MAX(tempReg2, tempReg2, R_ZERO); - MIN(tempReg2, tempReg2, scratchReg); - // If it's alpha, set tempReg3 as a flag. - if (i == 3) - SLTIU(tempReg3, tempReg2, 0xFF); - SLLI(tempReg2, tempReg2, i * 8); - OR(tempReg1, tempReg1, tempReg2); - } - } else { - // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... - LI(scratchReg, 255.0f); - FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); - FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); - for (int i = 0; i < 4; ++i) { - FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); - FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); - } - - FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - for (int i = 1; i < 4; ++i) { - FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); - // If it's alpha, set tempReg3 as a flag. - if (i == 3) - SLTIU(tempReg3, tempReg2, 0xFF); - SLLI(tempReg2, tempReg2, i * 8); - OR(tempReg1, tempReg1, tempReg2); - } - } - - // Now use the flag we set earlier to update fullAlphaReg. - // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. - ADDI(tempReg3, tempReg3, -1); - AND(fullAlphaReg, fullAlphaReg, tempReg3); - - SW(tempReg1, dstReg, dec_->decFmt.c0off); + Jit_WriteMorphColor(dec_->decFmt.c0off, true); } void VertexDecoderJitCache::Jit_Color4444Morph() { @@ -952,48 +911,7 @@ void VertexDecoderJitCache::Jit_Color4444Morph() { FMADD(32, fpSrc[3], fpScratchReg1, fpScratchReg4, fpSrc[3]); } - if (cpu_info.RiscV_B) { - LI(scratchReg, 0xFF); - FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - MAX(tempReg1, tempReg1, R_ZERO); - MIN(tempReg1, tempReg1, scratchReg); - for (int i = 1; i < 4; ++i) { - FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); - MAX(tempReg2, tempReg2, R_ZERO); - MIN(tempReg2, tempReg2, scratchReg); - // If it's alpha, set tempReg3 as a flag. - if (i == 3) - SLTIU(tempReg3, tempReg2, 0xFF); - SLLI(tempReg2, tempReg2, i * 8); - OR(tempReg1, tempReg1, tempReg2); - } - } else { - // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... - LI(scratchReg, 255.0f); - FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); - FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); - for (int i = 0; i < 4; ++i) { - FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); - FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); - } - - FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - for (int i = 1; i < 4; ++i) { - FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); - // If it's alpha, set tempReg3 as a flag. - if (i == 3) - SLTIU(tempReg3, tempReg2, 0xFF); - SLLI(tempReg2, tempReg2, i * 8); - OR(tempReg1, tempReg1, tempReg2); - } - } - - // Now use the flag we set earlier to update fullAlphaReg. - // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. - ADDI(tempReg3, tempReg3, -1); - AND(fullAlphaReg, fullAlphaReg, tempReg3); - - SW(tempReg1, dstReg, dec_->decFmt.c0off); + Jit_WriteMorphColor(dec_->decFmt.c0off, true); } void VertexDecoderJitCache::Jit_Color565Morph() { @@ -1033,43 +951,7 @@ void VertexDecoderJitCache::Jit_Color565Morph() { FMADD(32, fpSrc[2], fpScratchReg1, fpScratchReg3, fpSrc[2]); } - if (cpu_info.RiscV_B) { - LI(scratchReg, 0xFF); - FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - MAX(tempReg1, tempReg1, R_ZERO); - MIN(tempReg1, tempReg1, scratchReg); - for (int i = 1; i < 3; ++i) { - FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); - MAX(tempReg2, tempReg2, R_ZERO); - MIN(tempReg2, tempReg2, scratchReg); - SLLI(tempReg2, tempReg2, i * 8); - OR(tempReg1, tempReg1, tempReg2); - } - - SLLI(scratchReg, scratchReg, 24); - OR(tempReg1, tempReg1, scratchReg); - } else { - // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... - LI(scratchReg, 255.0f); - FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); - FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); - for (int i = 0; i < 3; ++i) { - FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); - FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); - } - - FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - for (int i = 1; i < 3; ++i) { - FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); - SLLI(tempReg2, tempReg2, i * 8); - OR(tempReg1, tempReg1, tempReg2); - } - - LI(scratchReg, (s32)0xFF000000); - OR(tempReg1, tempReg1, scratchReg); - } - - SW(tempReg1, dstReg, dec_->decFmt.c0off); + Jit_WriteMorphColor(dec_->decFmt.c0off, false); } void VertexDecoderJitCache::Jit_Color5551Morph() { @@ -1105,12 +987,16 @@ void VertexDecoderJitCache::Jit_Color5551Morph() { FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); FMUL(32, fpSrc[3], fpSrc[3], fpScratchReg2, Round::TOZERO); + Jit_WriteMorphColor(dec_->decFmt.c0off, true); +} + +void VertexDecoderJitCache::Jit_WriteMorphColor(int outOff, bool checkAlpha) { if (cpu_info.RiscV_B) { LI(scratchReg, 0xFF); FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); MAX(tempReg1, tempReg1, R_ZERO); MIN(tempReg1, tempReg1, scratchReg); - for (int i = 1; i < 4; ++i) { + for (int i = 1; i < (checkAlpha ? 4 : 3); ++i) { FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); MAX(tempReg2, tempReg2, R_ZERO); MIN(tempReg2, tempReg2, scratchReg); @@ -1120,17 +1006,24 @@ void VertexDecoderJitCache::Jit_Color5551Morph() { SLLI(tempReg2, tempReg2, i * 8); OR(tempReg1, tempReg1, tempReg2); } + + if (!checkAlpha) { + // For 565 only, take our 0xFF constant above and slot it into alpha. + SLLI(scratchReg, scratchReg, 24); + OR(tempReg1, tempReg1, scratchReg); + } } else { // Clamp to [0, 255] as floats, since we have FMIN/FMAX. Better than branching, probably... - // We still have 255.0f in fpScratchReg2. + LI(scratchReg, 255.0f); FMV(FMv::W, FMv::X, fpScratchReg1, R_ZERO); - for (int i = 0; i < 4; ++i) { + FMV(FMv::W, FMv::X, fpScratchReg2, scratchReg); + for (int i = 0; i < (checkAlpha ? 4 : 3); ++i) { FMAX(32, fpSrc[i], fpSrc[i], fpScratchReg1); FMIN(32, fpSrc[i], fpSrc[i], fpScratchReg2); } FCVT(FConv::WU, FConv::S, tempReg1, fpSrc[0], Round::TOZERO); - for (int i = 1; i < 4; ++i) { + for (int i = 1; i < (checkAlpha ? 4 : 3); ++i) { FCVT(FConv::WU, FConv::S, tempReg2, fpSrc[i], Round::TOZERO); // If it's alpha, set tempReg3 as a flag. if (i == 3) @@ -1138,14 +1031,22 @@ void VertexDecoderJitCache::Jit_Color5551Morph() { SLLI(tempReg2, tempReg2, i * 8); OR(tempReg1, tempReg1, tempReg2); } + + if (!checkAlpha) { + // For 565 only, we need to force alpha to 0xFF. + LI(scratchReg, (s32)0xFF000000); + OR(tempReg1, tempReg1, scratchReg); + } } - // Now use the flag we set earlier to update fullAlphaReg. - // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. - ADDI(tempReg3, tempReg3, -1); - AND(fullAlphaReg, fullAlphaReg, tempReg3); + if (checkAlpha) { + // Now use the flag we set earlier to update fullAlphaReg. + // We translate it to a mask, tempReg3=-1 if full alpha, 0 otherwise. + ADDI(tempReg3, tempReg3, -1); + AND(fullAlphaReg, fullAlphaReg, tempReg3); + } - SW(tempReg1, dstReg, dec_->decFmt.c0off); + SW(tempReg1, dstReg, outOff); } void VertexDecoderJitCache::Jit_AnyS8ToFloat(int srcoff) { From 037bf3575ee6b303463e1d515d9582b4f541f736 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 14 Feb 2023 21:30:06 -0800 Subject: [PATCH 116/424] libretro: Update flags for Android ndk-build. --- libretro/Makefile.common | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libretro/Makefile.common b/libretro/Makefile.common index ed11027f32..f5cc955e6c 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -192,7 +192,12 @@ SOURCES_C += \ $(EXTDIR)/libpng17/pngwtran.c \ $(EXTDIR)/libpng17/pngwutil.c -COREFLAGS += -DHAVE_STRONG_GETAUXVAL -DSTACK_LINE_READER_BUFFER_SIZE=1024 +COREFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 +ifeq ($(PLATFORM_EXT), android) +COREFLAGS += -DHAVE_DLFCN_H +else ifneq ($(PLATFORM_EXT), win32) +COREFLAGS += -DHAVE_STRONG_GETAUXVAL +endif ifneq (,$(findstring osx,$(platform))) ifneq (,$(findstring x86,$(TARGET_ARCH))) COREFLAGS += -DHAVE_SYSCTLBYNAME From 6b902a7d6b5783bf766f35073afe668765e83a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 10 Dec 2022 11:29:23 +0100 Subject: [PATCH 117/424] Minor code cleanup, one very minor stride bugfix --- GPU/Common/FramebufferManagerCommon.cpp | 23 +++++++++-------------- GPU/Common/FramebufferManagerCommon.h | 5 ++++- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 05289365e8..7dc490b04e 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -202,10 +202,6 @@ VirtualFramebuffer *FramebufferManagerCommon::GetDisplayVFB() { return GetExactVFB(displayFramebufPtr_, displayStride_, displayFormat_); } -u32 FramebufferManagerCommon::ColorBufferByteSize(const VirtualFramebuffer *vfb) const { - return vfb->fb_stride * vfb->height * (vfb->fb_format == GE_FORMAT_8888 ? 4 : 2); -} - // Heuristics to figure out the size of FBO to create. // TODO: Possibly differentiate on whether through mode is used (since in through mode, viewport is meaningless?) void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, int fb_stride, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int &drawing_width, int &drawing_height) { @@ -512,7 +508,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer vfb->fb_format = params.fb_format; vfb->usageFlags = FB_USAGE_RENDER_COLOR; - u32 colorByteSize = ColorBufferByteSize(vfb); + u32 colorByteSize = vfb->BufferByteSize(RASTER_COLOR); if (Memory::IsVRAMAddress(params.fb_address) && params.fb_address + colorByteSize > framebufRangeEnd_) { framebufRangeEnd_ = params.fb_address + colorByteSize; } @@ -1463,7 +1459,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { const u32 addr = fbaddr; for (auto v : vfbs_) { const u32 v_addr = v->fb_address; - const u32 v_size = ColorBufferByteSize(v); + const u32 v_size = v->BufferByteSize(RASTER_COLOR); if (v->fb_format != displayFormat_ || v->fb_stride != displayStride_) { // Displaying a buffer of the wrong format or stride is nonsense, ignore it. @@ -1715,12 +1711,12 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), msaaLevel_, true, tag }); if (Memory::IsVRAMAddress(vfb->fb_address) && vfb->fb_stride != 0) { - NotifyMemInfo(MemBlockFlags::ALLOC, vfb->fb_address, ColorBufferByteSize(vfb), tag, len); + NotifyMemInfo(MemBlockFlags::ALLOC, vfb->fb_address, vfb->BufferByteSize(RASTER_COLOR), tag, len); } if (Memory::IsVRAMAddress(vfb->z_address) && vfb->z_stride != 0) { char buf[128]; size_t len = snprintf(buf, sizeof(buf), "Z_%s", tag); - NotifyMemInfo(MemBlockFlags::ALLOC, vfb->z_address, vfb->fb_stride * vfb->height * sizeof(uint16_t), buf, len); + NotifyMemInfo(MemBlockFlags::ALLOC, vfb->z_address, vfb->z_stride * vfb->height * sizeof(uint16_t), buf, len); } if (old.fbo) { INFO_LOG(FRAMEBUF, "Resizing FBO for %08x : %dx%dx%s", vfb->fb_address, w, h, GeBufferFormatToString(vfb->fb_format)); @@ -1747,7 +1743,6 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, } // This is called from detected memcopies and framebuffer initialization from VRAM. Not block transfers. -// MotoGP goes this path so we need to catch those copies here. bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, GPUCopyFlag flags, u32 skipDrawReason) { if (size == 0) { return false; @@ -1781,7 +1776,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, // We only remove the kernel and uncached bits when comparing. const u32 vfb_address = vfb->fb_address; - const u32 vfb_size = ColorBufferByteSize(vfb); + const u32 vfb_size = vfb->BufferByteSize(RASTER_COLOR); const u32 vfb_bpp = BufferFormatBytesPerPixel(vfb->fb_format); const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp; const int vfb_byteWidth = vfb->width * vfb_bpp; @@ -1917,8 +1912,8 @@ std::string BlockTransferRect::ToString() const { return StringFromFormat("%08x/%d/%s seq:%d %d,%d %dx%d", vfb->fb_address, vfb->FbStrideInBytes(), GeBufferFormatToString(vfb->fb_format), vfb->colorBindSeq, x_bytes / bpp, y, w_bytes / bpp, h); } -// Only looks for color buffers. Due to swizzling and other concerns, games have not been seen using block copies -// for depth data yet. +// Only looks for color buffers for now. +// The only known game to block transfer depth buffers is Iron Man, see #16530. bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_pixels, int x_pixels, int y, int w_pixels, int h, int bpp, bool destination, BlockTransferRect *rect) { basePtr &= 0x3FFFFFFF; if (Memory::IsVRAMAddress(basePtr)) @@ -1951,7 +1946,7 @@ bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_p } const u32 vfb_address = vfb->fb_address; - const u32 vfb_size = ColorBufferByteSize(vfb); + const u32 vfb_size = vfb->BufferByteSize(RASTER_COLOR); if (basePtr < vfb_address || basePtr >= vfb_address + vfb_size) { continue; @@ -2087,7 +2082,7 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, true, name }); vfbs_.push_back(vfb); - u32 byteSize = ColorBufferByteSize(vfb); + u32 byteSize = vfb->BufferByteSize(RASTER_COLOR); if (fbAddress + byteSize > framebufRangeEnd_) { framebufRangeEnd_ = fbAddress + byteSize; } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index ea4565e6c0..26ed26128d 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -159,6 +159,10 @@ struct VirtualFramebuffer { inline int Stride(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_stride : z_stride; } inline u32 Address(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_address : z_address; } inline int Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; } + + int BufferByteSize(RasterChannel channel) const { + return channel == RASTER_COLOR ? fb_stride * height * (fb_format == GE_FORMAT_8888 ? 4 : 2) : z_stride * height * 2; + } }; struct FramebufferHeuristicParams { @@ -484,7 +488,6 @@ protected: void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags, int layer); void EstimateDrawingSize(u32 fb_address, int fb_stride, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int &drawing_width, int &drawing_height); - u32 ColorBufferByteSize(const VirtualFramebuffer *vfb) const; void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb); void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb); From 27a03de826b8d4b5c441f36044f6b2350aad786d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Feb 2023 23:28:37 +0100 Subject: [PATCH 118/424] CreateRAMFramebuffer: Don't create a depth buffer by default --- GPU/Common/FramebufferManagerCommon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 7dc490b04e..54ad12f6f0 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2079,7 +2079,7 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd char name[64]; snprintf(name, sizeof(name), "%08x_color_RAM", vfb->fb_address); textureCache_->NotifyFramebuffer(vfb, NOTIFY_FB_CREATED); - vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, true, name }); + vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, false, name }); vfbs_.push_back(vfb); u32 byteSize = vfb->BufferByteSize(RASTER_COLOR); From 62a6f351d5aae180a49282069e3cfe88d1e850b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Feb 2023 23:28:10 +0100 Subject: [PATCH 119/424] Initial work on depth copies --- Core/Compatibility.cpp | 1 + Core/Compatibility.h | 1 + GPU/Common/FramebufferManagerCommon.cpp | 69 ++++++++++++++++++------- GPU/Common/FramebufferManagerCommon.h | 3 +- assets/compat.ini | 12 +++++ 5 files changed, 66 insertions(+), 20 deletions(-) diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index 35d3b7cd9a..f6cf4a644c 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -126,6 +126,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "DisallowFramebufferAtOffset", &flags_.DisallowFramebufferAtOffset); CheckSetting(iniFile, gameID, "RockmanDash2SoundFix", &flags_.RockmanDash2SoundFix); CheckSetting(iniFile, gameID, "ReadbackDepth", &flags_.ReadbackDepth); + CheckSetting(iniFile, gameID, "BlockTransferDepth", &flags_.BlockTransferDepth); } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index dbc62c256c..d34722f4fa 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -97,6 +97,7 @@ struct CompatFlags { bool DisallowFramebufferAtOffset; bool RockmanDash2SoundFix; bool ReadbackDepth; + bool BlockTransferDepth; }; struct VRCompat { diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 54ad12f6f0..9ce0585990 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1908,12 +1908,13 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, } std::string BlockTransferRect::ToString() const { - int bpp = BufferFormatBytesPerPixel(vfb->fb_format); - return StringFromFormat("%08x/%d/%s seq:%d %d,%d %dx%d", vfb->fb_address, vfb->FbStrideInBytes(), GeBufferFormatToString(vfb->fb_format), vfb->colorBindSeq, x_bytes / bpp, y, w_bytes / bpp, h); + int bpp = BufferFormatBytesPerPixel(channel == RASTER_DEPTH ? GE_FORMAT_DEPTH16 : vfb->fb_format); + return StringFromFormat("%s %08x/%d/%s seq:%d %d,%d %dx%d", RasterChannelToString(channel), vfb->fb_address, vfb->FbStrideInBytes(), GeBufferFormatToString(vfb->fb_format), vfb->colorBindSeq, x_bytes / bpp, y, w_bytes / bpp, h); } -// Only looks for color buffers for now. -// The only known game to block transfer depth buffers is Iron Man, see #16530. +// This is used when looking for framebuffers for a block transfer. +// The only known game to block transfer depth buffers is Iron Man, see #16530, so +// we have a compat flag and pretty limited functionality for that. bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_pixels, int x_pixels, int y, int w_pixels, int h, int bpp, bool destination, BlockTransferRect *rect) { basePtr &= 0x3FFFFFFF; if (Memory::IsVRAMAddress(basePtr)) @@ -1938,11 +1939,20 @@ bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_p // We are only looking at color for now, have not found any block transfers of depth data (although it's plausible). for (auto vfb : vfbs_) { + BlockTransferRect candidate{ vfb, RASTER_COLOR }; + // Check for easily detected depth copies for logging purposes. // Depth copies are not that useful though because you manually need to account for swizzle, so - // not sure if games will use them. - if (vfb->z_address == basePtr) { + // not sure if games will use them. Actually we do have a case, Iron Man in issue #16530. + if (vfb->z_address == basePtr && vfb->z_stride == stride_pixels && PSP_CoreParameter().compat.flags().BlockTransferDepth) { WARN_LOG_N_TIMES(z_xfer, 5, G3D, "FindTransferFramebuffer: found matching depth buffer, %08x (dest=%d, bpp=%d)", basePtr, (int)destination, bpp); + candidate.channel = RASTER_DEPTH; + candidate.x_bytes = x_pixels * 2; + candidate.w_bytes = w_pixels * 2; + candidate.y = y; + candidate.h = h; + candidates.push_back(candidate); + continue; } const u32 vfb_address = vfb->fb_address; @@ -1956,7 +1966,6 @@ bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_p const u32 vfb_byteStride = vfb->FbStrideInBytes(); const u32 vfb_byteWidth = vfb->WidthInBytes(); - BlockTransferRect candidate{ vfb }; candidate.w_bytes = w_pixels * bpp; candidate.h = h; @@ -2018,7 +2027,18 @@ bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_p for (size_t i = 0; i < candidates.size(); i++) { const BlockTransferRect *candidate = &candidates[i]; - bool better = !best || candidate->vfb->colorBindSeq > best->vfb->colorBindSeq; + bool better = !best; + if (!better) { + if (candidate->channel == best->channel) { + better = candidate->vfb->BindSeq(candidate->channel) > best->vfb->BindSeq(candidate->channel); + } else { + // Prefer color over depth. + if (candidate->channel == RASTER_COLOR && best->channel == RASTER_DEPTH) { + better = true; + } + } + } + if ((candidate->vfb->usageFlags & FB_USAGE_CLUT) && candidate->x_bytes == 0 && candidate->y == 0 && destination) { // Hack to prioritize copies to clut buffers. best = candidate; @@ -2258,6 +2278,13 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst bool srcBuffer = FindTransferFramebuffer(srcBasePtr, srcStride, srcX, srcY, width, height, bpp, false, &srcRect); bool dstBuffer = FindTransferFramebuffer(dstBasePtr, dstStride, dstX, dstY, width, height, bpp, true, &dstRect); + if (srcRect.channel == RASTER_DEPTH) { + // Ignore the found buffer if it's not 16-bit - we create a new more suitable one instead. + if (dstRect.channel == RASTER_COLOR && dstRect.vfb->fb_format == GE_FORMAT_8888) { + dstBuffer = false; + } + } + if (srcBuffer && !dstBuffer) { // In here, we can't read from dstRect. if (PSP_CoreParameter().compat.flags().BlockTransferAllowCreateFB || @@ -2265,19 +2292,23 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst Memory::IsVRAMAddress(srcRect.vfb->fb_address) && Memory::IsVRAMAddress(dstBasePtr))) { GEBufferFormat ramFormat; // Try to guess the appropriate format. We only know the bpp from the block transfer command (16 or 32 bit). - if (bpp == 4) { - // Only one possibility unless it's doing split pixel tricks (which we could detect through stride maybe). - ramFormat = GE_FORMAT_8888; - } else if (srcRect.vfb->fb_format != GE_FORMAT_8888) { - // We guess that the game will interpret the data the same as it was in the source of the copy. - // Seems like a likely good guess, and works in Test Drive Unlimited. - ramFormat = srcRect.vfb->fb_format; + if (srcRect.channel == RASTER_COLOR) { + if (bpp == 4) { + // Only one possibility unless it's doing split pixel tricks (which we could detect through stride maybe). + ramFormat = GE_FORMAT_8888; + } else if (srcRect.vfb->fb_format != GE_FORMAT_8888) { + // We guess that the game will interpret the data the same as it was in the source of the copy. + // Seems like a likely good guess, and works in Test Drive Unlimited. + ramFormat = srcRect.vfb->fb_format; + } else { + // No info left - just fall back to something. But this is definitely split pixel tricks. + ramFormat = GE_FORMAT_5551; + } + dstBuffer = true; + dstRect.vfb = CreateRAMFramebuffer(dstBasePtr, width, height, dstStride, ramFormat); } else { - // No info left - just fall back to something. But this is definitely split pixel tricks. - ramFormat = GE_FORMAT_5551; + dstRect.vfb = CreateRAMFramebuffer(dstBasePtr, width, height, dstStride, GE_FORMAT_DEPTH16); } - dstBuffer = true; - dstRect.vfb = CreateRAMFramebuffer(dstBasePtr, width, height, dstStride, ramFormat); } } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 26ed26128d..c2bdac1607 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -159,6 +159,7 @@ struct VirtualFramebuffer { inline int Stride(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_stride : z_stride; } inline u32 Address(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_address : z_address; } inline int Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; } + inline int BindSeq(RasterChannel channel) const { return channel == RASTER_COLOR ? colorBindSeq : depthBindSeq; } int BufferByteSize(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_stride * height * (fb_format == GE_FORMAT_8888 ? 4 : 2) : z_stride * height * 2; @@ -242,7 +243,7 @@ inline Draw::DataFormat GEFormatToThin3D(GEBufferFormat geFormat) { // Makes it easy to see if blits match etc. struct BlockTransferRect { VirtualFramebuffer *vfb; - // RasterChannel channel; // We currently only deal with color for block copies. + RasterChannel channel; // We usually only deal with color, but we have limited depth block transfer support now. int x_bytes; int y; diff --git a/assets/compat.ini b/assets/compat.ini index 58f88da370..2cfaf38ffe 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -698,6 +698,11 @@ ULKS46010 = true ULJM05223 = true ULJM05362 = true +# Iron Man, see [BlockTransferDepth] below. +ULES01070 = true +ULES01071 = true +ULUS10347 = true + # Note! This whole flag is disabled temporarily by appending "Disabled" to its name). See 7914 [YugiohSaveFixDisabled] # The cause of Yu-gi-oh series 's bad save (cannot save) are load "save status" and use cwcheat, @@ -1458,3 +1463,10 @@ SYPH04036 = true # Prototype? # Syphon Filter - Combat Ops (weird multiplayer-only variant) NPUG80114 = true NPEG00004 = true + +[BlockTransferDepth] +# Iron Man - see issue #16530 +# Note that this option also requires IntraVRAMBlockTransferAllowCreateFB. +ULES01070 = true +ULES01071 = true +ULUS10347 = true From ae9291f3b549e14660ef55f7d9880f43cee30add Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Feb 2023 00:00:04 +0100 Subject: [PATCH 120/424] More work on depth copies. Seems to be enough for Iron Man. --- GPU/Common/FramebufferManagerCommon.cpp | 73 ++++++++++++++++--------- GPU/Common/FramebufferManagerCommon.h | 2 +- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 9ce0585990..31981d722f 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -2032,8 +2032,8 @@ bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_p if (candidate->channel == best->channel) { better = candidate->vfb->BindSeq(candidate->channel) > best->vfb->BindSeq(candidate->channel); } else { - // Prefer color over depth. - if (candidate->channel == RASTER_COLOR && best->channel == RASTER_DEPTH) { + // Prefer depth over color if the address match is perfect. + if (candidate->channel == RASTER_DEPTH && best->channel == RASTER_COLOR && candidate->vfb->z_address == basePtr) { better = true; } } @@ -2073,17 +2073,27 @@ bool FramebufferManagerCommon::FindTransferFramebuffer(u32 basePtr, int stride_p VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAddress, int width, int height, int stride, GEBufferFormat format) { INFO_LOG(G3D, "Creating RAM framebuffer at %08x (%dx%d, stride %d, fb_format %d)", fbAddress, width, height, stride, format); + RasterChannel channel = format == GE_FORMAT_DEPTH16 ? RASTER_DEPTH : RASTER_COLOR; + // A target for the destination is missing - so just create one! // Make sure this one would be found by the algorithm above so we wouldn't // create a new one each frame. VirtualFramebuffer *vfb = new VirtualFramebuffer{}; vfb->fbo = nullptr; uint32_t mask = Memory::IsVRAMAddress(fbAddress) ? 0x041FFFFF : 0x3FFFFFFF; - vfb->fb_address = fbAddress & mask; // NOTE - not necessarily in VRAM! - vfb->fb_stride = stride; - vfb->z_address = 0; // marks that if anyone tries to render to this framebuffer, it should be dropped and recreated. - vfb->z_stride = 0; - vfb->width = std::max(width, stride); + if (format == GE_FORMAT_DEPTH16) { + vfb->fb_address = 0xFFFFFFFF; // Invalid address + vfb->fb_stride = 0; + vfb->z_address = fbAddress; // marks that if anyone tries to render with depth to this framebuffer, it should be dropped and recreated. + vfb->z_stride = stride; + vfb->width = width; + } else { + vfb->fb_address = fbAddress & mask; // NOTE - not necessarily in VRAM! + vfb->fb_stride = stride; + vfb->z_address = 0; + vfb->z_stride = 0; + vfb->width = std::max(width, stride); + } vfb->height = height; vfb->newWidth = vfb->width; vfb->newHeight = vfb->height; @@ -2093,16 +2103,19 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd vfb->renderHeight = (u16)(vfb->height * renderScaleFactor_); vfb->bufferWidth = vfb->width; vfb->bufferHeight = vfb->height; - vfb->fb_format = format; - vfb->usageFlags = FB_USAGE_RENDER_COLOR; - SetColorUpdated(vfb, 0); + vfb->fb_format = format == GE_FORMAT_DEPTH16 ? GE_FORMAT_8888 : format; + vfb->usageFlags = format == GE_FORMAT_DEPTH16 ? FB_USAGE_RENDER_DEPTH : FB_USAGE_RENDER_COLOR; + if (format != GE_FORMAT_DEPTH16) { + SetColorUpdated(vfb, 0); + } char name[64]; - snprintf(name, sizeof(name), "%08x_color_RAM", vfb->fb_address); + snprintf(name, sizeof(name), "%08x_%s_RAM", vfb->Address(channel), RasterChannelToString(channel)); textureCache_->NotifyFramebuffer(vfb, NOTIFY_FB_CREATED); - vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, false, name }); + bool createDepthBuffer = format == GE_FORMAT_DEPTH16; + vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), 0, createDepthBuffer, name }); vfbs_.push_back(vfb); - u32 byteSize = vfb->BufferByteSize(RASTER_COLOR); + u32 byteSize = vfb->BufferByteSize(channel); if (fbAddress + byteSize > framebufRangeEnd_) { framebufRangeEnd_ = fbAddress + byteSize; } @@ -2304,22 +2317,31 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst // No info left - just fall back to something. But this is definitely split pixel tricks. ramFormat = GE_FORMAT_5551; } - dstBuffer = true; dstRect.vfb = CreateRAMFramebuffer(dstBasePtr, width, height, dstStride, ramFormat); } else { dstRect.vfb = CreateRAMFramebuffer(dstBasePtr, width, height, dstStride, GE_FORMAT_DEPTH16); + dstRect.x_bytes = 0; + dstRect.w_bytes = 2 * width; + dstRect.y = 0; + dstRect.h = height; + dstRect.channel = RASTER_DEPTH; } + dstBuffer = true; } } if (dstBuffer) { dstRect.vfb->last_frame_used = gpuStats.numFlips; // Mark the destination as fresh. - dstRect.vfb->colorBindSeq = GetBindSeqCount(); + if (dstRect.channel == RASTER_COLOR) { + dstRect.vfb->colorBindSeq = GetBindSeqCount(); + } else { + dstRect.vfb->depthBindSeq = GetBindSeqCount(); + } } if (dstBuffer && srcBuffer) { - if (srcRect.vfb == dstRect.vfb) { + if (srcRect.vfb && srcRect.vfb == dstRect.vfb && srcRect.channel == dstRect.channel) { // Transfer within the same buffer. // This is a simple case because there will be no format conversion or similar shenanigans needed. // However, the BPP might still mismatch, but in such a case we can convert the coordinates. @@ -2329,7 +2351,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst return true; } - int buffer_bpp = BufferFormatBytesPerPixel(srcRect.vfb->fb_format); + int buffer_bpp = BufferFormatBytesPerPixel(srcRect.vfb->Format(srcRect.channel)); if (bpp != buffer_bpp) { WARN_LOG_ONCE(intrabpp, G3D, "Mismatched transfer bpp in intra-buffer block transfer. Was %d, expected %d.", bpp, buffer_bpp); @@ -2343,28 +2365,29 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst dstBasePtr, dstRect.x_bytes / bpp, dstRect.y, dstStride); FlushBeforeCopy(); // Some backends can handle blitting within a framebuffer. Others will just have to deal with it or ignore it, apparently. - BlitFramebuffer(dstRect.vfb, dstX, dstY, srcRect.vfb, srcX, srcY, dstRect.w_bytes / bpp, dstRect.h / bpp, bpp, RASTER_COLOR, "Blit_IntraBufferBlockTransfer"); + BlitFramebuffer(dstRect.vfb, dstX, dstY, srcRect.vfb, srcX, srcY, dstRect.w_bytes / bpp, dstRect.h / bpp, bpp, dstRect.channel, "Blit_IntraBufferBlockTransfer"); RebindFramebuffer("rebind after intra block transfer"); SetColorUpdated(dstRect.vfb, skipDrawReason); return true; // Skip the memory copy. } // Straightforward blit between two same-format framebuffers. - if (srcRect.vfb->fb_format == dstRect.vfb->fb_format) { - WARN_LOG_N_TIMES(dstnotsrc, 5, G3D, "Inter-buffer block transfer %dx%d %dbpp from %08x (x:%d y:%d stride:%d %s) -> %08x (x:%d y:%d stride:%d %s)", + if (srcRect.vfb && srcRect.channel == dstRect.channel && srcRect.vfb->Format(srcRect.channel) == dstRect.vfb->Format(dstRect.channel)) { + WARN_LOG_N_TIMES(dstnotsrc, 5, G3D, "Inter-buffer %s block transfer %dx%d %dbpp from %08x (x:%d y:%d stride:%d %s) -> %08x (x:%d y:%d stride:%d %s)", + RasterChannelToString(srcRect.channel), width, height, bpp, srcBasePtr, srcRect.x_bytes / bpp, srcRect.y, srcStride, GeBufferFormatToString(srcRect.vfb->fb_format), dstBasePtr, dstRect.x_bytes / bpp, dstRect.y, dstStride, GeBufferFormatToString(dstRect.vfb->fb_format)); // Straight blit will do, but check the bpp, we might need to convert coordinates differently. - int buffer_bpp = BufferFormatBytesPerPixel(srcRect.vfb->fb_format); + int buffer_bpp = BufferFormatBytesPerPixel(srcRect.vfb->Format(srcRect.channel)); if (bpp != buffer_bpp) { WARN_LOG_ONCE(intrabpp, G3D, "Mismatched transfer bpp in inter-buffer block transfer. Was %d, expected %d.", bpp, buffer_bpp); // We just switch to using the buffer's bpp, since we've already converted the rectangle to byte offsets. bpp = buffer_bpp; } FlushBeforeCopy(); - BlitFramebuffer(dstRect.vfb, dstRect.x_bytes / bpp, dstRect.y, srcRect.vfb, srcRect.x_bytes / bpp, srcRect.y, srcRect.w_bytes / bpp, height, bpp, RASTER_COLOR, "Blit_InterBufferBlockTransfer"); + BlitFramebuffer(dstRect.vfb, dstRect.x_bytes / bpp, dstRect.y, srcRect.vfb, srcRect.x_bytes / bpp, srcRect.y, srcRect.w_bytes / bpp, height, bpp, srcRect.channel, "Blit_InterBufferBlockTransfer"); RebindFramebuffer("RebindFramebuffer - Inter-buffer block transfer"); SetColorUpdated(dstRect.vfb, skipDrawReason); return true; @@ -2372,7 +2395,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst // Getting to the more complex cases. Have not actually seen much of these yet. WARN_LOG_N_TIMES(blockformat, 5, G3D, "Mismatched buffer formats in block transfer: %s->%s (%dx%d)", - GeBufferFormatToString(srcRect.vfb->fb_format), GeBufferFormatToString(dstRect.vfb->fb_format), + GeBufferFormatToString(srcRect.vfb->Format(srcRect.channel)), GeBufferFormatToString(dstRect.vfb->Format(dstRect.channel)), width, height); // TODO @@ -3115,7 +3138,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX float srcXFactor = src->renderScaleFactor; float srcYFactor = src->renderScaleFactor; - const int srcBpp = BufferFormatBytesPerPixel(src->fb_format); + const int srcBpp = BufferFormatBytesPerPixel(src->Format(channel)); if (srcBpp != bpp && bpp != 0) { // If we do this, we're kinda in nonsense territory since the actual formats won't match (unless intentionally blitting black or white). srcXFactor = (srcXFactor * bpp) / srcBpp; @@ -3127,7 +3150,7 @@ void FramebufferManagerCommon::BlitFramebuffer(VirtualFramebuffer *dst, int dstX float dstXFactor = dst->renderScaleFactor; float dstYFactor = dst->renderScaleFactor; - const int dstBpp = BufferFormatBytesPerPixel(dst->fb_format); + const int dstBpp = BufferFormatBytesPerPixel(dst->Format(channel)); if (dstBpp != bpp && bpp != 0) { // If we do this, we're kinda in nonsense territory since the actual formats won't match (unless intentionally blitting black or white). dstXFactor = (dstXFactor * bpp) / dstBpp; diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index c2bdac1607..672130f7aa 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -158,7 +158,7 @@ struct VirtualFramebuffer { inline int Stride(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_stride : z_stride; } inline u32 Address(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_address : z_address; } - inline int Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; } + inline GEBufferFormat Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; } inline int BindSeq(RasterChannel channel) const { return channel == RASTER_COLOR ? colorBindSeq : depthBindSeq; } int BufferByteSize(RasterChannel channel) const { From 8ff78cb921c3721e60ab799a1d507b1990e867d6 Mon Sep 17 00:00:00 2001 From: xielei Date: Sun, 12 Feb 2023 20:49:58 +0800 Subject: [PATCH 121/424] aioemu --- .gitignore | 2 ++ .gitmodules | 3 +++ Core/FileLoaders/LocalFileLoader.cpp | 36 +++++++++++++++++++++++----- Core/FileLoaders/LocalFileLoader.h | 7 +++++- libretro/LibretroGraphicsContext.cpp | 2 +- libretro/Makefile.common | 16 +++++++++++++ libretro/jni/Android.mk | 5 ++-- libretro/libretro-common | 1 + libretro/libretro.cpp | 10 ++++++++ 9 files changed, 72 insertions(+), 10 deletions(-) create mode 160000 libretro/libretro-common diff --git a/.gitignore b/.gitignore index b7653209ae..fd1d2d372f 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,5 @@ CMakeFiles # Clangd .cache/ +build +libretro/obj/local diff --git a/.gitmodules b/.gitmodules index da3169b8eb..a3c92a9929 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ +[submodule "libretro/libretro-common"] + path = libretro/libretro-common + url = https://github.com/libretro/libretro-common.git [submodule "pspautotests"] path = pspautotests url = https://github.com/hrydgard/pspautotests.git diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index 08c6ceea3d..3a329cc36d 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -38,7 +38,11 @@ #include #endif -#ifndef _WIN32 +#ifdef HAVE_LIBRETRO_VFS +#include +#endif + +#if !defined(_WIN32) && !defined(HAVE_LIBRETRO_VFS) void LocalFileLoader::DetectSizeFd() { #if PPSSPP_PLATFORM(ANDROID) || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64) @@ -60,7 +64,16 @@ LocalFileLoader::LocalFileLoader(const Path &filename) return; } -#if PPSSPP_PLATFORM(ANDROID) +#if HAVE_LIBRETRO_VFS + isOpenedByFd_ = false; + handle_ = filestream_open(filename.c_str(), RETRO_VFS_FILE_ACCESS_READ, RETRO_VFS_FILE_ACCESS_HINT_NONE); + filestream_seek(handle_, 0, RETRO_VFS_SEEK_POSITION_END); + filesize_ = filestream_tell(handle_); + filestream_seek(handle_, 0, RETRO_VFS_SEEK_POSITION_START); + return; +#endif + +#if PPSSPP_PLATFORM(ANDROID) && !defined(HAVE_LIBRETRO_VFS) if (filename.Type() == PathType::CONTENT_URI) { int fd = Android_OpenContentUriFd(filename.ToString(), Android_OpenContentUriMode::READ); VERBOSE_LOG(SYSTEM, "LocalFileLoader Fd %d for content URI: '%s'", fd, filename.c_str()); @@ -75,7 +88,9 @@ LocalFileLoader::LocalFileLoader(const Path &filename) } #endif -#ifndef _WIN32 +#if defined(HAVE_LIBRETRO_VFS) + // Nothing to do here... +#elif !defined(_WIN32) fd_ = open(filename.c_str(), O_RDONLY | O_CLOEXEC); if (fd_ == -1) { @@ -109,7 +124,9 @@ LocalFileLoader::LocalFileLoader(const Path &filename) } LocalFileLoader::~LocalFileLoader() { -#ifndef _WIN32 +#if defined(HAVE_LIBRETRO_VFS) + filestream_close(handle_); +#elif !defined(_WIN32) if (fd_ != -1) { close(fd_); } @@ -122,7 +139,10 @@ LocalFileLoader::~LocalFileLoader() { bool LocalFileLoader::Exists() { // If we opened it for reading, it must exist. Done. -#ifndef _WIN32 +#if defined(HAVE_LIBRETRO_VFS) + return handle_ != 0; + +#elif !defined(_WIN32) if (isOpenedByFd_) { // As an optimization, if we already tried and failed, quickly return. // This is used because Android Content URIs are so slow. @@ -164,7 +184,11 @@ size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void return 0; } -#if PPSSPP_PLATFORM(SWITCH) +#if defined(HAVE_LIBRETRO_VFS) + std::lock_guard guard(readLock_); + filestream_seek(handle_, absolutePos, RETRO_VFS_SEEK_POSITION_START); + return filestream_read(handle_, data, bytes * count) / bytes; +#elif PPSSPP_PLATFORM(SWITCH) // Toolchain has no fancy IO API. We must lock. std::lock_guard guard(readLock_); lseek(fd_, absolutePos, SEEK_SET); diff --git a/Core/FileLoaders/LocalFileLoader.h b/Core/FileLoaders/LocalFileLoader.h index 8db0b24b02..d5b29cbe42 100644 --- a/Core/FileLoaders/LocalFileLoader.h +++ b/Core/FileLoaders/LocalFileLoader.h @@ -27,6 +27,11 @@ typedef void *HANDLE; #endif +#ifdef HAVE_LIBRETRO_VFS +#include +typedef RFILE* HANDLE; +#endif + class LocalFileLoader : public FileLoader { public: LocalFileLoader(const Path &filename); @@ -41,7 +46,7 @@ public: size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override; private: -#ifndef _WIN32 +#if !defined(_WIN32) && !defined(HAVE_LIBRETRO_VFS) void DetectSizeFd(); int fd_ = -1; #else diff --git a/libretro/LibretroGraphicsContext.cpp b/libretro/LibretroGraphicsContext.cpp index 1ead57a63e..ca11400491 100644 --- a/libretro/LibretroGraphicsContext.cpp +++ b/libretro/LibretroGraphicsContext.cpp @@ -100,7 +100,7 @@ LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() { } #endif - if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL) { + if (preferred == RETRO_HW_CONTEXT_DUMMY || preferred == RETRO_HW_CONTEXT_OPENGL || preferred == RETRO_HW_CONTEXT_OPENGLES3) { ctx = new LibretroGLContext(); if (ctx->Init()) { diff --git a/libretro/Makefile.common b/libretro/Makefile.common index f5cc955e6c..e734a43415 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -7,6 +7,7 @@ GPUDIR = $(CORE_DIR)/GPU EXTDIR = $(CORE_DIR)/ext NATIVEDIR = $(EXTDIR)/native ZSTDDIR = $(EXTDIR)/zstd/lib +LIBRETROCOMMONDIR = $(LIBRETRODIR)/libretro-common SOURCES_CXX := SOURCES_C := @@ -882,6 +883,21 @@ SOURCES_C += \ $(EXTDIR)/zlib/zutil.c endif +ifeq ($(HAVE_LIBRETRO_VFS), 1) +DEFINES += -DHAVE_LIBRETRO_VFS +INCFLAGS += -I$(LIBRETROCOMMONDIR)/include +SOURCES_C += $(LIBRETROCOMMONDIR)/compat/compat_posix_string.c \ + $(LIBRETROCOMMONDIR)/compat/fopen_utf8.c \ + $(LIBRETROCOMMONDIR)/encodings/encoding_utf.c \ + $(LIBRETROCOMMONDIR)/compat/compat_strl.c \ + $(LIBRETROCOMMONDIR)/file/file_path.c \ + $(LIBRETROCOMMONDIR)/streams/file_stream.c \ + $(LIBRETROCOMMONDIR)/streams/file_stream_transforms.c \ + $(LIBRETROCOMMONDIR)/string/stdstring.c \ + $(LIBRETROCOMMONDIR)/time/rtime.c \ + $(LIBRETROCOMMONDIR)/vfs/vfs_implementation.c +endif + GIT_VERSION_SRC = $(CORE_DIR)/git-version.cpp GIT_VERSION := $(shell git describe --always || echo v1.7.0-git) GIT_VERSION_NO_UPDATE = $(findstring 1,$(shell grep -s PPSSPP_GIT_VERSION_NO_UPDATE $(GIT_VERSION_SRC))) diff --git a/libretro/jni/Android.mk b/libretro/jni/Android.mk index 0d5b95d7fd..1d6e33b58a 100644 --- a/libretro/jni/Android.mk +++ b/libretro/jni/Android.mk @@ -10,6 +10,7 @@ CORE_DIR := ../.. FFMPEGDIR := $(CORE_DIR)/ffmpeg FFMPEGLIBS += libavformat libavcodec libavutil libswresample libswscale WITH_DYNAREC := 1 +HAVE_LIBRETRO_VFS := 1 ifeq ($(TARGET_ARCH),arm64) COREFLAGS += -D_ARCH_64 @@ -74,8 +75,8 @@ include $(CORE_DIR)/libretro/Makefile.common COREFLAGS += -DINLINE="inline" -DPPSSPP -DUSE_FFMPEG -DWITH_UPNP -DMOBILE_DEVICE -DBAKE_IN_GIT -DDYNAREC -D__LIBRETRO__ -DUSING_GLES2 -D__STDC_CONSTANT_MACROS -DGLEW_NO_GLU -DMINIUPNP_STATICLIB $(INCFLAGS) LOCAL_SRC_FILES = $(SOURCES_CXX) $(SOURCES_C) $(ASMFILES) -LOCAL_CPPFLAGS := -Wall -std=c++17 $(COREFLAGS) -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS -LOCAL_CFLAGS := -O2 -DANDROID $(COREFLAGS) +LOCAL_CPPFLAGS := -Wall -std=c++17 $(COREFLAGS) -DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS $(DEFINES) +LOCAL_CFLAGS := -O2 -DANDROID $(COREFLAGS) $(DEFINES) LOCAL_LDLIBS += -lz -llog -lGLESv2 -lEGL -latomic LOCAL_STATIC_LIBRARIES += $(FFMPEGLIBS) diff --git a/libretro/libretro-common b/libretro/libretro-common new file mode 160000 index 0000000000..2a4b12d1a3 --- /dev/null +++ b/libretro/libretro-common @@ -0,0 +1 @@ +Subproject commit 2a4b12d1a3aa69f521b8322ef48b23a4a585b38c diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 72db7aa22b..a5909da4ae 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -61,6 +61,10 @@ #define DIR_SEP_CHRS "/" #endif +#ifdef HAVE_LIBRETRO_VFS +#include "streams/file_stream.h" +#endif + #define SAMPLERATE 44100 #define AUDIO_RING_BUFFER_SIZE (1 << 16) @@ -516,6 +520,12 @@ void retro_set_environment(retro_environment_t cb) struct retro_core_options_update_display_callback update_display_cb; update_display_cb.callback = set_variable_visibility; environ_cb(RETRO_ENVIRONMENT_SET_CORE_OPTIONS_UPDATE_DISPLAY_CALLBACK, &update_display_cb); + + #ifdef HAVE_LIBRETRO_VFS + struct retro_vfs_interface_info vfs_iface_info { 1, nullptr }; + if (cb(RETRO_ENVIRONMENT_GET_VFS_INTERFACE, &vfs_iface_info)) + filestream_vfs_init(&vfs_iface_info); + #endif } static int get_language_auto(void) From adda49d05d1091decb8832259f0ca4e9e085f143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Feb 2023 15:28:33 +0100 Subject: [PATCH 122/424] Add a heuristic avoiding joining framebuffers horizontally ...when texturing from the other one. Greatly improves GPU performance in Rainbow Six: Vegas. Fixes #9324. --- GPU/Common/FramebufferManagerCommon.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 31981d722f..a126bb7fb2 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -426,6 +426,14 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer u32 v_fb_end_ptr = v->fb_address + v->fb_stride * v->height * bpp; if (params.fb_address > v->fb_address && params.fb_address < v_fb_first_line_end_ptr) { + // If the framebuffer we can join to is currently bound as a texture, we likely have + // a situation like in #9324 and don't want to do this. + u32 curTextureAddress = gstate.getTextureAddress(0); + if (v->fb_address == curTextureAddress) { + // Don't try these joining shenanigans. + continue; + } + const int x_offset = (params.fb_address - v->fb_address) / bpp; if (x_offset < params.fb_stride && v->height >= drawing_height) { // Pretty certainly a pure render-to-X-offset. From a288c598413e3d9ab52999bd009484bd19b3fce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Feb 2023 10:33:47 +0100 Subject: [PATCH 123/424] Simplify tilt, step 1 --- Core/TiltEventProcessor.cpp | 18 +++++++++++------- Core/TiltEventProcessor.h | 11 +---------- UI/NativeApp.cpp | 4 +--- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 536c8b90d8..6bf962c6c7 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -19,6 +19,13 @@ static u32 tiltButtonsDown = 0; float rawTiltAnalogX; float rawTiltAnalogY; +// Represents a generic Tilt event +struct Tilt { + Tilt() : x_(0), y_(0) {} + Tilt(const float x, const float y) : x_(x), y_(y) {} + float x_, y_; +}; + // These functions generate tilt events given the current Tilt amount, // and the deadzone radius. void GenerateAnalogStickEvent(const Tilt &tilt); @@ -51,7 +58,7 @@ inline Tilt DampenTilt(const Tilt &tilt, float deadzone, float xSensitivity, flo ); } -Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity) { +void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity) { if (landscape) { std::swap(x, y); } else { @@ -78,18 +85,15 @@ Tilt GenTilt(bool landscape, float calibrationAngle, float x, float y, float z, } // finally, dampen the tilt according to our curve. - return DampenTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); -} - -void TranslateTiltToInput(const Tilt &tilt) { - rawTiltAnalogX = tilt.x_; - rawTiltAnalogY = tilt.y_; + Tilt tilt = DampenTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); switch (g_Config.iTiltInputType) { case TILT_NULL: break; case TILT_ANALOG: + rawTiltAnalogX = tilt.x_; + rawTiltAnalogY = tilt.y_; GenerateAnalogStickEvent(tilt); break; diff --git a/Core/TiltEventProcessor.h b/Core/TiltEventProcessor.h index fb7156b9a2..3eda969e17 100644 --- a/Core/TiltEventProcessor.h +++ b/Core/TiltEventProcessor.h @@ -2,18 +2,9 @@ namespace TiltEventProcessor { -// Represents a generic Tilt event -struct Tilt { - Tilt() : x_(0), y_(0) {} - Tilt(const float x, const float y) : x_(x), y_(y) {} - float x_, y_; -}; - // generates a tilt in the correct coordinate system based on // calibration. x, y, z is the current accelerometer reading (with no conversion). -Tilt GenTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity); - -void TranslateTiltToInput(const Tilt &tilt); +void ProcessTilt(bool landscape, const float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity); void ResetTiltEvents(); // Lets you preview the amount of tilt in TiltAnalogSettingsScreen. diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index bd3a062f82..50aa992c8b 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1404,11 +1404,9 @@ void NativeAxis(const AxisInput &axis) { // see [http://developer.android.com/guide/topics/sensors/sensors_overview.html] for details bool landscape = dp_yres < dp_xres; // now transform out current tilt to the calibrated coordinate system - Tilt trueTilt = GenTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, + ProcessTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, g_Config.bInvertTiltX, g_Config.bInvertTiltY, xSensitivity, ySensitivity); - - TranslateTiltToInput(trueTilt); } void NativeMessageReceived(const char *message, const char *value) { From 3e286b7a27d7f9bf57d9af163a284b312cdf9a8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Feb 2023 10:35:38 +0100 Subject: [PATCH 124/424] Apply sensitivity before deadzone. Feels more intuitive --- Core/TiltEventProcessor.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index 6bf962c6c7..a78649d1fa 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -35,8 +35,8 @@ void GenerateTriggerButtonEvent(const Tilt &tilt); // deadzone is normalized - 0 to 1 // sensitivity controls how fast the deadzone reaches max value -inline float TiltInputCurve(float x, float deadzone, float sensitivity) { - const float factor = sensitivity * 1.0f / (1.0f - deadzone); +inline float ApplyDeadzone(float x, float deadzone) { + const float factor = 1.0f / (1.0f - deadzone); if (x > deadzone) { return (x - deadzone) * factor + deadzone; @@ -53,8 +53,8 @@ inline Tilt DampenTilt(const Tilt &tilt, float deadzone, float xSensitivity, flo //sensitivity >1 for kingdom hearts and < 1 for Gods Eater. so yes, overshoot is nice //to have. return Tilt( - TiltInputCurve(tilt.x_, deadzone, 2.0f * xSensitivity), - TiltInputCurve(tilt.y_, deadzone, 2.0f * ySensitivity) + ApplyDeadzone(tilt.x_ * xSensitivity, deadzone), + ApplyDeadzone(tilt.y_ * ySensitivity, deadzone) ); } @@ -85,7 +85,7 @@ void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float } // finally, dampen the tilt according to our curve. - Tilt tilt = DampenTilt(transformedTilt, deadzone, xSensitivity, ySensitivity); + Tilt tilt = DampenTilt(transformedTilt, deadzone, xSensitivity * 2.0f, ySensitivity * 2.0f); switch (g_Config.iTiltInputType) { case TILT_NULL: From 64e80423a684501bfaf5e8384567df360581ecc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Feb 2023 11:07:57 +0100 Subject: [PATCH 125/424] Simplify the tilt code, tweak a bit --- Common/GPU/Vulkan/VulkanContext.cpp | 1 + Core/Config.cpp | 5 +- Core/Config.h | 12 +-- Core/TiltEventProcessor.cpp | 156 +++++++++++++++------------- UI/TiltAnalogSettingsScreen.cpp | 4 +- 5 files changed, 92 insertions(+), 86 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 6768602852..23b0f8adb0 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1663,6 +1663,7 @@ void VulkanDeleteList::PerformDeletes(VulkanContext *vulkan, VmaAllocator alloca } imagesWithAllocs_.clear(); for (auto &imageView : imageViews_) { + INFO_LOG(G3D, "deleting imageview %p", imageView); vkDestroyImageView(device, imageView, nullptr); } imageViews_.clear(); diff --git a/Core/Config.cpp b/Core/Config.cpp index ff957a4a72..3cf4d788b6 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -975,10 +975,9 @@ static const ConfigSetting controlSettings[] = { ConfigSetting("TiltBaseAngleY", &g_Config.fTiltBaseAngleY, 0.9f, true, true), ConfigSetting("TiltInvertX", &g_Config.bInvertTiltX, false, true, true), ConfigSetting("TiltInvertY", &g_Config.bInvertTiltY, false, true, true), - ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 70, true, true), - ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 70, true, true), + ConfigSetting("TiltSensitivityX", &g_Config.iTiltSensitivityX, 60, true, true), + ConfigSetting("TiltSensitivityY", &g_Config.iTiltSensitivityY, 60, true, true), ConfigSetting("TiltAnalogDeadzoneRadius", &g_Config.fTiltAnalogDeadzoneRadius, 0.0f, true, true), - ConfigSetting("TiltDigitalDeadzoneRadius", &g_Config.fTiltDigitalDeadzoneRadius, 0.15f, true, true), ConfigSetting("TiltInputType", &g_Config.iTiltInputType, 0, true, true), #endif diff --git a/Core/Config.h b/Core/Config.h index 7d90f6de8f..a87fbc005d 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -284,20 +284,18 @@ public: bool bShowGpuProfile; // Analog stick tilting - // This is the held base angle, that we compute the tilt relative from. + // This is the held base angle (from the horizon), that we compute the tilt relative from. float fTiltBaseAngleY; - // whether the x axes and y axes should invert directions (left becomes right, top becomes bottom.) + // Inverts the direction of the x axes and y axes for the purposes of tilt input. bool bInvertTiltX; bool bInvertTiltY; // The sensitivity of the tilt in the X and Y directions, separately. int iTiltSensitivityX; int iTiltSensitivityY; - // The deadzone radius of the tilt. - // Separate settings for analog vs digital since the usable ranges differ. + // The deadzone radius of the tilt. Only used in the analog mapping. float fTiltAnalogDeadzoneRadius; - float fTiltDigitalDeadzoneRadius; - //type of tilt input currently selected: Defined in TiltEventProcessor.h - //0 - no tilt, 1 - analog stick, 2 - D-Pad, 3 - Action Buttons (Tri, Cross, Square, Circle) + // Type of tilt input currently selected: Defined in TiltEventProcessor.h + // 0 - no tilt, 1 - analog stick, 2 - D-Pad, 3 - Action Buttons (Tri, Cross, Square, Circle) int iTiltInputType; // The three tabs. diff --git a/Core/TiltEventProcessor.cpp b/Core/TiltEventProcessor.cpp index a78649d1fa..5d142955a8 100644 --- a/Core/TiltEventProcessor.cpp +++ b/Core/TiltEventProcessor.cpp @@ -19,19 +19,12 @@ static u32 tiltButtonsDown = 0; float rawTiltAnalogX; float rawTiltAnalogY; -// Represents a generic Tilt event -struct Tilt { - Tilt() : x_(0), y_(0) {} - Tilt(const float x, const float y) : x_(x), y_(y) {} - float x_, y_; -}; - // These functions generate tilt events given the current Tilt amount, // and the deadzone radius. -void GenerateAnalogStickEvent(const Tilt &tilt); -void GenerateDPadEvent(const Tilt &tilt); -void GenerateActionButtonEvent(const Tilt &tilt); -void GenerateTriggerButtonEvent(const Tilt &tilt); +void GenerateAnalogStickEvent(float analogX, float analogY); +void GenerateDPadEvent(int digitalX, int digitalY); +void GenerateActionButtonEvent(int digitalX, int digitalY); +void GenerateTriggerButtonEvent(int digitalX, int digitalY); // deadzone is normalized - 0 to 1 // sensitivity controls how fast the deadzone reaches max value @@ -47,66 +40,85 @@ inline float ApplyDeadzone(float x, float deadzone) { } } -// dampen the tilt according to the given deadzone amount. -inline Tilt DampenTilt(const Tilt &tilt, float deadzone, float xSensitivity, float ySensitivity) { - //multiply sensitivity by 2 so that "overshoot" is possible. I personally prefer a - //sensitivity >1 for kingdom hearts and < 1 for Gods Eater. so yes, overshoot is nice - //to have. - return Tilt( - ApplyDeadzone(tilt.x_ * xSensitivity, deadzone), - ApplyDeadzone(tilt.y_ * ySensitivity, deadzone) - ); -} - void ProcessTilt(bool landscape, float calibrationAngle, float x, float y, float z, bool invertX, bool invertY, float xSensitivity, float ySensitivity) { + if (g_Config.iTiltInputType == TILT_NULL) { + // Turned off - nothing to do. + return; + } + if (landscape) { std::swap(x, y); } else { x *= -1.0f; } - float deadzone = g_Config.iTiltInputType > 1 ? g_Config.fTiltDigitalDeadzoneRadius : g_Config.fTiltAnalogDeadzoneRadius; - Lin::Vec3 down = Lin::Vec3(x, y, z).normalized(); float angleAroundX = atan2(down.z, down.y); float yAngle = angleAroundX - calibrationAngle; float xAngle = asinf(down.x); - Tilt transformedTilt(xAngle, yAngle); + float tiltX = xAngle; + float tiltY = yAngle; // invert x and y axes if requested. Can probably remove this. if (invertX) { - transformedTilt.x_ *= -1.0f; + tiltX = -tiltX; } - if (invertY) { - transformedTilt.y_ *= -1.0f; + tiltY = -tiltY; } - // finally, dampen the tilt according to our curve. - Tilt tilt = DampenTilt(transformedTilt, deadzone, xSensitivity * 2.0f, ySensitivity * 2.0f); + // It's not obvious what the factor for converting from tilt angle to value should be, + // but there's nothing that says that 1 would make sense. The important thing is that + // the sensitivity sliders get a range of values that makes sense. + const float tiltFactor = 3.0f; + + tiltX *= xSensitivity * tiltFactor; + tiltY *= ySensitivity * tiltFactor; + + if (g_Config.iTiltInputType == TILT_ANALOG) { + // Only analog mappings use the deadzone. + + float adjustedTiltX = ApplyDeadzone(tiltX, g_Config.fTiltAnalogDeadzoneRadius); + float adjustedTiltY = ApplyDeadzone(tiltY, g_Config.fTiltAnalogDeadzoneRadius); + rawTiltAnalogX = adjustedTiltX; + rawTiltAnalogY = adjustedTiltY; + GenerateAnalogStickEvent(adjustedTiltX, adjustedTiltY); + return; + } + + // Remaining are digital now so do the digital check here. + // We use a fixed 0.3 threshold instead of a deadzone since you can simply use sensitivity to set it - + // these parameters were never independent. It should feel similar to analog that way. + int digitalX = 0; + int digitalY = 0; + const float threshold = 0.5f; + if (tiltX < -threshold) { + digitalX = -1; + } else if (tiltX > threshold) { + digitalX = 1; + } + if (tiltY < -threshold) { + digitalY = -1; + } else if (tiltY > threshold) { + digitalY = 1; + } switch (g_Config.iTiltInputType) { - case TILT_NULL: - break; - - case TILT_ANALOG: - rawTiltAnalogX = tilt.x_; - rawTiltAnalogY = tilt.y_; - GenerateAnalogStickEvent(tilt); - break; - case TILT_DPAD: - GenerateDPadEvent(tilt); + GenerateDPadEvent(digitalX, digitalY); break; case TILT_ACTION_BUTTON: - GenerateActionButtonEvent(tilt); + GenerateActionButtonEvent(digitalX, digitalY); break; case TILT_TRIGGER_BUTTONS: - GenerateTriggerButtonEvent(tilt); + GenerateTriggerButtonEvent(digitalX, digitalY); + break; + + default: break; } } @@ -117,80 +129,78 @@ inline float clamp(float f) { return f; } -void GenerateAnalogStickEvent(const Tilt &tilt) { - __CtrlSetAnalogXY(CTRL_STICK_LEFT, clamp(tilt.x_), clamp(tilt.y_)); +void GenerateAnalogStickEvent(float tiltX, float tiltY) { + __CtrlSetAnalogXY(CTRL_STICK_LEFT, clamp(tiltX), clamp(tiltY)); } -void GenerateDPadEvent(const Tilt &tilt) { +void GenerateDPadEvent(int digitalX, int digitalY) { static const int dir[4] = { CTRL_RIGHT, CTRL_DOWN, CTRL_LEFT, CTRL_UP }; - if (tilt.x_ == 0) { + if (digitalX == 0) { __CtrlButtonUp(tiltButtonsDown & (CTRL_RIGHT | CTRL_LEFT)); tiltButtonsDown &= ~(CTRL_LEFT | CTRL_RIGHT); } - if (tilt.y_ == 0) { + if (digitalY == 0) { __CtrlButtonUp(tiltButtonsDown & (CTRL_UP | CTRL_DOWN)); tiltButtonsDown &= ~(CTRL_UP | CTRL_DOWN); } - if (tilt.x_ == 0 && tilt.y_ == 0) { + if (digitalX == 0 && digitalY == 0) { return; } int ctrlMask = 0; - int direction = (int)(floorf((atan2f(-tilt.y_, tilt.x_) / (2.0f * (float)M_PI) * 8.0f) + 0.5f)) & 7; - switch (direction) { - case 0: ctrlMask |= CTRL_RIGHT; break; - case 1: ctrlMask |= CTRL_RIGHT | CTRL_DOWN; break; - case 2: ctrlMask |= CTRL_DOWN; break; - case 3: ctrlMask |= CTRL_DOWN | CTRL_LEFT; break; - case 4: ctrlMask |= CTRL_LEFT; break; - case 5: ctrlMask |= CTRL_UP | CTRL_LEFT; break; - case 6: ctrlMask |= CTRL_UP; break; - case 7: ctrlMask |= CTRL_UP | CTRL_RIGHT; break; - } + if (digitalX == -1) ctrlMask |= CTRL_LEFT; + if (digitalX == 1) ctrlMask |= CTRL_RIGHT; + if (digitalY == -1) ctrlMask |= CTRL_DOWN; + if (digitalY == 1) ctrlMask |= CTRL_UP; ctrlMask &= ~__CtrlPeekButtons(); __CtrlButtonDown(ctrlMask); tiltButtonsDown |= ctrlMask; } -void GenerateActionButtonEvent(const Tilt &tilt) { +void GenerateActionButtonEvent(int digitalX, int digitalY) { static const int buttons[4] = { CTRL_CIRCLE, CTRL_CROSS, CTRL_SQUARE, CTRL_TRIANGLE }; - if (tilt.x_ == 0) { + if (digitalX == 0) { __CtrlButtonUp(tiltButtonsDown & (CTRL_SQUARE | CTRL_CIRCLE)); tiltButtonsDown &= ~(CTRL_SQUARE | CTRL_CIRCLE); } - if (tilt.y_ == 0) { + if (digitalY == 0) { __CtrlButtonUp(tiltButtonsDown & (CTRL_TRIANGLE | CTRL_CROSS)); tiltButtonsDown &= ~(CTRL_TRIANGLE | CTRL_CROSS); } - if (tilt.x_ == 0 && tilt.y_ == 0) { + if (digitalX == 0 && digitalY == 0) { return; } - int direction = (int)(floorf((atan2f(-tilt.y_, tilt.x_) / (2.0f * (float)M_PI) * 4.0f) + 0.5f)) & 3; - int downButtons = buttons[direction] & ~__CtrlPeekButtons(); - __CtrlButtonDown(downButtons); - tiltButtonsDown |= downButtons; + int ctrlMask = 0; + if (digitalX == -1) ctrlMask |= CTRL_SQUARE; + if (digitalX == 1) ctrlMask |= CTRL_CIRCLE; + if (digitalY == -1) ctrlMask |= CTRL_CROSS; + if (digitalY == 1) ctrlMask |= CTRL_TRIANGLE; + + ctrlMask &= ~__CtrlPeekButtons(); + __CtrlButtonDown(ctrlMask); + tiltButtonsDown |= ctrlMask; } -void GenerateTriggerButtonEvent(const Tilt &tilt) { +void GenerateTriggerButtonEvent(int digitalX, int digitalY) { u32 upButtons = 0; u32 downButtons = 0; - // Y axis for both - if (tilt.y_ < 0.0f) { + // Y axis up for both + if (digitalY == 1) { downButtons = CTRL_LTRIGGER | CTRL_RTRIGGER; - } else if (tilt.x_ == 0.0f) { + } else if (digitalX == 0) { upButtons = CTRL_LTRIGGER | CTRL_RTRIGGER; - } else if (tilt.x_ < 0.0f) { + } else if (digitalX == -1) { downButtons = CTRL_LTRIGGER; upButtons = CTRL_RTRIGGER; - } else if (tilt.x_ > 0.0f) { + } else if (digitalX == 1) { downButtons = CTRL_RTRIGGER; upButtons = CTRL_LTRIGGER; } diff --git a/UI/TiltAnalogSettingsScreen.cpp b/UI/TiltAnalogSettingsScreen.cpp index ff0bc965f2..45509278b8 100644 --- a/UI/TiltAnalogSettingsScreen.cpp +++ b/UI/TiltAnalogSettingsScreen.cpp @@ -121,9 +121,7 @@ void TiltAnalogSettingsScreen::CreateViews() { settings->Add(calibrate); settings->Add(new ItemHeader(co->T("Sensitivity"))); - if (g_Config.iTiltInputType > 1) { - settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltDigitalDeadzoneRadius, 0.05f, 0.5f, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); - } else { + if (g_Config.iTiltInputType == 1) { settings->Add(new PopupSliderChoiceFloat(&g_Config.fTiltAnalogDeadzoneRadius, 0.0f, 0.8f, co->T("Deadzone radius"), 0.01f, screenManager(), "/ 1.0"))->SetEnabledFunc(enabledFunc); } settings->Add(new PopupSliderChoice(&g_Config.iTiltSensitivityX, 0, 100, co->T("Tilt Sensitivity along X axis"), screenManager(), "%"))->SetEnabledFunc(enabledFunc); From 04ce3a0572bd232b65fcf838881ee627973f8bd0 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 16 Feb 2023 16:09:22 -0800 Subject: [PATCH 126/424] riscv: Allow subset of B extension to be used. --- Common/CPUDetect.h | 4 ++++ Common/RiscVCPUDetect.cpp | 10 ++++++++++ Common/RiscVEmitter.cpp | 31 ++++++++++++++++++------------- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/Common/CPUDetect.h b/Common/CPUDetect.h index 13e1170acc..1feb20483f 100644 --- a/Common/CPUDetect.h +++ b/Common/CPUDetect.h @@ -111,6 +111,10 @@ struct CPUInfo { bool RiscV_V; bool RiscV_B; bool RiscV_Zicsr; + bool RiscV_Zba; + bool RiscV_Zbb; + bool RiscV_Zbc; + bool RiscV_Zbs; // Quirks struct { diff --git a/Common/RiscVCPUDetect.cpp b/Common/RiscVCPUDetect.cpp index dfcaf74618..f05203488a 100644 --- a/Common/RiscVCPUDetect.cpp +++ b/Common/RiscVCPUDetect.cpp @@ -183,6 +183,12 @@ void CPUInfo::Detect() // Let's assume for now... RiscV_Zicsr = RiscV_M && RiscV_A && RiscV_F && RiscV_D; + // A number of CPUs support a limited set of B. + if (!strcmp(brand_string, "sifive,u74-mc")) { + RiscV_Zba = true; + RiscV_Zbb = true; + } + #ifdef USE_CPU_FEATURES cpu_features::RiscvInfo info = cpu_features::GetRiscvInfo(); CPU64bit = info.features.RV64I; @@ -212,6 +218,10 @@ std::vector CPUInfo::Features() { { RiscV_C, "Compressed" }, { RiscV_V, "Vector" }, { RiscV_B, "Bitmanip" }, + { RiscV_Zba, "Zba" }, + { RiscV_Zbb, "Zbb" }, + { RiscV_Zbc, "Zbc" }, + { RiscV_Zbs, "Zbs" }, { RiscV_Zicsr, "Zicsr" }, { CPU64bit, "64-bit" }, }; diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index b5b7a29a42..20f9708db2 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -61,8 +61,13 @@ static inline bool SupportsVector() { } static inline bool SupportsBitmanip(char zbx) { - // TODO: Allow and detect sub-support? - return cpu_info.RiscV_B; + switch (zbx) { + case 'a': return cpu_info.RiscV_B || cpu_info.RiscV_Zba; + case 'b': return cpu_info.RiscV_B || cpu_info.RiscV_Zbb; + case 'c': return cpu_info.RiscV_B || cpu_info.RiscV_Zbc; + case 's': return cpu_info.RiscV_B || cpu_info.RiscV_Zbs; + default: return false; + } } static inline bool SupportsFloatHalf(bool allowMin = false) { @@ -3894,67 +3899,67 @@ void RiscVEmitter::REV8(RiscVReg rd, RiscVReg rs) { void RiscVEmitter::CLMUL(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('c'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::CLMUL, rs1, rs2, Funct7::MINMAX_CLMUL)); } void RiscVEmitter::CLMULH(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('c'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::CLMULH, rs1, rs2, Funct7::MINMAX_CLMUL)); } void RiscVEmitter::CLMULR(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('c'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::CLMULR, rs1, rs2, Funct7::MINMAX_CLMUL)); } void RiscVEmitter::BCLR(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::BSET, rs1, rs2, Funct7::BCLREXT)); } void RiscVEmitter::BCLRI(RiscVReg rd, RiscVReg rs1, u32 shamt) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGIShift(Opcode32::OP_IMM, rd, Funct3::BSET, rs1, shamt, Funct7::BCLREXT)); } void RiscVEmitter::BEXT(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::BEXT, rs1, rs2, Funct7::BCLREXT)); } void RiscVEmitter::BEXTI(RiscVReg rd, RiscVReg rs1, u32 shamt) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGIShift(Opcode32::OP_IMM, rd, Funct3::BEXT, rs1, shamt, Funct7::BCLREXT)); } void RiscVEmitter::BINV(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::BSET, rs1, rs2, Funct7::BINV_REV)); } void RiscVEmitter::BINVI(RiscVReg rd, RiscVReg rs1, u32 shamt) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGIShift(Opcode32::OP_IMM, rd, Funct3::BSET, rs1, shamt, Funct7::BINV_REV)); } void RiscVEmitter::BSET(RiscVReg rd, RiscVReg rs1, RiscVReg rs2) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGR(Opcode32::OP, rd, Funct3::BSET, rs1, rs2, Funct7::BSET_ORC)); } void RiscVEmitter::BSETI(RiscVReg rd, RiscVReg rs1, u32 shamt) { _assert_msg_(rd != R_ZERO, "%s should avoid write to zero", __func__); - _assert_msg_(SupportsBitmanip('b'), "%s instruction unsupported without B", __func__); + _assert_msg_(SupportsBitmanip('s'), "%s instruction unsupported without B", __func__); Write32(EncodeGIShift(Opcode32::OP_IMM, rd, Funct3::BSET, rs1, shamt, Funct7::BSET_ORC)); } From 27e60a9f2efd684be0564669a9d2353f7d8e721d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 16 Feb 2023 16:10:04 -0800 Subject: [PATCH 127/424] riscv: Sum weighted matrices in vertexjit. Not yet doing pos/norm, so not used yet. --- Common/RiscVEmitter.cpp | 13 ++++ Common/RiscVEmitter.h | 5 ++ GPU/Common/VertexDecoderCommon.h | 1 - GPU/Common/VertexDecoderRiscV.cpp | 109 +++++++++++++++++++++++++++++- 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/Common/RiscVEmitter.cpp b/Common/RiscVEmitter.cpp index 20f9708db2..1fa966e1fb 100644 --- a/Common/RiscVEmitter.cpp +++ b/Common/RiscVEmitter.cpp @@ -1068,10 +1068,23 @@ void RiscVEmitter::FlushIcacheSection(const u8 *start, const u8 *end) { #endif } +FixupBranch::FixupBranch(FixupBranch &&other) { + ptr = other.ptr; + type = other.type; + other.ptr = nullptr; +} + FixupBranch::~FixupBranch() { _assert_msg_(ptr == nullptr, "FixupBranch never set (left infinite loop)"); } +FixupBranch &FixupBranch::operator =(FixupBranch &&other) { + ptr = other.ptr; + type = other.type; + other.ptr = nullptr; + return *this; +} + void RiscVEmitter::SetJumpTarget(FixupBranch &branch) { SetJumpTarget(branch, code_); } diff --git a/Common/RiscVEmitter.h b/Common/RiscVEmitter.h index 7fd0ac0597..720db3faac 100644 --- a/Common/RiscVEmitter.h +++ b/Common/RiscVEmitter.h @@ -182,8 +182,13 @@ enum class VUseMask { struct FixupBranch { FixupBranch() {} FixupBranch(const u8 *p, FixupBranchType t) : ptr(p), type(t) {} + FixupBranch(FixupBranch &&other); + FixupBranch(const FixupBranch &) = delete; ~FixupBranch(); + FixupBranch &operator =(FixupBranch &&other); + FixupBranch &operator =(const FixupBranch &other) = delete; + const u8 *ptr = nullptr; FixupBranchType type = FixupBranchType::B; }; diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 7de309b406..2c1055935f 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -549,7 +549,6 @@ public: void Jit_NormalFloatSkin(); void Jit_PosS8(); - void Jit_PosS8ToFloat(); void Jit_PosS16(); void Jit_PosFloat(); void Jit_PosS8Through(); diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 9a052242b1..941c43f3a4 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -18,6 +18,7 @@ #include "ppsspp_config.h" #if PPSSPP_ARCH(RISCV64) +#include #include "Common/CPUDetect.h" #include "Common/Log.h" #include "Common/RiscVEmitter.h" @@ -55,6 +56,7 @@ static const RiscVReg fpScratchReg3 = F12; // We want most of these within 8-15, to be compressible. static const RiscVReg fpSrc[4] = { F13, F14, F15, F16 }; static const RiscVReg fpScratchReg4 = F17; +static const RiscVReg fpExtra[4] = { F28, F29, F30, F31 }; struct UVScaleRegs { struct { @@ -90,6 +92,7 @@ enum class MorphValuesIndex { COLOR_6 = 5, }; static MorphValues morphValues; +static float skinMatrix[12]; static uint32_t GetMorphValueUsage(uint32_t vtype) { uint32_t morphFlags = 0; @@ -123,6 +126,9 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8}, {&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16}, {&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat}, + {&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin}, + {&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin}, + {&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin}, {&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat}, {&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat}, @@ -275,6 +281,8 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int if ((morphFlags & (1 << (int)MorphValuesIndex::COLOR_6)) != 0) storePremultiply(fpScratchReg3, MorphValuesIndex::COLOR_6, n); } + } else if (dec_->skinInDecode) { + LI(morphBaseReg, &skinMatrix[0]); } if (dec.col) { @@ -291,8 +299,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int LH(boundsMaxVReg, tempReg1, offsetof(KnownVertexBounds, maxV)); } - // TODO: Skinning. - const u8 *loopStart = GetCodePtr(); for (int i = 0; i < dec.numSteps_; i++) { if (!CompileStep(dec, i)) { @@ -397,6 +403,105 @@ void VertexDecoderJitCache::Jit_WeightsFloat() { } } +void VertexDecoderJitCache::Jit_WeightsU8Skin() { + Jit_ApplyWeights(); +} + +void VertexDecoderJitCache::Jit_WeightsU16Skin() { + Jit_ApplyWeights(); +} + +void VertexDecoderJitCache::Jit_WeightsFloatSkin() { + Jit_ApplyWeights(); +} + +void VertexDecoderJitCache::Jit_ApplyWeights() { + int weightSize = 4; + switch (dec_->weighttype) { + case 1: weightSize = 1; break; + case 2: weightSize = 2; break; + case 3: weightSize = 4; break; + default: + _assert_(false); + break; + } + + const RiscVReg boneMatrixReg = tempReg1; + // If we are doing morph + skin, we abuse morphBaseReg. + const RiscVReg skinMatrixReg = morphBaseReg; + const RiscVReg loopEndReg = tempReg3; + + LI(boneMatrixReg, &gstate.boneMatrix[0]); + if (dec_->morphcount > 1) + LI(skinMatrixReg, &skinMatrix[0]); + if (weightSize == 4) + FMV(FMv::W, FMv::X, fpScratchReg3, R_ZERO); + + for (int j = 0; j < 12; ++j) { + if (cpu_info.Mode64bit) { + SD(R_ZERO, skinMatrixReg, j * 4); + ++j; + } else { + SW(R_ZERO, skinMatrixReg, j * 4); + } + } + + // Now let's loop through each weight. This is the end point. + ADDI(loopEndReg, srcReg, dec_->nweights * weightSize); + const u8 *weightLoop = GetCodePointer(); + + FixupBranch skipZero; + + switch (weightSize) { + case 1: + LBU(scratchReg, srcReg, dec_->weightoff); + skipZero = std::move(BEQ(R_ZERO, scratchReg)); + FCVT(FConv::S, FConv::WU, fpScratchReg4, scratchReg, Round::TOZERO); + FMUL(32, fpScratchReg4, fpScratchReg4, by128Reg); + break; + case 2: + LHU(scratchReg, srcReg, dec_->weightoff); + skipZero = std::move(BEQ(R_ZERO, scratchReg)); + FCVT(FConv::S, FConv::WU, fpScratchReg4, scratchReg, Round::TOZERO); + FMUL(32, fpScratchReg4, fpScratchReg4, by32768Reg); + break; + case 4: + FL(32, fpScratchReg4, srcReg, dec_->weightoff); + FEQ(32, scratchReg, fpScratchReg3, fpScratchReg4); + skipZero = std::move(BNE(R_ZERO, scratchReg)); + break; + default: + _assert_(false); + break; + } + + // This is the loop where we add up the skinMatrix itself by the weight. + for (int j = 0; j < 12; j += 4) { + for (int i = 0; i < 4; ++i) + FL(32, fpSrc[i], boneMatrixReg, (j + i) * 4); + for (int i = 0; i < 4; ++i) + FL(32, fpExtra[i], skinMatrixReg, (j + i) * 4); + for (int i = 0; i < 4; ++i) + FMADD(32, fpExtra[i], fpSrc[i], fpScratchReg4, fpExtra[i]); + for (int i = 0; i < 4; ++i) + FS(32, fpExtra[i], skinMatrixReg, (j + i) * 4); + } + + SetJumpTarget(skipZero); + + // Okay, now return back for the next weight. + ADDI(boneMatrixReg, boneMatrixReg, 12 * 4); + ADDI(srcReg, srcReg, weightSize); + BLT(srcReg, loopEndReg, weightLoop); + + // Undo the changes to srcReg. + ADDI(srcReg, srcReg, dec_->nweights * -weightSize); + + // Restore if we abused this. + if (dec_->morphcount > 1) + LI(morphBaseReg, &morphValues); +} + void VertexDecoderJitCache::Jit_TcU8ToFloat() { Jit_AnyU8ToFloat(dec_->tcoff, 16); FS(32, fpSrc[0], dstReg, dec_->decFmt.uvoff); From 71f4b116fe7212f1af7b9e5694fdd1ccabe0668d Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 16 Feb 2023 17:04:48 -0800 Subject: [PATCH 128/424] riscv: Implement skinning in vertexjit. --- GPU/Common/VertexDecoderRiscV.cpp | 82 ++++++++++++++++++++++++++++--- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index 941c43f3a4..ffbdd8e8d8 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -154,6 +154,9 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8}, {&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16}, {&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat}, + {&VertexDecoder::Step_NormalS8Skin, &VertexDecoderJitCache::Jit_NormalS8Skin}, + {&VertexDecoder::Step_NormalS16Skin, &VertexDecoderJitCache::Jit_NormalS16Skin}, + {&VertexDecoder::Step_NormalFloatSkin, &VertexDecoderJitCache::Jit_NormalFloatSkin}, {&VertexDecoder::Step_NormalS8Morph, &VertexDecoderJitCache::Jit_NormalS8Morph}, {&VertexDecoder::Step_NormalS16Morph, &VertexDecoderJitCache::Jit_NormalS16Morph}, @@ -162,6 +165,9 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, {&VertexDecoder::Step_PosFloat, &VertexDecoderJitCache::Jit_PosFloat}, + {&VertexDecoder::Step_PosS8Skin, &VertexDecoderJitCache::Jit_PosS8Skin}, + {&VertexDecoder::Step_PosS16Skin, &VertexDecoderJitCache::Jit_PosS16Skin}, + {&VertexDecoder::Step_PosFloatSkin, &VertexDecoderJitCache::Jit_PosFloatSkin}, {&VertexDecoder::Step_PosS8Through, &VertexDecoderJitCache::Jit_PosS8Through}, {&VertexDecoder::Step_PosS16Through, &VertexDecoderJitCache::Jit_PosS16Through}, @@ -757,6 +763,23 @@ void VertexDecoderJitCache::Jit_NormalFloat() { SW(tempReg3, dstReg, dec_->decFmt.nrmoff + 8); } +void VertexDecoderJitCache::Jit_NormalS8Skin() { + Jit_AnyS8ToFloat(dec_->nrmoff); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalS16Skin() { + Jit_AnyS16ToFloat(dec_->nrmoff); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalFloatSkin() { + FL(32, fpSrc[0], srcReg, dec_->nrmoff + 0); + FL(32, fpSrc[1], srcReg, dec_->nrmoff + 4); + FL(32, fpSrc[2], srcReg, dec_->nrmoff + 8); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + void VertexDecoderJitCache::Jit_NormalS8Morph() { Jit_AnyS8Morph(dec_->nrmoff, dec_->decFmt.nrmoff); } @@ -771,31 +794,48 @@ void VertexDecoderJitCache::Jit_NormalFloatMorph() { void VertexDecoderJitCache::Jit_PosS8() { Jit_AnyS8ToFloat(dec_->posoff); - FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); + FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff + 0); FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); } void VertexDecoderJitCache::Jit_PosS16() { Jit_AnyS16ToFloat(dec_->posoff); - FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); + FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff + 0); FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); } void VertexDecoderJitCache::Jit_PosFloat() { // Just copy 12 bytes, play with over read/write later. - LW(tempReg1, srcReg, dec_->posoff); + LW(tempReg1, srcReg, dec_->posoff + 0); LW(tempReg2, srcReg, dec_->posoff + 4); LW(tempReg3, srcReg, dec_->posoff + 8); - SW(tempReg1, dstReg, dec_->decFmt.posoff); + SW(tempReg1, dstReg, dec_->decFmt.posoff + 0); SW(tempReg2, dstReg, dec_->decFmt.posoff + 4); SW(tempReg3, dstReg, dec_->decFmt.posoff + 8); } +void VertexDecoderJitCache::Jit_PosS8Skin() { + Jit_AnyS8ToFloat(dec_->nrmoff); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); +} + +void VertexDecoderJitCache::Jit_PosS16Skin() { + Jit_AnyS16ToFloat(dec_->nrmoff); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); +} + +void VertexDecoderJitCache::Jit_PosFloatSkin() { + FL(32, fpSrc[0], srcReg, dec_->nrmoff + 0); + FL(32, fpSrc[1], srcReg, dec_->nrmoff + 4); + FL(32, fpSrc[2], srcReg, dec_->nrmoff + 8); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); +} + void VertexDecoderJitCache::Jit_PosS8Through() { // 8-bit positions in throughmode always decode to 0, depth included. - SW(R_ZERO, dstReg, dec_->decFmt.posoff); + SW(R_ZERO, dstReg, dec_->decFmt.posoff + 0); SW(R_ZERO, dstReg, dec_->decFmt.posoff + 4); SW(R_ZERO, dstReg, dec_->decFmt.posoff + 8); } @@ -809,17 +849,17 @@ void VertexDecoderJitCache::Jit_PosS16Through() { FCVT(FConv::S, FConv::WU, fpSrc[0], tempReg1, Round::TOZERO); FCVT(FConv::S, FConv::WU, fpSrc[1], tempReg2, Round::TOZERO); FCVT(FConv::S, FConv::WU, fpSrc[2], tempReg3, Round::TOZERO); - FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff); + FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff + 0); FS(32, fpSrc[1], dstReg, dec_->decFmt.posoff + 4); FS(32, fpSrc[2], dstReg, dec_->decFmt.posoff + 8); } void VertexDecoderJitCache::Jit_PosFloatThrough() { // Start by copying 8 bytes, then handle Z separately to clamp it. - LW(tempReg1, srcReg, dec_->posoff); + LW(tempReg1, srcReg, dec_->posoff + 0); LW(tempReg2, srcReg, dec_->posoff + 4); FL(32, fpSrc[2], srcReg, dec_->posoff + 8); - SW(tempReg1, dstReg, dec_->decFmt.posoff); + SW(tempReg1, dstReg, dec_->decFmt.posoff + 0); SW(tempReg2, dstReg, dec_->decFmt.posoff + 4); // Load the constant zero and clamp. Maybe could static alloc zero, but fairly cheap... @@ -1304,4 +1344,30 @@ void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) { FS(32, fpSrc[2], dstReg, dstoff + 8); } +void VertexDecoderJitCache::Jit_WriteMatrixMul(int dstoff, bool pos) { + const RiscVReg fpDst[3] = { fpScratchReg1, fpScratchReg2, fpScratchReg3 }; + + // First, take care of the 3x3 portion of the matrix. + for (int y = 0; y < 3; ++y) { + for (int x = 0; x < 3; ++x) { + FL(32, fpScratchReg4, morphBaseReg, (y * 3 + x) * 4); + if (y == 0) + FMUL(32, fpDst[x], fpSrc[x], fpScratchReg4); + else + FMADD(32, fpDst[x], fpSrc[x], fpScratchReg4, fpDst[x]); + } + } + + // For normal, z is 0 so we skip. + if (pos) { + for (int x = 0; x < 3; ++x) + FL(32, fpSrc[x], morphBaseReg, (9 + x) * 4); + for (int x = 0; x < 3; ++x) + FADD(32, fpDst[x], fpDst[x], fpSrc[x]); + } + + for (int x = 0; x < 3; ++x) + FS(32, fpDst[x], dstReg, dstoff + x * 4); +} + #endif // PPSSPP_ARCH(RISCV64) From df1bd64662d01d195db242d2e09b2a94d27f7765 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 16 Feb 2023 18:39:14 -0800 Subject: [PATCH 129/424] riscv: Add morph+skin to vertexjit. --- GPU/Common/VertexDecoderCommon.h | 8 +++++ GPU/Common/VertexDecoderRiscV.cpp | 60 ++++++++++++++++++++++++++----- 2 files changed, 59 insertions(+), 9 deletions(-) diff --git a/GPU/Common/VertexDecoderCommon.h b/GPU/Common/VertexDecoderCommon.h index 2c1055935f..423dbd918d 100644 --- a/GPU/Common/VertexDecoderCommon.h +++ b/GPU/Common/VertexDecoderCommon.h @@ -563,10 +563,18 @@ public: void Jit_NormalS16Morph(); void Jit_NormalFloatMorph(); + void Jit_NormalS8MorphSkin(); + void Jit_NormalS16MorphSkin(); + void Jit_NormalFloatMorphSkin(); + void Jit_PosS8Morph(); void Jit_PosS16Morph(); void Jit_PosFloatMorph(); + void Jit_PosS8MorphSkin(); + void Jit_PosS16MorphSkin(); + void Jit_PosFloatMorphSkin(); + void Jit_Color8888Morph(); void Jit_Color4444Morph(); void Jit_Color565Morph(); diff --git a/GPU/Common/VertexDecoderRiscV.cpp b/GPU/Common/VertexDecoderRiscV.cpp index ffbdd8e8d8..accaebcc45 100644 --- a/GPU/Common/VertexDecoderRiscV.cpp +++ b/GPU/Common/VertexDecoderRiscV.cpp @@ -161,6 +161,9 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_NormalS8Morph, &VertexDecoderJitCache::Jit_NormalS8Morph}, {&VertexDecoder::Step_NormalS16Morph, &VertexDecoderJitCache::Jit_NormalS16Morph}, {&VertexDecoder::Step_NormalFloatMorph, &VertexDecoderJitCache::Jit_NormalFloatMorph}, + {&VertexDecoder::Step_NormalS8MorphSkin, &VertexDecoderJitCache::Jit_NormalS8MorphSkin}, + {&VertexDecoder::Step_NormalS16MorphSkin, &VertexDecoderJitCache::Jit_NormalS16MorphSkin}, + {&VertexDecoder::Step_NormalFloatMorphSkin, &VertexDecoderJitCache::Jit_NormalFloatMorphSkin}, {&VertexDecoder::Step_PosS8, &VertexDecoderJitCache::Jit_PosS8}, {&VertexDecoder::Step_PosS16, &VertexDecoderJitCache::Jit_PosS16}, @@ -176,6 +179,9 @@ static const JitLookup jitLookup[] = { {&VertexDecoder::Step_PosS8Morph, &VertexDecoderJitCache::Jit_PosS8Morph}, {&VertexDecoder::Step_PosS16Morph, &VertexDecoderJitCache::Jit_PosS16Morph}, {&VertexDecoder::Step_PosFloatMorph, &VertexDecoderJitCache::Jit_PosFloatMorph}, + {&VertexDecoder::Step_PosS8MorphSkin, &VertexDecoderJitCache::Jit_PosS8MorphSkin}, + {&VertexDecoder::Step_PosS16MorphSkin, &VertexDecoderJitCache::Jit_PosS16MorphSkin}, + {&VertexDecoder::Step_PosFloatMorphSkin, &VertexDecoderJitCache::Jit_PosFloatMorphSkin}, {&VertexDecoder::Step_Color8888, &VertexDecoderJitCache::Jit_Color8888}, {&VertexDecoder::Step_Color4444, &VertexDecoderJitCache::Jit_Color4444}, @@ -792,6 +798,21 @@ void VertexDecoderJitCache::Jit_NormalFloatMorph() { Jit_AnyFloatMorph(dec_->nrmoff, dec_->decFmt.nrmoff); } +void VertexDecoderJitCache::Jit_NormalS8MorphSkin() { + Jit_AnyS8Morph(dec_->nrmoff, -1); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalS16MorphSkin() { + Jit_AnyS16Morph(dec_->nrmoff, -1); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + +void VertexDecoderJitCache::Jit_NormalFloatMorphSkin() { + Jit_AnyFloatMorph(dec_->nrmoff, -1); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false); +} + void VertexDecoderJitCache::Jit_PosS8() { Jit_AnyS8ToFloat(dec_->posoff); FS(32, fpSrc[0], dstReg, dec_->decFmt.posoff + 0); @@ -881,6 +902,21 @@ void VertexDecoderJitCache::Jit_PosFloatMorph() { Jit_AnyFloatMorph(dec_->posoff, dec_->decFmt.posoff); } +void VertexDecoderJitCache::Jit_PosS8MorphSkin() { + Jit_AnyS8Morph(dec_->posoff, -1); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); +} + +void VertexDecoderJitCache::Jit_PosS16MorphSkin() { + Jit_AnyS16Morph(dec_->posoff, -1); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); +} + +void VertexDecoderJitCache::Jit_PosFloatMorphSkin() { + Jit_AnyFloatMorph(dec_->posoff, -1); + Jit_WriteMatrixMul(dec_->decFmt.nrmoff, true); +} + void VertexDecoderJitCache::Jit_Color8888() { LWU(tempReg1, srcReg, dec_->coloff); @@ -1285,9 +1321,11 @@ void VertexDecoderJitCache::Jit_AnyS8Morph(int srcoff, int dstoff) { FMADD(32, fpSrc[2], fpScratchReg3, fpScratchReg4, fpSrc[2]); } - FS(32, fpSrc[0], dstReg, dstoff + 0); - FS(32, fpSrc[1], dstReg, dstoff + 4); - FS(32, fpSrc[2], dstReg, dstoff + 8); + if (dstoff >= 0) { + FS(32, fpSrc[0], dstReg, dstoff + 0); + FS(32, fpSrc[1], dstReg, dstoff + 4); + FS(32, fpSrc[2], dstReg, dstoff + 8); + } } void VertexDecoderJitCache::Jit_AnyS16Morph(int srcoff, int dstoff) { @@ -1315,9 +1353,11 @@ void VertexDecoderJitCache::Jit_AnyS16Morph(int srcoff, int dstoff) { FMADD(32, fpSrc[2], fpScratchReg3, fpScratchReg4, fpSrc[2]); } - FS(32, fpSrc[0], dstReg, dstoff + 0); - FS(32, fpSrc[1], dstReg, dstoff + 4); - FS(32, fpSrc[2], dstReg, dstoff + 8); + if (dstoff >= 0) { + FS(32, fpSrc[0], dstReg, dstoff + 0); + FS(32, fpSrc[1], dstReg, dstoff + 4); + FS(32, fpSrc[2], dstReg, dstoff + 8); + } } void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) { @@ -1339,9 +1379,11 @@ void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) { FMADD(32, fpSrc[2], fpScratchReg3, fpScratchReg4, fpSrc[2]); } - FS(32, fpSrc[0], dstReg, dstoff + 0); - FS(32, fpSrc[1], dstReg, dstoff + 4); - FS(32, fpSrc[2], dstReg, dstoff + 8); + if (dstoff >= 0) { + FS(32, fpSrc[0], dstReg, dstoff + 0); + FS(32, fpSrc[1], dstReg, dstoff + 4); + FS(32, fpSrc[2], dstReg, dstoff + 8); + } } void VertexDecoderJitCache::Jit_WriteMatrixMul(int dstoff, bool pos) { From 335788a932b56149a3204aeda6c885c9136ea4aa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 16 Feb 2023 19:34:44 -0800 Subject: [PATCH 130/424] Vulkan: Remove logspam. --- Common/GPU/Vulkan/VulkanContext.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 23b0f8adb0..6768602852 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1663,7 +1663,6 @@ void VulkanDeleteList::PerformDeletes(VulkanContext *vulkan, VmaAllocator alloca } imagesWithAllocs_.clear(); for (auto &imageView : imageViews_) { - INFO_LOG(G3D, "deleting imageview %p", imageView); vkDestroyImageView(device, imageView, nullptr); } imageViews_.clear(); From 34e6dcb2878e47e4460b6b48381ad29c54985359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Feb 2023 22:50:36 +0100 Subject: [PATCH 131/424] compat/perf: Enable BlockTransferAllowCreateFB for Naruto Shippuden: Ultimate Ninja Heroes 3 See issue #16733 --- assets/compat.ini | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/assets/compat.ini b/assets/compat.ini index 2cfaf38ffe..91b673fb7a 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -605,6 +605,15 @@ ULJS19071 = true NPJH50435 = true NPJH50435 = true +# Naruto Shippuden: Ultimate Ninja Heroes 3 (issue #16733) +ULJS00236 = true +ULAS42208 = true +ULUS10518 = true +ULAS42231 = true +ULJS19066 = true +ULAS42317 = true +ULUS10518 = true + # Gradius Collection ULUS10103 = true ULES00381 = true From be4af6874ffa9a53d81491a4f5f65faac983dfc0 Mon Sep 17 00:00:00 2001 From: Narugakuruga <31060534+Narugakuruga@users.noreply.github.com> Date: Sat, 18 Feb 2023 22:32:38 +0800 Subject: [PATCH 132/424] Update zh_CN.ini --- assets/lang/zh_CN.ini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 12b0227052..9bb0c7a322 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -91,11 +91,11 @@ Swipe = 滑动 Swipe sensitivity = 滑动灵敏度 Swipe smoothing = 滑动平滑度 Thin borders = 细边框 -Tilt control setup = 倾斜控制设置… -Tilt Input Type = 倾斜输入类型 +Tilt control setup = 设置重力感应… +Tilt Input Type = 重力操作模式 Tilt Sensitivity along X axis = 沿X轴倾斜灵敏度 Tilt Sensitivity along Y axis = 沿Y轴倾斜灵敏度 -To Calibrate = 以您喜欢的角度握住设备,然后按“校准”。 +To Calibrate = 以喜欢的角度握住设备,然后按“校准”。 Toggle mode = 开关模式(只需按一次) Touch Control Visibility = 显示的按键 Use custom right analog = 自定义右摇杆用途 @@ -1124,7 +1124,7 @@ Failed to save state. Error in the file system. = 无法保存即时存档。文 Fast (lag on slow storage) = 快速模式(存储低速时有延迟) Fast Memory = 快速内存(不稳定) Force real clock sync (slower, less lag) = 强制同步实际时钟(降低延迟,很慢) -seconds, 0:off = 秒, 0=关 +seconds, 0:off = 每n秒,0=不回档 Games list settings = 游戏列表设置 General = 常规设置 Grid icon size = 图标方格尺寸 From 37ca5d5e95ace6ba24d20447791589f84c8f6a9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Moraz=C3=A1n?= <35014183+GABO1423@users.noreply.github.com> Date: Wed, 22 Feb 2023 18:03:12 -0400 Subject: [PATCH 133/424] (UWP) File Tweaks --- UWP/PackageGold.appxmanifest | 2 +- UWP/PackageNormal.appxmanifest | 2 +- UWP/cpu_features_UWP/cpu_features_UWP.vcxproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/UWP/PackageGold.appxmanifest b/UWP/PackageGold.appxmanifest index d428bcd738..216c2dfb5e 100644 --- a/UWP/PackageGold.appxmanifest +++ b/UWP/PackageGold.appxmanifest @@ -1,6 +1,6 @@ - + PPSSPP Gold - PSP emulator diff --git a/UWP/PackageNormal.appxmanifest b/UWP/PackageNormal.appxmanifest index ef79928e4c..c564357242 100644 --- a/UWP/PackageNormal.appxmanifest +++ b/UWP/PackageNormal.appxmanifest @@ -1,6 +1,6 @@  - + PPSSPP - PSP emulator diff --git a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj index f4d225d3b3..7e9cc89900 100644 --- a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj +++ b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj @@ -398,7 +398,7 @@ - + From cbc1ed4bfe44b6c36f44d570620771e4a8633fa7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 22 Feb 2023 21:14:33 -0800 Subject: [PATCH 134/424] Debugger: Lock memory during stack walk. In case of shutdown during it. --- Windows/Debugger/Debugger_Disasm.cpp | 7 +++---- Windows/Debugger/Debugger_Lists.cpp | 7 +++++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Windows/Debugger/Debugger_Disasm.cpp b/Windows/Debugger/Debugger_Disasm.cpp index 584533703d..580166e407 100644 --- a/Windows/Debugger/Debugger_Disasm.cpp +++ b/Windows/Debugger/Debugger_Disasm.cpp @@ -291,11 +291,10 @@ void CDisasm::stepOver() UpdateDialog(); } -void CDisasm::stepOut() -{ - if (!PSP_IsInited()) { +void CDisasm::stepOut() { + auto memLock = Memory::Lock(); + if (!PSP_IsInited()) return; - } auto threads = GetThreadsInfo(); diff --git a/Windows/Debugger/Debugger_Lists.cpp b/Windows/Debugger/Debugger_Lists.cpp index 97be390f59..0c76c4d936 100644 --- a/Windows/Debugger/Debugger_Lists.cpp +++ b/Windows/Debugger/Debugger_Lists.cpp @@ -700,8 +700,11 @@ void CtrlStackTraceView::OnDoubleClick(int itemIndex, int column) SendMessage(GetParent(GetHandle()),WM_DEB_GOTOWPARAM,frames[itemIndex].pc,0); } -void CtrlStackTraceView::loadStackTrace() -{ +void CtrlStackTraceView::loadStackTrace() { + auto memLock = Memory::Lock(); + if (!PSP_IsInited()) + return; + auto threads = GetThreadsInfo(); u32 entry = 0, stackTop = 0; From cd3fc26190c4ef0897884449094a724022b4d2ae Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 22 Feb 2023 21:15:03 -0800 Subject: [PATCH 135/424] samplerjit: Prevent thread local stale cache read. If the generation count happens to match, would still get a stale pointer and crash. Let's just make the generation count static so it always increases. --- GPU/Software/DrawPixel.cpp | 2 ++ GPU/Software/DrawPixel.h | 2 +- GPU/Software/Sampler.cpp | 2 ++ GPU/Software/Sampler.h | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/GPU/Software/DrawPixel.cpp b/GPU/Software/DrawPixel.cpp index 72b6e2a91a..eda04b0b41 100644 --- a/GPU/Software/DrawPixel.cpp +++ b/GPU/Software/DrawPixel.cpp @@ -802,10 +802,12 @@ SingleFunc PixelJitCache::GenericSingle(const PixelFuncID &id) { } thread_local PixelJitCache::LastCache PixelJitCache::lastSingle_; +int PixelJitCache::clearGen_ = 0; // 256k should be plenty of space for plenty of variations. PixelJitCache::PixelJitCache() : CodeBlock(1024 * 64 * 4), cache_(64) { lastSingle_.gen = -1; + clearGen_++; } void PixelJitCache::Clear() { diff --git a/GPU/Software/DrawPixel.h b/GPU/Software/DrawPixel.h index d72c04a744..b0eae46ac6 100644 --- a/GPU/Software/DrawPixel.h +++ b/GPU/Software/DrawPixel.h @@ -128,7 +128,7 @@ private: DenseHashMap cache_; std::unordered_map addresses_; std::unordered_set compileQueue_; - int clearGen_ = 0; + static int clearGen_; static thread_local LastCache lastSingle_; const u8 *constBlendHalf_11_4s_ = nullptr; diff --git a/GPU/Software/Sampler.cpp b/GPU/Software/Sampler.cpp index dd022c5efd..eef759344f 100644 --- a/GPU/Software/Sampler.cpp +++ b/GPU/Software/Sampler.cpp @@ -109,12 +109,14 @@ FetchFunc GetFetchFunc(SamplerID id, BinManager *binner) { thread_local SamplerJitCache::LastCache SamplerJitCache::lastFetch_; thread_local SamplerJitCache::LastCache SamplerJitCache::lastNearest_; thread_local SamplerJitCache::LastCache SamplerJitCache::lastLinear_; +int SamplerJitCache::clearGen_ = 0; // 256k should be enough. SamplerJitCache::SamplerJitCache() : Rasterizer::CodeBlock(1024 * 64 * 4), cache_(64) { lastFetch_.gen = -1; lastNearest_.gen = -1; lastLinear_.gen = -1; + clearGen_++; } void SamplerJitCache::Clear() { diff --git a/GPU/Software/Sampler.h b/GPU/Software/Sampler.h index fbe606b110..ec8d4c2638 100644 --- a/GPU/Software/Sampler.h +++ b/GPU/Software/Sampler.h @@ -147,7 +147,7 @@ private: DenseHashMap cache_; std::unordered_map addresses_; std::unordered_set compileQueue_; - int clearGen_ = 0; + static int clearGen_; static thread_local LastCache lastFetch_; static thread_local LastCache lastNearest_; static thread_local LastCache lastLinear_; From bec429ed72049c8e2aba8842ac155c7cc77024d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Feb 2023 20:21:41 +0100 Subject: [PATCH 136/424] MacOS buildfix for some reason --- Core/SaveState.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 2715d897b0..3f51aebbc6 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -291,10 +291,10 @@ namespace SaveState } private: - static const int BLOCK_SIZE = 8192; - static const int REWIND_NUM_STATES = 20; + const int BLOCK_SIZE = 8192; + const int REWIND_NUM_STATES = 20; // TODO: Instead, based on size of compressed state? - static const int BASE_USAGE_INTERVAL = 15; + const int BASE_USAGE_INTERVAL = 15; typedef std::vector StateBuffer; From c6b44cd5d7ddbf8973747b7a415d8ecd4007ee4f Mon Sep 17 00:00:00 2001 From: Nemoumbra Date: Fri, 24 Feb 2023 23:44:32 +0300 Subject: [PATCH 137/424] Update gitignore --- Windows/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/Windows/.gitignore b/Windows/.gitignore index 653ef6879e..8d4dba11ef 100644 --- a/Windows/.gitignore +++ b/Windows/.gitignore @@ -1,3 +1,4 @@ *.VC.VC.opendb *.VC.db +*.txt enc_temp_folder From aab4a3034c4f611d47dd7250c6ec7e6774dc2515 Mon Sep 17 00:00:00 2001 From: Nemoumbra Date: Fri, 24 Feb 2023 23:13:48 +0300 Subject: [PATCH 138/424] Added new MainWindow menu item "copy PSP memory base pointer" --- Windows/MainWindowMenu.cpp | 8 ++++++++ Windows/ppsspp.rc | 1 + Windows/resource.h | 1 + 3 files changed, 10 insertions(+) diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index ee15fab63b..022e1e70cc 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -91,6 +91,7 @@ namespace MainWindow { EnableMenuItem(menu, ID_DEBUG_TAKESCREENSHOT, menuEnable); EnableMenuItem(menu, ID_DEBUG_SHOWDEBUGSTATISTICS, menuInGameEnable); EnableMenuItem(menu, ID_DEBUG_EXTRACTFILE, menuEnable); + EnableMenuItem(menu, ID_DEBUG_MEMORYBASE, menuInGameEnable); // While playing, this pop up doesn't work - and probably doesn't make sense. EnableMenuItem(menu, ID_OPTIONS_LANGUAGE, state == UISTATE_INGAME ? MF_GRAYED : MF_ENABLED); @@ -221,6 +222,7 @@ namespace MainWindow { TranslateMenuItem(menu, ID_DEBUG_GEDEBUGGER, g_Config.bSystemControls ? L"\tCtrl+G" : L""); TranslateMenuItem(menu, ID_DEBUG_EXTRACTFILE); TranslateMenuItem(menu, ID_DEBUG_LOG, g_Config.bSystemControls ? L"\tCtrl+L" : L""); + TranslateMenuItem(menu, ID_DEBUG_MEMORYBASE); TranslateMenuItem(menu, ID_DEBUG_MEMORYVIEW, g_Config.bSystemControls ? L"\tCtrl+M" : L""); // Options menu @@ -822,6 +824,12 @@ namespace MainWindow { memoryWindow->Show(true); break; + case ID_DEBUG_MEMORYBASE: + { + W32Util::CopyTextToClipboard(hWnd, ConvertUTF8ToWString(StringFromFormat("%016llx", (uintptr_t)Memory::base))); + break; + } + case ID_DEBUG_EXTRACTFILE: { std::string filename; diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index b547443913..d5109b9cd0 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -537,6 +537,7 @@ BEGIN MENUITEM "GE Debugger...", ID_DEBUG_GEDEBUGGER MENUITEM "Extract File...", ID_DEBUG_EXTRACTFILE MENUITEM "Log Console", ID_DEBUG_LOG + MENUITEM "Copy PSP memory base pointer", ID_DEBUG_MEMORYBASE MENUITEM "Memory View...", ID_DEBUG_MEMORYVIEW END diff --git a/Windows/resource.h b/Windows/resource.h index 66ec982d23..fc421b7e60 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -18,6 +18,7 @@ #define ID_DEBUG_DISASSEMBLY 119 #define WHEEL_DELTA 120 #define ID_DEBUG_LOG 121 +#define ID_DEBUG_MEMORYBASE 122 #define ID_FILE_OPEN_NEW_INSTANCE 123 #define ID_FILE_LOADSTATEFILE 126 #define ID_FILE_SAVESTATEFILE 127 From 0cb051a37f717cb6eb5c0953793d0763b88a5474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 24 Feb 2023 22:45:49 +0100 Subject: [PATCH 139/424] Update SPIRV-Cross to a version that builds in debug mode on the latest VS. The old bug that used to cause a warning now fails outright, so the upgrade is necessary. --- ext/SPIRV-Cross | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/SPIRV-Cross b/ext/SPIRV-Cross index c77b09b57c..4212eef67e 160000 --- a/ext/SPIRV-Cross +++ b/ext/SPIRV-Cross @@ -1 +1 @@ -Subproject commit c77b09b57c27837dc2d41aa371ed3d236ce9ce47 +Subproject commit 4212eef67ed0ca048cb726a6767185504e7695e5 From 61c5b9e0ca5bc16675fbe8fac93f2ffb28cea8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 24 Feb 2023 22:59:32 +0100 Subject: [PATCH 140/424] Retarget UWP projects for latest VS build 19061 is the oldest SDK installed by default. Also disable "SDL" (security development lifecycle) checks in SPIRV-Cross because it doesn't build with it... --- UWP/Armips_UWP/Armips_UWP.vcxproj | 4 ++-- UWP/CommonUWP/CommonUWP.vcxproj | 4 ++-- UWP/CoreUWP/CoreUWP.vcxproj | 4 ++-- UWP/GPU_UWP/GPU_UWP.vcxproj | 4 ++-- UWP/Package.appxmanifest | 2 +- UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj | 12 ++++++------ UWP/UI_UWP/UI_UWP.vcxproj | 4 ++-- UWP/UWP.vcxproj | 9 +++------ UWP/cpu_features_UWP/cpu_features_UWP.vcxproj | 6 +++--- .../cpu_features_UWP.vcxproj.filters | 8 ++------ UWP/glslang_UWP/glslang_UWP.vcxproj | 6 +++--- UWP/glslang_UWP/glslang_UWP.vcxproj.filters | 2 ++ UWP/libkirk_UWP/libkirk_UWP.vcxproj | 6 +++--- UWP/libzstd_UWP/libzstd_UWP.vcxproj | 4 ++-- UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj | 4 ++-- UWP/zlib_UWP/zlib_UWP.vcxproj | 6 +++--- 16 files changed, 40 insertions(+), 45 deletions(-) diff --git a/UWP/Armips_UWP/Armips_UWP.vcxproj b/UWP/Armips_UWP/Armips_UWP.vcxproj index 4610681d23..f10d16ddfa 100644 --- a/UWP/Armips_UWP/Armips_UWP.vcxproj +++ b/UWP/Armips_UWP/Armips_UWP.vcxproj @@ -42,8 +42,8 @@ 14.0 true Windows Store - 10.0.17763.0 - 10.0.15063.0 + 10.0 + 10.0.19041.0 10.0 diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 99e542cc99..4a10010455 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 2d89c268b3..886dc9f29e 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 369a75da72..0b8ed0070f 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 diff --git a/UWP/Package.appxmanifest b/UWP/Package.appxmanifest index 68b9c930d7..b1e9b4db73 100644 --- a/UWP/Package.appxmanifest +++ b/UWP/Package.appxmanifest @@ -1,6 +1,6 @@  - + PPSSPP - PSP emulator diff --git a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj index b27d1659aa..f57655dc95 100644 --- a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj +++ b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 @@ -202,7 +202,7 @@ Use false - true + false pch.h _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX @@ -244,7 +244,7 @@ Use false - true + false pch.h _ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions);NOMINMAX @@ -258,7 +258,7 @@ Use false - true + false pch.h _ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions);NOMINMAX @@ -328,7 +328,7 @@ Use false - true + false pch.h _UNICODE;UNICODE;%(PreprocessorDefinitions);NOMINMAX diff --git a/UWP/UI_UWP/UI_UWP.vcxproj b/UWP/UI_UWP/UI_UWP.vcxproj index eda2c2c994..ad66ad74dc 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj +++ b/UWP/UI_UWP/UI_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 5fcdbecf25..1cd5d12174 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -58,10 +58,10 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 PPSSPP_UWP - 10.0.17763.0 + 10.0 @@ -1734,9 +1734,6 @@ true - - - @@ -1746,4 +1743,4 @@ - + \ No newline at end of file diff --git a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj index 7e9cc89900..722e0e8b16 100644 --- a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj +++ b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 @@ -439,4 +439,4 @@ - + \ No newline at end of file diff --git a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters index 0fad65bc31..d0acee9d45 100644 --- a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters +++ b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters @@ -66,11 +66,6 @@ Header Files\internal - - - Resource Files - - Source Files @@ -87,6 +82,7 @@ Source Files + @@ -130,4 +126,4 @@ Source Files - + \ No newline at end of file diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj b/UWP/glslang_UWP/glslang_UWP.vcxproj index 2242d14f57..656b796b7d 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 @@ -508,4 +508,4 @@ - + \ No newline at end of file diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj.filters b/UWP/glslang_UWP/glslang_UWP.vcxproj.filters index dc0cd80fc3..bff8201bc4 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj.filters +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj.filters @@ -170,6 +170,7 @@ hlsl + @@ -348,5 +349,6 @@ glslang + \ No newline at end of file diff --git a/UWP/libkirk_UWP/libkirk_UWP.vcxproj b/UWP/libkirk_UWP/libkirk_UWP.vcxproj index 510ff09681..5664ad0d4a 100644 --- a/UWP/libkirk_UWP/libkirk_UWP.vcxproj +++ b/UWP/libkirk_UWP/libkirk_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 @@ -396,4 +396,4 @@ - + \ No newline at end of file diff --git a/UWP/libzstd_UWP/libzstd_UWP.vcxproj b/UWP/libzstd_UWP/libzstd_UWP.vcxproj index 78101ed883..3f063dfb71 100644 --- a/UWP/libzstd_UWP/libzstd_UWP.vcxproj +++ b/UWP/libzstd_UWP/libzstd_UWP.vcxproj @@ -42,8 +42,8 @@ 14.0 true Windows Store - 10.0.17763.0 - 10.0.15063.0 + 10.0 + 10.0.19041.0 10.0 diff --git a/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj b/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj index 5e42ecf2a4..e89bebd5f5 100644 --- a/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj +++ b/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 diff --git a/UWP/zlib_UWP/zlib_UWP.vcxproj b/UWP/zlib_UWP/zlib_UWP.vcxproj index 5ac9ab5c08..ea314b2c44 100644 --- a/UWP/zlib_UWP/zlib_UWP.vcxproj +++ b/UWP/zlib_UWP/zlib_UWP.vcxproj @@ -58,9 +58,9 @@ 14.0 true Windows Store - 10.0.15063.0 + 10.0.19041.0 10.0 - 10.0.17763.0 + 10.0 @@ -396,4 +396,4 @@ - + \ No newline at end of file From 1b5148bb6c5a32e85aea6414badb71d5065b84cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 24 Feb 2023 21:53:12 +0100 Subject: [PATCH 141/424] Remove kinda-duplicate function. --- GPU/Common/TextureCacheCommon.cpp | 8 ++++---- GPU/Common/TextureCacheCommon.h | 1 - GPU/D3D11/TextureCacheD3D11.cpp | 12 +++--------- GPU/D3D11/TextureCacheD3D11.h | 1 - GPU/Directx9/TextureCacheDX9.cpp | 6 +++--- GPU/Directx9/TextureCacheDX9.h | 5 +---- GPU/GLES/TextureCacheGLES.cpp | 6 +++--- GPU/GLES/TextureCacheGLES.h | 3 --- GPU/Vulkan/TextureCacheVulkan.cpp | 2 -- GPU/Vulkan/TextureCacheVulkan.h | 2 -- 10 files changed, 14 insertions(+), 32 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index e6c29e8264..6178df18b8 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -817,7 +817,7 @@ void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c gpuStats.numTextureInvalidations++; DEBUG_LOG(G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason); if (doDelete) { - InvalidateLastTexture(); + ForgetLastTexture(); ReleaseTexture(entry, true); entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; } @@ -1990,7 +1990,7 @@ void TextureCacheCommon::ApplyTexture() { TexCacheEntry *entry = nextTexture_; if (!entry) { // Maybe we bound a framebuffer? - InvalidateLastTexture(); + ForgetLastTexture(); if (failedTexture_) { // Backends should handle this by binding a black texture with 0 alpha. BindTexture(nullptr); @@ -2050,7 +2050,7 @@ void TextureCacheCommon::ApplyTexture() { if (nextNeedsRebuild_) { _assert_(!entry->texturePtr); BuildTexture(entry); - InvalidateLastTexture(); + ForgetLastTexture(); } if (entry->status & TexCacheEntry::STATUS_CLUT_GPU) { @@ -2205,7 +2205,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer gstate_c.SetTextureFullAlpha(alphaStatus == CHECKALPHA_FULL); draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); - InvalidateLastTexture(); + ForgetLastTexture(); return; } diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 6d3fcd604f..f85e09b9a4 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -329,7 +329,6 @@ public: TextureShaderCache *GetTextureShaderCache() { return textureShaderCache_; } virtual void ForgetLastTexture() = 0; - virtual void InvalidateLastTexture() = 0; virtual void Clear(bool delete_them); virtual void NotifyConfigChanged(); virtual void ApplySamplingParams(const SamplerCacheKey &key) = 0; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 31433016ee..c8d6b9194a 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -179,20 +179,16 @@ void TextureCacheD3D11::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { } void TextureCacheD3D11::ForgetLastTexture() { - InvalidateLastTexture(); + lastBoundTexture = INVALID_TEX; ID3D11ShaderResourceView *nullTex[4]{}; context_->PSSetShaderResources(0, 4, nullTex); } -void TextureCacheD3D11::InvalidateLastTexture() { - lastBoundTexture = INVALID_TEX; -} - void TextureCacheD3D11::StartFrame() { TextureCacheCommon::StartFrame(); - InvalidateLastTexture(); + lastBoundTexture = INVALID_TEX; timesInvalidatedAllThisFrame_ = 0; replacementTimeThisFrame_ = 0.0; @@ -268,9 +264,7 @@ void TextureCacheD3D11::ApplySamplingParams(const SamplerCacheKey &key) { } void TextureCacheD3D11::Unbind() { - ID3D11ShaderResourceView *nullView = nullptr; - context_->PSSetShaderResources(0, 1, &nullView); - InvalidateLastTexture(); + ForgetLastTexture(); } void TextureCacheD3D11::BindAsClutTexture(Draw::Texture *tex, bool smooth) { diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 20d84d6d48..4cb01375ff 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -51,7 +51,6 @@ public: void SetFramebufferManager(FramebufferManagerD3D11 *fbManager); void ForgetLastTexture() override; - void InvalidateLastTexture() override; bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 591dc3f85c..d615c4e330 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -111,7 +111,7 @@ void TextureCacheDX9::ReleaseTexture(TexCacheEntry *entry, bool delete_them) { } } -void TextureCacheDX9::InvalidateLastTexture() { +void TextureCacheDX9::ForgetLastTexture() { lastBoundTexture = INVALID_TEX; } @@ -154,7 +154,7 @@ void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) { void TextureCacheDX9::StartFrame() { TextureCacheCommon::StartFrame(); - InvalidateLastTexture(); + lastBoundTexture = nullptr; timesInvalidatedAllThisFrame_ = 0; replacementTimeThisFrame_ = 0.0; @@ -229,7 +229,7 @@ void TextureCacheDX9::BindTexture(TexCacheEntry *entry) { void TextureCacheDX9::Unbind() { device_->SetTexture(0, nullptr); - InvalidateLastTexture(); + ForgetLastTexture(); } void TextureCacheDX9::BindAsClutTexture(Draw::Texture *tex, bool smooth) { diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 23c2e0163b..0080fbdef3 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -38,10 +38,7 @@ public: void SetFramebufferManager(FramebufferManagerDX9 *fbManager); - void ForgetLastTexture() override { - InvalidateLastTexture(); - } - void InvalidateLastTexture() override; + void ForgetLastTexture() override; bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 36ce7837d9..c4ed59221d 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -143,7 +143,7 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dst void TextureCacheGLES::StartFrame() { TextureCacheCommon::StartFrame(); - InvalidateLastTexture(); + ForgetLastTexture(); timesInvalidatedAllThisFrame_ = 0; replacementTimeThisFrame_ = 0.0; @@ -234,7 +234,7 @@ void TextureCacheGLES::BindTexture(TexCacheEntry *entry) { void TextureCacheGLES::Unbind() { render_->BindTexture(TEX_SLOT_PSP_TEXTURE, nullptr); - InvalidateLastTexture(); + ForgetLastTexture(); } void TextureCacheGLES::BindAsClutTexture(Draw::Texture *tex, bool smooth) { @@ -385,7 +385,7 @@ Draw::DataFormat TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPalet } bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) { - InvalidateLastTexture(); + ForgetLastTexture(); SetTexture(); if (!nextTexture_) { return GetCurrentFramebufferTextureDebug(buffer, isFramebuffer); diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 8f9517371b..2546c605b9 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -51,9 +51,6 @@ public: void ForgetLastTexture() override { lastBoundTexture = nullptr; } - void InvalidateLastTexture() override { - lastBoundTexture = nullptr; - } bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 1e43f8d355..349d608c3a 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -329,7 +329,6 @@ static const VkFilter MagFiltVK[2] = { void TextureCacheVulkan::StartFrame() { TextureCacheCommon::StartFrame(); - InvalidateLastTexture(); textureShaderCache_->Decimate(); timesInvalidatedAllThisFrame_ = 0; @@ -419,7 +418,6 @@ void TextureCacheVulkan::ApplySamplingParams(const SamplerCacheKey &key) { void TextureCacheVulkan::Unbind() { imageView_ = VK_NULL_HANDLE; curSampler_ = VK_NULL_HANDLE; - InvalidateLastTexture(); } void TextureCacheVulkan::BindAsClutTexture(Draw::Texture *tex, bool smooth) { diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 2c16d02a03..3654101b90 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -72,8 +72,6 @@ public: } void ForgetLastTexture() override {} - void InvalidateLastTexture() override {} - void NotifyConfigChanged() override; void GetVulkanHandles(VkImageView &imageView, VkSampler &sampler) { From 49e5460c9c3da2a0ebd99d99aaffe9bc0bb8703d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 24 Feb 2023 22:09:32 +0100 Subject: [PATCH 142/424] Remove count parameter from SetViewports. No use foreseen. --- Common/GPU/D3D11/thin3d_d3d11.cpp | 28 ++++++++++++------------- Common/GPU/D3D9/thin3d_d3d9.cpp | 14 ++++++------- Common/GPU/OpenGL/thin3d_gl.cpp | 4 ++-- Common/GPU/Vulkan/thin3d_vulkan.cpp | 24 ++++++++++----------- Common/GPU/thin3d.h | 2 +- Common/UI/UIScreen.cpp | 2 +- GPU/Common/DepthBufferCommon.cpp | 2 +- GPU/Common/FramebufferManagerCommon.cpp | 8 +++---- GPU/Common/PresentationCommon.cpp | 4 ++-- GPU/Common/StencilCommon.cpp | 2 +- GPU/Common/TextureCacheCommon.cpp | 8 +++---- GPU/D3D11/StateMappingD3D11.cpp | 2 +- GPU/GLES/StencilBufferGLES.cpp | 2 +- UI/EmuScreen.cpp | 4 ++-- UI/MiscScreens.cpp | 2 +- UWP/PPSSPP_UWPMain.cpp | 2 +- 16 files changed, 53 insertions(+), 57 deletions(-) diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index c0fcb9afbb..120f8db5ea 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -112,7 +112,7 @@ public: // Raster state void SetScissorRect(int left, int top, int width, int height) override; - void SetViewports(int count, Viewport *viewports) override; + void SetViewport(const Viewport &viewport) override; void SetBlendFactor(float color[4]) override { if (memcmp(blendFactor_, color, sizeof(float) * 4)) { memcpy(blendFactor_, color, sizeof(float) * 4); @@ -420,20 +420,18 @@ void D3D11DrawContext::EndFrame() { curPipeline_ = nullptr; } -void D3D11DrawContext::SetViewports(int count, Viewport *viewports) { - D3D11_VIEWPORT vp[4]; - for (int i = 0; i < count; i++) { - DisplayRect rc{ viewports[i].TopLeftX , viewports[i].TopLeftY, viewports[i].Width, viewports[i].Height }; - if (curRenderTargetView_ == bbRenderTargetView_) // Only the backbuffer is actually rotated wrong! - RotateRectToDisplay(rc, curRTWidth_, curRTHeight_); - vp[i].TopLeftX = rc.x; - vp[i].TopLeftY = rc.y; - vp[i].Width = rc.w; - vp[i].Height = rc.h; - vp[i].MinDepth = viewports[i].MinDepth; - vp[i].MaxDepth = viewports[i].MaxDepth; - } - context_->RSSetViewports(count, vp); +void D3D11DrawContext::SetViewport(const Viewport &viewport) { + DisplayRect rc{ viewport.TopLeftX , viewport.TopLeftY, viewport.Width, viewport.Height }; + if (curRenderTargetView_ == bbRenderTargetView_) // Only the backbuffer is actually rotated wrong! + RotateRectToDisplay(rc, curRTWidth_, curRTHeight_); + D3D11_VIEWPORT vp; + vp.TopLeftX = rc.x; + vp.TopLeftY = rc.y; + vp.Width = rc.w; + vp.Height = rc.h; + vp.MinDepth = viewport.MinDepth; + vp.MaxDepth = viewport.MaxDepth; + context_->RSSetViewports(1, &vp); } void D3D11DrawContext::SetScissorRect(int left, int top, int width, int height) { diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index b0116c875a..b130aae436 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -573,7 +573,7 @@ public: // Raster state void SetScissorRect(int left, int top, int width, int height) override; - void SetViewports(int count, Viewport *viewports) override; + void SetViewport(const Viewport &viewport) override; void SetBlendFactor(float color[4]) override; void SetStencilParams(uint8_t refValue, uint8_t writeMask, uint8_t compareMask) override; @@ -1173,12 +1173,12 @@ void D3D9Context::SetScissorRect(int left, int top, int width, int height) { dxstate.scissorTest.set(true); } -void D3D9Context::SetViewports(int count, Viewport *viewports) { - int x = (int)viewports[0].TopLeftX; - int y = (int)viewports[0].TopLeftY; - int w = (int)viewports[0].Width; - int h = (int)viewports[0].Height; - dxstate.viewport.set(x, y, w, h, viewports[0].MinDepth, viewports[0].MaxDepth); +void D3D9Context::SetViewport(const Viewport &viewport) { + int x = (int)viewport.TopLeftX; + int y = (int)viewport.TopLeftY; + int w = (int)viewport.Width; + int h = (int)viewport.Height; + dxstate.viewport.set(x, y, w, h, viewport.MinDepth, viewport.MaxDepth); } void D3D9Context::SetBlendFactor(float color[4]) { diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index ca539f1f17..5cb85ac9c7 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -385,9 +385,9 @@ public: renderManager_.SetScissor({ left, top, width, height }); } - void SetViewports(int count, Viewport *viewports) override { + void SetViewport(const Viewport &viewport) override { // Same structure, different name. - renderManager_.SetViewport((GLRViewport &)*viewports); + renderManager_.SetViewport((GLRViewport &)viewport); } void SetBlendFactor(float color[4]) override { diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 14c1c0e502..b0c74c5c76 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -425,7 +425,7 @@ public: void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; void SetScissorRect(int left, int top, int width, int height) override; - void SetViewports(int count, Viewport *viewports) override; + void SetViewport(const Viewport &viewport) override; void SetBlendFactor(float color[4]) override; void SetStencilParams(uint8_t refValue, uint8_t writeMask, uint8_t compareMask) override; @@ -1237,18 +1237,16 @@ void VKContext::SetScissorRect(int left, int top, int width, int height) { renderManager_.SetScissor(left, top, width, height); } -void VKContext::SetViewports(int count, Viewport *viewports) { - if (count > 0) { - // Ignore viewports more than the first. - VkViewport viewport; - viewport.x = viewports[0].TopLeftX; - viewport.y = viewports[0].TopLeftY; - viewport.width = viewports[0].Width; - viewport.height = viewports[0].Height; - viewport.minDepth = viewports[0].MinDepth; - viewport.maxDepth = viewports[0].MaxDepth; - renderManager_.SetViewport(viewport); - } +void VKContext::SetViewport(const Viewport &viewport) { + // Ignore viewports more than the first. + VkViewport vkViewport; + vkViewport.x = viewport.TopLeftX; + vkViewport.y = viewport.TopLeftY; + vkViewport.width = viewport.Width; + vkViewport.height = viewport.Height; + vkViewport.minDepth = viewport.MinDepth; + vkViewport.maxDepth = viewport.MaxDepth; + renderManager_.SetViewport(vkViewport); } void VKContext::SetBlendFactor(float color[4]) { diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 3db2d7b8db..9a427027a9 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -733,7 +733,7 @@ public: // Dynamic state virtual void SetScissorRect(int left, int top, int width, int height) = 0; - virtual void SetViewports(int count, Viewport *viewports) = 0; + virtual void SetViewport(const Viewport &viewport) = 0; virtual void SetBlendFactor(float color[4]) = 0; virtual void SetStencilParams(uint8_t refValue, uint8_t writeMask, uint8_t compareMask) = 0; diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index 768fc88b16..d1fc99595f 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -102,7 +102,7 @@ void UIScreen::preRender() { viewport.Height = pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; - draw->SetViewports(1, &viewport); + draw->SetViewport(viewport); draw->SetTargetSize(pixel_xres, pixel_yres); } diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 3c78362352..46a2ecfb6f 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -207,7 +207,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width() * scaleX, fbo->Height() * scaleY); draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackDepthbufferSync"); Draw::Viewport viewport = { 0.0f, 0.0f, (float)destW, (float)destH, 0.0f, 1.0f }; - draw_->SetViewports(1, &viewport); + draw_->SetViewport(viewport); draw_->SetScissorRect(0, 0, fbo->Width() * scaleX, fbo->Height() * scaleY); draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_DEPTH_BIT, 0); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index a126bb7fb2..4c0c4dea0b 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1429,8 +1429,8 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int } void FramebufferManagerCommon::SetViewport2D(int x, int y, int w, int h) { - Draw::Viewport vp{ (float)x, (float)y, (float)w, (float)h, 0.0f, 1.0f }; - draw_->SetViewports(1, &vp); + Draw::Viewport viewport{ (float)x, (float)y, (float)w, (float)h, 0.0f, 1.0f }; + draw_->SetViewport(viewport); } void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { @@ -3235,8 +3235,8 @@ void FramebufferManagerCommon::BlitUsingRaster( draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_LOAD, pipeline->info.writeChannel == RASTER_COLOR ? Draw::FB_COLOR_BIT : Draw::FB_DEPTH_BIT); } - Draw::Viewport vp{ 0.0f, 0.0f, (float)dest->Width(), (float)dest->Height(), 0.0f, 1.0f }; - draw_->SetViewports(1, &vp); + Draw::Viewport viewport{ 0.0f, 0.0f, (float)dest->Width(), (float)dest->Height(), 0.0f, 1.0f }; + draw_->SetViewport(viewport); draw_->SetScissorRect(0, 0, (int)dest->Width(), (int)dest->Height()); draw2D_.Blit(pipeline, srcX1, srcY1, srcX2, srcY2, destX1, destY1, destX2, destY2, (float)srcW, (float)srcH, (float)destW, (float)destH, linearFilter, scaleFactor); diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 4341961214..0c027ae796 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -734,7 +734,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u int nextWidth, nextHeight; draw_->GetFramebufferDimensions(postShaderFramebuffer, &nextWidth, &nextHeight); Draw::Viewport viewport{ 0, 0, (float)nextWidth, (float)nextHeight, 0.0f, 1.0f }; - draw_->SetViewports(1, &viewport); + draw_->SetViewport(viewport); draw_->SetScissorRect(0, 0, nextWidth, nextHeight); CalculatePostShaderUniforms(lastWidth, lastHeight, nextWidth, nextHeight, shaderInfo, &uniforms); @@ -853,7 +853,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u auto setViewport = [&](float x, float y, float w, float h) { Draw::Viewport viewport{ x, y, w, h, 0.0f, 1.0f }; - draw_->SetViewports(1, &viewport); + draw_->SetViewport(viewport); }; CardboardSettings cardboardSettings; diff --git a/GPU/Common/StencilCommon.cpp b/GPU/Common/StencilCommon.cpp index 9bf141756c..00e81b19d1 100644 --- a/GPU/Common/StencilCommon.cpp +++ b/GPU/Common/StencilCommon.cpp @@ -304,7 +304,7 @@ bool FramebufferManagerCommon::PerformWriteStencilFromMemory(u32 addr, int size, } Draw::Viewport viewport = { 0.0f, 0.0f, (float)w, (float)h, 0.0f, 1.0f }; - draw_->SetViewports(1, &viewport); + draw_->SetViewport(viewport); // TODO: Switch the format to a single channel format? Draw::Texture *tex = MakePixelTexture(src, dstBuffer->fb_format, dstBuffer->fb_stride, dstBuffer->width, dstBuffer->height); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 6178df18b8..6611c21156 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2247,8 +2247,8 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "Depal"); draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_STORE, Draw::FB_DEPTH_BIT | Draw::FB_STENCIL_BIT); draw_->SetScissorRect(u1, v1, u2 - u1, v2 - v1); - Draw::Viewport vp{ 0.0f, 0.0f, (float)depalWidth, (float)framebuffer->renderHeight, 0.0f, 1.0f }; - draw_->SetViewports(1, &vp); + Draw::Viewport viewport{ 0.0f, 0.0f, (float)depalWidth, (float)framebuffer->renderHeight, 0.0f, 1.0f }; + draw_->SetViewport(viewport); draw_->BindFramebufferAsTexture(framebuffer->fbo, 0, depth ? Draw::FB_DEPTH_BIT : Draw::FB_COLOR_BIT, Draw::ALL_LAYERS); if (clutRenderAddress_ == 0xFFFFFFFF) { @@ -2352,8 +2352,8 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) { draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "Depal"); draw_->InvalidateFramebuffer(Draw::FB_INVALIDATION_STORE, Draw::FB_DEPTH_BIT | Draw::FB_STENCIL_BIT); draw_->SetScissorRect(u1, v1, u2 - u1, v2 - v1); - Draw::Viewport vp{ 0.0f, 0.0f, (float)texWidth, (float)texHeight, 0.0f, 1.0f }; - draw_->SetViewports(1, &vp); + Draw::Viewport viewport{ 0.0f, 0.0f, (float)texWidth, (float)texHeight, 0.0f, 1.0f }; + draw_->SetViewport(viewport); draw_->BindNativeTexture(0, GetNativeTextureView(entry)); draw_->BindFramebufferAsTexture(dynamicClutFbo_, 1, Draw::FB_COLOR_BIT, 0); diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index ac80c9627a..1d00bfb46d 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -442,7 +442,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { void DrawEngineD3D11::ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRef) { // we go through Draw here because it automatically handles screen rotation, as needed in UWP on mobiles. if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) { - draw_->SetViewports(1, &dynState_.viewport); + draw_->SetViewport(dynState_.viewport); draw_->SetScissorRect(dynState_.scissor.left, dynState_.scissor.top, dynState_.scissor.right - dynState_.scissor.left, dynState_.scissor.bottom - dynState_.scissor.top); } if (gstate_c.IsDirty(DIRTY_RASTER_STATE)) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 110d2d94f7..763e5a95fe 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -133,7 +133,7 @@ bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width(), fbo->Height()); draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackStencilbufferSync"); Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f }; - draw_->SetViewports(1, &viewport); + draw_->SetViewport(viewport); draw_->BindFramebufferAsTexture(fbo, TEX_SLOT_PSP_TEXTURE, FB_STENCIL_BIT, 0); draw_->BindSamplerStates(TEX_SLOT_PSP_TEXTURE, 1, &stencilReadbackSampler_); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 28287cc786..b95b41de36 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1375,7 +1375,7 @@ void EmuScreen::preRender() { viewport.Height = pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; - draw->SetViewports(1, &viewport); + draw->SetViewport(viewport); } draw->SetTargetSize(pixel_xres, pixel_yres); } @@ -1523,7 +1523,7 @@ void EmuScreen::renderUI() { viewport.Height = pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; - thin3d->SetViewports(1, &viewport); + thin3d->SetViewport(viewport); if (root_) { UI::LayoutViewHierarchy(*ctx, root_, false); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index c1bb989b01..7a8984dfef 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -375,7 +375,7 @@ void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, f viewport.Height = pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; - draw->SetViewports(1, &viewport); + draw->SetViewport(viewport); dc.BeginFrame(); dc.RebindTexture(); dc.Begin(); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index b734f6e3d2..0438575d7c 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -201,7 +201,7 @@ bool PPSSPP_UWPMain::Render() { dp_xres = pixel_xres * g_dpi_scale_x; dp_yres = pixel_yres * g_dpi_scale_y; - context->RSSetViewports(1, &viewport); + context->RSSetViewport(viewport); NativeRender(ctx_.get()); return true; From e332259e7a94554afa9d5e16c8c3682f915dee45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 24 Feb 2023 23:51:01 +0100 Subject: [PATCH 143/424] Oops (fix UWP) --- UWP/PPSSPP_UWPMain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 0438575d7c..b734f6e3d2 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -201,7 +201,7 @@ bool PPSSPP_UWPMain::Render() { dp_xres = pixel_xres * g_dpi_scale_x; dp_yres = pixel_yres * g_dpi_scale_y; - context->RSSetViewport(viewport); + context->RSSetViewports(1, &viewport); NativeRender(ctx_.get()); return true; From 30120560ab73caec5d0b598d8beed578a06c420b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 11:31:59 +0100 Subject: [PATCH 144/424] Include file cleanup in framebuffer managers --- GPU/D3D11/FramebufferManagerD3D11.cpp | 4 ---- GPU/D3D11/FramebufferManagerD3D11.h | 7 ------ GPU/D3D11/GPU_D3D11.cpp | 2 +- GPU/Directx9/FramebufferManagerDX9.cpp | 24 +++----------------- GPU/Directx9/FramebufferManagerDX9.h | 8 ------- GPU/Directx9/GPU_DX9.cpp | 2 +- GPU/GLES/FramebufferManagerGLES.cpp | 18 ++------------- GPU/GLES/FramebufferManagerGLES.h | 7 +----- GPU/Vulkan/FramebufferManagerVulkan.cpp | 30 ------------------------- GPU/Vulkan/FramebufferManagerVulkan.h | 16 +++---------- 10 files changed, 11 insertions(+), 107 deletions(-) diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index f05bc499fe..3e4b5c949c 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -15,10 +15,6 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include -#include -#include - #include "Common/Common.h" #include "Common/GPU/thin3d.h" diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index fc280e9de6..c105e16682 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -17,20 +17,13 @@ #pragma once -#include - // Keeps track of allocated FBOs. // Also provides facilities for drawing and later converting raw // pixel data. -#include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "Common/GPU/thin3d.h" -class TextureCacheD3D11; -class DrawEngineD3D11; -class ShaderManagerD3D11; - class FramebufferManagerD3D11 : public FramebufferManagerCommon { public: FramebufferManagerD3D11(Draw::DrawContext *draw); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 5706c45fca..2b8179e472 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -15,7 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include +#include #include "Common/Log.h" #include "Common/Serialize/Serializer.h" diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp index 58d92756f0..e0eda00207 100644 --- a/GPU/Directx9/FramebufferManagerDX9.cpp +++ b/GPU/Directx9/FramebufferManagerDX9.cpp @@ -15,34 +15,16 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include + #include "Common/Common.h" -#include "Common/Data/Convert/ColorConv.h" #include "Common/GPU/thin3d.h" -#include "Common/Math/lin/matrix4x4.h" -#include "Core/MemMap.h" -#include "Core/Config.h" -#include "Core/ConfigValues.h" -#include "Core/System.h" -#include "GPU/ge_constants.h" -#include "GPU/GPUState.h" -#include "GPU/Debugger/Stepping.h" -#include "Common/GPU/D3D9/D3D9StateCache.h" #include "GPU/Common/FramebufferManagerCommon.h" +#include "GPU/Common/GPUStateUtils.h" #include "GPU/Common/PresentationCommon.h" #include "GPU/Common/TextureDecoder.h" #include "GPU/Directx9/FramebufferManagerDX9.h" -#include "GPU/Directx9/ShaderManagerDX9.h" -#include "GPU/Directx9/TextureCacheDX9.h" -#include "GPU/Directx9/DrawEngineDX9.h" - -#include "Common/GPU/thin3d.h" - -#include - -#ifdef _M_SSE -#include -#endif FramebufferManagerDX9::FramebufferManagerDX9(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { diff --git a/GPU/Directx9/FramebufferManagerDX9.h b/GPU/Directx9/FramebufferManagerDX9.h index 37458526fd..5a76d05944 100644 --- a/GPU/Directx9/FramebufferManagerDX9.h +++ b/GPU/Directx9/FramebufferManagerDX9.h @@ -17,17 +17,9 @@ #pragma once -#include - -#include - #include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" -class TextureCacheDX9; -class DrawEngineDX9; -class ShaderManagerDX9; - class FramebufferManagerDX9 : public FramebufferManagerCommon { public: FramebufferManagerDX9(Draw::DrawContext *draw); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index af8d80e327..a85903a94c 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -15,7 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include +#include #include "Common/Serialize/Serializer.h" #include "Common/GraphicsContext.h" diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index d88800873e..b226e9a5ce 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -15,28 +15,14 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include - -#include "Common/Data/Convert/ColorConv.h" -#include "Common/Profiler/Profiler.h" -#include "Common/GPU/OpenGL/GLCommon.h" -#include "Common/GPU/OpenGL/GLDebugLog.h" -#include "Common/GPU/OpenGL/GLSLProgram.h" +#include "Common/GPU/OpenGL/GLFeatures.h" +#include "Common/GPU/OpenGL/GLRenderManager.h" #include "Common/GPU/thin3d.h" -#include "Core/MemMap.h" -#include "Core/Config.h" -#include "Core/ConfigValues.h" #include "Core/System.h" -#include "Core/Reporting.h" -#include "GPU/ge_constants.h" -#include "GPU/GPUState.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/Common/PresentationCommon.h" #include "GPU/Common/TextureDecoder.h" -#include "GPU/Debugger/Stepping.h" #include "GPU/GLES/FramebufferManagerGLES.h" -#include "GPU/GLES/TextureCacheGLES.h" -#include "GPU/GLES/ShaderManagerGLES.h" FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index bdfaa27e8d..1cbe825d60 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -18,13 +18,8 @@ #pragma once #include "Common/GPU/thin3d.h" -#include "GPU/GPUCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" - -class TextureCacheGLES; -class DrawEngineGLES; -class ShaderManagerGLES; -class GLRProgram; +#include "GPU/Common/GPUDebugInterface.h" class FramebufferManagerGLES : public FramebufferManagerCommon { public: diff --git a/GPU/Vulkan/FramebufferManagerVulkan.cpp b/GPU/Vulkan/FramebufferManagerVulkan.cpp index 7d47fda518..d5d4bdae50 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.cpp +++ b/GPU/Vulkan/FramebufferManagerVulkan.cpp @@ -15,35 +15,9 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include - -#include "Common/Profiler/Profiler.h" - -#include "Common/System/Display.h" -#include "Common/Math/lin/matrix4x4.h" -#include "Common/Data/Convert/ColorConv.h" -#include "Common/Data/Convert/SmallDataConvert.h" -#include "Common/GPU/thin3d.h" - -#include "Common/GPU/Vulkan/VulkanContext.h" -#include "Common/GPU/Vulkan/VulkanMemory.h" -#include "Common/GPU/Vulkan/VulkanImage.h" -#include "Common/GPU/Vulkan/VulkanRenderManager.h" -#include "Core/MemMap.h" -#include "Core/Config.h" -#include "Core/ConfigValues.h" -#include "Core/System.h" -#include "GPU/ge_constants.h" -#include "GPU/GPUInterface.h" #include "GPU/GPUState.h" -#include "GPU/Common/TextureDecoder.h" -#include "GPU/Common/FramebufferManagerCommon.h" -#include "GPU/Debugger/Stepping.h" #include "GPU/Vulkan/FramebufferManagerVulkan.h" -#include "GPU/Vulkan/DrawEngineVulkan.h" -#include "GPU/Vulkan/TextureCacheVulkan.h" -#include "GPU/Vulkan/ShaderManagerVulkan.h" #include "GPU/Vulkan/VulkanUtil.h" using namespace PPSSPP_VK; @@ -53,10 +27,6 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw) : presentation_->SetLanguage(GLSL_VULKAN); } -FramebufferManagerVulkan::~FramebufferManagerVulkan() { - DeviceLost(); -} - void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth) { int mask = 0; // The Clear detection takes care of doing a regular draw instead if separate masking diff --git a/GPU/Vulkan/FramebufferManagerVulkan.h b/GPU/Vulkan/FramebufferManagerVulkan.h index d3370fafb7..c2e575f0b2 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.h +++ b/GPU/Vulkan/FramebufferManagerVulkan.h @@ -17,24 +17,14 @@ #pragma once -#include "Common/GPU/Vulkan/VulkanLoader.h" -#include "GPU/GPUInterface.h" -#include "GPU/Common/FramebufferManagerCommon.h" -#include "GPU/Common/GPUDebugInterface.h" -#include "GPU/Common/PresentationCommon.h" -#include "GPU/Vulkan/VulkanUtil.h" +#include "Common/GPU/thin3d.h" -class TextureCacheVulkan; -class DrawEngineVulkan; -class VulkanContext; -class ShaderManagerVulkan; -class VulkanTexture; -class VulkanPushBuffer; +#include "GPU/Common/FramebufferManagerCommon.h" +#include "GPU/Common/PresentationCommon.h" class FramebufferManagerVulkan : public FramebufferManagerCommon { public: explicit FramebufferManagerVulkan(Draw::DrawContext *draw); - ~FramebufferManagerVulkan(); // If within a render pass, this will just issue a regular clear. If beginning a new render pass, // do that. From 16eded4e1c798ab043385ab52fa86055fcd6bcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 11:46:06 +0100 Subject: [PATCH 145/424] Comment on why FinishDeferred is not unified. --- GPU/GPUCommon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 9529be025e..a63677bfe1 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -310,7 +310,7 @@ protected: void FlushImm(); void DoBlockTransfer(u32 skipDrawReason); - // TODO: Unify this. + // TODO: Unify this. The only backend that differs is Vulkan. virtual void FinishDeferred() {} void AdvanceVerts(u32 vertType, int count, int bytesRead) { From da561aa9debed4d57934f8ebe3d600b47c567c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 11:53:37 +0100 Subject: [PATCH 146/424] Unify CheckFlushOp --- GPU/D3D11/GPU_D3D11.cpp | 10 ---------- GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 10 ---------- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 10 ---------- GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommon.cpp | 10 ++++++++++ GPU/GPUCommon.h | 2 ++ GPU/Vulkan/GPU_Vulkan.cpp | 10 ---------- GPU/Vulkan/GPU_Vulkan.h | 1 - 10 files changed, 12 insertions(+), 45 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 2b8179e472..c230723a8e 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -185,16 +185,6 @@ void GPU_D3D11::FinishDeferred() { drawEngine_.FinishDeferred(); } -inline void GPU_D3D11::CheckFlushOp(int cmd, u32 diff) { - const u8 cmdFlags = cmdInfo_[cmd].flags; - if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { - if (dumpThisFrame_) { - NOTICE_LOG(G3D, "================ FLUSH ================"); - } - drawEngine_.Flush(); - } -} - void GPU_D3D11::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 0fece6f431..bba27d040c 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -54,8 +54,6 @@ protected: void FinishDeferred() override; private: - // void ApplyDrawState(int prim); - void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo() override; void InitClear() override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index a85903a94c..cfe17016a5 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -181,16 +181,6 @@ void GPU_DX9::FinishDeferred() { drawEngine_.FinishDeferred(); } -inline void GPU_DX9::CheckFlushOp(int cmd, u32 diff) { - const u8 cmdFlags = cmdInfo_[cmd].flags; - if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { - if (dumpThisFrame_) { - NOTICE_LOG(G3D, "================ FLUSH ================"); - } - drawEngine_.Flush(); - } -} - void GPU_DX9::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 621ad79857..2e0e697b3c 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -54,7 +54,6 @@ protected: void FinishDeferred() override; private: - void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo() override; void InitClear() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 3646fc802c..5b882f32f8 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -334,16 +334,6 @@ void GPU_GLES::FinishDeferred() { drawEngine_.FinishDeferred(); } -inline void GPU_GLES::CheckFlushOp(int cmd, u32 diff) { - const u8 cmdFlags = cmdInfo_[cmd].flags; - if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { - if (dumpThisFrame_) { - NOTICE_LOG(G3D, "================ FLUSH ================"); - } - drawEngine_.Flush(); - } -} - void GPU_GLES::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index ce2b363149..94e921ca7b 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -65,7 +65,6 @@ protected: void FinishDeferred() override; private: - void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo() override; void InitClear() override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 836af1236d..bfc2123b3a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3609,3 +3609,13 @@ void GPUCommon::UpdateMSAALevel(Draw::DrawContext *draw) { msaaLevel_ = 0; } } + +void GPUCommon::CheckFlushOp(int cmd, u32 diff) { + const u8 cmdFlags = cmdInfo_[cmd].flags; + if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { + if (dumpThisFrame_) { + NOTICE_LOG(G3D, "================ FLUSH ================"); + } + drawEngineCommon_->DispatchFlush(); + } +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index a63677bfe1..ff53cb6e49 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -313,6 +313,8 @@ protected: // TODO: Unify this. The only backend that differs is Vulkan. virtual void FinishDeferred() {} + void CheckFlushOp(int cmd, u32 diff); + void AdvanceVerts(u32 vertType, int count, int bytesRead) { if ((vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { int indexShift = ((vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT) - 1; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 8e1ad1e2d1..258b7d5821 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -416,16 +416,6 @@ void GPU_Vulkan::FinishDeferred() { drawEngine_.FinishDeferred(); } -inline void GPU_Vulkan::CheckFlushOp(int cmd, u32 diff) { - const u8 cmdFlags = cmdInfo_[cmd].flags; - if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { - if (dumpThisFrame_) { - NOTICE_LOG(G3D, "================ FLUSH ================"); - } - drawEngine_.Flush(); - } -} - void GPU_Vulkan::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 67f8301e00..6544b1de41 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -71,7 +71,6 @@ protected: void CheckRenderResized() override; private: - void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo() override; void InitClear() override; void CopyDisplayToOutput(bool reallyDirty) override; From ed03348c6570931927fbd21abe8267bbc35b22c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 11:56:30 +0100 Subject: [PATCH 147/424] Unify PreExecuteOp, keep the soft GPU as a special case --- GPU/D3D11/GPU_D3D11.cpp | 4 ---- GPU/D3D11/GPU_D3D11.h | 1 - GPU/Directx9/GPU_DX9.cpp | 4 ---- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 4 ---- GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommon.cpp | 2 +- GPU/Software/SoftGpu.h | 1 + GPU/Vulkan/GPU_Vulkan.cpp | 4 ---- GPU/Vulkan/GPU_Vulkan.h | 1 - 10 files changed, 2 insertions(+), 21 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index c230723a8e..512e155743 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -185,10 +185,6 @@ void GPU_D3D11::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_D3D11::PreExecuteOp(u32 op, u32 diff) { - CheckFlushOp(op >> 24, diff); -} - void GPU_D3D11::ExecuteOp(u32 op, u32 diff) { const u8 cmd = op >> 24; const CommandInfo info = cmdInfo_[cmd]; diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index bba27d040c..311d6044dd 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -37,7 +37,6 @@ public: ~GPU_D3D11(); u32 CheckGPUFeatures() const override; - void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; void GetStats(char *buffer, size_t bufsize) override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index cfe17016a5..2fc33297da 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -181,10 +181,6 @@ void GPU_DX9::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_DX9::PreExecuteOp(u32 op, u32 diff) { - CheckFlushOp(op >> 24, diff); -} - void GPU_DX9::ExecuteOp(u32 op, u32 diff) { const u8 cmd = op >> 24; const CommandInfo info = cmdInfo_[cmd]; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 2e0e697b3c..ec0b759a3a 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -36,7 +36,6 @@ public: ~GPU_DX9(); u32 CheckGPUFeatures() const override; - void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxState() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 5b882f32f8..55c1f3eb7a 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -334,10 +334,6 @@ void GPU_GLES::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_GLES::PreExecuteOp(u32 op, u32 diff) { - CheckFlushOp(op >> 24, diff); -} - void GPU_GLES::ExecuteOp(u32 op, u32 diff) { const u8 cmd = op >> 24; const CommandInfo info = cmdInfo_[cmd]; diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 94e921ca7b..9ee2d3b8f2 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -43,7 +43,6 @@ public: bool IsReady() override; void CancelReady() override; - void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxState() override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index bfc2123b3a..636965c4ff 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1411,7 +1411,7 @@ void GPUCommon::ProcessDLQueue() { } void GPUCommon::PreExecuteOp(u32 op, u32 diff) { - // Nothing to do + CheckFlushOp(op >> 24, diff); } void GPUCommon::Execute_OffsetAddr(u32 op, u32 diff) { diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 2496c7b474..f60f26a9b1 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -210,6 +210,7 @@ protected: void ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, int srcheight, const uint16_t *overrideData = nullptr); void BuildReportingInfo() override {} + void PreExecuteOp(u32 op, u32 diff) override {} private: void MarkDirty(uint32_t addr, uint32_t stride, uint32_t height, GEBufferFormat fmt, SoftGPUVRAMDirty value); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 258b7d5821..dbbb731d4c 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -416,10 +416,6 @@ void GPU_Vulkan::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_Vulkan::PreExecuteOp(u32 op, u32 diff) { - CheckFlushOp(op >> 24, diff); -} - void GPU_Vulkan::ExecuteOp(u32 op, u32 diff) { const u8 cmd = op >> 24; const CommandInfo info = cmdInfo_[cmd]; diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 6544b1de41..86951f11dc 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -47,7 +47,6 @@ public: void BeginHostFrame() override; void EndHostFrame() override; - void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; void GetStats(char *buffer, size_t bufsize) override; From 3823c08771e416278f5429226697d13d1c526d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 11:58:14 +0100 Subject: [PATCH 148/424] Remove PreExecuteOp from GPUInterface --- GPU/GPUCommon.h | 2 +- GPU/GPUInterface.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index ff53cb6e49..92c8d0d0ae 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -109,7 +109,7 @@ public: void DumpNextFrame() override; void ExecuteOp(u32 op, u32 diff) override; - void PreExecuteOp(u32 op, u32 diff) override; + virtual void PreExecuteOp(u32 op, u32 diff); bool InterpretList(DisplayList &list); void ProcessDLQueue(); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 2e1af82a66..8403d6f048 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -221,7 +221,6 @@ public: virtual void InterruptEnd(int listid) = 0; virtual void SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) = 0; - virtual void PreExecuteOp(u32 op, u32 diff) = 0; virtual void ExecuteOp(u32 op, u32 diff) = 0; // Framebuffer management From 6b91647209ea65d4da819fd9e1b1d07909533f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 12:01:11 +0100 Subject: [PATCH 149/424] Remove unused ExeuteOp in GPUCommon.cpp --- GPU/GPUCommon.cpp | 47 ----------------------------------------------- GPU/GPUCommon.h | 1 - 2 files changed, 48 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 636965c4ff..40be69be68 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2706,53 +2706,6 @@ void GPUCommon::FlushImm() { } } -void GPUCommon::ExecuteOp(u32 op, u32 diff) { - const u32 cmd = op >> 24; - - // Handle control and drawing commands here directly. The others we delegate. - switch (cmd) { - case GE_CMD_NOP: - break; - - case GE_CMD_OFFSETADDR: - Execute_OffsetAddr(op, diff); - break; - - case GE_CMD_ORIGIN: - Execute_Origin(op, diff); - break; - - case GE_CMD_JUMP: - Execute_Jump(op, diff); - break; - - case GE_CMD_BJUMP: - Execute_BJump(op, diff); - break; - - case GE_CMD_CALL: - Execute_Call(op, diff); - break; - - case GE_CMD_RET: - Execute_Ret(op, diff); - break; - - case GE_CMD_SIGNAL: - case GE_CMD_FINISH: - // Processed in GE_END. - break; - - case GE_CMD_END: - Execute_End(op, diff); - break; - - default: - DEBUG_LOG(G3D, "DL Unknown: %08x @ %08x", op, currentList == NULL ? 0 : currentList->pc); - break; - } -} - void GPUCommon::Execute_Unknown(u32 op, u32 diff) { if ((op & 0xFFFFFF) != 0) WARN_LOG_REPORT_ONCE(unknowncmd, G3D, "Unknown GE command : %08x ", op); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 92c8d0d0ae..8fccd97cd9 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -108,7 +108,6 @@ public: void DumpNextFrame() override; - void ExecuteOp(u32 op, u32 diff) override; virtual void PreExecuteOp(u32 op, u32 diff); bool InterpretList(DisplayList &list); From 609a8f6d362a763fbec740b3f3fed7bb6790c01d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 12:02:52 +0100 Subject: [PATCH 150/424] Unify ExecuteOp between the accelerated backends --- GPU/D3D11/GPU_D3D11.cpp | 13 ------------- GPU/D3D11/GPU_D3D11.h | 1 - GPU/Directx9/GPU_DX9.cpp | 13 ------------- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 13 ------------- GPU/GLES/GPU_GLES.h | 2 -- GPU/GPUCommon.cpp | 13 +++++++++++++ GPU/GPUCommon.h | 1 + GPU/Vulkan/GPU_Vulkan.cpp | 13 ------------- GPU/Vulkan/GPU_Vulkan.h | 2 -- 10 files changed, 14 insertions(+), 58 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 512e155743..0c5c1312e5 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -185,19 +185,6 @@ void GPU_D3D11::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_D3D11::ExecuteOp(u32 op, u32 diff) { - const u8 cmd = op >> 24; - const CommandInfo info = cmdInfo_[cmd]; - const u8 cmdFlags = info.flags; - if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { - (this->*info.func)(op, diff); - } else if (diff) { - uint64_t dirty = info.flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } -} - void GPU_D3D11::GetStats(char *buffer, size_t bufsize) { size_t offset = FormatGPUStatsCommon(buffer, bufsize); buffer += offset; diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 311d6044dd..619ca841b6 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -37,7 +37,6 @@ public: ~GPU_D3D11(); u32 CheckGPUFeatures() const override; - void ExecuteOp(u32 op, u32 diff) override; void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 2fc33297da..adc006efd7 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -181,19 +181,6 @@ void GPU_DX9::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_DX9::ExecuteOp(u32 op, u32 diff) { - const u8 cmd = op >> 24; - const CommandInfo info = cmdInfo_[cmd]; - const u8 cmdFlags = info.flags; - if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { - (this->*info.func)(op, diff); - } else if (diff) { - uint64_t dirty = info.flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } -} - void GPU_DX9::GetStats(char *buffer, size_t bufsize) { size_t offset = FormatGPUStatsCommon(buffer, bufsize); buffer += offset; diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index ec0b759a3a..1385ea8999 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -36,7 +36,6 @@ public: ~GPU_DX9(); u32 CheckGPUFeatures() const override; - void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 55c1f3eb7a..e6f67be12d 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -334,19 +334,6 @@ void GPU_GLES::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_GLES::ExecuteOp(u32 op, u32 diff) { - const u8 cmd = op >> 24; - const CommandInfo info = cmdInfo_[cmd]; - const u8 cmdFlags = info.flags; - if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { - (this->*info.func)(op, diff); - } else if (diff) { - uint64_t dirty = info.flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } -} - void GPU_GLES::GetStats(char *buffer, size_t bufsize) { size_t offset = FormatGPUStatsCommon(buffer, bufsize); buffer += offset; diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 9ee2d3b8f2..5ebba38098 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -43,8 +43,6 @@ public: bool IsReady() override; void CancelReady() override; - void ExecuteOp(u32 op, u32 diff) override; - void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 40be69be68..23d3fb7e03 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2706,6 +2706,19 @@ void GPUCommon::FlushImm() { } } +void GPUCommon::ExecuteOp(u32 op, u32 diff) { + const u8 cmd = op >> 24; + const CommandInfo info = cmdInfo_[cmd]; + const u8 cmdFlags = info.flags; + if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { + (this->*info.func)(op, diff); + } else if (diff) { + uint64_t dirty = info.flags >> 8; + if (dirty) + gstate_c.Dirty(dirty); + } +} + void GPUCommon::Execute_Unknown(u32 op, u32 diff) { if ((op & 0xFFFFFF) != 0) WARN_LOG_REPORT_ONCE(unknowncmd, G3D, "Unknown GE command : %08x ", op); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 8fccd97cd9..92c8d0d0ae 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -108,6 +108,7 @@ public: void DumpNextFrame() override; + void ExecuteOp(u32 op, u32 diff) override; virtual void PreExecuteOp(u32 op, u32 diff); bool InterpretList(DisplayList &list); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index dbbb731d4c..78afe87e2e 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -416,19 +416,6 @@ void GPU_Vulkan::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_Vulkan::ExecuteOp(u32 op, u32 diff) { - const u8 cmd = op >> 24; - const CommandInfo info = cmdInfo_[cmd]; - const u8 cmdFlags = info.flags; - if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { - (this->*info.func)(op, diff); - } else if (diff) { - uint64_t dirty = info.flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } -} - void GPU_Vulkan::InitDeviceObjects() { INFO_LOG(G3D, "GPU_Vulkan::InitDeviceObjects"); VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 86951f11dc..f8884ac762 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -47,8 +47,6 @@ public: void BeginHostFrame() override; void EndHostFrame() override; - void ExecuteOp(u32 op, u32 diff) override; - void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; From 0d57f3beee169c98636b71ee3407bc72e3c7a83e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 12:07:28 +0100 Subject: [PATCH 151/424] Unify GPUCommon::DoState. --- GPU/Common/DrawEngineCommon.h | 3 ++- GPU/D3D11/GPU_D3D11.cpp | 14 -------------- GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 14 -------------- GPU/Directx9/GPU_DX9.h | 2 -- GPU/GLES/GPU_GLES.cpp | 15 --------------- GPU/GLES/GPU_GLES.h | 2 -- GPU/GPUCommon.cpp | 11 +++++++++++ GPU/Vulkan/GPU_Vulkan.cpp | 14 -------------- GPU/Vulkan/GPU_Vulkan.h | 2 -- 10 files changed, 13 insertions(+), 66 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 3e2891c4a3..78473c3cf3 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -123,9 +123,10 @@ public: VertexDecoder *GetVertexDecoder(u32 vtype); + virtual void ClearTrackedVertexArrays() {} + protected: virtual bool UpdateUseHWTessellation(bool enabled) { return enabled; } - virtual void ClearTrackedVertexArrays() {} int ComputeNumVertsToDecode() const; void DecodeVerts(u8 *dest); diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 0c5c1312e5..a9c6632a88 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -198,20 +198,6 @@ void GPU_D3D11::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_D3D11::DoState(PointerWrap &p) { - GPUCommon::DoState(p); - - // TODO: Some of these things may not be necessary. - // None of these are necessary when saving. - if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_->Clear(true); - drawEngine_.ClearTrackedVertexArrays(); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); - framebufferManager_->DestroyAllFBOs(); - } -} - std::vector GPU_D3D11::DebugGetShaderIDs(DebugShaderType type) { switch (type) { case SHADER_TYPE_VERTEXLOADER: diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 619ca841b6..cdb3ddbfb7 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -42,8 +42,6 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; - void DoState(PointerWrap &p) override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index adc006efd7..90f7e1a0dd 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -194,20 +194,6 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_DX9::DoState(PointerWrap &p) { - GPUCommon::DoState(p); - - // TODO: Some of these things may not be necessary. - // None of these are necessary when saving. - if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_->Clear(true); - drawEngine_.ClearTrackedVertexArrays(); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); - framebufferManager_->DestroyAllFBOs(); - } -} - std::vector GPU_DX9::DebugGetShaderIDs(DebugShaderType type) { switch (type) { case SHADER_TYPE_VERTEXLOADER: diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 1385ea8999..218145ab15 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -42,8 +42,6 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; - void DoState(PointerWrap &p) override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index e6f67be12d..f63c61dd59 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -348,21 +348,6 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_GLES::DoState(PointerWrap &p) { - GPUCommon::DoState(p); - - // TODO: Some of these things may not be necessary. - // None of these are necessary when saving. - // In Freeze-Frame mode, we don't want to do any of this. - if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_->Clear(true); - drawEngine_.ClearTrackedVertexArrays(); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); - framebufferManager_->DestroyAllFBOs(); - } -} - std::vector GPU_GLES::DebugGetShaderIDs(DebugShaderType type) { switch (type) { case SHADER_TYPE_VERTEXLOADER: diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 5ebba38098..ff9bc1373b 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -49,8 +49,6 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; - void DoState(PointerWrap &p) override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 23d3fb7e03..0725563bc0 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2871,6 +2871,17 @@ void GPUCommon::DoState(PointerWrap &p) { if (s >= 6) { Do(p, edramTranslation_); } + + // TODO: Some of these things may not be necessary. + // None of these are necessary when saving. + // The textureCache_ check avoids this getting called in SoftGPU. + if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen && textureCache_) { + textureCache_->Clear(true); + drawEngineCommon_->ClearTrackedVertexArrays(); + + gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); + framebufferManager_->DestroyAllFBOs(); + } } void GPUCommon::InterruptStart(int listid) { diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 78afe87e2e..54953c879b 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -523,20 +523,6 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_Vulkan::DoState(PointerWrap &p) { - GPUCommon::DoState(p); - - // TODO: Some of these things may not be necessary. - // None of these are necessary when saving. - // In Freeze-Frame mode, we don't want to do any of this. - if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_->Clear(true); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); - framebufferManager_->DestroyAllFBOs(); - } -} - std::vector GPU_Vulkan::DebugGetShaderIDs(DebugShaderType type) { if (type == SHADER_TYPE_VERTEXLOADER) { return drawEngine_.DebugGetVertexLoaderIDs(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index f8884ac762..58e1726f20 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -51,8 +51,6 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; - void DoState(PointerWrap &p) override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; From 8b431b39babdcf6f0c6e04aae7615f680f3d5eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 13:09:44 +0100 Subject: [PATCH 152/424] Wrap the display globals in a struct (#16998) * Wrap the display globals in a struct Makes it easier to search/replace these, for future refactorings. * Some renaming * Qt buildfix, also fix the Qt build on Mac (got broken with battery changes) * Attempt at buildfixing ios * UWP buildfix --- CMakeLists.txt | 10 +++- Common/GPU/Vulkan/VulkanContext.cpp | 18 ++++---- Common/GPU/Vulkan/VulkanRenderManager.cpp | 3 +- Common/Render/DrawBuffer.cpp | 16 +++---- Common/Render/Text/draw_text.cpp | 2 +- Common/System/Display.cpp | 20 +------- Common/System/Display.h | 41 +++++++++------- Common/UI/Context.cpp | 24 +++++----- Common/UI/Screen.cpp | 2 +- Common/UI/UIScreen.cpp | 20 ++++---- Core/Core.cpp | 52 ++++++++++----------- Core/HLE/sceIo.cpp | 4 +- Core/Screenshot.cpp | 4 +- GPU/Common/FramebufferManagerCommon.cpp | 8 ++-- GPU/Common/PresentationCommon.cpp | 18 ++++---- GPU/Common/ShaderUniforms.cpp | 10 ++-- GPU/GLES/ShaderManagerGLES.cpp | 2 +- Qt/QtMain.cpp | 36 +++++++-------- Qt/mainwindow.cpp | 4 +- SDL/SDLGLGraphicsContext.cpp | 4 +- SDL/SDLMain.cpp | 48 +++++++++---------- SDL/SDLVulkanGraphicsContext.cpp | 2 +- UI/ControlMappingScreen.cpp | 12 ++--- UI/DevScreens.cpp | 6 +-- UI/DisplayLayoutScreen.cpp | 10 ++-- UI/EmuScreen.cpp | 22 ++++----- UI/GameSettingsScreen.cpp | 8 ++-- UI/GamepadEmu.cpp | 6 +-- UI/MiscScreens.cpp | 12 ++--- UI/NativeApp.cpp | 26 ++++++----- UI/ReportScreen.cpp | 2 +- UI/TouchControlLayoutScreen.cpp | 4 +- UWP/PPSSPP_UWPMain.cpp | 38 +++++++-------- Windows/Debugger/CtrlDisAsmView.cpp | 2 +- Windows/Debugger/CtrlMemView.cpp | 2 +- Windows/Debugger/CtrlRegisterList.cpp | 2 +- Windows/Debugger/Debugger_MemoryDlg.cpp | 2 +- Windows/GEDebugger/CtrlDisplayListView.cpp | 2 +- Windows/GPU/D3D11Context.cpp | 4 +- Windows/GPU/D3D9Context.cpp | 4 +- Windows/MainWindow.cpp | 12 ++--- Windows/TouchInputHandler.cpp | 4 +- Windows/WindowsHost.cpp | 4 +- android/jni/AndroidJavaGLContext.cpp | 4 +- android/jni/TestRunner.cpp | 8 ++-- android/jni/app-android.cpp | 54 +++++++++++----------- ios/DisplayManager.mm | 30 ++++++------ ios/ViewController.mm | 4 +- 48 files changed, 319 insertions(+), 313 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b0206f664..fadd2853c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1188,7 +1188,15 @@ elseif(USING_QT_UI) if(USING_GLES2) add_definitions(-DQT_OPENGL_ES -DQT_OPENGL_ES_2) endif() - + if(APPLE) + list(APPEND NativeAppSource + UI/DarwinFileSystemServices.mm + UI/DarwinFileSystemServices.h + Common/Battery/AppleBatteryClient.m) + set_source_files_properties(Common/Battery/AppleBatteryClient.m PROPERTIES COMPILE_FLAGS -fobjc-arc) + set_source_files_properties(UI/DarwinFileSystemServices.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) + set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY}) + endif() include_directories(Qt) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(nativeExtraLibs ${nativeExtraLibs} Qt5::OpenGL Qt5::Gui Qt5::Core Qt5::Multimedia) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index 6768602852..fe15710d70 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1288,8 +1288,8 @@ bool VulkanContext::InitSwapchain() { VkSurfaceTransformFlagBitsKHR preTransform; std::string supportedTransforms = surface_transforms_to_string(surfCapabilities_.supportedTransforms); std::string currentTransform = surface_transforms_to_string(surfCapabilities_.currentTransform); - g_display_rotation = DisplayRotation::ROTATE_0; - g_display_rot_matrix.setIdentity(); + g_display.rotation = DisplayRotation::ROTATE_0; + g_display.rot_matrix.setIdentity(); uint32_t allowedRotations = VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR | VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR; // Hack: Don't allow 270 degrees pretransform (inverse landscape), it creates bizarre issues on some devices (see #15773). @@ -1300,20 +1300,20 @@ bool VulkanContext::InitSwapchain() { } else if (surfCapabilities_.currentTransform & allowedRotations) { // Normal, sensible rotations. Let's handle it. preTransform = surfCapabilities_.currentTransform; - g_display_rot_matrix.setIdentity(); + g_display.rot_matrix.setIdentity(); switch (surfCapabilities_.currentTransform) { case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: - g_display_rotation = DisplayRotation::ROTATE_90; - g_display_rot_matrix.setRotationZ90(); + g_display.rotation = DisplayRotation::ROTATE_90; + g_display.rot_matrix.setRotationZ90(); std::swap(swapChainExtent_.width, swapChainExtent_.height); break; case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: - g_display_rotation = DisplayRotation::ROTATE_180; - g_display_rot_matrix.setRotationZ180(); + g_display.rotation = DisplayRotation::ROTATE_180; + g_display.rot_matrix.setRotationZ180(); break; case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: - g_display_rotation = DisplayRotation::ROTATE_270; - g_display_rot_matrix.setRotationZ270(); + g_display.rotation = DisplayRotation::ROTATE_270; + g_display.rot_matrix.setRotationZ270(); std::swap(swapChainExtent_.width, swapChainExtent_.height); break; default: diff --git a/Common/GPU/Vulkan/VulkanRenderManager.cpp b/Common/GPU/Vulkan/VulkanRenderManager.cpp index 55298b3be4..7ab778d8c2 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.cpp +++ b/Common/GPU/Vulkan/VulkanRenderManager.cpp @@ -884,7 +884,8 @@ void VulkanRenderManager::BindFramebufferAsRenderTarget(VKRFramebuffer *fb, VKRR } else { curWidthRaw_ = vulkan_->GetBackbufferWidth(); curHeightRaw_ = vulkan_->GetBackbufferHeight(); - if (g_display_rotation == DisplayRotation::ROTATE_90 || g_display_rotation == DisplayRotation::ROTATE_270) { + if (g_display.rotation == DisplayRotation::ROTATE_90 || + g_display.rotation == DisplayRotation::ROTATE_270) { curWidth_ = curHeightRaw_; curHeight_ = curWidthRaw_; } else { diff --git a/Common/Render/DrawBuffer.cpp b/Common/Render/DrawBuffer.cpp index bf49bc4774..73c0f30a68 100644 --- a/Common/Render/DrawBuffer.cpp +++ b/Common/Render/DrawBuffer.cpp @@ -111,14 +111,14 @@ void DrawBuffer::Rect(float x, float y, float w, float h, uint32_t color, int al void DrawBuffer::hLine(float x1, float y, float x2, uint32_t color) { // Round Y to the closest full pixel, since we're making it 1-pixel-thin. - y -= fmodf(y, pixel_in_dps_y); - Rect(x1, y, x2 - x1, pixel_in_dps_y, color); + y -= fmodf(y, g_display.pixel_in_dps_y); + Rect(x1, y, x2 - x1, g_display.pixel_in_dps_y, color); } void DrawBuffer::vLine(float x, float y1, float y2, uint32_t color) { // Round X to the closest full pixel, since we're making it 1-pixel-thin. - x -= fmodf(x, pixel_in_dps_x); - Rect(x, y1, pixel_in_dps_x, y2 - y1, color); + x -= fmodf(x, g_display.pixel_in_dps_x); + Rect(x, y1, g_display.pixel_in_dps_x, y2 - y1, color); } void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32_t colorTop, uint32_t colorBottom) { @@ -131,11 +131,11 @@ void DrawBuffer::RectVGradient(float x, float y, float w, float h, uint32_t colo } void DrawBuffer::RectOutline(float x, float y, float w, float h, uint32_t color, int align) { - hLine(x, y, x + w + pixel_in_dps_x, color); - hLine(x, y + h, x + w + pixel_in_dps_x, color); + hLine(x, y, x + w + g_display.pixel_in_dps_x, color); + hLine(x, y + h, x + w + g_display.pixel_in_dps_x, color); - vLine(x, y, y + h + pixel_in_dps_y, color); - vLine(x + w, y, y + h + pixel_in_dps_y, color); + vLine(x, y, y + h + g_display.pixel_in_dps_y, color); + vLine(x + w, y, y + h + g_display.pixel_in_dps_y, color); } void DrawBuffer::MultiVGradient(float x, float y, float w, float h, const GradientStop *stops, int numStops) { diff --git a/Common/Render/Text/draw_text.cpp b/Common/Render/Text/draw_text.cpp index e236065483..4d4b58e7f9 100644 --- a/Common/Render/Text/draw_text.cpp +++ b/Common/Render/Text/draw_text.cpp @@ -38,7 +38,7 @@ void TextDrawer::SetFontScale(float xscale, float yscale) { float TextDrawer::CalculateDPIScale() { if (ignoreGlobalDpi_) return dpiScale_; - float scale = g_dpi_scale_y; + float scale = g_display.dpi_scale_y; if (scale >= 1.0f) { scale = 1.0f; } diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 0e9c1ffb62..90644a592a 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -1,27 +1,11 @@ #include "Common/System/Display.h" #include "Common/Math/math_util.h" -int dp_xres; -int dp_yres; - -int pixel_xres; -int pixel_yres; - -float g_dpi = 1.0f; // will be overwritten with a value that makes sense. -float g_dpi_scale_x = 1.0f; -float g_dpi_scale_y = 1.0f; -float g_dpi_scale_real_x = 1.0f; -float g_dpi_scale_real_y = 1.0f; -float pixel_in_dps_x = 1.0f; -float pixel_in_dps_y = 1.0f; -float display_hz = 60.0f; - -DisplayRotation g_display_rotation; -Lin::Matrix4x4 g_display_rot_matrix = Lin::Matrix4x4::identity(); +DisplayProperties g_display; template void RotateRectToDisplayImpl(DisplayRect &rect, T curRTWidth, T curRTHeight) { - switch (g_display_rotation) { + switch (g_display.rotation) { case DisplayRotation::ROTATE_180: rect.x = curRTWidth - rect.w - rect.x; rect.y = curRTHeight - rect.h - rect.y; diff --git a/Common/System/Display.h b/Common/System/Display.h index 586c346f77..c7e826394c 100644 --- a/Common/System/Display.h +++ b/Common/System/Display.h @@ -5,20 +5,6 @@ // This is meant to be a framework for handling DPI scaling etc. // For now, it just consists of these ugly globals. -extern int dp_xres; -extern int dp_yres; -extern int pixel_xres; -extern int pixel_yres; - -extern float g_dpi; -extern float g_dpi_scale_x; -extern float g_dpi_scale_y; -extern float g_dpi_scale_real_x; -extern float g_dpi_scale_real_y; -extern float pixel_in_dps_x; -extern float pixel_in_dps_y; -extern float display_hz; - // On some platforms (currently only Windows UWP) we need to manually rotate // our rendered output to match the display. Use these to do so. enum class DisplayRotation { @@ -28,8 +14,31 @@ enum class DisplayRotation { ROTATE_270, }; -extern DisplayRotation g_display_rotation; -extern Lin::Matrix4x4 g_display_rot_matrix; +struct DisplayProperties { + int dp_xres; + int dp_yres; + int pixel_xres; + int pixel_yres; + + float dpi = 1.0f; // will be overwritten with a value that makes sense. + float dpi_scale_x = 1.0f; + float dpi_scale_y = 1.0f; + + // pixel_xres/yres in dps + float pixel_in_dps_x = 1.0f; + float pixel_in_dps_y = 1.0f; + + // If DPI is overridden (like in small window mode), these are still the original DPI. + float dpi_scale_real_x = 1.0f; + float dpi_scale_real_y = 1.0f; + + float display_hz = 60.0f; + + DisplayRotation rotation; + Lin::Matrix4x4 rot_matrix; +}; + +extern DisplayProperties g_display; template struct DisplayRect { diff --git a/Common/UI/Context.cpp b/Common/UI/Context.cpp index 70202f44a3..cb62571bf0 100644 --- a/Common/UI/Context.cpp +++ b/Common/UI/Context.cpp @@ -15,7 +15,7 @@ UIContext::UIContext() { fontStyle_ = new UI::FontStyle(); - bounds_ = Bounds(0, 0, dp_xres, dp_yres); + bounds_ = Bounds(0, 0, g_display.dp_xres, g_display.dp_yres); } UIContext::~UIContext() { @@ -163,22 +163,22 @@ Bounds UIContext::GetLayoutBounds() const { void UIContext::ActivateTopScissor() { Bounds bounds; if (scissorStack_.size()) { - float scale_x = pixel_in_dps_x; - float scale_y = pixel_in_dps_y; + float scale_x = g_display.pixel_in_dps_x; + float scale_y = g_display.pixel_in_dps_y; bounds = scissorStack_.back(); int x = floorf(scale_x * bounds.x); int y = floorf(scale_y * bounds.y); int w = std::max(0.0f, ceilf(scale_x * bounds.w)); int h = std::max(0.0f, ceilf(scale_y * bounds.h)); - if (x < 0 || y < 0 || x + w > pixel_xres || y + h > pixel_yres) { + if (x < 0 || y < 0 || x + w > g_display.pixel_xres || y + h > g_display.pixel_yres) { // This won't actually report outside a game, but we can try. - DEBUG_LOG(G3D, "UI scissor out of bounds in %sScreen: %d,%d-%d,%d / %d,%d", screenTag_ ? screenTag_ : "N/A", x, y, w, h, pixel_xres, pixel_yres); + DEBUG_LOG(G3D, "UI scissor out of bounds in %sScreen: %d,%d-%d,%d / %d,%d", screenTag_ ? screenTag_ : "N/A", x, y, w, h, g_display.pixel_xres, g_display.pixel_yres); if (x < 0) { w += x; x = 0; } if (y < 0) { h += y; y = 0; } - if (x >= pixel_xres) { x = pixel_xres - 1; } - if (y >= pixel_yres) { y = pixel_yres - 1; } - if (x + w > pixel_xres) { w = std::min(w, pixel_xres - x); } - if (y + w > pixel_yres) { h = std::min(h, pixel_yres - y); } + if (x >= g_display.pixel_xres) { x = g_display.pixel_xres - 1; } + if (y >= g_display.pixel_yres) { y = g_display.pixel_yres - 1; } + if (x + w > g_display.pixel_xres) { w = std::min(w, g_display.pixel_xres - x); } + if (y + w > g_display.pixel_yres) { h = std::min(h, g_display.pixel_yres - y); } if (w == 0) w = 1; if (h == 0) h = 1; draw_->SetScissorRect(x, y, w, h); @@ -190,7 +190,7 @@ void UIContext::ActivateTopScissor() { } } else { // Avoid rounding errors - draw_->SetScissorRect(0, 0, pixel_xres, pixel_yres); + draw_->SetScissorRect(0, 0, g_display.pixel_xres, g_display.pixel_yres); } } @@ -351,8 +351,8 @@ Bounds UIContext::TransformBounds(const Bounds &bounds) { Bounds translated = bounds.Offset(t.translate.x, t.translate.y); // Scale around the center as the origin. - float scaledX = (translated.x - dp_xres * 0.5f) * t.scale.x + dp_xres * 0.5f; - float scaledY = (translated.y - dp_yres * 0.5f) * t.scale.y + dp_yres * 0.5f; + float scaledX = (translated.x - g_display.dp_xres * 0.5f) * t.scale.x + g_display.dp_xres * 0.5f; + float scaledY = (translated.y - g_display.dp_yres * 0.5f) * t.scale.y + g_display.dp_yres * 0.5f; return Bounds(scaledX, scaledY, translated.w * t.scale.x, translated.h * t.scale.y); } diff --git a/Common/UI/Screen.cpp b/Common/UI/Screen.cpp index 59ea6a320b..047ec04483 100644 --- a/Common/UI/Screen.cpp +++ b/Common/UI/Screen.cpp @@ -138,7 +138,7 @@ void ScreenManager::deviceRestored() { } void ScreenManager::resized() { - INFO_LOG(SYSTEM, "ScreenManager::resized(dp: %dx%d)", dp_xres, dp_yres); + INFO_LOG(SYSTEM, "ScreenManager::resized(dp: %dx%d)", g_display.dp_xres, g_display.dp_yres); std::lock_guard guard(inputLock_); // Have to notify the whole stack, otherwise there will be problems when going back // to non-top screens. diff --git a/Common/UI/UIScreen.cpp b/Common/UI/UIScreen.cpp index d1fc99595f..a412df9abb 100644 --- a/Common/UI/UIScreen.cpp +++ b/Common/UI/UIScreen.cpp @@ -24,7 +24,7 @@ UIScreen::~UIScreen() { } bool UIScreen::UseVerticalLayout() const { - return dp_yres > dp_xres * 1.1f; + return g_display.dp_yres > g_display.dp_xres * 1.1f; } void UIScreen::DoRecreateViews() { @@ -98,12 +98,12 @@ void UIScreen::preRender() { Draw::Viewport viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = pixel_xres; - viewport.Height = pixel_yres; + viewport.Width = g_display.pixel_xres; + viewport.Height = g_display.pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; draw->SetViewport(viewport); - draw->SetTargetSize(pixel_xres, pixel_yres); + draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres); } void UIScreen::postRender() { @@ -141,8 +141,8 @@ TouchInput UIScreen::transformTouch(const TouchInput &touch) { float x = touch.x - translation_.x; float y = touch.y - translation_.y; // Scale around the center as the origin. - updated.x = (x - dp_xres * 0.5f) / scale_.x + dp_xres * 0.5f; - updated.y = (y - dp_yres * 0.5f) / scale_.y + dp_yres * 0.5f; + updated.x = (x - g_display.dp_xres * 0.5f) / scale_.x + g_display.dp_xres * 0.5f; + updated.y = (y - g_display.dp_yres * 0.5f) / scale_.y + g_display.dp_yres * 0.5f; return updated; } @@ -280,14 +280,14 @@ void PopupScreen::update() { scale_.y = 0.9f + animatePos * 0.1f; if (hasPopupOrigin_) { - float xoff = popupOrigin_.x - dp_xres / 2; - float yoff = popupOrigin_.y - dp_yres / 2; + float xoff = popupOrigin_.x - g_display.dp_xres / 2; + float yoff = popupOrigin_.y - g_display.dp_yres / 2; // Pull toward the origin a bit. translation_.x = xoff * (1.0f - animatePos) * 0.2f; translation_.y = yoff * (1.0f - animatePos) * 0.2f; } else { - translation_.y = -dp_yres * (1.0f - animatePos) * 0.2f; + translation_.y = -g_display.dp_yres * (1.0f - animatePos) * 0.2f; } } else { alpha_ = 1.0f; @@ -333,7 +333,7 @@ void PopupScreen::CreateViews() { box_->SetBG(dc.theme->popupStyle.background); box_->SetHasDropShadow(hasDropShadow_); // Since we scale a bit, make the dropshadow bleed past the edges. - box_->SetDropShadowExpand(std::max(dp_xres, dp_yres)); + box_->SetDropShadowExpand(std::max(g_display.dp_xres, g_display.dp_yres)); box_->SetSpacing(0.0f); View *title = new PopupHeader(title_); diff --git a/Core/Core.cpp b/Core/Core.cpp index 611dad8457..95864b197a 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -154,8 +154,8 @@ bool Core_GetPowerSaving() { static bool IsWindowSmall(int pixelWidth, int pixelHeight) { // Can't take this from config as it will not be set if windows is maximized. - int w = (int)(pixelWidth * g_dpi_scale_x); - int h = (int)(pixelHeight * g_dpi_scale_y); + int w = (int)(pixelWidth * g_display.dpi_scale_x); + int h = (int)(pixelHeight * g_display.dpi_scale_y); return g_Config.IsPortrait() ? (h < 480 + 80) : (w < 480 + 80); } @@ -163,42 +163,42 @@ static bool IsWindowSmall(int pixelWidth, int pixelHeight) { bool UpdateScreenScale(int width, int height) { bool smallWindow; #if defined(USING_QT_UI) - g_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); + g_display.dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); float g_logical_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_LOGICAL_DPI); - g_dpi_scale_x = g_logical_dpi / g_dpi; - g_dpi_scale_y = g_logical_dpi / g_dpi; + g_display.dpi_scale_x = g_logical_dpi / g_display.dpi; + g_display.dpi_scale_y = g_logical_dpi / g_display.dpi; #elif PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP) - g_dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); - g_dpi_scale_x = 96.0f / g_dpi; - g_dpi_scale_y = 96.0f / g_dpi; + g_display.dpi = System_GetPropertyFloat(SYSPROP_DISPLAY_DPI); + g_display.dpi_scale_x = 96.0f / g_display.dpi; + g_display.dpi_scale_y = 96.0f / g_display.dpi; #else - g_dpi = 96.0f; - g_dpi_scale_x = 1.0f; - g_dpi_scale_y = 1.0f; + g_display.dpi = 96.0f; + g_display.dpi_scale_x = 1.0f; + g_display.dpi_scale_y = 1.0f; #endif - g_dpi_scale_real_x = g_dpi_scale_x; - g_dpi_scale_real_y = g_dpi_scale_y; + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; smallWindow = IsWindowSmall(width, height); if (smallWindow) { - g_dpi /= 2.0f; - g_dpi_scale_x *= 2.0f; - g_dpi_scale_y *= 2.0f; + g_display.dpi /= 2.0f; + g_display.dpi_scale_x *= 2.0f; + g_display.dpi_scale_y *= 2.0f; } - pixel_in_dps_x = 1.0f / g_dpi_scale_x; - pixel_in_dps_y = 1.0f / g_dpi_scale_y; + g_display.pixel_in_dps_x = 1.0f / g_display.dpi_scale_x; + g_display.pixel_in_dps_y = 1.0f / g_display.dpi_scale_y; - int new_dp_xres = (int)(width * g_dpi_scale_x); - int new_dp_yres = (int)(height * g_dpi_scale_y); + int new_dp_xres = (int)(width * g_display.dpi_scale_x); + int new_dp_yres = (int)(height * g_display.dpi_scale_y); - bool dp_changed = new_dp_xres != dp_xres || new_dp_yres != dp_yres; - bool px_changed = pixel_xres != width || pixel_yres != height; + bool dp_changed = new_dp_xres != g_display.dp_xres || new_dp_yres != g_display.dp_yres; + bool px_changed = g_display.pixel_xres != width || g_display.pixel_yres != height; if (dp_changed || px_changed) { - dp_xres = new_dp_xres; - dp_yres = new_dp_yres; - pixel_xres = width; - pixel_yres = height; + g_display.dp_xres = new_dp_xres; + g_display.dp_yres = new_dp_yres; + g_display.pixel_xres = width; + g_display.pixel_yres = height; NativeResized(); return true; } diff --git a/Core/HLE/sceIo.cpp b/Core/HLE/sceIo.cpp index 9eb3a678b0..ade4158218 100644 --- a/Core/HLE/sceIo.cpp +++ b/Core/HLE/sceIo.cpp @@ -2055,7 +2055,7 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o // I have a planned further refactoring. float ar; if (g_Config.bDisplayStretch) { - ar = (float)dp_xres / (float)dp_yres; + ar = (float)g_display.dp_xres / (float)g_display.dp_yres; } else { ar = g_Config.fDisplayAspectRatio * (480.0f / 272.0f); } @@ -2066,7 +2066,7 @@ static u32 sceIoDevctl(const char *name, int cmd, u32 argAddr, int argLen, u32 o if (Memory::IsValidAddress(outPtr)) { // TODO: Maybe do something more sophisticated taking the longest side and screen rotation // into account, etc. - float scale = float(dp_xres) * g_Config.fDisplayScale / 480.0f; + float scale = (float)g_display.dp_xres * g_Config.fDisplayScale / 480.0f; Memory::Write_Float(scale, outPtr); } return 0; diff --git a/Core/Screenshot.cpp b/Core/Screenshot.cpp index 6ad9de9316..492ffab35c 100644 --- a/Core/Screenshot.cpp +++ b/Core/Screenshot.cpp @@ -344,11 +344,11 @@ bool TakeGameScreenshot(const Path &filename, ScreenshotFormat fmt, ScreenshotTy // Only crop to the top left when using a render screenshot. w = maxRes > 0 ? 480 * maxRes : PSP_CoreParameter().renderWidth; h = maxRes > 0 ? 272 * maxRes : PSP_CoreParameter().renderHeight; - } else if (g_display_rotation != DisplayRotation::ROTATE_0) { + } else if (g_display.rotation != DisplayRotation::ROTATE_0) { GPUDebugBuffer temp; success = gpuDebug->GetOutputFramebuffer(temp); if (success) { - buf = ApplyRotation(temp, g_display_rotation); + buf = ApplyRotation(temp, g_display.rotation); } } else { success = gpuDebug->GetOutputFramebuffer(buf); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 4c0c4dea0b..deba2f8d39 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1205,8 +1205,8 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int // TODO: Replace with draw2D_.Blit() directly. DrawActiveTexture(dstX, dstY, width, height, - vfb ? vfb->bufferWidth : pixel_xres, - vfb ? vfb->bufferHeight : pixel_yres, + vfb ? vfb->bufferWidth : g_display.pixel_xres, + vfb ? vfb->bufferHeight : g_display.pixel_yres, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags); gpuStats.numUploads++; @@ -3081,11 +3081,11 @@ void FramebufferManagerCommon::DrawActiveTexture(float x, float y, float w, floa coord[i].y = coord[i].y * invDestH - 1.0f; } - if ((flags & DRAWTEX_TO_BACKBUFFER) && g_display_rotation != DisplayRotation::ROTATE_0) { + if ((flags & DRAWTEX_TO_BACKBUFFER) && g_display.rotation != DisplayRotation::ROTATE_0) { for (int i = 0; i < 4; i++) { // backwards notation, should fix that... Lin::Vec3 pos = Lin::Vec3(coord[i].x, coord[i].y, 0.0); - pos = pos * g_display_rot_matrix; + pos = pos * g_display.rot_matrix; coord[i].x = pos.x; coord[i].y = pos.y; } diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 0c027ae796..3305e03b73 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -55,10 +55,10 @@ FRect GetScreenFrame(float pixelWidth, float pixelHeight) { if (applyInset) { // Remove the DPI scale to get back to pixels. - float left = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) / g_dpi_scale_x; - float right = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) / g_dpi_scale_x; - float top = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) / g_dpi_scale_y; - float bottom = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) / g_dpi_scale_y; + float left = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT) / g_display.dpi_scale_x; + float right = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_RIGHT) / g_display.dpi_scale_x; + float top = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP) / g_display.dpi_scale_y; + float bottom = System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_BOTTOM) / g_display.dpi_scale_y; // Adjust left edge to compensate for cutouts (notches) if any. rc.x += left; @@ -100,8 +100,8 @@ void CenterDisplayOutputRect(FRect *rc, float origW, float origH, const FRect &f if (stretch) { // Automatically set aspect ratio to match the display, IF the rotation matches the output display ratio! Otherwise, just // sets standard aspect ratio because actually stretching will just look silly. - bool globalRotated = g_display_rotation == DisplayRotation::ROTATE_90 || g_display_rotation == DisplayRotation::ROTATE_270; - if (rotated == dp_yres > dp_xres) { + bool globalRotated = g_display.rotation == DisplayRotation::ROTATE_90 || g_display.rotation == DisplayRotation::ROTATE_270; + if (rotated == g_display.dp_yres > g_display.dp_xres) { origRatio = frameRatio; } else { origRatio *= aspectRatioAdjust; @@ -699,11 +699,11 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u if (isFinalAtOutputResolution || useStereo) { // In this mode, we ignore the g_display_rot_matrix. Apply manually. - if (g_display_rotation != DisplayRotation::ROTATE_0) { + if (g_display.rotation != DisplayRotation::ROTATE_0) { for (int i = 0; i < 4; i++) { Lin::Vec3 v(verts[i].x, verts[i].y, verts[i].z); // Backwards notation, should fix that... - v = v * g_display_rot_matrix; + v = v * g_display.rot_matrix; verts[i].x = v.x; verts[i].y = v.y; } @@ -840,7 +840,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u draw_->UpdateDynamicUniformBuffer(&uniforms, sizeof(uniforms)); } else { Draw::VsTexColUB ub{}; - memcpy(ub.WorldViewProj, g_display_rot_matrix.m, sizeof(float) * 16); + memcpy(ub.WorldViewProj, g_display.rot_matrix.m, sizeof(float) * 16); draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub)); } diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 011d09a49b..207778cf56 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -135,12 +135,12 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView ConvertProjMatrixToVulkan(flippedMatrix); } - if (!useBufferedRendering && g_display_rotation != DisplayRotation::ROTATE_0) { - flippedMatrix = flippedMatrix * g_display_rot_matrix; + if (!useBufferedRendering && g_display.rotation != DisplayRotation::ROTATE_0) { + flippedMatrix = flippedMatrix * g_display.rot_matrix; } CopyMatrix4x4(ub->proj, flippedMatrix.getReadPtr()); - ub->rotation = useBufferedRendering ? 0 : (float)g_display_rotation; + ub->rotation = useBufferedRendering ? 0 : (float)g_display.rotation; } if (dirtyUniforms & DIRTY_PROJTHROUGHMATRIX) { @@ -150,8 +150,8 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView } else { proj_through.setOrthoVulkan(0.0f, gstate_c.curRTWidth, 0, gstate_c.curRTHeight, 0, 1); } - if (!useBufferedRendering && g_display_rotation != DisplayRotation::ROTATE_0) { - proj_through = proj_through * g_display_rot_matrix; + if (!useBufferedRendering && g_display.rotation != DisplayRotation::ROTATE_0) { + proj_through = proj_through * g_display.rot_matrix; } // Negative RT offsets come from split framebuffers (Killzone) diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 9df5b7f28d..d80cfb494f 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -443,7 +443,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin ScaleProjMatrix(flippedMatrix, useBufferedRendering); render_->SetUniformM4x4(&u_proj, flippedMatrix.m); - render_->SetUniformF1(&u_rotation, useBufferedRendering ? 0 : (float)g_display_rotation); + render_->SetUniformF1(&u_rotation, useBufferedRendering ? 0 : (float)g_display.rotation); } if (dirty & DIRTY_PROJTHROUGHMATRIX) { Matrix4x4 proj_through; diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 2baf523f8e..6809e9fec9 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -423,8 +423,8 @@ void MainUI::resizeGL(int w, int h) { xscale = w / this->width(); yscale = h / this->height(); - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().pixelWidth = g_display.pixel_xres; + PSP_CoreParameter().pixelHeight = g_display.pixel_yres; } void MainUI::timerEvent(QTimerEvent *) { @@ -453,15 +453,15 @@ bool MainUI::event(QEvent *e) { break; case Qt::TouchPointPressed: case Qt::TouchPointReleased: - input.x = touchPoint.pos().x() * g_dpi_scale_x * xscale; - input.y = touchPoint.pos().y() * g_dpi_scale_y * yscale; + input.x = touchPoint.pos().x() * g_display.dpi_scale_x * xscale; + input.y = touchPoint.pos().y() * g_display.dpi_scale_y * yscale; input.flags = (touchPoint.state() == Qt::TouchPointPressed) ? TOUCH_DOWN : TOUCH_UP; input.id = touchPoint.id(); NativeTouch(input); break; case Qt::TouchPointMoved: - input.x = touchPoint.pos().x() * g_dpi_scale_x * xscale; - input.y = touchPoint.pos().y() * g_dpi_scale_y * yscale; + input.x = touchPoint.pos().x() * g_display.dpi_scale_x * xscale; + input.y = touchPoint.pos().y() * g_display.dpi_scale_y * yscale; input.flags = TOUCH_MOVE; input.id = touchPoint.id(); NativeTouch(input); @@ -479,8 +479,8 @@ bool MainUI::event(QEvent *e) { case QEvent::MouseButtonRelease: switch(((QMouseEvent*)e)->button()) { case Qt::LeftButton: - input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale_x * xscale; - input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale_y * yscale; + input.x = ((QMouseEvent*)e)->pos().x() * g_display.dpi_scale_x * xscale; + input.y = ((QMouseEvent*)e)->pos().y() * g_display.dpi_scale_y * yscale; input.flags = (e->type() == QEvent::MouseButtonPress) ? TOUCH_DOWN : TOUCH_UP; input.id = 0; NativeTouch(input); @@ -502,8 +502,8 @@ bool MainUI::event(QEvent *e) { } break; case QEvent::MouseMove: - input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale_x * xscale; - input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale_y * yscale; + input.x = ((QMouseEvent*)e)->pos().x() * g_display.dpi_scale_x * xscale; + input.y = ((QMouseEvent*)e)->pos().y() * g_display.dpi_scale_y * yscale; input.flags = TOUCH_MOVE; input.id = 0; NativeTouch(input); @@ -738,15 +738,15 @@ int main(int argc, char *argv[]) if (res.width() < res.height()) res.transpose(); - pixel_xres = res.width(); - pixel_yres = res.height(); + g_display.pixel_xres = res.width(); + g_display.pixel_yres = res.height(); - g_dpi_scale_x = screen->logicalDotsPerInchX() / screen->physicalDotsPerInchX(); - g_dpi_scale_y = screen->logicalDotsPerInchY() / screen->physicalDotsPerInchY(); - g_dpi_scale_real_x = g_dpi_scale_x; - g_dpi_scale_real_y = g_dpi_scale_y; - dp_xres = (int)(pixel_xres * g_dpi_scale_x); - dp_yres = (int)(pixel_yres * g_dpi_scale_y); + g_display.dpi_scale_x = screen->logicalDotsPerInchX() / screen->physicalDotsPerInchX(); + g_display.dpi_scale_y = screen->logicalDotsPerInchY() / screen->physicalDotsPerInchY(); + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; + g_display.dp_xres = (int)(g_display.pixel_xres * g_display.dpi_scale_x); + g_display.dp_yres = (int)(g_display.pixel_yres * g_display.dpi_scale_y); refreshRate = screen->refreshRate(); diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 3ab5f4ac37..593fe5a0ec 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -375,7 +375,7 @@ void MainWindow::SetFullScreen(bool fullscreen) { #endif showFullScreen(); - InitPadLayout(dp_xres, dp_yres); + InitPadLayout(g_display.dp_xres, g_display.dp_yres); if (GetUIState() == UISTATE_INGAME && !g_Config.bShowTouchControls) QApplication::setOverrideCursor(QCursor(Qt::BlankCursor)); @@ -387,7 +387,7 @@ void MainWindow::SetFullScreen(bool fullscreen) { showNormal(); SetWindowScale(-1); - InitPadLayout(dp_xres, dp_yres); + InitPadLayout(g_display.dp_xres, g_display.dp_yres); if (GetUIState() == UISTATE_INGAME && QApplication::overrideCursor()) QApplication::restoreOverrideCursor(); diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 62fba14b81..b1906ac7d4 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -333,7 +333,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std: SetGLCoreContext(true); #endif - window = SDL_CreateWindow("PPSSPP", x, y, pixel_xres, pixel_yres, mode); + window = SDL_CreateWindow("PPSSPP", x, y, g_display.pixel_xres, g_display.pixel_yres, mode); if (!window) { // Definitely don't shutdown here: we'll keep trying more GL versions. fprintf(stderr, "SDL_CreateWindow failed for GL %d.%d: %s\n", ver.major, ver.minor, SDL_GetError()); @@ -358,7 +358,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std: SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); SetGLCoreContext(false); - window = SDL_CreateWindow("PPSSPP", x, y, pixel_xres, pixel_yres, mode); + window = SDL_CreateWindow("PPSSPP", x, y, g_display.pixel_xres, g_display.pixel_yres, mode); if (window == nullptr) { NativeShutdown(); fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError()); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 406f303a73..d1e71462a3 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -670,16 +670,16 @@ int main(int argc, char *argv[]) { #endif if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) { - pixel_xres = g_DesktopWidth; - pixel_yres = g_DesktopHeight; + g_display.pixel_xres = g_DesktopWidth; + g_display.pixel_yres = g_DesktopHeight; if (g_Config.iForceFullScreen == -1) g_Config.bFullScreen = true; } else { // set a sensible default resolution (2x) - pixel_xres = 480 * 2 * set_scale; - pixel_yres = 272 * 2 * set_scale; + g_display.pixel_xres = 480 * 2 * set_scale; + g_display.pixel_yres = 272 * 2 * set_scale; if (portrait) { - std::swap(pixel_xres, pixel_yres); + std::swap(g_display.pixel_xres, g_display.pixel_yres); } if (g_Config.iForceFullScreen == -1) g_Config.bFullScreen = false; @@ -688,26 +688,26 @@ int main(int argc, char *argv[]) { set_dpi = 1.0f / set_dpi; if (set_ipad) { - pixel_xres = 1024; - pixel_yres = 768; + g_display.pixel_xres = 1024; + g_display.pixel_yres = 768; } if (!landscape) { - std::swap(pixel_xres, pixel_yres); + std::swap(g_display.pixel_xres, g_display.pixel_yres); } if (set_xres > 0) { - pixel_xres = set_xres; + g_display.pixel_xres = set_xres; } if (set_yres > 0) { - pixel_yres = set_yres; + g_display.pixel_yres = set_yres; } float dpi_scale = 1.0f; if (set_dpi > 0) { dpi_scale = set_dpi; } - dp_xres = (float)pixel_xres * dpi_scale; - dp_yres = (float)pixel_yres * dpi_scale; + g_display.dp_xres = (float)g_display.pixel_xres * dpi_scale; + g_display.dp_yres = (float)g_display.pixel_yres * dpi_scale; // Mac / Linux char path[2048]; @@ -745,15 +745,15 @@ int main(int argc, char *argv[]) { int x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()); int y = SDL_WINDOWPOS_UNDEFINED; - pixel_in_dps_x = (float)pixel_xres / dp_xres; - pixel_in_dps_y = (float)pixel_yres / dp_yres; - g_dpi_scale_x = dp_xres / (float)pixel_xres; - g_dpi_scale_y = dp_yres / (float)pixel_yres; - g_dpi_scale_real_x = g_dpi_scale_x; - g_dpi_scale_real_y = g_dpi_scale_y; + g_display.pixel_in_dps_x = (float)g_display.pixel_xres / g_display.dp_xres; + g_display.pixel_in_dps_y = (float)g_display.pixel_yres / g_display.dp_yres; + g_display.dpi_scale_x = g_display.dp_xres / (float)g_display.pixel_xres; + g_display.dpi_scale_y = g_display.dp_yres / (float)g_display.pixel_yres; + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; - printf("Pixels: %i x %i\n", pixel_xres, pixel_yres); - printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres); + printf("Pixels: %i x %i\n", g_display.pixel_xres, g_display.pixel_yres); + printf("Virtual pixels: %i x %i\n", g_display.dp_xres, g_display.dp_yres); GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; @@ -873,8 +873,8 @@ int main(int argc, char *argv[]) { } SDL_Event event, touchEvent; while (SDL_PollEvent(&event)) { - float mx = event.motion.x * g_dpi_scale_x; - float my = event.motion.y * g_dpi_scale_y; + float mx = event.motion.x * g_display.dpi_scale_x; + float my = event.motion.y * g_display.dpi_scale_y; switch (event.type) { case SDL_QUIT: @@ -1182,8 +1182,8 @@ int main(int argc, char *argv[]) { // Disabled by default, needs a workaround to map to psp keys. if (g_Config.bMouseControl) { - float scaleFactor_x = g_dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; - float scaleFactor_y = g_dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; + float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; + float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; AxisInput axisX, axisY; axisX.axisId = JOYSTICK_AXIS_MOUSE_REL_X; diff --git a/SDL/SDLVulkanGraphicsContext.cpp b/SDL/SDLVulkanGraphicsContext.cpp index b01571b626..21108d18b3 100644 --- a/SDL/SDLVulkanGraphicsContext.cpp +++ b/SDL/SDLVulkanGraphicsContext.cpp @@ -33,7 +33,7 @@ static uint32_t FlagsFromConfig() { } bool SDLVulkanGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std::string *error_message) { - window = SDL_CreateWindow("Initializing Vulkan...", x, y, pixel_xres, pixel_yres, mode); + window = SDL_CreateWindow("Initializing Vulkan...", x, y, g_display.pixel_xres, g_display.pixel_yres, mode); if (!window) { fprintf(stderr, "Error creating SDL window: %s\n", SDL_GetError()); exit(1); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index a639d29b26..bfcb9e662c 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -684,7 +684,7 @@ void TouchTestScreen::render() { if (touches_[i].id != -1) { ui_context->Draw()->Circle(touches_[i].x, touches_[i].y, 100.0, 3.0, 80, 0.0f, 0xFFFFFFFF, 1.0); snprintf(buffer, sizeof(buffer), "%0.1fx%0.1f", touches_[i].x, touches_[i].y); - ui_context->DrawText(buffer, touches_[i].x, touches_[i].y + (touches_[i].y > dp_yres - 100.0f ? -135.0f : 95.0f), 0xFFFFFFFF, ALIGN_HCENTER | FLAG_DYNAMIC_ASCII); + ui_context->DrawText(buffer, touches_[i].x, touches_[i].y + (touches_[i].y > g_display.dp_yres - 100.0f ? -135.0f : 95.0f), 0xFFFFFFFF, ALIGN_HCENTER | FLAG_DYNAMIC_ASCII); } } @@ -704,11 +704,11 @@ void TouchTestScreen::render() { #if PPSSPP_PLATFORM(ANDROID) display_xres, display_yres, #endif - dp_xres, dp_yres, - pixel_xres, pixel_yres, - g_dpi, - g_dpi_scale_x, g_dpi_scale_y, - g_dpi_scale_real_x, g_dpi_scale_real_y, extra_debug); + g_display.dp_xres, g_display.dp_yres, + g_display.pixel_xres, g_display.pixel_yres, + g_display.dpi, + g_display.dpi_scale_x, g_display.dpi_scale_y, + g_display.dpi_scale_real_x, g_display.dpi_scale_real_y, extra_debug); // On Android, also add joystick debug data. diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index d9fc09d7de..eb3de25579 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -585,10 +585,10 @@ void SystemInfoScreen::CreateViews() { System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES)))); deviceSpecs->Add(new InfoItem(si->T("UI Resolution"), StringFromFormat("%dx%d (%s: %0.2f)", - dp_xres, - dp_yres, + g_display.dp_xres, + g_display.dp_yres, si->T("DPI"), - g_dpi))); + g_display.dpi))); #endif #if !PPSSPP_PLATFORM(WINDOWS) diff --git a/UI/DisplayLayoutScreen.cpp b/UI/DisplayLayoutScreen.cpp index 2c661d2965..791dc8c414 100644 --- a/UI/DisplayLayoutScreen.cpp +++ b/UI/DisplayLayoutScreen.cpp @@ -50,10 +50,10 @@ enum Mode { static Bounds FRectToBounds(FRect rc) { Bounds b; - b.x = rc.x * g_dpi_scale_x; - b.y = rc.y * g_dpi_scale_y; - b.w = rc.w * g_dpi_scale_x; - b.h = rc.h * g_dpi_scale_y; + b.x = rc.x * g_display.dpi_scale_x; + b.y = rc.y * g_display.dpi_scale_y; + b.w = rc.w * g_display.dpi_scale_x; + b.h = rc.h * g_display.dpi_scale_y; return b; } @@ -132,7 +132,7 @@ void DisplayLayoutScreen::DrawBackground(UIContext &dc) { // we have to draw a substitute ourselves. // TODO: Clean this up a bit, this GetScreenFrame/CenterDisplay combo is too common. - FRect screenFrame = GetScreenFrame(pixel_xres, pixel_yres); + FRect screenFrame = GetScreenFrame(g_display.pixel_xres, g_display.pixel_yres); FRect rc; CenterDisplayOutputRect(&rc, 480.0f, 272.0f, screenFrame, g_Config.iInternalScreenRotation); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index b95b41de36..a86a460acb 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -311,16 +311,16 @@ void EmuScreen::bootGame(const Path &filename) { coreParam.headLess = false; if (g_Config.iInternalResolution == 0) { - coreParam.renderWidth = pixel_xres; - coreParam.renderHeight = pixel_yres; + coreParam.renderWidth = g_display.pixel_xres; + coreParam.renderHeight = g_display.pixel_yres; } else { if (g_Config.iInternalResolution < 0) g_Config.iInternalResolution = 1; coreParam.renderWidth = 480 * g_Config.iInternalResolution; coreParam.renderHeight = 272 * g_Config.iInternalResolution; } - coreParam.pixelWidth = pixel_xres; - coreParam.pixelHeight = pixel_yres; + coreParam.pixelWidth = g_display.pixel_xres; + coreParam.pixelHeight = g_display.pixel_yres; std::string error_string; if (!PSP_InitStart(coreParam, &error_string)) { @@ -1027,8 +1027,8 @@ void EmuScreen::update() { #ifndef _WIN32 const Bounds &bounds = screenManager()->getUIContext()->GetBounds(); - PSP_CoreParameter().pixelWidth = pixel_xres * bounds.w / dp_xres; - PSP_CoreParameter().pixelHeight = pixel_yres * bounds.h / dp_yres; + PSP_CoreParameter().pixelWidth = g_display.pixel_xres * bounds.w / g_display.dp_xres; + PSP_CoreParameter().pixelHeight = g_display.pixel_yres * bounds.h / g_display.dp_yres; #endif if (!invalid_) { @@ -1371,13 +1371,13 @@ void EmuScreen::preRender() { Viewport viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = pixel_xres; - viewport.Height = pixel_yres; + viewport.Width = g_display.pixel_xres; + viewport.Height = g_display.pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; draw->SetViewport(viewport); } - draw->SetTargetSize(pixel_xres, pixel_yres); + draw->SetTargetSize(g_display.pixel_xres, g_display.pixel_yres); } void EmuScreen::postRender() { @@ -1519,8 +1519,8 @@ void EmuScreen::renderUI() { Viewport viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = pixel_xres; - viewport.Height = pixel_yres; + viewport.Width = g_display.pixel_xres; + viewport.Height = g_display.pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; thin3d->SetViewport(viewport); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 9e4bb43a6f..454eec0d03 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -237,8 +237,10 @@ void GameSettingsScreen::CreateViews() { if (!vertical) { leftSide += 200.0f; } - settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams(dp_xres - leftSide - 40.0f, WRAP_CONTENT, leftSide, dp_yres - 80.0f - 40.0f, NONE, NONE)); - settingInfo_->SetBottomCutoff(dp_yres - 200.0f); + settingInfo_ = new SettingInfoMessage(ALIGN_CENTER | FLAG_WRAP_TEXT, new AnchorLayoutParams( + g_display.dp_xres - leftSide - 40.0f, WRAP_CONTENT, + leftSide, g_display.dp_yres - 80.0f - 40.0f, NONE, NONE)); + settingInfo_->SetBottomCutoff(g_display.dp_yres - 200.0f); root_->Add(settingInfo_); // Show it again if we recreated the view @@ -273,7 +275,7 @@ void GameSettingsScreen::CreateViews() { #if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID) // Hide search if screen is too small. - if (dp_xres < dp_yres || dp_yres >= 500) { + if (g_display.dp_xres < g_display.dp_yres || g_display.dp_yres >= 500) { auto se = GetI18NCategory("Search"); // Search LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true); diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index efb5b6bc3a..5f997fca42 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -711,7 +711,7 @@ void InitPadLayout(float xres, float yres, float globalScale) { //select, start, throttle-------------------------------------------- //space between the bottom keys (space between select, start and un-throttle) float bottom_key_spacing = 100; - if (dp_xres < 750) { + if (g_display.dp_xres < 750) { bottom_key_spacing *= 0.8f; } @@ -956,8 +956,8 @@ bool GestureGamepad::Touch(const TouchInput &input) { void GestureGamepad::Update() { const float th = 1.0f; - float dx = deltaX_ * g_dpi_scale_x * g_Config.fSwipeSensitivity; - float dy = deltaY_ * g_dpi_scale_y * g_Config.fSwipeSensitivity; + float dx = deltaX_ * g_display.dpi_scale_x * g_Config.fSwipeSensitivity; + float dy = deltaY_ * g_display.dpi_scale_y * g_Config.fSwipeSensitivity; if (g_Config.iSwipeRight != 0) { if (dx > th) { controlMapper_->pspKey(DEVICE_ID_TOUCH, GestureKey::keyList[g_Config.iSwipeRight-1], KEY_DOWN); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 7a8984dfef..6887d5ecd2 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -134,7 +134,7 @@ public: dc.BeginNoTex(); // Be sure to not overflow our vertex buffer - const float step = ceil(24*bounds.w/pixel_in_dps_x) > MAX_VERTS ? 24*bounds.w/(MAX_VERTS-48) : pixel_in_dps_x; + const float step = ceilf(24*bounds.w/ g_display.pixel_in_dps_x) > MAX_VERTS ? 24*bounds.w/(MAX_VERTS-48) : g_display.pixel_in_dps_x; t *= speed; for (float x = 0; x < bounds.w; x += step) { @@ -146,8 +146,8 @@ public: dc.Draw()->RectVGradient(x, wave1*bounds.h, step, (1.0-wave1)*bounds.h, color, 0x00000000); // Add some "antialiasing" - dc.Draw()->RectVGradient(x, wave0*bounds.h-3*pixel_in_dps_y, step, 3*pixel_in_dps_y, 0x00000000, color); - dc.Draw()->RectVGradient(x, wave1*bounds.h-3*pixel_in_dps_y, step, 3*pixel_in_dps_y, 0x00000000, color); + dc.Draw()->RectVGradient(x, wave0*bounds.h-3.0f * g_display.pixel_in_dps_y, step, 3.0f * g_display.pixel_in_dps_y, 0x00000000, color); + dc.Draw()->RectVGradient(x, wave1*bounds.h-3.0f * g_display.pixel_in_dps_y, step, 3.0f * g_display.pixel_in_dps_y, 0x00000000, color); } dc.Flush(); @@ -371,8 +371,8 @@ void DrawGameBackground(UIContext &dc, const Path &gamePath, float x, float y, f Viewport viewport; viewport.TopLeftX = 0; viewport.TopLeftY = 0; - viewport.Width = pixel_xres; - viewport.Height = pixel_yres; + viewport.Width = g_display.pixel_xres; + viewport.Height = g_display.pixel_yres; viewport.MaxDepth = 1.0; viewport.MinDepth = 0.0; draw->SetViewport(viewport); @@ -1080,7 +1080,7 @@ void SettingInfoMessage::Show(const std::string &text, const UI::View *refView) if (b.y >= cutOffY_) { ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, 80.0f, lp->right, lp->bottom, lp->center)); } else { - ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, dp_yres - 80.0f - 40.0f, lp->right, lp->bottom, lp->center)); + ReplaceLayoutParams(new UI::AnchorLayoutParams(lp->width, lp->height, lp->left, g_display.dp_yres - 80.0f - 40.0f, lp->right, lp->bottom, lp->center)); } } text_->SetText(text); diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 50aa992c8b..65fd9fac70 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1095,8 +1095,8 @@ void NativeRender(GraphicsContext *graphicsContext) { g_BackgroundAudio.Update(); } - float xres = dp_xres; - float yres = dp_yres; + float xres = g_display.dp_xres; + float yres = g_display.dp_yres; // Apply the UIContext bounds as a 2D transformation matrix. // TODO: This should be moved into the draw context... @@ -1109,7 +1109,9 @@ void NativeRender(GraphicsContext *graphicsContext) { ortho.setOrthoD3D(0.0f, xres, yres, 0.0f, -1.0f, 1.0f); Matrix4x4 translation; // Account for the small window adjustment. - translation.setTranslation(Vec3(-0.5f * g_dpi_scale_x / g_dpi_scale_real_x, -0.5f * g_dpi_scale_y / g_dpi_scale_real_y, 0.0f)); + translation.setTranslation(Vec3( + -0.5f * g_display.dpi_scale_x / g_display.dpi_scale_real_x, + -0.5f * g_display.dpi_scale_y / g_display.dpi_scale_real_y, 0.0f)); ortho = translation * ortho; break; case GPUBackend::DIRECT3D11: @@ -1122,8 +1124,8 @@ void NativeRender(GraphicsContext *graphicsContext) { } // Compensate for rotated display if needed. - if (g_display_rotation != DisplayRotation::ROTATE_0) { - ortho = ortho * g_display_rot_matrix; + if (g_display.rotation != DisplayRotation::ROTATE_0) { + ortho = ortho * g_display.rot_matrix; } ui_draw2d.PushDrawMatrix(ortho); @@ -1151,13 +1153,13 @@ void NativeRender(GraphicsContext *graphicsContext) { if (uiContext) { // Modifying the bounds here can be used to "inset" the whole image to gain borders for TV overscan etc. // The UI now supports any offset but not the EmuScreen yet. - uiContext->SetBounds(Bounds(0, 0, dp_xres, dp_yres)); + uiContext->SetBounds(Bounds(0, 0, g_display.dp_xres, g_display.dp_yres)); // OSX 10.6 and SDL 1.2 bug. #if defined(__APPLE__) && !defined(USING_QT_UI) - static int dp_xres_old = dp_xres; - if (dp_xres != dp_xres_old) { - dp_xres_old = dp_xres; + static int dp_xres_old = g_display.dp_xres; + if (g_display.dp_xres != dp_xres_old) { + dp_xres_old = g_display.dp_xres; } #endif } @@ -1167,8 +1169,8 @@ void NativeRender(GraphicsContext *graphicsContext) { // TODO: Move this to the GraphicsContext objects for each backend. #if !PPSSPP_PLATFORM(WINDOWS) && !defined(ANDROID) - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().pixelWidth = g_display.pixel_xres; + PSP_CoreParameter().pixelHeight = g_display.pixel_yres; NativeMessageReceived("gpu_displayResized", ""); #endif } else { @@ -1402,7 +1404,7 @@ void NativeAxis(const AxisInput &axis) { // sent with respect to the portrait coordinate system, while we // take all events in landscape. // see [http://developer.android.com/guide/topics/sensors/sensors_overview.html] for details - bool landscape = dp_yres < dp_xres; + bool landscape = g_display.dp_yres < g_display.dp_xres; // now transform out current tilt to the calibrated coordinate system ProcessTilt(landscape, tiltBaseAngleY, tiltX, tiltY, tiltZ, g_Config.bInvertTiltX, g_Config.bInvertTiltY, diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index c192a021a5..7bd0815de5 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -253,7 +253,7 @@ void ReportScreen::CreateViews() { Margins actionMenuMargins(0, 20, 15, 0); Margins contentMargins(0, 20, 5, 5); - float leftColumnWidth = dp_xres - actionMenuMargins.horiz() - contentMargins.horiz() - 300.0f; + float leftColumnWidth = g_display.dp_xres - actionMenuMargins.horiz() - contentMargins.horiz() - 300.0f; ViewGroup *leftColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(WRAP_CONTENT, FILL_PARENT, 0.4f, contentMargins)); LinearLayout *leftColumnItems = new LinearLayout(ORIENT_VERTICAL, new LayoutParams(WRAP_CONTENT, FILL_PARENT)); ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); diff --git a/UI/TouchControlLayoutScreen.cpp b/UI/TouchControlLayoutScreen.cpp index d3c85b63dc..32b230c93d 100644 --- a/UI/TouchControlLayoutScreen.cpp +++ b/UI/TouchControlLayoutScreen.cpp @@ -318,8 +318,8 @@ public: float xOffset = bounds_.x; float yOffset = bounds_.y; - dc.Draw()->Rect((x1+x2)/2 + xOffset - pixel_in_dps_x, y1 + yOffset, 3.0*pixel_in_dps_x, y2-y1, col); - dc.Draw()->Rect(x1 + xOffset, (y1+y2)/2 + yOffset - pixel_in_dps_y, x2-x1, 3.0*pixel_in_dps_y, col); + dc.Draw()->Rect((x1+x2)/2 + xOffset - g_display.pixel_in_dps_x, y1 + yOffset, 3.0f * g_display.pixel_in_dps_x, y2-y1, col); + dc.Draw()->Rect(x1 + xOffset, (y1+y2)/2 + yOffset - g_display.pixel_in_dps_y, x2-x1, 3.0f * g_display.pixel_in_dps_y, col); for (int x = x1 + (x1+x2)/2 % g_Config.iTouchSnapGridSize; x < x2; x += g_Config.iTouchSnapGridSize) dc.Draw()->vLine(x + xOffset, y1 + yOffset, y2 + yOffset, col); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index b734f6e3d2..23d1801cf2 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -167,39 +167,39 @@ bool PPSSPP_UWPMain::Render() { auto context = m_deviceResources->GetD3DDeviceContext(); switch (m_deviceResources->ComputeDisplayRotation()) { - case DXGI_MODE_ROTATION_IDENTITY: g_display_rotation = DisplayRotation::ROTATE_0; break; - case DXGI_MODE_ROTATION_ROTATE90: g_display_rotation = DisplayRotation::ROTATE_90; break; - case DXGI_MODE_ROTATION_ROTATE180: g_display_rotation = DisplayRotation::ROTATE_180; break; - case DXGI_MODE_ROTATION_ROTATE270: g_display_rotation = DisplayRotation::ROTATE_270; break; + case DXGI_MODE_ROTATION_IDENTITY: g_display.rotation = DisplayRotation::ROTATE_0; break; + case DXGI_MODE_ROTATION_ROTATE90: g_display.rotation = DisplayRotation::ROTATE_90; break; + case DXGI_MODE_ROTATION_ROTATE180: g_display.rotation = DisplayRotation::ROTATE_180; break; + case DXGI_MODE_ROTATION_ROTATE270: g_display.rotation = DisplayRotation::ROTATE_270; break; } // Not super elegant but hey. - memcpy(&g_display_rot_matrix, &m_deviceResources->GetOrientationTransform3D(), sizeof(float) * 16); + memcpy(&g_display.rot_matrix, &m_deviceResources->GetOrientationTransform3D(), sizeof(float) * 16); // Reset the viewport to target the whole screen. auto viewport = m_deviceResources->GetScreenViewport(); - pixel_xres = viewport.Width; - pixel_yres = viewport.Height; + g_display.pixel_xres = viewport.Width; + g_display.pixel_yres = viewport.Height; - if (g_display_rotation == DisplayRotation::ROTATE_90 || g_display_rotation == DisplayRotation::ROTATE_270) { + if (g_display.rotation == DisplayRotation::ROTATE_90 || g_display.rotation == DisplayRotation::ROTATE_270) { // We need to swap our width/height. - std::swap(pixel_xres, pixel_yres); + std::swap(g_display.pixel_xres, g_display.pixel_yres); } - g_dpi = m_deviceResources->GetActualDpi(); + g_display.dpi = m_deviceResources->GetActualDpi(); if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) { // Boost DPI a bit to look better. - g_dpi *= 96.0f / 136.0f; + g_display.dpi *= 96.0f / 136.0f; } - g_dpi_scale_x = 96.0f / g_dpi; - g_dpi_scale_y = 96.0f / g_dpi; + g_display.dpi_scale_x = 96.0f / g_display.dpi; + g_display.dpi_scale_y = 96.0f / g_display.dpi; - pixel_in_dps_x = 1.0f / g_dpi_scale_x; - pixel_in_dps_y = 1.0f / g_dpi_scale_y; + g_display.pixel_in_dps_x = 1.0f / g_display.dpi_scale_x; + g_display.pixel_in_dps_y = 1.0f / g_display.dpi_scale_y; - dp_xres = pixel_xres * g_dpi_scale_x; - dp_yres = pixel_yres * g_dpi_scale_y; + g_display.dp_xres = g_display.pixel_xres * g_display.dpi_scale_x; + g_display.dp_yres = g_display.pixel_yres * g_display.dpi_scale_y; context->RSSetViewports(1, &viewport); @@ -274,8 +274,8 @@ void PPSSPP_UWPMain::OnTouchEvent(int touchEvent, int touchId, float x, float y, // and then apply our own "dpi". float dpiFactor_x = m_deviceResources->GetActualDpi() / 96.0f; float dpiFactor_y = dpiFactor_x; - dpiFactor_x /= pixel_in_dps_x; - dpiFactor_y /= pixel_in_dps_y; + dpiFactor_x /= g_display.pixel_in_dps_x; + dpiFactor_y /= g_display.pixel_in_dps_y; TouchInput input{}; input.id = touchId; diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index a179749ecf..3f54114fc5 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -172,7 +172,7 @@ CtrlDisAsmView::CtrlDisAsmView(HWND _wnd) SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL); SetScrollRange(wnd, SB_VERT, -1, 1, TRUE); - const float fontScale = 1.0f / g_dpi_scale_real_y; + const float fontScale = 1.0f / g_display.dpi_scale_real_y; charWidth = g_Config.iFontWidth * fontScale; rowHeight = (g_Config.iFontHeight + 2) * fontScale; int scaledFontHeight = g_Config.iFontHeight * fontScale; diff --git a/Windows/Debugger/CtrlMemView.cpp b/Windows/Debugger/CtrlMemView.cpp index 598763df85..f4eb61df2e 100644 --- a/Windows/Debugger/CtrlMemView.cpp +++ b/Windows/Debugger/CtrlMemView.cpp @@ -34,7 +34,7 @@ CtrlMemView::CtrlMemView(HWND _wnd) { SetWindowLong(wnd, GWL_STYLE, GetWindowLong(wnd,GWL_STYLE) | WS_VSCROLL); SetScrollRange(wnd, SB_VERT, -1,1,TRUE); - const float fontScale = 1.0f / g_dpi_scale_real_y; + const float fontScale = 1.0f / g_display.dpi_scale_real_y; charWidth_ = g_Config.iFontWidth * fontScale; rowHeight_ = g_Config.iFontHeight * fontScale; offsetPositionY_ = offsetLine * rowHeight_; diff --git a/Windows/Debugger/CtrlRegisterList.cpp b/Windows/Debugger/CtrlRegisterList.cpp index 8df25e6429..6fcf215b76 100644 --- a/Windows/Debugger/CtrlRegisterList.cpp +++ b/Windows/Debugger/CtrlRegisterList.cpp @@ -133,7 +133,7 @@ CtrlRegisterList::CtrlRegisterList(HWND _wnd) : wnd(_wnd) { SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)this); - const float fontScale = 1.0f / g_dpi_scale_real_y; + const float fontScale = 1.0f / g_display.dpi_scale_real_y; rowHeight = g_Config.iFontHeight * fontScale; int charWidth = g_Config.iFontWidth * fontScale; font = CreateFont(rowHeight, charWidth, 0, 0, diff --git a/Windows/Debugger/Debugger_MemoryDlg.cpp b/Windows/Debugger/Debugger_MemoryDlg.cpp index d016afaafa..5382a69b71 100644 --- a/Windows/Debugger/Debugger_MemoryDlg.cpp +++ b/Windows/Debugger/Debugger_MemoryDlg.cpp @@ -257,7 +257,7 @@ void CMemoryDlg::Goto(u32 addr) void CMemoryDlg::Size() { - const float fontScale = 1.0f / g_dpi_scale_real_y; + const float fontScale = 1.0f / g_display.dpi_scale_real_y; GetClientRect(m_hDlg,&winRect); int dlg_w = winRect.right - winRect.left; diff --git a/Windows/GEDebugger/CtrlDisplayListView.cpp b/Windows/GEDebugger/CtrlDisplayListView.cpp index eaaa8577f8..4c341c7e4b 100644 --- a/Windows/GEDebugger/CtrlDisplayListView.cpp +++ b/Windows/GEDebugger/CtrlDisplayListView.cpp @@ -45,7 +45,7 @@ CtrlDisplayListView::CtrlDisplayListView(HWND _wnd) instructionSize = 4; // In small window mode, g_dpi_scale may have been adjusted. - const float fontScale = 1.0f / g_dpi_scale_real_y; + const float fontScale = 1.0f / g_display.dpi_scale_real_y; int fontHeight = g_Config.iFontHeight * fontScale; int charWidth = g_Config.iFontWidth * fontScale; diff --git a/Windows/GPU/D3D11Context.cpp b/Windows/GPU/D3D11Context.cpp index 6207b8fd75..6d04c24b0c 100644 --- a/Windows/GPU/D3D11Context.cpp +++ b/Windows/GPU/D3D11Context.cpp @@ -51,8 +51,8 @@ void D3D11Context::SwapInterval(int interval) { HRESULT D3D11Context::CreateTheDevice(IDXGIAdapter *adapter) { bool windowed = true; // D3D11 has no need for display rotation. - g_display_rotation = DisplayRotation::ROTATE_0; - g_display_rot_matrix.setIdentity(); + g_display.rotation = DisplayRotation::ROTATE_0; + g_display.rot_matrix.setIdentity(); #if defined(_DEBUG) && !PPSSPP_ARCH(ARM) && !PPSSPP_ARCH(ARM64) UINT createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG; #else diff --git a/Windows/GPU/D3D9Context.cpp b/Windows/GPU/D3D9Context.cpp index dc02dade21..7ffe7f79f0 100644 --- a/Windows/GPU/D3D9Context.cpp +++ b/Windows/GPU/D3D9Context.cpp @@ -51,8 +51,8 @@ bool D3D9Context::Init(HINSTANCE hInst, HWND wnd, std::string *error_message) { hWnd_ = wnd; // D3D9 has no need for display rotation. - g_display_rotation = DisplayRotation::ROTATE_0; - g_display_rot_matrix.setIdentity(); + g_display.rotation = DisplayRotation::ROTATE_0; + g_display.rot_matrix.setIdentity(); DIRECT3DCREATE9EX g_pfnCreate9ex; diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index 6c30fa9d71..f02d1e4f79 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -643,8 +643,8 @@ namespace MainWindow // Hack: Take the opportunity to show the cursor. mouseButtonDown = true; - float x = GET_X_LPARAM(lParam) * g_dpi_scale_x; - float y = GET_Y_LPARAM(lParam) * g_dpi_scale_y; + float x = GET_X_LPARAM(lParam) * g_display.dpi_scale_x; + float y = GET_Y_LPARAM(lParam) * g_display.dpi_scale_y; WindowsRawInput::SetMousePos(x, y); TouchInput touch; @@ -684,8 +684,8 @@ namespace MainWindow prevCursorX = cursorX; prevCursorY = cursorY; - float x = (float)cursorX * g_dpi_scale_x; - float y = (float)cursorY * g_dpi_scale_y; + float x = (float)cursorX * g_display.dpi_scale_x; + float y = (float)cursorY * g_display.dpi_scale_y; WindowsRawInput::SetMousePos(x, y); if (wParam & MK_LBUTTON) { @@ -706,8 +706,8 @@ namespace MainWindow // Hack: Take the opportunity to hide the cursor. mouseButtonDown = false; - float x = (float)GET_X_LPARAM(lParam) * g_dpi_scale_x; - float y = (float)GET_Y_LPARAM(lParam) * g_dpi_scale_y; + float x = (float)GET_X_LPARAM(lParam) * g_display.dpi_scale_x; + float y = (float)GET_Y_LPARAM(lParam) * g_display.dpi_scale_y; WindowsRawInput::SetMousePos(x, y); TouchInput touch; diff --git a/Windows/TouchInputHandler.cpp b/Windows/TouchInputHandler.cpp index d0f00e59f6..63b25934de 100644 --- a/Windows/TouchInputHandler.cpp +++ b/Windows/TouchInputHandler.cpp @@ -54,8 +54,8 @@ bool TouchInputHandler::GetTouchPoint(HWND hWnd, const TOUCHINPUT &input, float point.x = (LONG)(TOUCH_COORD_TO_PIXEL(input.x)); point.y = (LONG)(TOUCH_COORD_TO_PIXEL(input.y)); if (ScreenToClient(hWnd, &point)) { - x = point.x * g_dpi_scale_x; - y = point.y * g_dpi_scale_y; + x = point.x * g_display.dpi_scale_x; + y = point.y * g_display.dpi_scale_y; return true; } diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index b6cd28286c..5f194bcd88 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -238,8 +238,8 @@ void WindowsHost::PollControllers() { // Disabled by default, needs a workaround to map to psp keys. if (g_Config.bMouseControl) { - float scaleFactor_x = g_dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; - float scaleFactor_y = g_dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; + float scaleFactor_x = g_display.dpi_scale_x * 0.1 * g_Config.fMouseSensitivity; + float scaleFactor_y = g_display.dpi_scale_y * 0.1 * g_Config.fMouseSensitivity; float mx = std::max(-1.0f, std::min(1.0f, g_mouseDeltaX * scaleFactor_x)); float my = std::max(-1.0f, std::min(1.0f, g_mouseDeltaY * scaleFactor_y)); diff --git a/android/jni/AndroidJavaGLContext.cpp b/android/jni/AndroidJavaGLContext.cpp index ebf22b143c..a2cada60f5 100644 --- a/android/jni/AndroidJavaGLContext.cpp +++ b/android/jni/AndroidJavaGLContext.cpp @@ -19,8 +19,8 @@ bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int } // OpenGL handles rotated rendering in the driver. - g_display_rotation = DisplayRotation::ROTATE_0; - g_display_rot_matrix.setIdentity(); + g_display.rotation = DisplayRotation::ROTATE_0; + g_display.rot_matrix.setIdentity(); draw_ = Draw::T3DCreateGLContext(); // Can't fail renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); diff --git a/android/jni/TestRunner.cpp b/android/jni/TestRunner.cpp index 64e6f7761c..1b9a8acb52 100644 --- a/android/jni/TestRunner.cpp +++ b/android/jni/TestRunner.cpp @@ -119,8 +119,8 @@ bool RunTests() { output.clear(); if (!PSP_Init(coreParam, &error_string)) { ERROR_LOG(SYSTEM, "Failed to init unittest %s : %s", testsToRun[i], error_string.c_str()); - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().pixelWidth = g_display.pixel_xres; + PSP_CoreParameter().pixelHeight = g_display.pixel_yres; return false; } @@ -176,8 +176,8 @@ bool RunTests() { } PSP_Shutdown(); } - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().pixelWidth = g_display.pixel_xres; + PSP_CoreParameter().pixelHeight = g_display.pixel_yres; PSP_CoreParameter().headLess = false; PSP_CoreParameter().graphicsContext = tempCtx; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index b510942036..67e2fc9238 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -461,7 +461,7 @@ int System_GetPropertyInt(SystemProperty prop) { float System_GetPropertyFloat(SystemProperty prop) { switch (prop) { case SYSPROP_DISPLAY_REFRESH_RATE: - return display_hz; + return g_display.display_hz; case SYSPROP_DISPLAY_SAFE_INSET_LEFT: return g_safeInsetLeft; case SYSPROP_DISPLAY_SAFE_INSET_RIGHT: @@ -977,35 +977,35 @@ extern "C" bool Java_org_ppsspp_ppsspp_NativeRenderer_displayInit(JNIEnv * env, } static void recalculateDpi() { - g_dpi = display_dpi_x; - g_dpi_scale_x = 240.0f / display_dpi_x; - g_dpi_scale_y = 240.0f / display_dpi_y; - g_dpi_scale_real_x = g_dpi_scale_x; - g_dpi_scale_real_y = g_dpi_scale_y; + g_display.dpi = display_dpi_x; + g_display.dpi_scale_x = 240.0f / display_dpi_x; + g_display.dpi_scale_y = 240.0f / display_dpi_y; + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; - dp_xres = display_xres * g_dpi_scale_x; - dp_yres = display_yres * g_dpi_scale_y; + g_display.dp_xres = display_xres * g_display.dpi_scale_x; + g_display.dp_yres = display_yres * g_display.dpi_scale_y; - pixel_in_dps_x = (float)pixel_xres / dp_xres; - pixel_in_dps_y = (float)pixel_yres / dp_yres; + g_display.pixel_in_dps_x = (float)g_display.pixel_xres / g_display.dp_xres; + g_display.pixel_in_dps_y = (float)g_display.pixel_yres / g_display.dp_yres; - INFO_LOG(G3D, "RecalcDPI: display_xres=%d display_yres=%d pixel_xres=%d pixel_yres=%d", display_xres, display_yres, pixel_xres, pixel_yres); - INFO_LOG(G3D, "RecalcDPI: g_dpi=%f g_dpi_scale_x=%f g_dpi_scale_y=%f dp_xres=%d dp_yres=%d", g_dpi, g_dpi_scale_x, g_dpi_scale_y, dp_xres, dp_yres); + INFO_LOG(G3D, "RecalcDPI: display_xres=%d display_yres=%d pixel_xres=%d pixel_yres=%d", display_xres, display_yres, g_display.pixel_xres, g_display.pixel_yres); + INFO_LOG(G3D, "RecalcDPI: g_dpi=%f g_dpi_scale_x=%f g_dpi_scale_y=%f dp_xres=%d dp_yres=%d", g_display.dpi, g_display.dpi_scale_x, g_display.dpi_scale_y, g_display.dp_xres, g_display.dp_yres); } extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv *, jclass, jint bufw, jint bufh, jint format) { INFO_LOG(SYSTEM, "NativeApp.backbufferResize(%d x %d)", bufw, bufh); - bool new_size = pixel_xres != bufw || pixel_yres != bufh; - int old_w = pixel_xres; - int old_h = pixel_yres; + bool new_size = g_display.pixel_xres != bufw || g_display.pixel_yres != bufh; + int old_w = g_display.pixel_xres; + int old_h = g_display.pixel_yres; // pixel_*res is the backbuffer resolution. - pixel_xres = bufw; - pixel_yres = bufh; + g_display.pixel_xres = bufw; + g_display.pixel_yres = bufh; backbuffer_format = format; if (IsVREnabled()) { - GetVRResolutionPerEye(&pixel_xres, &pixel_yres); + GetVRResolutionPerEye(&g_display.pixel_xres, &g_display.pixel_yres); } recalculateDpi(); @@ -1093,7 +1093,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeRenderer_displayRender(JNIEnv *env, } if (IsVREnabled()) { - UpdateVRInput(g_Config.bHapticFeedback, g_dpi_scale_x, g_dpi_scale_y); + UpdateVRInput(g_Config.bHapticFeedback, g_display.dpi_scale_x, g_display.dpi_scale_y); FinishVRRender(); } } @@ -1117,8 +1117,8 @@ PermissionStatus System_GetPermissionStatus(SystemPermission permission) { extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_touch (JNIEnv *, jclass, float x, float y, int code, int pointerId) { - float scaledX = x * g_dpi_scale_x; - float scaledY = y * g_dpi_scale_y; + float scaledX = x * g_display.dpi_scale_x; + float scaledY = y * g_display.dpi_scale_y; TouchInput touch; touch.id = pointerId; @@ -1215,10 +1215,10 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env // We don't bother with supporting exact rectangular regions. Safe insets are good enough. int left, right, top, bottom; if (4 == sscanf(prm.c_str(), "%d:%d:%d:%d", &left, &right, &top, &bottom)) { - g_safeInsetLeft = (float)left * g_dpi_scale_x; - g_safeInsetRight = (float)right * g_dpi_scale_x; - g_safeInsetTop = (float)top * g_dpi_scale_y; - g_safeInsetBottom = (float)bottom * g_dpi_scale_y; + g_safeInsetLeft = (float)left * g_display.dpi_scale_x; + g_safeInsetRight = (float)right * g_display.dpi_scale_x; + g_safeInsetTop = (float)top * g_display.dpi_scale_y; + g_safeInsetBottom = (float)bottom * g_display.dpi_scale_y; } } @@ -1251,14 +1251,14 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_setDisplayParameters(JN bool changed = false; changed = changed || display_xres != xres || display_yres != yres; changed = changed || display_dpi_x != dpi || display_dpi_y != dpi; - changed = changed || display_hz != refreshRate; + changed = changed || g_display.display_hz != refreshRate; if (changed) { display_xres = xres; display_yres = yres; display_dpi_x = dpi; display_dpi_y = dpi; - display_hz = refreshRate; + g_display.display_hz = refreshRate; recalculateDpi(); NativeResized(); diff --git a/ios/DisplayManager.mm b/ios/DisplayManager.mm index 19f828d380..ba369e64e1 100644 --- a/ios/DisplayManager.mm +++ b/ios/DisplayManager.mm @@ -148,33 +148,33 @@ } if (screen == [UIScreen mainScreen]) { - g_dpi = (IS_IPAD() ? 200.0f : 150.0f) * scale; + g_display.dpi = (IS_IPAD() ? 200.0f : 150.0f) * scale; } else { float diagonal = sqrt(size.height * size.height + size.width * size.width); - g_dpi = diagonal * scale * 0.1f; + g_display.dpi = diagonal * scale * 0.1f; } - g_dpi_scale_x = 240.0f / g_dpi; - g_dpi_scale_y = 240.0f / g_dpi; - g_dpi_scale_real_x = g_dpi_scale_x; - g_dpi_scale_real_y = g_dpi_scale_y; - pixel_xres = size.width * scale; - pixel_yres = size.height * scale; + g_display.dpi_scale_x = 240.0f / g_display.dpi; + g_display.dpi_scale_y = 240.0f / g_display.dpi; + g_display.dpi_scale_real_x = g_display.dpi_scale_x; + g_display.dpi_scale_real_y = g_display.dpi_scale_y; + g_display.pixel_xres = size.width * scale; + g_display.pixel_yres = size.height * scale; - dp_xres = pixel_xres * g_dpi_scale_x; - dp_yres = pixel_yres * g_dpi_scale_y; + g_display.dp_xres = g_display.pixel_xres * g_display.dpi_scale_x; + g_display.dp_yres = g_display.pixel_yres * g_display.dpi_scale_y; - pixel_in_dps_x = (float)pixel_xres / (float)dp_xres; - pixel_in_dps_y = (float)pixel_yres / (float)dp_yres; + g_display.pixel_in_dps_x = (float)g_display.pixel_xres / (float)g_display.dp_xres; + g_display.pixel_in_dps_y = (float)g_display.pixel_yres / (float)g_display.dp_yres; [[sharedViewController view] setContentScaleFactor:scale]; // PSP native resize - PSP_CoreParameter().pixelWidth = pixel_xres; - PSP_CoreParameter().pixelHeight = pixel_yres; + PSP_CoreParameter().pixelWidth = g_display.pixel_xres; + PSP_CoreParameter().pixelHeight = g_display.pixel_yres; NativeResized(); - NSLog(@"Updated display resolution: (%d, %d) @%.1fx", pixel_xres, pixel_yres, scale); + NSLog(@"Updated display resolution: (%d, %d) @%.1fx", g_display.pixel_xres, g_display.pixel_yres, scale); } @end diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 74852291d4..8e30578dec 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -200,8 +200,8 @@ static LocationHelper *locationHelper; graphicsContext->ThreadStart(); - dp_xscale = (float)dp_xres / (float)pixel_xres; - dp_yscale = (float)dp_yres / (float)pixel_yres; + dp_xscale = (float)g_display.dp_xres / (float)g_display.pixel_xres; + dp_yscale = (float)g_display.dp_yres / (float)g_display.pixel_yres; /*self.iCadeView = [[iCadeReaderView alloc] init]; [self.view addSubview:self.iCadeView]; From 18999c3687d458ae5e691a7149e3e8c2073b6e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 14:24:59 +0100 Subject: [PATCH 153/424] Create the GPUCommonHW class. --- CMakeLists.txt | 2 ++ GPU/D3D11/GPU_D3D11.cpp | 2 +- GPU/D3D11/GPU_D3D11.h | 6 ++---- GPU/Directx9/GPU_DX9.cpp | 2 +- GPU/Directx9/GPU_DX9.h | 4 ++-- GPU/GLES/GPU_GLES.cpp | 2 +- GPU/GLES/GPU_GLES.h | 4 ++-- GPU/GPU.vcxproj | 2 ++ GPU/GPU.vcxproj.filters | 6 ++++++ GPU/GPUCommon.cpp | 4 ---- GPU/GPUCommon.h | 2 +- GPU/GPUCommonHW.cpp | 13 +++++++++++++ GPU/GPUCommonHW.h | 16 ++++++++++++++++ GPU/Software/SoftGpu.h | 1 - GPU/Vulkan/GPU_Vulkan.cpp | 2 +- GPU/Vulkan/GPU_Vulkan.h | 4 ++-- UWP/GPU_UWP/GPU_UWP.vcxproj | 2 ++ UWP/GPU_UWP/GPU_UWP.vcxproj.filters | 2 ++ android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 20 files changed, 58 insertions(+), 20 deletions(-) create mode 100644 GPU/GPUCommonHW.cpp create mode 100644 GPU/GPUCommonHW.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fadd2853c7..20cd4d0e74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1659,6 +1659,8 @@ set(GPU_SOURCES GPU/GPU.h GPU/GPUCommon.cpp GPU/GPUCommon.h + GPU/GPUCommonHW.cpp + GPU/GPUCommonHW.h GPU/GPUState.cpp GPU/GPUState.h GPU/Math3D.cpp diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index a9c6632a88..dd87755570 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -42,7 +42,7 @@ #include "GPU/D3D11/D3D11Util.h" GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) - : GPUCommon(gfxCtx, draw), drawEngine_(draw, + : GPUCommonHW(gfxCtx, draw), drawEngine_(draw, (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE), (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT)) { device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index cdb3ddbfb7..7a6418bb34 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -21,17 +21,15 @@ #include #include -#include "GPU/GPUCommon.h" +#include "GPU/GPUCommonHW.h" #include "GPU/D3D11/DrawEngineD3D11.h" -#include "GPU/Common/TextureShaderCommon.h" #include "GPU/Common/VertexDecoderCommon.h" class FramebufferManagerD3D11; class ShaderManagerD3D11; -class LinkedShaderD3D11; class TextureCacheD3D11; -class GPU_D3D11 : public GPUCommon { +class GPU_D3D11 : public GPUCommonHW { public: GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_D3D11(); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 90f7e1a0dd..d0ad42dfc5 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -44,7 +44,7 @@ #include "GPU/Directx9/TextureCacheDX9.h" GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) - : GPUCommon(gfxCtx, draw), + : GPUCommonHW(gfxCtx, draw), drawEngine_(draw) { device_ = (LPDIRECT3DDEVICE9)draw->GetNativeObject(Draw::NativeObject::DEVICE); deviceEx_ = (LPDIRECT3DDEVICE9EX)draw->GetNativeObject(Draw::NativeObject::DEVICE_EX); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 218145ab15..a1e5c1102c 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -20,7 +20,7 @@ #include #include -#include "GPU/GPUCommon.h" +#include "GPU/GPUCommonHW.h" #include "GPU/Directx9/FramebufferManagerDX9.h" #include "GPU/Directx9/DrawEngineDX9.h" #include "GPU/Common/TextureShaderCommon.h" @@ -30,7 +30,7 @@ class ShaderManagerDX9; class LinkedShaderDX9; class TextureCacheDX9; -class GPU_DX9 : public GPUCommon { +class GPU_DX9 : public GPUCommonHW { public: GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_DX9(); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index f63c61dd59..6cffceb53d 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -48,7 +48,7 @@ #endif GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw) - : GPUCommon(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw) { + : GPUCommonHW(gfxCtx, draw), drawEngine_(draw), fragmentTestCache_(draw) { UpdateVsyncInterval(true); gstate_c.SetUseFlags(CheckGPUFeatures()); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index ff9bc1373b..8cb6be8fc7 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -22,7 +22,7 @@ #include "Common/File/Path.h" -#include "GPU/GPUCommon.h" +#include "GPU/GPUCommonHW.h" #include "GPU/Common/TextureShaderCommon.h" #include "GPU/GLES/FramebufferManagerGLES.h" #include "GPU/GLES/DrawEngineGLES.h" @@ -32,7 +32,7 @@ class ShaderManagerGLES; class TextureCacheGLES; class LinkedShader; -class GPU_GLES : public GPUCommon { +class GPU_GLES : public GPUCommonHW { public: GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_GLES(); diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 625bfb112c..606e169859 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -427,6 +427,7 @@ + @@ -572,6 +573,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index e30366acb3..b34942e06c 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -264,6 +264,9 @@ Common + + Common + @@ -524,6 +527,9 @@ Common + + Common + diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 0725563bc0..8f8c410fa1 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1410,10 +1410,6 @@ void GPUCommon::ProcessDLQueue() { // Since the event is in CoreTiming, we're in sync. Just set 0 now. } -void GPUCommon::PreExecuteOp(u32 op, u32 diff) { - CheckFlushOp(op >> 24, diff); -} - void GPUCommon::Execute_OffsetAddr(u32 op, u32 diff) { gstate_c.offsetAddr = op << 8; } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 92c8d0d0ae..ddc955a237 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -109,7 +109,7 @@ public: void DumpNextFrame() override; void ExecuteOp(u32 op, u32 diff) override; - virtual void PreExecuteOp(u32 op, u32 diff); + virtual void PreExecuteOp(u32 op, u32 diff) {} bool InterpretList(DisplayList &list); void ProcessDLQueue(); diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp new file mode 100644 index 0000000000..e1438db9db --- /dev/null +++ b/GPU/GPUCommonHW.cpp @@ -0,0 +1,13 @@ +#include "Common/GPU/thin3d.h" +#include "GPU/GPUCommonHW.h" + + +GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) { + +} + +GPUCommonHW::~GPUCommonHW() {} + +void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { + CheckFlushOp(op >> 24, diff); +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h new file mode 100644 index 0000000000..9efe41d80b --- /dev/null +++ b/GPU/GPUCommonHW.h @@ -0,0 +1,16 @@ +#pragma once + +#include "GPUCommon.h" + +// Shared GPUCommon implementation for the HW backends. +// Things that are irrelevant for SoftGPU should live here. +class GPUCommonHW : public GPUCommon { +public: + GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw); + ~GPUCommonHW(); + +protected: + void PreExecuteOp(u32 op, u32 diff); + +}; + diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index f60f26a9b1..2496c7b474 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -210,7 +210,6 @@ protected: void ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, int srcheight, const uint16_t *overrideData = nullptr); void BuildReportingInfo() override {} - void PreExecuteOp(u32 op, u32 diff) override {} private: void MarkDirty(uint32_t addr, uint32_t stride, uint32_t height, GEBufferFormat fmt, SoftGPUVRAMDirty value); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 54953c879b..513a2906d6 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -46,7 +46,7 @@ #include "Common/GPU/Vulkan/VulkanQueueRunner.h" GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw) - : GPUCommon(gfxCtx, draw), drawEngine_(draw) { + : GPUCommonHW(gfxCtx, draw), drawEngine_(draw) { gstate_c.SetUseFlags(CheckGPUFeatures()); drawEngine_.InitDeviceObjects(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 58e1726f20..c2bb6bf73b 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -22,7 +22,7 @@ #include "Common/File/Path.h" -#include "GPU/GPUCommon.h" +#include "GPU/GPUCommonHW.h" #include "GPU/Vulkan/DrawEngineVulkan.h" #include "GPU/Vulkan/PipelineManagerVulkan.h" #include "GPU/Common/TextureShaderCommon.h" @@ -32,7 +32,7 @@ class ShaderManagerVulkan; class LinkedShader; class TextureCacheVulkan; -class GPU_Vulkan : public GPUCommon { +class GPU_Vulkan : public GPUCommonHW { public: GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPU_Vulkan(); diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 0b8ed0070f..03ce6c90bb 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -423,6 +423,7 @@ + @@ -487,6 +488,7 @@ + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index 2481c765c9..dc746a6f6d 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -61,6 +61,7 @@ + @@ -123,5 +124,6 @@ + \ No newline at end of file diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 9c7912881b..9af8d57b17 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -358,6 +358,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/Math3D.cpp \ $(SRC)/GPU/GPU.cpp \ $(SRC)/GPU/GPUCommon.cpp \ + $(SRC)/GPU/GPUCommonHW.cpp \ $(SRC)/GPU/GPUState.cpp \ $(SRC)/GPU/GeConstants.cpp \ $(SRC)/GPU/GeDisasm.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index e734a43415..7e602464b4 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -406,6 +406,7 @@ SOURCES_CXX += \ $(GPUDIR)/GeConstants.cpp \ $(GPUDIR)/GeDisasm.cpp \ $(GPUDIR)/GPUCommon.cpp \ + $(GPUDIR)/GPUCommonHW.cpp \ $(GPUDIR)/GPU.cpp \ $(GPUDIR)/GPUState.cpp \ $(GPUDIR)/Math3D.cpp \ From 285ffbaa52949340cc8506701cc3cf0eee0666e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 14:28:22 +0100 Subject: [PATCH 154/424] Unify CopyDisplayToOutput --- GPU/D3D11/GPU_D3D11.cpp | 11 ----------- GPU/D3D11/GPU_D3D11.h | 1 - GPU/Directx9/GPU_DX9.cpp | 10 ---------- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 12 ------------ GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommonHW.cpp | 13 +++++++++++++ GPU/GPUCommonHW.h | 3 ++- GPU/Vulkan/GPU_Vulkan.cpp | 11 ----------- GPU/Vulkan/GPU_Vulkan.h | 1 - 10 files changed, 15 insertions(+), 49 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index dd87755570..0d03b6292d 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -169,17 +169,6 @@ void GPU_D3D11::BeginFrame() { } } -void GPU_D3D11::CopyDisplayToOutput(bool reallyDirty) { - // Flush anything left over. - drawEngine_.Flush(); - - shaderManager_->DirtyLastShader(); - - framebufferManagerD3D11_->CopyDisplayToOutput(reallyDirty); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); -} - void GPU_D3D11::FinishDeferred() { // This finishes reading any vertex data that is pending. drawEngine_.FinishDeferred(); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 7a6418bb34..42a2ea0c24 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -52,7 +52,6 @@ private: void InitClear() override; void BeginFrame() override; - void CopyDisplayToOutput(bool reallyDirty) override; ID3D11Device *device_; ID3D11DeviceContext *context_; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index d0ad42dfc5..efe4c11fd0 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -166,16 +166,6 @@ void GPU_DX9::BeginFrame() { } } -void GPU_DX9::CopyDisplayToOutput(bool reallyDirty) { - drawEngine_.Flush(); - - shaderManager_->DirtyLastShader(); - - framebufferManagerDX9_->CopyDisplayToOutput(reallyDirty); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); -} - void GPU_DX9::FinishDeferred() { // This finishes reading any vertex data that is pending. drawEngine_.FinishDeferred(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index a1e5c1102c..d89a2bf546 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -54,7 +54,6 @@ private: void InitClear() override; void BeginFrame() override; - void CopyDisplayToOutput(bool reallyDirty) override; LPDIRECT3DDEVICE9 device_; LPDIRECT3DDEVICE9EX deviceEx_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 6cffceb53d..2cb6a88504 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -317,18 +317,6 @@ void GPU_GLES::BeginFrame() { framebufferManagerGL_->BeginFrame(); } -void GPU_GLES::CopyDisplayToOutput(bool reallyDirty) { - // Flush anything left over. - framebufferManagerGL_->RebindFramebuffer("RebindFramebuffer - CopyDisplayToOutput"); - drawEngine_.Flush(); - - shaderManagerGL_->DirtyLastShader(); - - framebufferManagerGL_->CopyDisplayToOutput(reallyDirty); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); -} - void GPU_GLES::FinishDeferred() { // This finishes reading any vertex data that is pending. drawEngine_.FinishDeferred(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 8cb6be8fc7..912c253188 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -64,7 +64,6 @@ private: void InitClear() override; void BeginFrame() override; - void CopyDisplayToOutput(bool reallyDirty) override; void Reinitialize() override; FramebufferManagerGLES *framebufferManagerGL_; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index e1438db9db..a2307d734b 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1,5 +1,7 @@ #include "Common/GPU/thin3d.h" #include "GPU/GPUCommonHW.h" +#include "GPU/Common/DrawEngineCommon.h" +#include "GPU/Common/FramebufferManagerCommon.h" GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) { @@ -11,3 +13,14 @@ GPUCommonHW::~GPUCommonHW() {} void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } + +void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) { + // Flush anything left over. + drawEngineCommon_->DispatchFlush(); + + shaderManager_->DirtyLastShader(); + + framebufferManager_->CopyDisplayToOutput(reallyDirty); + + gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 9efe41d80b..d0ff630437 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -9,8 +9,9 @@ public: GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw); ~GPUCommonHW(); + void CopyDisplayToOutput(bool reallyDirty) override; + protected: void PreExecuteOp(u32 op, u32 diff); - }; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 513a2906d6..faed3b7e4c 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -401,17 +401,6 @@ void GPU_Vulkan::InitClear() { } } -void GPU_Vulkan::CopyDisplayToOutput(bool reallyDirty) { - // Flush anything left over. - drawEngine_.Flush(); - - shaderManagerVulkan_->DirtyLastShader(); - - framebufferManagerVulkan_->CopyDisplayToOutput(reallyDirty); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); -} - void GPU_Vulkan::FinishDeferred() { drawEngine_.FinishDeferred(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index c2bb6bf73b..f468ec8b68 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -68,7 +68,6 @@ protected: private: void BuildReportingInfo() override; void InitClear() override; - void CopyDisplayToOutput(bool reallyDirty) override; void Reinitialize() override; void InitDeviceObjects(); From 9e8f1d3cb37ea50fb7c824e621c6222ca7d77282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 14:34:30 +0100 Subject: [PATCH 155/424] Make the DoState stuff less ugly --- GPU/GPUCommon.cpp | 11 ----------- GPU/GPUCommon.h | 3 ++- GPU/GPUCommonHW.cpp | 25 ++++++++++++++++++++----- GPU/GPUCommonHW.h | 2 ++ 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 8f8c410fa1..2e683d73be 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2867,17 +2867,6 @@ void GPUCommon::DoState(PointerWrap &p) { if (s >= 6) { Do(p, edramTranslation_); } - - // TODO: Some of these things may not be necessary. - // None of these are necessary when saving. - // The textureCache_ check avoids this getting called in SoftGPU. - if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen && textureCache_) { - textureCache_->Clear(true); - drawEngineCommon_->ClearTrackedVertexArrays(); - - gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); - framebufferManager_->DestroyAllFBOs(); - } } void GPUCommon::InterruptStart(int listid) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index ddc955a237..fd17ebc6e3 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -330,9 +330,10 @@ protected: void UpdateMSAALevel(Draw::DrawContext *draw); + DrawEngineCommon *drawEngineCommon_ = nullptr; + FramebufferManagerCommon *framebufferManager_ = nullptr; TextureCacheCommon *textureCache_ = nullptr; - DrawEngineCommon *drawEngineCommon_ = nullptr; ShaderManagerCommon *shaderManager_ = nullptr; bool flushOnParams_ = true; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index a2307d734b..27dc1981b7 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1,13 +1,14 @@ #include "Common/GPU/thin3d.h" +#include "Common/Serialize/Serializer.h" + +#include "Core/System.h" + #include "GPU/GPUCommonHW.h" #include "GPU/Common/DrawEngineCommon.h" +#include "GPU/Common/TextureCacheCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" - -GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) { - -} - +GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) {} GPUCommonHW::~GPUCommonHW() {} void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { @@ -24,3 +25,17 @@ void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) { gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); } + +void GPUCommonHW::DoState(PointerWrap &p) { + GPUCommon::DoState(p); + + // TODO: Some of these things may not be necessary. + // None of these are necessary when saving. + if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { + textureCache_->Clear(true); + drawEngineCommon_->ClearTrackedVertexArrays(); + + gstate_c.Dirty(DIRTY_TEXTURE_IMAGE); + framebufferManager_->DestroyAllFBOs(); + } +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index d0ff630437..aa0a189564 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -10,8 +10,10 @@ public: ~GPUCommonHW(); void CopyDisplayToOutput(bool reallyDirty) override; + void DoState(PointerWrap &p) override; protected: void PreExecuteOp(u32 op, u32 diff); + }; From b6846646af0e2f4d4c3b85bb01d6a70735aea422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 14:59:14 +0100 Subject: [PATCH 156/424] Remove some uses of gfxCtx_ --- GPU/D3D11/GPU_D3D11.cpp | 5 ++--- GPU/Directx9/GPU_DX9.cpp | 6 ++---- GPU/GPUCommon.cpp | 1 + 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 0d03b6292d..e11d1c8156 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -119,10 +119,9 @@ u32 GPU_D3D11::CheckGPUFeatures() const { // Needs to be called on GPU thread, not reporting thread. void GPU_D3D11::BuildReportingInfo() { using namespace Draw; - DrawContext *thin3d = gfxCtx_->GetDrawContext(); - reportingPrimaryInfo_ = thin3d->GetInfoString(InfoField::VENDORSTRING); - reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + thin3d->GetInfoString(InfoField::SHADELANGVERSION); + reportingPrimaryInfo_ = draw_->GetInfoString(InfoField::VENDORSTRING); + reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + draw_->GetInfoString(InfoField::SHADELANGVERSION); } void GPU_D3D11::DeviceLost() { diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index efe4c11fd0..8569a6639e 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -116,10 +116,8 @@ GPU_DX9::~GPU_DX9() { // Needs to be called on GPU thread, not reporting thread. void GPU_DX9::BuildReportingInfo() { using namespace Draw; - DrawContext *thin3d = gfxCtx_->GetDrawContext(); - - reportingPrimaryInfo_ = thin3d->GetInfoString(InfoField::VENDORSTRING); - reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + thin3d->GetInfoString(InfoField::SHADELANGVERSION); + reportingPrimaryInfo_ = draw_->GetInfoString(InfoField::VENDORSTRING); + reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + draw_->GetInfoString(InfoField::SHADELANGVERSION); } void GPU_DX9::DeviceLost() { diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 2e683d73be..af0d7d7a3d 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -796,6 +796,7 @@ int GPUCommon::GetStack(int index, u32 stackPtr) { } static void CopyMatrix24(u32_le *result, const float *mtx, u32 count, u32 cmdbits) { + // Screams out for simple SIMD, but probably not called often enough to be worth it. for (u32 i = 0; i < count; ++i) { result[i] = toFloat24(mtx[i]) | cmdbits; } From e136ad795a9fa769d2508041d3c8fedbcebfa582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 15:07:00 +0100 Subject: [PATCH 157/424] Some slight unification --- GPU/D3D11/GPU_D3D11.cpp | 8 -------- GPU/D3D11/GPU_D3D11.h | 2 -- GPU/Directx9/GPU_DX9.cpp | 7 ------- GPU/Directx9/GPU_DX9.h | 2 -- GPU/GPUCommon.cpp | 4 ---- GPU/GPUCommon.h | 4 +++- GPU/GPUCommonHW.cpp | 13 +++++++++++++ GPU/GPUCommonHW.h | 3 +++ GPU/Software/SoftGpu.h | 1 - 9 files changed, 19 insertions(+), 25 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index e11d1c8156..d20b36edbd 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -116,14 +116,6 @@ u32 GPU_D3D11::CheckGPUFeatures() const { return CheckGPUFeaturesLate(features); } -// Needs to be called on GPU thread, not reporting thread. -void GPU_D3D11::BuildReportingInfo() { - using namespace Draw; - - reportingPrimaryInfo_ = draw_->GetInfoString(InfoField::VENDORSTRING); - reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + draw_->GetInfoString(InfoField::SHADELANGVERSION); -} - void GPU_D3D11::DeviceLost() { draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); // Simply drop all caches and textures. diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 42a2ea0c24..3112c1b437 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -48,8 +48,6 @@ protected: void FinishDeferred() override; private: - void BuildReportingInfo() override; - void InitClear() override; void BeginFrame() override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 8569a6639e..96ea5ae435 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -113,13 +113,6 @@ GPU_DX9::~GPU_DX9() { delete shaderManagerDX9_; } -// Needs to be called on GPU thread, not reporting thread. -void GPU_DX9::BuildReportingInfo() { - using namespace Draw; - reportingPrimaryInfo_ = draw_->GetInfoString(InfoField::VENDORSTRING); - reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + draw_->GetInfoString(InfoField::SHADELANGVERSION); -} - void GPU_DX9::DeviceLost() { // Simply drop all caches and textures. shaderManagerDX9_->ClearCache(false); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index d89a2bf546..6d1001d90c 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -50,8 +50,6 @@ protected: void FinishDeferred() override; private: - void BuildReportingInfo() override; - void InitClear() override; void BeginFrame() override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index af0d7d7a3d..6d650e3d26 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -633,10 +633,6 @@ void GPUCommon::NotifyDisplayResized() { displayResized_ = true; } -void GPUCommon::ClearCacheNextFrame() { - textureCache_->ClearNextFrame(); -} - // Called once per frame. Might also get called during the pause screen // if "transparent". void GPUCommon::CheckConfigChanged() { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index fd17ebc6e3..98905a4f0b 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -272,7 +272,7 @@ protected: void DeviceLost() override; void DeviceRestore() override; - void ClearCacheNextFrame() override; + void ClearCacheNextFrame() override {} virtual void CheckRenderResized(); @@ -332,9 +332,11 @@ protected: DrawEngineCommon *drawEngineCommon_ = nullptr; + // TODO: These should live in GPUCommonHW. FramebufferManagerCommon *framebufferManager_ = nullptr; TextureCacheCommon *textureCache_ = nullptr; ShaderManagerCommon *shaderManager_ = nullptr; + bool flushOnParams_ = true; GraphicsContext *gfxCtx_; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 27dc1981b7..6c98d9f44c 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1,5 +1,6 @@ #include "Common/GPU/thin3d.h" #include "Common/Serialize/Serializer.h" +#include "Common/System/System.h" #include "Core/System.h" @@ -39,3 +40,15 @@ void GPUCommonHW::DoState(PointerWrap &p) { framebufferManager_->DestroyAllFBOs(); } } + +void GPUCommonHW::ClearCacheNextFrame() { + textureCache_->ClearNextFrame(); +} + +// Needs to be called on GPU thread, not reporting thread. +void GPUCommonHW::BuildReportingInfo() { + using namespace Draw; + + reportingPrimaryInfo_ = draw_->GetInfoString(InfoField::VENDORSTRING); + reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + draw_->GetInfoString(InfoField::SHADELANGVERSION); +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index aa0a189564..924a60c5f4 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -14,6 +14,9 @@ public: protected: void PreExecuteOp(u32 op, u32 diff); + void ClearCacheNextFrame() override; + // Needs to be called on GPU thread, not reporting thread. + void BuildReportingInfo() override; }; diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 2496c7b474..ef61d59663 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -145,7 +145,6 @@ public: bool PerformReadbackToMemory(u32 dest, int size) override; bool PerformWriteColorFromMemory(u32 dest, int size) override; bool PerformWriteStencilFromMemory(u32 dest, int size, WriteStencil flags) override; - void ClearCacheNextFrame() override {} void DeviceLost() override; void DeviceRestore() override; From c74f5b21890e74992a6178cb41b8948cc7bd2e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 15:59:35 +0100 Subject: [PATCH 158/424] Prepare for unifying more stuff --- GPU/Common/ShaderCommon.h | 4 ++++ GPU/Common/TextureCacheCommon.cpp | 8 +++---- GPU/Common/TextureCacheCommon.h | 7 +++++-- GPU/D3D11/GPU_D3D11.cpp | 12 +++++------ GPU/D3D11/ShaderManagerD3D11.h | 4 +++- GPU/D3D11/TextureCacheD3D11.h | 3 +++ GPU/Directx9/GPU_DX9.cpp | 21 +++++++------------ GPU/Directx9/GPU_DX9.h | 1 - GPU/Directx9/ShaderManagerDX9.cpp | 5 ++--- GPU/Directx9/ShaderManagerDX9.h | 5 ++++- GPU/Directx9/TextureCacheDX9.h | 3 +++ GPU/GLES/GPU_GLES.cpp | 35 ++++++++++++++----------------- GPU/GLES/ShaderManagerGLES.cpp | 2 +- GPU/GLES/ShaderManagerGLES.h | 6 +++--- GPU/GLES/TextureCacheGLES.h | 4 ++-- GPU/GPUCommonHW.cpp | 6 +++++- GPU/Vulkan/GPU_Vulkan.cpp | 23 ++++++++------------ GPU/Vulkan/GPU_Vulkan.h | 1 - GPU/Vulkan/ShaderManagerVulkan.h | 4 ++-- GPU/Vulkan/TextureCacheVulkan.cpp | 8 ------- GPU/Vulkan/TextureCacheVulkan.h | 1 - GPU/Vulkan/VulkanUtil.cpp | 3 --- GPU/Vulkan/VulkanUtil.h | 1 - 23 files changed, 80 insertions(+), 87 deletions(-) diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 73f748003e..025576ea6f 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -126,8 +126,12 @@ public: ShaderManagerCommon(Draw::DrawContext *draw) : draw_(draw) {} virtual ~ShaderManagerCommon() {} + virtual void ClearShaders() = 0; virtual void DirtyLastShader() = 0; + virtual void DeviceLost() = 0; + virtual void DeviceRestore(Draw::DrawContext *draw) = 0; // must set draw_ to draw + protected: Draw::DrawContext *draw_ = nullptr; }; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 6611c21156..5a88a718b0 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -138,6 +138,10 @@ TextureCacheCommon::~TextureCacheCommon() { FreeAlignedMemory(expandClut_); } +void TextureCacheCommon::StartFrame() { + textureShaderCache_->Decimate(); +} + // Produces a signed 1.23.8 value. static int TexLog2(float delta) { union FloatBits { @@ -2906,7 +2910,3 @@ CheckAlphaResult TextureCacheCommon::CheckCLUTAlpha(const uint8_t *pixelData, GE return CheckAlpha32((const u32 *)pixelData, w, 0xFF000000); } } - -void TextureCacheCommon::StartFrame() { - textureShaderCache_->Decimate(); -} diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index f85e09b9a4..ec45251fa8 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -350,6 +350,11 @@ public: } virtual bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) { return false; } + virtual void StartFrame(); + + virtual void DeviceLost() = 0; + virtual void DeviceRestore(Draw::DrawContext *draw) = 0; + protected: virtual void *GetNativeTextureView(const TexCacheEntry *entry) = 0; bool PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEntry *entry); @@ -403,8 +408,6 @@ protected: virtual void BoundFramebufferTexture() {} - virtual void StartFrame(); - void DecimateVideos(); bool IsVideo(u32 texaddr) const; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index d20b36edbd..1b58db17c8 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -120,9 +120,9 @@ void GPU_D3D11::DeviceLost() { draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); // Simply drop all caches and textures. // FBOs appear to survive? Or no? - shaderManagerD3D11_->ClearShaders(); + shaderManager_->ClearShaders(); drawEngine_.ClearInputLayoutMap(); - textureCacheD3D11_->Clear(false); + textureCache_->Clear(false); GPUCommon::DeviceLost(); } @@ -141,19 +141,19 @@ void GPU_D3D11::InitClear() { void GPU_D3D11::BeginFrame() { GPUCommon::BeginFrame(); - textureCacheD3D11_->StartFrame(); + textureCache_->StartFrame(); drawEngine_.BeginFrame(); - shaderManagerD3D11_->DirtyLastShader(); + shaderManager_->DirtyLastShader(); - framebufferManagerD3D11_->BeginFrame(); + framebufferManager_->BeginFrame(); gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX); if (gstate_c.useFlagsChanged) { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); - shaderManagerD3D11_->ClearShaders(); + shaderManager_->ClearShaders(); framebufferManager_->ClearAllDepthBuffers(); drawEngine_.ClearInputLayoutMap(); gstate_c.useFlagsChanged = false; diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 75203f9533..5dacd408a5 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -86,9 +86,11 @@ public: ~ShaderManagerD3D11(); void GetShaders(int prim, VertexDecoder *decoder, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); - void ClearShaders(); + void ClearShaders() override; void DirtyLastShader() override; + void DeviceLost() override {} + void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 4cb01375ff..8c2ff77f62 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -54,6 +54,9 @@ public: bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; + void DeviceLost() override {} + void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 96ea5ae435..b857fcfa80 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -106,25 +106,20 @@ u32 GPU_DX9::CheckGPUFeatures() const { } GPU_DX9::~GPU_DX9() { - framebufferManagerDX9_->DestroyAllFBOs(); - delete framebufferManagerDX9_; + framebufferManager_->DestroyAllFBOs(); + delete framebufferManager_; delete textureCache_; - shaderManagerDX9_->ClearCache(true); - delete shaderManagerDX9_; + shaderManager_->ClearShaders(); + delete shaderManager_; } void GPU_DX9::DeviceLost() { // Simply drop all caches and textures. - shaderManagerDX9_->ClearCache(false); - textureCacheDX9_->Clear(false); + shaderManager_->ClearShaders(); + textureCache_->Clear(false); GPUCommon::DeviceLost(); } -void GPU_DX9::DeviceRestore() { - GPUCommon::DeviceRestore(); - // Nothing needed. -} - void GPU_DX9::InitClear() { if (!framebufferManager_->UseBufferedRendering()) { dxstate.depthWrite.set(true); @@ -139,7 +134,7 @@ void GPU_DX9::ReapplyGfxState() { } void GPU_DX9::BeginFrame() { - textureCacheDX9_->StartFrame(); + textureCache_->StartFrame(); drawEngine_.BeginFrame(); GPUCommon::BeginFrame(); @@ -151,7 +146,7 @@ void GPU_DX9::BeginFrame() { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); - shaderManagerDX9_->ClearCache(true); + shaderManager_->ClearShaders(); framebufferManager_->ClearAllDepthBuffers(); gstate_c.useFlagsChanged = false; } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 6d1001d90c..7e1132175e 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -40,7 +40,6 @@ public: void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. - void DeviceRestore() override; // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index 1571d517bd..dee68027b1 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -540,11 +540,10 @@ void ShaderManagerDX9::Clear() { DirtyShader(); } -void ShaderManagerDX9::ClearCache(bool deleteThem) { +void ShaderManagerDX9::ClearShaders() { Clear(); } - void ShaderManagerDX9::DirtyShader() { // Forget the last shader ID lastFSID_.set_invalid(); @@ -554,7 +553,7 @@ void ShaderManagerDX9::DirtyShader() { gstate_c.Dirty(DIRTY_ALL_UNIFORMS | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE); } -void ShaderManagerDX9::DirtyLastShader() { // disables vertex arrays +void ShaderManagerDX9::DirtyLastShader() { lastVShader_ = nullptr; lastPShader_ = nullptr; } diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 299eb677d2..a0ccce98ed 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -77,7 +77,7 @@ public: ShaderManagerDX9(Draw::DrawContext *draw, LPDIRECT3DDEVICE9 device); ~ShaderManagerDX9(); - void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected + void ClearShaders() override; VSShader *ApplyShader(bool useHWTransform, bool useHWTessellation, VertexDecoder *decoder, bool weightsAsFloat, bool useSkinInDecode, const ComputedPipelineState &pipelineState); void DirtyShader(); void DirtyLastShader() override; @@ -85,6 +85,9 @@ public: int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } + void DeviceLost() override {} + void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + std::vector DebugGetShaderIDs(DebugShaderType type); std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 0080fbdef3..8b2a9eaec8 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -42,6 +42,9 @@ public: bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; + void DeviceLost() override {} + void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + protected: void BindTexture(TexCacheEntry *entry) override; void Unbind() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 2cb6a88504..4d5abeadb7 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -139,17 +139,14 @@ GPU_GLES::~GPU_GLES() { } } - framebufferManagerGL_->DestroyAllFBOs(); - shaderManagerGL_->ClearCache(true); + framebufferManager_->DestroyAllFBOs(); + shaderManager_->ClearShaders(); fragmentTestCache_.Clear(); - delete shaderManagerGL_; - shaderManagerGL_ = nullptr; - delete framebufferManagerGL_; - delete textureCacheGL_; - - // Clear features so they're not visible in system info. - gstate_c.SetUseFlags(0); + delete shaderManager_; + shaderManager_ = nullptr; + delete framebufferManager_; + delete textureCache_; } // Take the raw GL extension and versioning data and turn into feature flags. @@ -249,8 +246,8 @@ void GPU_GLES::DeviceLost() { // FBOs appear to survive? Or no? // TransformDraw has registered as a GfxResourceHolder. CancelReady(); - shaderManagerGL_->DeviceLost(); - textureCacheGL_->DeviceLost(); + shaderManager_->DeviceLost(); + textureCache_->DeviceLost(); fragmentTestCache_.DeviceLost(); drawEngine_.DeviceLost(); @@ -263,8 +260,8 @@ void GPU_GLES::DeviceRestore() { UpdateCmdInfo(); UpdateVsyncInterval(true); - shaderManagerGL_->DeviceRestore(draw_); - textureCacheGL_->DeviceRestore(draw_); + shaderManager_->DeviceRestore(draw_); + textureCache_->DeviceRestore(draw_); drawEngine_.DeviceRestore(draw_); fragmentTestCache_.DeviceRestore(draw_); } @@ -284,7 +281,7 @@ void GPU_GLES::BeginHostFrame() { // TODO: It'd be better to recompile them in the background, probably? // This most likely means that saw equal depth changed. WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); - shaderManagerGL_->ClearCache(true); + shaderManager_->ClearShaders(); framebufferManager_->ClearAllDepthBuffers(); gstate_c.useFlagsChanged = false; } @@ -299,22 +296,22 @@ void GPU_GLES::ReapplyGfxState() { } void GPU_GLES::BeginFrame() { - textureCacheGL_->StartFrame(); - fragmentTestCache_.Decimate(); - GPUCommon::BeginFrame(); + textureCache_->StartFrame(); + // Save the cache from time to time. TODO: How often? We save on exit, so shouldn't need to do this all that often. if (shaderCachePath_.Valid() && (gpuStats.numFlips & 4095) == 0) { shaderManagerGL_->SaveCache(shaderCachePath_, &drawEngine_); } - shaderManagerGL_->DirtyShader(); // Not sure if this is really needed. gstate_c.Dirty(DIRTY_ALL_UNIFORMS); - framebufferManagerGL_->BeginFrame(); + framebufferManager_->BeginFrame(); + + fragmentTestCache_.Decimate(); } void GPU_GLES::FinishDeferred() { diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index d80cfb494f..e050b9381a 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -715,7 +715,7 @@ void ShaderManagerGLES::Clear() { DirtyShader(); } -void ShaderManagerGLES::ClearCache(bool deleteThem) { +void ShaderManagerGLES::ClearShaders() { // TODO: Recreate all from the diskcache when we come back. Clear(); } diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index b37604ba5d..6435b44d7d 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -165,15 +165,15 @@ public: ShaderManagerGLES(Draw::DrawContext *draw); ~ShaderManagerGLES(); - void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected + void ClearShaders() override; // This is the old ApplyShader split into two parts, because of annoying information dependencies. // If you call ApplyVertexShader, you MUST call ApplyFragmentShader soon afterwards. Shader *ApplyVertexShader(bool useHWTransform, bool useHWTessellation, VertexDecoder *vertexDecoder, bool weightsAsFloat, bool useSkinInDecode, VShaderID *VSID); LinkedShader *ApplyFragmentShader(VShaderID VSID, Shader *vs, const ComputedPipelineState &pipelineState, bool useBufferedRendering); - void DeviceLost(); - void DeviceRestore(Draw::DrawContext *draw); + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void DirtyShader(); void DirtyLastShader() override; diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 2546c605b9..6f90475ed1 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -54,8 +54,8 @@ public: bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; - void DeviceLost(); - void DeviceRestore(Draw::DrawContext *draw); + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; protected: void BindTexture(TexCacheEntry *entry) override; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 6c98d9f44c..8f587d6f77 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -10,7 +10,11 @@ #include "GPU/Common/FramebufferManagerCommon.h" GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) {} -GPUCommonHW::~GPUCommonHW() {} + +GPUCommonHW::~GPUCommonHW() { + // Clear features so they're not visible in system info. + gstate_c.SetUseFlags(0); +} void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index faed3b7e4c..11d7b562cc 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -187,10 +187,10 @@ GPU_Vulkan::~GPU_Vulkan() { DestroyDeviceObjects(); framebufferManagerVulkan_->DestroyAllFBOs(); drawEngine_.DeviceLost(); - delete textureCacheVulkan_; + delete textureCache_; delete pipelineManager_; - delete shaderManagerVulkan_; - delete framebufferManagerVulkan_; + delete shaderManager_; + delete framebufferManager_; } u32 GPU_Vulkan::CheckGPUFeatures() const { @@ -292,7 +292,7 @@ void GPU_Vulkan::BeginHostFrame() { GPUCommon::BeginHostFrame(); drawEngine_.BeginFrame(); - textureCacheVulkan_->StartFrame(); + textureCache_->StartFrame(); VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); int curFrame = vulkan->GetCurFrame(); @@ -301,7 +301,7 @@ void GPU_Vulkan::BeginHostFrame() { frame.push_->Reset(); frame.push_->Begin(vulkan); - framebufferManagerVulkan_->BeginFrame(); + framebufferManager_->BeginFrame(); textureCacheVulkan_->SetPushBuffer(frameData_[curFrame].push_); shaderManagerVulkan_->DirtyShader(); @@ -313,7 +313,7 @@ void GPU_Vulkan::BeginHostFrame() { WARN_LOG(G3D, "Shader use flags changed, clearing all shaders and depth buffers"); // TODO: Not all shaders need to be recompiled. In fact, quite few? Of course, depends on // the use flag change.. This is a major frame rate hitch in the start of a race in Outrun. - shaderManagerVulkan_->ClearShaders(); + shaderManager_->ClearShaders(); pipelineManager_->Clear(); framebufferManager_->ClearAllDepthBuffers(); gstate_c.useFlagsChanged = false; @@ -335,7 +335,6 @@ void GPU_Vulkan::EndHostFrame() { frame.push_->End(); drawEngine_.EndFrame(); - textureCacheVulkan_->EndFrame(); GPUCommon::EndHostFrame(); } @@ -391,10 +390,6 @@ void GPU_Vulkan::BuildReportingInfo() { Reporting::UpdateConfig(); } -void GPU_Vulkan::Reinitialize() { - GPUCommon::Reinitialize(); -} - void GPU_Vulkan::InitClear() { if (!framebufferManager_->UseBufferedRendering()) { // TODO? @@ -450,8 +445,8 @@ void GPU_Vulkan::DestroyDeviceObjects() { } void GPU_Vulkan::CheckRenderResized() { + GPUCommon::CheckRenderResized(); if (renderResized_) { - GPUCommon::CheckRenderResized(); pipelineManager_->InvalidateMSAAPipelines(); framebufferManager_->ReleasePipelines(); } @@ -471,11 +466,11 @@ void GPU_Vulkan::DeviceLost() { textureCacheVulkan_->DeviceLost(); shaderManagerVulkan_->DeviceLost(); - GPUCommon::DeviceLost(); + GPUCommonHW::DeviceLost(); } void GPU_Vulkan::DeviceRestore() { - GPUCommon::DeviceRestore(); + GPUCommonHW::DeviceRestore(); InitDeviceObjects(); gstate_c.SetUseFlags(CheckGPUFeatures()); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index f468ec8b68..6892eafa58 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -68,7 +68,6 @@ protected: private: void BuildReportingInfo() override; void InitClear() override; - void Reinitialize() override; void InitDeviceObjects(); void DestroyDeviceObjects(); diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 91544124f3..a29ea06be3 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -114,8 +114,8 @@ public: ShaderManagerVulkan(Draw::DrawContext *draw); ~ShaderManagerVulkan(); - void DeviceLost(); - void DeviceRestore(Draw::DrawContext *draw); + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void GetShaders(int prim, VertexDecoder *decoder, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); void ClearShaders(); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 349d608c3a..da69158dc3 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -352,14 +352,6 @@ void TextureCacheVulkan::StartFrame() { computeShaderManager_.BeginFrame(); } -void TextureCacheVulkan::EndFrame() { - computeShaderManager_.EndFrame(); - - if (texelsScaledThisFrame_) { - VERBOSE_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_); - } -} - void TextureCacheVulkan::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { const u32 clutBaseBytes = clutFormat == GE_CMODE_32BIT_ABGR8888 ? (clutBase * sizeof(u32)) : (clutBase * sizeof(u16)); // Technically, these extra bytes weren't loaded, but hopefully it was loaded earlier. diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 3654101b90..2c7c149ef6 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -58,7 +58,6 @@ public: ~TextureCacheVulkan(); void StartFrame() override; - void EndFrame(); void DeviceLost(); void DeviceRestore(Draw::DrawContext *draw); diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index c47fd21d9c..0d87ebc153 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -208,6 +208,3 @@ void VulkanComputeShaderManager::BeginFrame() { FrameData &frame = frameData_[curFrame]; frame.descPool.Reset(); } - -void VulkanComputeShaderManager::EndFrame() { -} diff --git a/GPU/Vulkan/VulkanUtil.h b/GPU/Vulkan/VulkanUtil.h index 8663d3ce1e..2046f6201f 100644 --- a/GPU/Vulkan/VulkanUtil.h +++ b/GPU/Vulkan/VulkanUtil.h @@ -61,7 +61,6 @@ public: VkPipelineLayout GetPipelineLayout() const { return pipelineLayout_; } void BeginFrame(); - void EndFrame(); private: void InitDeviceObjects(Draw::DrawContext *draw); From 8ba665e2586ca9b13b228eb4b0c57f88ec5c89b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:12:24 +0100 Subject: [PATCH 159/424] More unification work --- GPU/D3D11/GPU_D3D11.cpp | 13 ++++--------- GPU/Directx9/GPU_DX9.cpp | 18 ++++-------------- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 26 ++++++-------------------- GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommonHW.cpp | 14 ++++++++++++++ GPU/GPUCommonHW.h | 1 + GPU/Vulkan/GPU_Vulkan.cpp | 17 +++++++---------- GPU/Vulkan/TextureCacheVulkan.cpp | 1 - 9 files changed, 36 insertions(+), 56 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 1b58db17c8..c0b419184a 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -87,16 +87,11 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } GPU_D3D11::~GPU_D3D11() { - framebufferManagerD3D11_->DestroyAllFBOs(); - delete framebufferManagerD3D11_; - shaderManagerD3D11_->ClearShaders(); - delete shaderManagerD3D11_; - delete textureCacheD3D11_; stockD3D11.Destroy(); } u32 GPU_D3D11::CheckGPUFeatures() const { - u32 features = GPUCommon::CheckGPUFeatures(); + u32 features = GPUCommonHW::CheckGPUFeatures(); // Accurate depth is required because the Direct3D API does not support inverse Z. // So we cannot incorrectly use the viewport transform as the depth range on Direct3D. @@ -124,11 +119,11 @@ void GPU_D3D11::DeviceLost() { drawEngine_.ClearInputLayoutMap(); textureCache_->Clear(false); - GPUCommon::DeviceLost(); + GPUCommonHW::DeviceLost(); } void GPU_D3D11::DeviceRestore() { - GPUCommon::DeviceRestore(); + GPUCommonHW::DeviceRestore(); // Nothing needed. } @@ -139,7 +134,7 @@ void GPU_D3D11::InitClear() { } void GPU_D3D11::BeginFrame() { - GPUCommon::BeginFrame(); + GPUCommonHW::BeginFrame(); textureCache_->StartFrame(); drawEngine_.BeginFrame(); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index b857fcfa80..a95c6155fd 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -94,7 +94,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw) } u32 GPU_DX9::CheckGPUFeatures() const { - u32 features = GPUCommon::CheckGPUFeatures(); + u32 features = GPUCommonHW::CheckGPUFeatures(); features |= GPU_USE_16BIT_FORMATS; features |= GPU_USE_TEXTURE_LOD_CONTROL; @@ -105,19 +105,9 @@ u32 GPU_DX9::CheckGPUFeatures() const { return CheckGPUFeaturesLate(features); } -GPU_DX9::~GPU_DX9() { - framebufferManager_->DestroyAllFBOs(); - delete framebufferManager_; - delete textureCache_; - shaderManager_->ClearShaders(); - delete shaderManager_; -} - void GPU_DX9::DeviceLost() { // Simply drop all caches and textures. - shaderManager_->ClearShaders(); - textureCache_->Clear(false); - GPUCommon::DeviceLost(); + GPUCommonHW::DeviceLost(); } void GPU_DX9::InitClear() { @@ -130,14 +120,14 @@ void GPU_DX9::InitClear() { void GPU_DX9::ReapplyGfxState() { dxstate.Restore(); - GPUCommon::ReapplyGfxState(); + GPUCommonHW::ReapplyGfxState(); } void GPU_DX9::BeginFrame() { textureCache_->StartFrame(); drawEngine_.BeginFrame(); - GPUCommon::BeginFrame(); + GPUCommonHW::BeginFrame(); shaderManagerDX9_->DirtyShader(); framebufferManager_->BeginFrame(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 7e1132175e..eda85cb387 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -33,7 +33,6 @@ class TextureCacheDX9; class GPU_DX9 : public GPUCommonHW { public: GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw); - ~GPU_DX9(); u32 CheckGPUFeatures() const override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 4d5abeadb7..6bf1046764 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -138,22 +138,14 @@ GPU_GLES::~GPU_GLES() { INFO_LOG(G3D, "Shader cache disabled. Not saving."); } } - - framebufferManager_->DestroyAllFBOs(); - shaderManager_->ClearShaders(); fragmentTestCache_.Clear(); - - delete shaderManager_; - shaderManager_ = nullptr; - delete framebufferManager_; - delete textureCache_; } // Take the raw GL extension and versioning data and turn into feature flags. // TODO: This should use DrawContext::GetDeviceCaps() more and more, and eventually // this can be shared between all the backends. u32 GPU_GLES::CheckGPUFeatures() const { - u32 features = GPUCommon::CheckGPUFeatures(); + u32 features = GPUCommonHW::CheckGPUFeatures(); features |= GPU_USE_16BIT_FORMATS; @@ -246,16 +238,14 @@ void GPU_GLES::DeviceLost() { // FBOs appear to survive? Or no? // TransformDraw has registered as a GfxResourceHolder. CancelReady(); - shaderManager_->DeviceLost(); - textureCache_->DeviceLost(); fragmentTestCache_.DeviceLost(); drawEngine_.DeviceLost(); - GPUCommon::DeviceLost(); + GPUCommonHW::DeviceLost(); } void GPU_GLES::DeviceRestore() { - GPUCommon::DeviceRestore(); + GPUCommonHW::DeviceRestore(); UpdateCmdInfo(); UpdateVsyncInterval(true); @@ -266,15 +256,11 @@ void GPU_GLES::DeviceRestore() { fragmentTestCache_.DeviceRestore(draw_); } -void GPU_GLES::Reinitialize() { - GPUCommon::Reinitialize(); -} - void GPU_GLES::InitClear() { } void GPU_GLES::BeginHostFrame() { - GPUCommon::BeginHostFrame(); + GPUCommonHW::BeginHostFrame(); drawEngine_.BeginFrame(); if (gstate_c.useFlagsChanged) { @@ -292,11 +278,11 @@ void GPU_GLES::EndHostFrame() { } void GPU_GLES::ReapplyGfxState() { - GPUCommon::ReapplyGfxState(); + GPUCommonHW::ReapplyGfxState(); } void GPU_GLES::BeginFrame() { - GPUCommon::BeginFrame(); + GPUCommonHW::BeginFrame(); textureCache_->StartFrame(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 912c253188..4ab375840a 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -64,7 +64,6 @@ private: void InitClear() override; void BeginFrame() override; - void Reinitialize() override; FramebufferManagerGLES *framebufferManagerGL_; TextureCacheGLES *textureCacheGL_; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 8f587d6f77..0ab31d9cbd 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -14,6 +14,20 @@ GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPU GPUCommonHW::~GPUCommonHW() { // Clear features so they're not visible in system info. gstate_c.SetUseFlags(0); + + // Delete the various common managers. + framebufferManager_->DestroyAllFBOs(); + delete framebufferManager_; + delete textureCache_; + shaderManager_->ClearShaders(); + delete shaderManager_; +} + +void GPUCommonHW::DeviceLost() { + textureCache_->Clear(false); + framebufferManager_->DeviceLost(); + textureCache_->DeviceLost(); + shaderManager_->DeviceLost(); } void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 924a60c5f4..a427f27963 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -11,6 +11,7 @@ public: void CopyDisplayToOutput(bool reallyDirty) override; void DoState(PointerWrap &p) override; + void DeviceLost() override; protected: void PreExecuteOp(u32 op, u32 diff); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 11d7b562cc..ffe2e61755 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -185,16 +185,15 @@ GPU_Vulkan::~GPU_Vulkan() { SaveCache(shaderCachePath_); // Note: We save the cache in DeviceLost DestroyDeviceObjects(); - framebufferManagerVulkan_->DestroyAllFBOs(); drawEngine_.DeviceLost(); - delete textureCache_; + shaderManager_->ClearShaders(); + delete pipelineManager_; - delete shaderManager_; - delete framebufferManager_; + // other managers are deleted in ~GPUCommonHW. } u32 GPU_Vulkan::CheckGPUFeatures() const { - uint32_t features = GPUCommon::CheckGPUFeatures(); + uint32_t features = GPUCommonHW::CheckGPUFeatures(); VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); switch (vulkan->GetPhysicalDeviceProperties().properties.vendorID) { @@ -289,7 +288,7 @@ u32 GPU_Vulkan::CheckGPUFeatures() const { } void GPU_Vulkan::BeginHostFrame() { - GPUCommon::BeginHostFrame(); + GPUCommonHW::BeginHostFrame(); drawEngine_.BeginFrame(); textureCache_->StartFrame(); @@ -336,7 +335,7 @@ void GPU_Vulkan::EndHostFrame() { drawEngine_.EndFrame(); - GPUCommon::EndHostFrame(); + GPUCommonHW::EndHostFrame(); } // Needs to be called on GPU thread, not reporting thread. @@ -445,7 +444,7 @@ void GPU_Vulkan::DestroyDeviceObjects() { } void GPU_Vulkan::CheckRenderResized() { - GPUCommon::CheckRenderResized(); + GPUCommonHW::CheckRenderResized(); if (renderResized_) { pipelineManager_->InvalidateMSAAPipelines(); framebufferManager_->ReleasePipelines(); @@ -463,8 +462,6 @@ void GPU_Vulkan::DeviceLost() { DestroyDeviceObjects(); drawEngine_.DeviceLost(); pipelineManager_->DeviceLost(); - textureCacheVulkan_->DeviceLost(); - shaderManagerVulkan_->DeviceLost(); GPUCommonHW::DeviceLost(); } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index da69158dc3..d47ed1ee2d 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -217,7 +217,6 @@ void TextureCacheVulkan::DeviceLost() { Clear(true); samplerCache_.DeviceLost(); - if (samplerNearest_) vulkan->Delete().QueueDeleteSampler(samplerNearest_); From 9d6c3c329e0511a25f55cea9238c345492663461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:13:54 +0100 Subject: [PATCH 160/424] Move CheckGPUFeatures() to GPUCommonHW --- GPU/GPUCommon.cpp | 64 -------------------------------------------- GPU/GPUCommon.h | 2 +- GPU/GPUCommonHW.cpp | 65 +++++++++++++++++++++++++++++++++++++++++++++ GPU/GPUCommonHW.h | 2 ++ 4 files changed, 68 insertions(+), 65 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 6d650e3d26..780610ac6b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -3464,70 +3464,6 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { ); } -u32 GPUCommon::CheckGPUFeatures() const { - u32 features = 0; - if (draw_->GetDeviceCaps().logicOpSupported) { - features |= GPU_USE_LOGIC_OP; - } - if (draw_->GetDeviceCaps().anisoSupported) { - features |= GPU_USE_ANISOTROPY; - } - if (draw_->GetDeviceCaps().textureNPOTFullySupported) { - features |= GPU_USE_TEXTURE_NPOT; - } - if (draw_->GetDeviceCaps().dualSourceBlend) { - if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { - features |= GPU_USE_DUALSOURCE_BLEND; - } - } - if (draw_->GetDeviceCaps().blendMinMaxSupported) { - features |= GPU_USE_BLEND_MINMAX; - } - - if (draw_->GetDeviceCaps().clipDistanceSupported) { - features |= GPU_USE_CLIP_DISTANCE; - } - - if (draw_->GetDeviceCaps().cullDistanceSupported) { - features |= GPU_USE_CULL_DISTANCE; - } - - if (draw_->GetDeviceCaps().textureDepthSupported) { - features |= GPU_USE_DEPTH_TEXTURE; - } - - if (draw_->GetDeviceCaps().depthClampSupported) { - // Some backends always do GPU_USE_ACCURATE_DEPTH, but it's required for depth clamp. - features |= GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH; - } - - bool canClipOrCull = draw_->GetDeviceCaps().clipDistanceSupported || draw_->GetDeviceCaps().cullDistanceSupported; - bool canDiscardVertex = !draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL); - if (canClipOrCull || canDiscardVertex) { - // We'll dynamically use the parts that are supported, to reduce artifacts as much as possible. - features |= GPU_USE_VS_RANGE_CULLING; - } - - if (draw_->GetDeviceCaps().framebufferFetchSupported) { - features |= GPU_USE_FRAMEBUFFER_FETCH; - } - - if (draw_->GetShaderLanguageDesc().bitwiseOps) { - features |= GPU_USE_LIGHT_UBERSHADER; - } - - if (PSP_CoreParameter().compat.flags().ClearToRAM) { - features |= GPU_USE_CLEAR_RAM_HACK; - } - - // Even without depth clamp, force accurate depth on for some games that break without it. - if (PSP_CoreParameter().compat.flags().DepthRangeHack) { - features |= GPU_USE_ACCURATE_DEPTH; - } - - return features; -} - u32 GPUCommon::CheckGPUFeaturesLate(u32 features) const { // If we already have a 16-bit depth buffer, we don't need to round. bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 98905a4f0b..0c614d9310 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -76,7 +76,7 @@ public: Draw::DrawContext *GetDrawContext() override { return draw_; } - virtual u32 CheckGPUFeatures() const; + virtual u32 CheckGPUFeatures() const = 0; void CheckDisplayResized() override; void CheckConfigChanged() override; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 0ab31d9cbd..666f41d5db 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -3,6 +3,7 @@ #include "Common/System/System.h" #include "Core/System.h" +#include "Core/Config.h" #include "GPU/GPUCommonHW.h" #include "GPU/Common/DrawEngineCommon.h" @@ -70,3 +71,67 @@ void GPUCommonHW::BuildReportingInfo() { reportingPrimaryInfo_ = draw_->GetInfoString(InfoField::VENDORSTRING); reportingFullInfo_ = reportingPrimaryInfo_ + " - " + System_GetProperty(SYSPROP_GPUDRIVER_VERSION) + " - " + draw_->GetInfoString(InfoField::SHADELANGVERSION); } + +u32 GPUCommonHW::CheckGPUFeatures() const { + u32 features = 0; + if (draw_->GetDeviceCaps().logicOpSupported) { + features |= GPU_USE_LOGIC_OP; + } + if (draw_->GetDeviceCaps().anisoSupported) { + features |= GPU_USE_ANISOTROPY; + } + if (draw_->GetDeviceCaps().textureNPOTFullySupported) { + features |= GPU_USE_TEXTURE_NPOT; + } + if (draw_->GetDeviceCaps().dualSourceBlend) { + if (!g_Config.bVendorBugChecksEnabled || !draw_->GetBugs().Has(Draw::Bugs::DUAL_SOURCE_BLENDING_BROKEN)) { + features |= GPU_USE_DUALSOURCE_BLEND; + } + } + if (draw_->GetDeviceCaps().blendMinMaxSupported) { + features |= GPU_USE_BLEND_MINMAX; + } + + if (draw_->GetDeviceCaps().clipDistanceSupported) { + features |= GPU_USE_CLIP_DISTANCE; + } + + if (draw_->GetDeviceCaps().cullDistanceSupported) { + features |= GPU_USE_CULL_DISTANCE; + } + + if (draw_->GetDeviceCaps().textureDepthSupported) { + features |= GPU_USE_DEPTH_TEXTURE; + } + + if (draw_->GetDeviceCaps().depthClampSupported) { + // Some backends always do GPU_USE_ACCURATE_DEPTH, but it's required for depth clamp. + features |= GPU_USE_DEPTH_CLAMP | GPU_USE_ACCURATE_DEPTH; + } + + bool canClipOrCull = draw_->GetDeviceCaps().clipDistanceSupported || draw_->GetDeviceCaps().cullDistanceSupported; + bool canDiscardVertex = !draw_->GetBugs().Has(Draw::Bugs::BROKEN_NAN_IN_CONDITIONAL); + if (canClipOrCull || canDiscardVertex) { + // We'll dynamically use the parts that are supported, to reduce artifacts as much as possible. + features |= GPU_USE_VS_RANGE_CULLING; + } + + if (draw_->GetDeviceCaps().framebufferFetchSupported) { + features |= GPU_USE_FRAMEBUFFER_FETCH; + } + + if (draw_->GetShaderLanguageDesc().bitwiseOps) { + features |= GPU_USE_LIGHT_UBERSHADER; + } + + if (PSP_CoreParameter().compat.flags().ClearToRAM) { + features |= GPU_USE_CLEAR_RAM_HACK; + } + + // Even without depth clamp, force accurate depth on for some games that break without it. + if (PSP_CoreParameter().compat.flags().DepthRangeHack) { + features |= GPU_USE_ACCURATE_DEPTH; + } + + return features; +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index a427f27963..5e258027e8 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -13,6 +13,8 @@ public: void DoState(PointerWrap &p) override; void DeviceLost() override; + u32 CheckGPUFeatures() const override; + protected: void PreExecuteOp(u32 op, u32 diff); void ClearCacheNextFrame() override; From 8b54a14bf2302c2d1edff5d281de0bd865a51bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:20:34 +0100 Subject: [PATCH 161/424] Move the big command table to where it belongs, GPUCommonHW --- GPU/GPUCommon.cpp | 393 +--------------------------------------- GPU/GPUCommon.h | 2 +- GPU/GPUCommonHW.cpp | 395 ++++++++++++++++++++++++++++++++++++++++- GPU/GPUCommonHW.h | 2 + GPU/Software/SoftGpu.h | 1 + 5 files changed, 399 insertions(+), 394 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 780610ac6b..f48661000f 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -49,329 +49,6 @@ #include "GPU/Debugger/Debugger.h" #include "GPU/Debugger/Record.h" -const CommonCommandTableEntry commonCommandTable[] = { - // From Common. No flushing but definitely need execute. - { GE_CMD_OFFSETADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_OffsetAddr }, - { GE_CMD_ORIGIN, FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommon::Execute_Origin }, - { GE_CMD_JUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_Jump }, - { GE_CMD_CALL, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_Call }, - { GE_CMD_RET, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_Ret }, - { GE_CMD_END, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_End }, - { GE_CMD_VADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_Vaddr }, - { GE_CMD_IADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_Iaddr }, - { GE_CMD_BJUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BJump }, // EXECUTE - { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoundingBox }, // Shouldn't need to FLUSHBEFORE. - - { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPUCommon::Execute_Prim }, - { GE_CMD_BEZIER, FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, - { GE_CMD_SPLINE, FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, - - // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, - - { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_LoadClut }, - - // These two are actually processed in CMD_END. - { GE_CMD_SIGNAL }, - { GE_CMD_FINISH }, - - // Changes that dirty the framebuffer - { GE_CMD_FRAMEBUFPTR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS }, - { GE_CMD_FRAMEBUFWIDTH, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - { GE_CMD_FRAMEBUFPIXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_ZBUFPTR, FLAG_FLUSHBEFOREONCHANGE }, - { GE_CMD_ZBUFWIDTH, FLAG_FLUSHBEFOREONCHANGE }, - - { GE_CMD_FOGCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOLOR }, - { GE_CMD_FOG1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEFENABLE }, - { GE_CMD_FOG2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEFENABLE }, - - // These affect the fragment shader so need flushing. - { GE_CMD_CLEARMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, - { GE_CMD_TEXTUREMAPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, - { GE_CMD_FOGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEFENABLE }, - { GE_CMD_TEXMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_TEXSHADELS, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - // Raster state for Direct3D 9, uncommon. - { GE_CMD_SHADEMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_RASTER_STATE }, - { GE_CMD_TEXFUNC, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEX_ALPHA_MUL }, - { GE_CMD_COLORTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_ALPHATESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_COLORTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_COLORTESTMASK, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORMASK | DIRTY_FRAGMENTSHADER_STATE }, - - // These change the vertex shader so need flushing. - { GE_CMD_REVERSENORMAL, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_LIGHTINGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, - { GE_CMD_LIGHTENABLE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_LIGHTENABLE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_LIGHTENABLE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_LIGHTENABLE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_LIGHTTYPE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT0 }, - { GE_CMD_LIGHTTYPE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT1 }, - { GE_CMD_LIGHTTYPE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT2 }, - { GE_CMD_LIGHTTYPE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT3 }, - { GE_CMD_MATERIALUPDATE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - - // These change vertex shaders (in non uber shader mode) so need flushing. - { GE_CMD_LIGHTMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - - { GE_CMD_TEXFILTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXWRAP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE }, - - // Uniform changes. though the fragmentshader optimizes based on these sometimes. - { GE_CMD_ALPHATEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORREF | DIRTY_ALPHACOLORMASK | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_COLORREF, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORREF | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_TEXENVCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXENV }, - - // Simple render state changes. Handled in StateMapping.cpp. - { GE_CMD_CULL, FLAG_FLUSHBEFOREONCHANGE, DIRTY_RASTER_STATE }, - { GE_CMD_CULLFACEENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_RASTER_STATE }, - { GE_CMD_DITHERENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_RASTER_STATE }, - { GE_CMD_STENCILOP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_STENCILTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_STENCILREPLACEVALUE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE }, - { GE_CMD_STENCILTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_ALPHABLENDENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_BLENDMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_BLENDFIXEDA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_BLENDFIXEDB, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_MASKRGB, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_COLORWRITEMASK }, - { GE_CMD_MASKALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_COLORWRITEMASK }, - { GE_CMD_ZTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE }, - { GE_CMD_ZTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_ZWRITEDISABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_LOGICOP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, - { GE_CMD_LOGICOPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, - - { GE_CMD_TEXMAPMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE }, - - // These are read on every SubmitPrim, no need for dirtying or flushing. - { GE_CMD_TEXSCALEU }, - { GE_CMD_TEXSCALEV }, - { GE_CMD_TEXOFFSETU }, - { GE_CMD_TEXOFFSETV }, - - { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, - { GE_CMD_TEXSIZE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXSIZE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXSIZE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXSIZE4, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXSIZE5, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXSIZE6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXSIZE7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, - { GE_CMD_TEXLEVEL, FLAG_EXECUTEONCHANGE, DIRTY_TEXTURE_PARAMS, &GPUCommon::Execute_TexLevel }, - { GE_CMD_TEXLODSLOPE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE | DIRTY_UVSCALEOFFSET }, - { GE_CMD_TEXADDR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR4, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR5, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXADDR7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, - { GE_CMD_TEXBUFWIDTH1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH4, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH5, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - { GE_CMD_TEXBUFWIDTH7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, - - // These must flush on change, so that LoadClut doesn't have to always flush. - { GE_CMD_CLUTADDR, FLAG_FLUSHBEFOREONCHANGE }, - { GE_CMD_CLUTADDRUPPER, FLAG_FLUSHBEFOREONCHANGE }, - { GE_CMD_CLUTFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_DEPAL }, - - // Morph weights. TODO: Remove precomputation? - { GE_CMD_MORPHWEIGHT0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT1, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT2, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT3, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT4, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT5, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT6, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - { GE_CMD_MORPHWEIGHT7, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, - - // Control spline/bezier patches. Don't really require flushing as such, but meh. - { GE_CMD_PATCHDIVISION, FLAG_FLUSHBEFOREONCHANGE }, - { GE_CMD_PATCHPRIMITIVE, FLAG_FLUSHBEFOREONCHANGE }, - { GE_CMD_PATCHFACING, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, - { GE_CMD_PATCHCULLENABLE, FLAG_FLUSHBEFOREONCHANGE }, - - // Can probably ignore this one as we don't support AA lines. - { GE_CMD_ANTIALIASENABLE, FLAG_FLUSHBEFOREONCHANGE }, - - // Viewport. - { GE_CMD_OFFSETX, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - { GE_CMD_OFFSETY, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - { GE_CMD_VIEWPORTXSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_VIEWPORTYSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_VIEWPORTXCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_VIEWPORTZSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_VIEWPORTZCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, - { GE_CMD_DEPTHCLAMPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_RASTER_STATE }, - - // Z clip - { GE_CMD_MINZ, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHRANGE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - { GE_CMD_MAXZ, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHRANGE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - - // Region - { GE_CMD_REGION1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - { GE_CMD_REGION2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - - // Scissor - { GE_CMD_SCISSOR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - { GE_CMD_SCISSOR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, - - // Lighting base colors - { GE_CMD_AMBIENTCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_AMBIENT }, - { GE_CMD_AMBIENTALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_AMBIENT }, - { GE_CMD_MATERIALDIFFUSE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATDIFFUSE }, - { GE_CMD_MATERIALEMISSIVE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATEMISSIVE }, - { GE_CMD_MATERIALAMBIENT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATAMBIENTALPHA }, - { GE_CMD_MATERIALALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATAMBIENTALPHA }, - { GE_CMD_MATERIALSPECULAR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATSPECULAR }, - { GE_CMD_MATERIALSPECULARCOEF, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATSPECULAR }, - - // Light parameters - { GE_CMD_LX0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LY0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LZ0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LX1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LY1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LZ1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LX2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LY2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LZ2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LX3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LY3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LZ3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - - { GE_CMD_LDX0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LDY0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LDZ0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LDX1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LDY1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LDZ1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LDX2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LDY2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LDZ2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LDX3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LDY3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LDZ3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - - { GE_CMD_LKA0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LKB0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LKC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LKA1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LKB1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LKC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LKA2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LKB2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LKC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LKA3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LKB3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LKC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - - { GE_CMD_LKS0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LKS1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LKS2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LKS3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - - { GE_CMD_LKO0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LKO1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LKO2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LKO3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - - { GE_CMD_LAC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LDC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LSC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, - { GE_CMD_LAC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LDC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LSC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, - { GE_CMD_LAC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LDC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LSC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, - { GE_CMD_LAC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LDC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - { GE_CMD_LSC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, - - // Ignored commands - { GE_CMD_TEXFLUSH, 0 }, - { GE_CMD_TEXSYNC, 0 }, - - // These are just nop or part of other later commands. - { GE_CMD_NOP, 0 }, - { GE_CMD_BASE, 0 }, - { GE_CMD_TRANSFERSRC, 0 }, - { GE_CMD_TRANSFERSRCW, 0 }, - { GE_CMD_TRANSFERDST, 0 }, - { GE_CMD_TRANSFERDSTW, 0 }, - { GE_CMD_TRANSFERSRCPOS, 0 }, - { GE_CMD_TRANSFERDSTPOS, 0 }, - { GE_CMD_TRANSFERSIZE, 0 }, - { GE_CMD_TRANSFERSTART, FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommon::Execute_BlockTransferStart }, - - // We don't use the dither table. - { GE_CMD_DITH0 }, - { GE_CMD_DITH1 }, - { GE_CMD_DITH2 }, - { GE_CMD_DITH3 }, - - // These handle their own flushing. - { GE_CMD_WORLDMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_WorldMtxNum }, - { GE_CMD_WORLDMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_WorldMtxData }, - { GE_CMD_VIEWMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_ViewMtxNum }, - { GE_CMD_VIEWMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_ViewMtxData }, - { GE_CMD_PROJMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_ProjMtxNum }, - { GE_CMD_PROJMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_ProjMtxData }, - { GE_CMD_TGENMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_TgenMtxNum }, - { GE_CMD_TGENMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_TgenMtxData }, - { GE_CMD_BONEMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BoneMtxNum }, - { GE_CMD_BONEMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoneMtxData }, - - // Vertex Screen/Texture/Color - { GE_CMD_VSCX }, - { GE_CMD_VSCY }, - { GE_CMD_VSCZ }, - { GE_CMD_VTCS }, - { GE_CMD_VTCT }, - { GE_CMD_VTCQ }, - { GE_CMD_VCV }, - { GE_CMD_VAP, FLAG_EXECUTE, 0, &GPUCommon::Execute_ImmVertexAlphaPrim }, - { GE_CMD_VFC }, - { GE_CMD_VSCV }, - - // "Missing" commands (gaps in the sequence) - { GE_CMD_UNKNOWN_03, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_0D, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_11, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_29, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_34, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_35, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_39, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_4E, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_4F, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_52, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_59, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_5A, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_B6, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_B7, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_D1, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_ED, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_EF, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_FA, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_FB, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_FC, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_FD, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - { GE_CMD_UNKNOWN_FE, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, - // Appears to be debugging related or something? Hit a lot in GoW. - { GE_CMD_NOP_FF, 0 }, -}; - // TODO: Make class member? GPUCommon::CommandInfo GPUCommon::cmdInfo_[256]; @@ -398,32 +75,6 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : gstate_c.Reset(); gpuStats.Reset(); - memset(cmdInfo_, 0, sizeof(cmdInfo_)); - - // Convert the command table to a faster format, and check for dupes. - std::set dupeCheck; - for (size_t i = 0; i < ARRAY_SIZE(commonCommandTable); i++) { - const u8 cmd = commonCommandTable[i].cmd; - if (dupeCheck.find(cmd) != dupeCheck.end()) { - ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); - } else { - dupeCheck.insert(cmd); - } - cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = commonCommandTable[i].func; - if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { - // Can't have FLAG_EXECUTE commands without a function pointer to execute. - Crash(); - } - } - // Find commands missing from the table. - for (int i = 0; i < 0xEF; i++) { - if (dupeCheck.find((u8)i) == dupeCheck.end()) { - ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); - } - } - - UpdateCmdInfo(); UpdateVsyncInterval(true); ResetMatrices(); @@ -437,49 +88,6 @@ GPUCommon::~GPUCommon() { PPGeSetDrawContext(nullptr); } -void GPUCommon::UpdateCmdInfo() { - if (g_Config.bSoftwareSkinning) { - cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; - } else { - cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; - } - - if (g_Config.bFastMemory) { - cmdInfo_[GE_CMD_JUMP].func = &GPUCommon::Execute_JumpFast; - cmdInfo_[GE_CMD_CALL].func = &GPUCommon::Execute_CallFast; - } else { - cmdInfo_[GE_CMD_JUMP].func = &GPUCommon::Execute_Jump; - cmdInfo_[GE_CMD_CALL].func = &GPUCommon::Execute_Call; - } - - // Reconfigure for light ubershader or not. - for (int i = 0; i < 4; i++) { - if (gstate_c.Use(GPU_USE_LIGHT_UBERSHADER)) { - cmdInfo_[GE_CMD_LIGHTENABLE0 + i].RemoveDirty(DIRTY_VERTEXSHADER_STATE); - cmdInfo_[GE_CMD_LIGHTENABLE0 + i].AddDirty(DIRTY_LIGHT_CONTROL); - cmdInfo_[GE_CMD_LIGHTTYPE0 + i].RemoveDirty(DIRTY_VERTEXSHADER_STATE); - cmdInfo_[GE_CMD_LIGHTTYPE0 + i].AddDirty(DIRTY_LIGHT_CONTROL); - } else { - cmdInfo_[GE_CMD_LIGHTENABLE0 + i].RemoveDirty(DIRTY_LIGHT_CONTROL); - cmdInfo_[GE_CMD_LIGHTENABLE0 + i].AddDirty(DIRTY_VERTEXSHADER_STATE); - cmdInfo_[GE_CMD_LIGHTTYPE0 + i].RemoveDirty(DIRTY_LIGHT_CONTROL); - cmdInfo_[GE_CMD_LIGHTTYPE0 + i].AddDirty(DIRTY_VERTEXSHADER_STATE); - } - } - - if (gstate_c.Use(GPU_USE_LIGHT_UBERSHADER)) { - cmdInfo_[GE_CMD_MATERIALUPDATE].RemoveDirty(DIRTY_VERTEXSHADER_STATE); - cmdInfo_[GE_CMD_MATERIALUPDATE].AddDirty(DIRTY_LIGHT_CONTROL); - cmdInfo_[GE_CMD_LIGHTMODE].AddDirty(DIRTY_LIGHT_CONTROL); - } else { - cmdInfo_[GE_CMD_MATERIALUPDATE].RemoveDirty(DIRTY_LIGHT_CONTROL); - cmdInfo_[GE_CMD_MATERIALUPDATE].AddDirty(DIRTY_VERTEXSHADER_STATE); - cmdInfo_[GE_CMD_LIGHTMODE].RemoveDirty(DIRTY_LIGHT_CONTROL); - } -} - void GPUCommon::BeginHostFrame() { UpdateVsyncInterval(displayResized_); ReapplyGfxState(); @@ -3464,6 +3072,7 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { ); } + u32 GPUCommon::CheckGPUFeaturesLate(u32 features) const { // If we already have a 16-bit depth buffer, we don't need to round. bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 0c614d9310..636cf00baf 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -81,7 +81,7 @@ public: void CheckDisplayResized() override; void CheckConfigChanged() override; - void UpdateCmdInfo(); + virtual void UpdateCmdInfo() = 0; bool IsReady() override { return true; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 666f41d5db..1b251f5f57 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -10,7 +10,357 @@ #include "GPU/Common/TextureCacheCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" -GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) {} +const CommonCommandTableEntry commonCommandTable[] = { + // From Common. No flushing but definitely need execute. + { GE_CMD_OFFSETADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_OffsetAddr }, + { GE_CMD_ORIGIN, FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommon::Execute_Origin }, + { GE_CMD_JUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_Jump }, + { GE_CMD_CALL, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_Call }, + { GE_CMD_RET, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_Ret }, + { GE_CMD_END, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_End }, + { GE_CMD_VADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_Vaddr }, + { GE_CMD_IADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_Iaddr }, + { GE_CMD_BJUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BJump }, // EXECUTE + { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoundingBox }, // Shouldn't need to FLUSHBEFORE. + + { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPUCommon::Execute_Prim }, + { GE_CMD_BEZIER, FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, + { GE_CMD_SPLINE, FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, + + // Changing the vertex type requires us to flush. + { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, + + { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_LoadClut }, + + // These two are actually processed in CMD_END. + { GE_CMD_SIGNAL }, + { GE_CMD_FINISH }, + + // Changes that dirty the framebuffer + { GE_CMD_FRAMEBUFPTR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS }, + { GE_CMD_FRAMEBUFWIDTH, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_FRAMEBUFPIXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_ZBUFPTR, FLAG_FLUSHBEFOREONCHANGE }, + { GE_CMD_ZBUFWIDTH, FLAG_FLUSHBEFOREONCHANGE }, + + { GE_CMD_FOGCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOLOR }, + { GE_CMD_FOG1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEFENABLE }, + { GE_CMD_FOG2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEFENABLE }, + + // These affect the fragment shader so need flushing. + { GE_CMD_CLEARMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, + { GE_CMD_TEXTUREMAPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, + { GE_CMD_FOGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FOGCOEFENABLE }, + { GE_CMD_TEXMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_TEXSHADELS, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + // Raster state for Direct3D 9, uncommon. + { GE_CMD_SHADEMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_RASTER_STATE }, + { GE_CMD_TEXFUNC, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE | DIRTY_TEX_ALPHA_MUL }, + { GE_CMD_COLORTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_ALPHATESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_COLORTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_COLORTESTMASK, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORMASK | DIRTY_FRAGMENTSHADER_STATE }, + + // These change the vertex shader so need flushing. + { GE_CMD_REVERSENORMAL, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + { GE_CMD_LIGHTINGENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE }, + { GE_CMD_LIGHTENABLE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + { GE_CMD_LIGHTENABLE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + { GE_CMD_LIGHTENABLE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + { GE_CMD_LIGHTENABLE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + { GE_CMD_LIGHTTYPE0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT0 }, + { GE_CMD_LIGHTTYPE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT1 }, + { GE_CMD_LIGHTTYPE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT2 }, + { GE_CMD_LIGHTTYPE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_LIGHT3 }, + { GE_CMD_MATERIALUPDATE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + + // These change vertex shaders (in non uber shader mode) so need flushing. + { GE_CMD_LIGHTMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + + { GE_CMD_TEXFILTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXWRAP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE }, + + // Uniform changes. though the fragmentshader optimizes based on these sometimes. + { GE_CMD_ALPHATEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORREF | DIRTY_ALPHACOLORMASK | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_COLORREF, FLAG_FLUSHBEFOREONCHANGE, DIRTY_ALPHACOLORREF | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_TEXENVCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXENV }, + + // Simple render state changes. Handled in StateMapping.cpp. + { GE_CMD_CULL, FLAG_FLUSHBEFOREONCHANGE, DIRTY_RASTER_STATE }, + { GE_CMD_CULLFACEENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_RASTER_STATE }, + { GE_CMD_DITHERENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_RASTER_STATE }, + { GE_CMD_STENCILOP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_STENCILTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_STENCILREPLACEVALUE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE }, + { GE_CMD_STENCILTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_ALPHABLENDENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_BLENDMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_BLENDFIXEDA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_BLENDFIXEDB, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_MASKRGB, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_COLORWRITEMASK }, + { GE_CMD_MASKALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_COLORWRITEMASK }, + { GE_CMD_ZTEST, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE }, + { GE_CMD_ZTESTENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_ZWRITEDISABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHSTENCIL_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_LOGICOP, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, + { GE_CMD_LOGICOPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_BLEND_STATE | DIRTY_FRAGMENTSHADER_STATE }, + + { GE_CMD_TEXMAPMODE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE }, + + // These are read on every SubmitPrim, no need for dirtying or flushing. + { GE_CMD_TEXSCALEU }, + { GE_CMD_TEXSCALEV }, + { GE_CMD_TEXOFFSETU }, + { GE_CMD_TEXOFFSETV }, + + { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, + { GE_CMD_TEXSIZE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXSIZE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXSIZE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXSIZE4, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXSIZE5, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXSIZE6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXSIZE7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, + { GE_CMD_TEXLEVEL, FLAG_EXECUTEONCHANGE, DIRTY_TEXTURE_PARAMS, &GPUCommon::Execute_TexLevel }, + { GE_CMD_TEXLODSLOPE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE | DIRTY_UVSCALEOFFSET }, + { GE_CMD_TEXADDR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR4, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR5, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXADDR7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, + { GE_CMD_TEXBUFWIDTH1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH4, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH5, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + { GE_CMD_TEXBUFWIDTH7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, + + // These must flush on change, so that LoadClut doesn't have to always flush. + { GE_CMD_CLUTADDR, FLAG_FLUSHBEFOREONCHANGE }, + { GE_CMD_CLUTADDRUPPER, FLAG_FLUSHBEFOREONCHANGE }, + { GE_CMD_CLUTFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS | DIRTY_DEPAL }, + + // Morph weights. TODO: Remove precomputation? + { GE_CMD_MORPHWEIGHT0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT1, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT2, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT3, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT4, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT5, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT6, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + { GE_CMD_MORPHWEIGHT7, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_MorphWeight }, + + // Control spline/bezier patches. Don't really require flushing as such, but meh. + { GE_CMD_PATCHDIVISION, FLAG_FLUSHBEFOREONCHANGE }, + { GE_CMD_PATCHPRIMITIVE, FLAG_FLUSHBEFOREONCHANGE }, + { GE_CMD_PATCHFACING, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VERTEXSHADER_STATE }, + { GE_CMD_PATCHCULLENABLE, FLAG_FLUSHBEFOREONCHANGE }, + + // Can probably ignore this one as we don't support AA lines. + { GE_CMD_ANTIALIASENABLE, FLAG_FLUSHBEFOREONCHANGE }, + + // Viewport. + { GE_CMD_OFFSETX, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_OFFSETY, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_VIEWPORTXSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTYSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTXCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTYCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTZSCALE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_VIEWPORTZCENTER, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_CULLRANGE | DIRTY_DEPTHRANGE | DIRTY_PROJMATRIX | DIRTY_VIEWPORTSCISSOR_STATE }, + { GE_CMD_DEPTHCLAMPENABLE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE | DIRTY_RASTER_STATE }, + + // Z clip + { GE_CMD_MINZ, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHRANGE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_MAXZ, FLAG_FLUSHBEFOREONCHANGE, DIRTY_DEPTHRANGE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + + // Region + { GE_CMD_REGION1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_REGION2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + + // Scissor + { GE_CMD_SCISSOR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + { GE_CMD_SCISSOR2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_FRAMEBUF | DIRTY_TEXTURE_PARAMS | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE }, + + // Lighting base colors + { GE_CMD_AMBIENTCOLOR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_AMBIENT }, + { GE_CMD_AMBIENTALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_AMBIENT }, + { GE_CMD_MATERIALDIFFUSE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATDIFFUSE }, + { GE_CMD_MATERIALEMISSIVE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATEMISSIVE }, + { GE_CMD_MATERIALAMBIENT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATAMBIENTALPHA }, + { GE_CMD_MATERIALALPHA, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATAMBIENTALPHA }, + { GE_CMD_MATERIALSPECULAR, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATSPECULAR }, + { GE_CMD_MATERIALSPECULARCOEF, FLAG_FLUSHBEFOREONCHANGE, DIRTY_MATSPECULAR }, + + // Light parameters + { GE_CMD_LX0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LY0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LZ0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LX1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LY1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LZ1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LX2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LY2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LZ2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LX3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LY3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LZ3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + + { GE_CMD_LDX0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LDY0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LDZ0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LDX1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LDY1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LDZ1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LDX2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LDY2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LDZ2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LDX3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LDY3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LDZ3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + + { GE_CMD_LKA0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LKB0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LKC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LKA1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LKB1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LKC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LKA2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LKB2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LKC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LKA3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LKB3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LKC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + + { GE_CMD_LKS0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LKS1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LKS2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LKS3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + + { GE_CMD_LKO0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LKO1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LKO2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LKO3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + + { GE_CMD_LAC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LDC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LSC0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT0 }, + { GE_CMD_LAC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LDC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LSC1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT1 }, + { GE_CMD_LAC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LDC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LSC2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT2 }, + { GE_CMD_LAC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LDC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + { GE_CMD_LSC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, + + // Ignored commands + { GE_CMD_TEXFLUSH, 0 }, + { GE_CMD_TEXSYNC, 0 }, + + // These are just nop or part of other later commands. + { GE_CMD_NOP, 0 }, + { GE_CMD_BASE, 0 }, + { GE_CMD_TRANSFERSRC, 0 }, + { GE_CMD_TRANSFERSRCW, 0 }, + { GE_CMD_TRANSFERDST, 0 }, + { GE_CMD_TRANSFERDSTW, 0 }, + { GE_CMD_TRANSFERSRCPOS, 0 }, + { GE_CMD_TRANSFERDSTPOS, 0 }, + { GE_CMD_TRANSFERSIZE, 0 }, + { GE_CMD_TRANSFERSTART, FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommon::Execute_BlockTransferStart }, + + // We don't use the dither table. + { GE_CMD_DITH0 }, + { GE_CMD_DITH1 }, + { GE_CMD_DITH2 }, + { GE_CMD_DITH3 }, + + // These handle their own flushing. + { GE_CMD_WORLDMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_WorldMtxNum }, + { GE_CMD_WORLDMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_WorldMtxData }, + { GE_CMD_VIEWMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_ViewMtxNum }, + { GE_CMD_VIEWMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_ViewMtxData }, + { GE_CMD_PROJMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_ProjMtxNum }, + { GE_CMD_PROJMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_ProjMtxData }, + { GE_CMD_TGENMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_TgenMtxNum }, + { GE_CMD_TGENMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_TgenMtxData }, + { GE_CMD_BONEMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BoneMtxNum }, + { GE_CMD_BONEMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoneMtxData }, + + // Vertex Screen/Texture/Color + { GE_CMD_VSCX }, + { GE_CMD_VSCY }, + { GE_CMD_VSCZ }, + { GE_CMD_VTCS }, + { GE_CMD_VTCT }, + { GE_CMD_VTCQ }, + { GE_CMD_VCV }, + { GE_CMD_VAP, FLAG_EXECUTE, 0, &GPUCommon::Execute_ImmVertexAlphaPrim }, + { GE_CMD_VFC }, + { GE_CMD_VSCV }, + + // "Missing" commands (gaps in the sequence) + { GE_CMD_UNKNOWN_03, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_0D, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_11, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_29, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_34, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_35, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_39, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_4E, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_4F, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_52, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_59, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_5A, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_B6, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_B7, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_D1, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_ED, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_EF, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_FA, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_FB, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_FC, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_FD, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + { GE_CMD_UNKNOWN_FE, FLAG_EXECUTE, 0, &GPUCommon::Execute_Unknown }, + // Appears to be debugging related or something? Hit a lot in GoW. + { GE_CMD_NOP_FF, 0 }, +}; + +GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPUCommon(gfxCtx, draw) { + memset(cmdInfo_, 0, sizeof(cmdInfo_)); + + // Convert the command table to a faster format, and check for dupes. + std::set dupeCheck; + for (size_t i = 0; i < ARRAY_SIZE(commonCommandTable); i++) { + const u8 cmd = commonCommandTable[i].cmd; + if (dupeCheck.find(cmd) != dupeCheck.end()) { + ERROR_LOG(G3D, "Command table Dupe: %02x (%i)", (int)cmd, (int)cmd); + } else { + dupeCheck.insert(cmd); + } + cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); + cmdInfo_[cmd].func = commonCommandTable[i].func; + if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { + // Can't have FLAG_EXECUTE commands without a function pointer to execute. + Crash(); + } + } + // Find commands missing from the table. + for (int i = 0; i < 0xEF; i++) { + if (dupeCheck.find((u8)i) == dupeCheck.end()) { + ERROR_LOG(G3D, "Command missing from table: %02x (%i)", i, i); + } + } + + UpdateCmdInfo(); +} GPUCommonHW::~GPUCommonHW() { // Clear features so they're not visible in system info. @@ -31,6 +381,49 @@ void GPUCommonHW::DeviceLost() { shaderManager_->DeviceLost(); } +void GPUCommonHW::UpdateCmdInfo() { + if (g_Config.bSoftwareSkinning) { + cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; + cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; + } else { + cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; + cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; + } + + if (g_Config.bFastMemory) { + cmdInfo_[GE_CMD_JUMP].func = &GPUCommon::Execute_JumpFast; + cmdInfo_[GE_CMD_CALL].func = &GPUCommon::Execute_CallFast; + } else { + cmdInfo_[GE_CMD_JUMP].func = &GPUCommon::Execute_Jump; + cmdInfo_[GE_CMD_CALL].func = &GPUCommon::Execute_Call; + } + + // Reconfigure for light ubershader or not. + for (int i = 0; i < 4; i++) { + if (gstate_c.Use(GPU_USE_LIGHT_UBERSHADER)) { + cmdInfo_[GE_CMD_LIGHTENABLE0 + i].RemoveDirty(DIRTY_VERTEXSHADER_STATE); + cmdInfo_[GE_CMD_LIGHTENABLE0 + i].AddDirty(DIRTY_LIGHT_CONTROL); + cmdInfo_[GE_CMD_LIGHTTYPE0 + i].RemoveDirty(DIRTY_VERTEXSHADER_STATE); + cmdInfo_[GE_CMD_LIGHTTYPE0 + i].AddDirty(DIRTY_LIGHT_CONTROL); + } else { + cmdInfo_[GE_CMD_LIGHTENABLE0 + i].RemoveDirty(DIRTY_LIGHT_CONTROL); + cmdInfo_[GE_CMD_LIGHTENABLE0 + i].AddDirty(DIRTY_VERTEXSHADER_STATE); + cmdInfo_[GE_CMD_LIGHTTYPE0 + i].RemoveDirty(DIRTY_LIGHT_CONTROL); + cmdInfo_[GE_CMD_LIGHTTYPE0 + i].AddDirty(DIRTY_VERTEXSHADER_STATE); + } + } + + if (gstate_c.Use(GPU_USE_LIGHT_UBERSHADER)) { + cmdInfo_[GE_CMD_MATERIALUPDATE].RemoveDirty(DIRTY_VERTEXSHADER_STATE); + cmdInfo_[GE_CMD_MATERIALUPDATE].AddDirty(DIRTY_LIGHT_CONTROL); + cmdInfo_[GE_CMD_LIGHTMODE].AddDirty(DIRTY_LIGHT_CONTROL); + } else { + cmdInfo_[GE_CMD_MATERIALUPDATE].RemoveDirty(DIRTY_LIGHT_CONTROL); + cmdInfo_[GE_CMD_MATERIALUPDATE].AddDirty(DIRTY_VERTEXSHADER_STATE); + cmdInfo_[GE_CMD_LIGHTMODE].RemoveDirty(DIRTY_LIGHT_CONTROL); + } +} + void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 5e258027e8..0e2dc59f05 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -16,6 +16,8 @@ public: u32 CheckGPUFeatures() const override; protected: + void UpdateCmdInfo() override; + void PreExecuteOp(u32 op, u32 diff); void ClearCacheNextFrame() override; diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index ef61d59663..25ce1d5f1a 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -134,6 +134,7 @@ public: void FinishDeferred() override; int ListSync(int listid, int mode) override; u32 DrawSync(int mode) override; + void UpdateCmdInfo() override {} void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput(bool reallyDirty) override; From 7bcc21b0e3549b9b63abe0c5377563c19c470bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:27:00 +0100 Subject: [PATCH 162/424] Move msaaLevel_ to GPUCommonHW --- GPU/GPUCommon.cpp | 19 ------------------- GPU/GPUCommon.h | 10 ++-------- GPU/GPUCommonHW.cpp | 18 ++++++++++++++++++ GPU/GPUCommonHW.h | 5 +++++ 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index f48661000f..a59e348d4c 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -79,8 +79,6 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : ResetMatrices(); PPGeSetDrawContext(draw); - - UpdateMSAALevel(draw); } GPUCommon::~GPUCommon() { @@ -267,13 +265,6 @@ void GPUCommon::CheckDisplayResized() { } } -void GPUCommon::CheckRenderResized() { - if (renderResized_) { - framebufferManager_->NotifyRenderResized(msaaLevel_); - renderResized_ = false; - } -} - void GPUCommon::DumpNextFrame() { dumpNextFrame_ = true; } @@ -3104,16 +3095,6 @@ u32 GPUCommon::CheckGPUFeaturesLate(u32 features) const { return features; } -void GPUCommon::UpdateMSAALevel(Draw::DrawContext *draw) { - int level = g_Config.iMultiSampleLevel; - if (draw && draw->GetDeviceCaps().multiSampleLevelsMask & (1 << level)) { - msaaLevel_ = level; - } else { - // Didn't support the configured level, so revert to 0. - msaaLevel_ = 0; - } -} - void GPUCommon::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 636cf00baf..facc94da07 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -264,17 +264,13 @@ public: fullInfo = reportingFullInfo_; } - int MSAALevel() const { - return msaaLevel_; - } - protected: void DeviceLost() override; void DeviceRestore() override; void ClearCacheNextFrame() override {} - virtual void CheckRenderResized(); + virtual void CheckRenderResized() {} // Add additional common features dependent on other features, which may be backend-determined. u32 CheckGPUFeaturesLate(u32 features) const; @@ -328,7 +324,7 @@ protected: virtual void BuildReportingInfo() = 0; - void UpdateMSAALevel(Draw::DrawContext *draw); + virtual void UpdateMSAALevel(Draw::DrawContext *draw) {} DrawEngineCommon *drawEngineCommon_ = nullptr; @@ -419,8 +415,6 @@ protected: std::string reportingPrimaryInfo_; std::string reportingFullInfo_; - int msaaLevel_ = 0; - private: void CheckDepthUsage(VirtualFramebuffer *vfb); void DoExecuteCall(u32 target); diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 1b251f5f57..2943a80cc5 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -360,6 +360,7 @@ GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPU } UpdateCmdInfo(); + UpdateMSAALevel(draw); } GPUCommonHW::~GPUCommonHW() { @@ -374,6 +375,13 @@ GPUCommonHW::~GPUCommonHW() { delete shaderManager_; } +void GPUCommonHW::CheckRenderResized() { + if (renderResized_) { + framebufferManager_->NotifyRenderResized(msaaLevel_); + renderResized_ = false; + } +} + void GPUCommonHW::DeviceLost() { textureCache_->Clear(false); framebufferManager_->DeviceLost(); @@ -528,3 +536,13 @@ u32 GPUCommonHW::CheckGPUFeatures() const { return features; } + +void GPUCommonHW::UpdateMSAALevel(Draw::DrawContext *draw) { + int level = g_Config.iMultiSampleLevel; + if (draw && draw->GetDeviceCaps().multiSampleLevelsMask & (1 << level)) { + msaaLevel_ = level; + } else { + // Didn't support the configured level, so revert to 0. + msaaLevel_ = 0; + } +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 0e2dc59f05..fea544911e 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -23,5 +23,10 @@ protected: // Needs to be called on GPU thread, not reporting thread. void BuildReportingInfo() override; + void UpdateMSAALevel(Draw::DrawContext *draw) override; + + void CheckRenderResized() override; + + int msaaLevel_ = 0; }; From c2c479b2173a7b9fcc7e364d67e08510c6e1a85f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:29:53 +0100 Subject: [PATCH 163/424] Remove function InitClear. Was only implemented for DX9, and only barely meaningful in non-buffered. --- Core/HLE/sceDisplay.cpp | 9 +-------- GPU/D3D11/GPU_D3D11.cpp | 6 ------ GPU/D3D11/GPU_D3D11.h | 1 - GPU/Directx9/GPU_DX9.cpp | 8 -------- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 3 --- GPU/GLES/GPU_GLES.h | 1 - GPU/GPUCommon.h | 1 - GPU/GPUInterface.h | 1 - GPU/Software/SoftGpu.h | 1 - GPU/Vulkan/GPU_Vulkan.cpp | 6 ------ GPU/Vulkan/GPU_Vulkan.h | 1 - 12 files changed, 1 insertion(+), 38 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 342d522627..953c2ab460 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -285,10 +285,6 @@ void __DisplayDoState(PointerWrap &p) { if (p.mode == p.MODE_READ) { gpu->ReapplyGfxState(); - - if (hasSetMode) { - gpu->InitClear(); - } gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.stride, framebuf.fmt); } } @@ -749,10 +745,7 @@ static u32 sceDisplaySetMode(int displayMode, int displayWidth, int displayHeigh return hleLogWarning(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_SIZE, "invalid size"); } - if (!hasSetMode) { - gpu->InitClear(); - hasSetMode = true; - } + hasSetMode = true; mode = displayMode; width = displayWidth; height = displayHeight; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index c0b419184a..fd8085f2e8 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -127,12 +127,6 @@ void GPU_D3D11::DeviceRestore() { // Nothing needed. } -void GPU_D3D11::InitClear() { - if (!framebufferManager_->UseBufferedRendering()) { - // device_->Clear(0, NULL, D3DCLEAR_STENCIL | D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0); - } -} - void GPU_D3D11::BeginFrame() { GPUCommonHW::BeginFrame(); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 3112c1b437..434a3c6303 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -48,7 +48,6 @@ protected: void FinishDeferred() override; private: - void InitClear() override; void BeginFrame() override; ID3D11Device *device_; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index a95c6155fd..d36b0693f7 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -110,14 +110,6 @@ void GPU_DX9::DeviceLost() { GPUCommonHW::DeviceLost(); } -void GPU_DX9::InitClear() { - if (!framebufferManager_->UseBufferedRendering()) { - dxstate.depthWrite.set(true); - dxstate.colorMask.set(0xF); - device_->Clear(0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0); - } -} - void GPU_DX9::ReapplyGfxState() { dxstate.Restore(); GPUCommonHW::ReapplyGfxState(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index eda85cb387..5e6495b60e 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -48,7 +48,6 @@ protected: void FinishDeferred() override; private: - void InitClear() override; void BeginFrame() override; LPDIRECT3DDEVICE9 device_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 6bf1046764..d1d4dd29e1 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -256,9 +256,6 @@ void GPU_GLES::DeviceRestore() { fragmentTestCache_.DeviceRestore(draw_); } -void GPU_GLES::InitClear() { -} - void GPU_GLES::BeginHostFrame() { GPUCommonHW::BeginHostFrame(); drawEngine_.BeginFrame(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 4ab375840a..4dd821b9fe 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -62,7 +62,6 @@ protected: private: void BuildReportingInfo() override; - void InitClear() override; void BeginFrame() override; FramebufferManagerGLES *framebufferManagerGL_; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index facc94da07..eecfaa68da 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -131,7 +131,6 @@ public: void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput(bool reallyDirty) override = 0; - void InitClear() override = 0; bool PerformMemoryCopy(u32 dest, u32 src, int size, GPUCopyFlag flags = GPUCopyFlag::NONE) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformReadbackToMemory(u32 dest, int size) override; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 8403d6f048..6bf3856e16 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -192,7 +192,6 @@ public: virtual bool IsReady() = 0; virtual void CancelReady() = 0; virtual bool IsStarted() = 0; - virtual void InitClear() = 0; virtual void Reinitialize() = 0; // Frame managment diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 25ce1d5f1a..61104a04bd 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -129,7 +129,6 @@ public: u32 CheckGPUFeatures() const override { return 0; } bool IsStarted() override; - void InitClear() override {} void ExecuteOp(u32 op, u32 diff) override; void FinishDeferred() override; int ListSync(int listid, int mode) override; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index ffe2e61755..119414aef5 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -389,12 +389,6 @@ void GPU_Vulkan::BuildReportingInfo() { Reporting::UpdateConfig(); } -void GPU_Vulkan::InitClear() { - if (!framebufferManager_->UseBufferedRendering()) { - // TODO? - } -} - void GPU_Vulkan::FinishDeferred() { drawEngine_.FinishDeferred(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 6892eafa58..1e52e8e0de 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -67,7 +67,6 @@ protected: private: void BuildReportingInfo() override; - void InitClear() override; void InitDeviceObjects(); void DestroyDeviceObjects(); From 92ee6e6a758ffc69ca22a526281b8e80cc2d6a63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:33:09 +0100 Subject: [PATCH 164/424] Remove more redundant functions --- GPU/Directx9/GPU_DX9.cpp | 5 ----- GPU/Directx9/GPU_DX9.h | 1 - GPU/GLES/GPU_GLES.cpp | 4 ---- GPU/GLES/GPU_GLES.h | 1 - 4 files changed, 11 deletions(-) diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index d36b0693f7..928a399635 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -105,11 +105,6 @@ u32 GPU_DX9::CheckGPUFeatures() const { return CheckGPUFeaturesLate(features); } -void GPU_DX9::DeviceLost() { - // Simply drop all caches and textures. - GPUCommonHW::DeviceLost(); -} - void GPU_DX9::ReapplyGfxState() { dxstate.Restore(); GPUCommonHW::ReapplyGfxState(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 5e6495b60e..41e057ab74 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -38,7 +38,6 @@ public: void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; - void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index d1d4dd29e1..a8f8a9c449 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -274,10 +274,6 @@ void GPU_GLES::EndHostFrame() { drawEngine_.EndFrame(); } -void GPU_GLES::ReapplyGfxState() { - GPUCommonHW::ReapplyGfxState(); -} - void GPU_GLES::BeginFrame() { GPUCommonHW::BeginFrame(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 4dd821b9fe..21c9adba08 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -43,7 +43,6 @@ public: bool IsReady() override; void CancelReady() override; - void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. From 8fb75e0c123ba9fe37877aa1ecfcb538311cba63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 16:40:52 +0100 Subject: [PATCH 165/424] Unify most of the DebugGetShader* functions --- GPU/Common/ShaderCommon.h | 5 +++++ GPU/D3D11/GPU_D3D11.cpp | 22 ---------------------- GPU/D3D11/GPU_D3D11.h | 4 ---- GPU/Directx9/GPU_DX9.cpp | 22 ---------------------- GPU/Directx9/GPU_DX9.h | 4 ---- GPU/GLES/GPU_GLES.cpp | 22 ---------------------- GPU/GLES/GPU_GLES.h | 4 ---- GPU/GPUCommonHW.cpp | 22 ++++++++++++++++++++++ GPU/GPUCommonHW.h | 4 ++++ GPU/Vulkan/GPU_Vulkan.cpp | 30 ++++++++++-------------------- 10 files changed, 41 insertions(+), 98 deletions(-) diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 025576ea6f..380a9e240a 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -18,6 +18,8 @@ #pragma once #include +#include +#include namespace Draw { class DrawContext; @@ -132,6 +134,9 @@ public: virtual void DeviceLost() = 0; virtual void DeviceRestore(Draw::DrawContext *draw) = 0; // must set draw_ to draw + virtual std::vector DebugGetShaderIDs(DebugShaderType type) = 0; + virtual std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) = 0; + protected: Draw::DrawContext *draw_ = nullptr; }; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index fd8085f2e8..28043a1d68 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -166,25 +166,3 @@ void GPU_D3D11::GetStats(char *buffer, size_t bufsize) { shaderManagerD3D11_->GetNumFragmentShaders() ); } - -std::vector GPU_D3D11::DebugGetShaderIDs(DebugShaderType type) { - switch (type) { - case SHADER_TYPE_VERTEXLOADER: - return drawEngine_.DebugGetVertexLoaderIDs(); - case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderIDs(type); - default: - return shaderManagerD3D11_->DebugGetShaderIDs(type); - } -} - -std::string GPU_D3D11::DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) { - switch (type) { - case SHADER_TYPE_VERTEXLOADER: - return drawEngine_.DebugGetVertexLoaderString(id, stringType); - case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderString(id, type, stringType); - default: - return shaderManagerD3D11_->DebugGetShaderString(id, type, stringType); - } -} diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 434a3c6303..782ef7f029 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -40,10 +40,6 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. - std::vector DebugGetShaderIDs(DebugShaderType shader) override; - std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; - protected: void FinishDeferred() override; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 928a399635..1c748980c0 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -146,25 +146,3 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { shaderManagerDX9_->GetNumFragmentShaders() ); } - -std::vector GPU_DX9::DebugGetShaderIDs(DebugShaderType type) { - switch (type) { - case SHADER_TYPE_VERTEXLOADER: - return drawEngine_.DebugGetVertexLoaderIDs(); - case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderIDs(type); - default: - return shaderManagerDX9_->DebugGetShaderIDs(type); - } -} - -std::string GPU_DX9::DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) { - switch (type) { - case SHADER_TYPE_VERTEXLOADER: - return drawEngine_.DebugGetVertexLoaderString(id, stringType); - case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderString(id, type, stringType); - default: - return shaderManagerDX9_->DebugGetShaderString(id, type, stringType); - } -} diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 41e057ab74..1da17b2e3e 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -39,10 +39,6 @@ public: void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. - std::vector DebugGetShaderIDs(DebugShaderType shader) override; - std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; - protected: void FinishDeferred() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index a8f8a9c449..756cf81937 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -311,25 +311,3 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { shaderManagerGL_->GetNumPrograms() ); } - -std::vector GPU_GLES::DebugGetShaderIDs(DebugShaderType type) { - switch (type) { - case SHADER_TYPE_VERTEXLOADER: - return drawEngine_.DebugGetVertexLoaderIDs(); - case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderIDs(type); - default: - return shaderManagerGL_->DebugGetShaderIDs(type); - } -} - -std::string GPU_GLES::DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) { - switch (type) { - case SHADER_TYPE_VERTEXLOADER: - return drawEngine_.DebugGetVertexLoaderString(id, stringType); - case SHADER_TYPE_TEXTURE: - return textureCache_->GetTextureShaderCache()->DebugGetShaderString(id, type, stringType); - default: - return shaderManagerGL_->DebugGetShaderString(id, type, stringType); - } -} diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 21c9adba08..a56765a580 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -48,10 +48,6 @@ public: void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; - // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. - std::vector DebugGetShaderIDs(DebugShaderType shader) override; - std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; - void BeginHostFrame() override; void EndHostFrame() override; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 2943a80cc5..2f5029d5f7 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -546,3 +546,25 @@ void GPUCommonHW::UpdateMSAALevel(Draw::DrawContext *draw) { msaaLevel_ = 0; } } + +std::vector GPUCommonHW::DebugGetShaderIDs(DebugShaderType type) { + switch (type) { + case SHADER_TYPE_VERTEXLOADER: + return drawEngineCommon_->DebugGetVertexLoaderIDs(); + case SHADER_TYPE_TEXTURE: + return textureCache_->GetTextureShaderCache()->DebugGetShaderIDs(type); + default: + return shaderManager_->DebugGetShaderIDs(type); + } +} + +std::string GPUCommonHW::DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) { + switch (type) { + case SHADER_TYPE_VERTEXLOADER: + return drawEngineCommon_->DebugGetVertexLoaderString(id, stringType); + case SHADER_TYPE_TEXTURE: + return textureCache_->GetTextureShaderCache()->DebugGetShaderString(id, type, stringType); + default: + return shaderManager_->DebugGetShaderString(id, type, stringType); + } +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index fea544911e..f059d93fc0 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -15,6 +15,10 @@ public: u32 CheckGPUFeatures() const override; + // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. + std::vector DebugGetShaderIDs(DebugShaderType shader) override; + std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; + protected: void UpdateCmdInfo() override; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 119414aef5..532811f365 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -499,34 +499,24 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { } std::vector GPU_Vulkan::DebugGetShaderIDs(DebugShaderType type) { - if (type == SHADER_TYPE_VERTEXLOADER) { - return drawEngine_.DebugGetVertexLoaderIDs(); - } else if (type == SHADER_TYPE_PIPELINE) { + switch (type) { + case SHADER_TYPE_PIPELINE: return pipelineManager_->DebugGetObjectIDs(type); - } else if (type == SHADER_TYPE_TEXTURE) { - return textureCache_->GetTextureShaderCache()->DebugGetShaderIDs(type); - } else if (type == SHADER_TYPE_VERTEX || type == SHADER_TYPE_FRAGMENT || type == SHADER_TYPE_GEOMETRY) { - return shaderManagerVulkan_->DebugGetShaderIDs(type); - } else if (type == SHADER_TYPE_SAMPLER) { + case SHADER_TYPE_SAMPLER: return textureCacheVulkan_->DebugGetSamplerIDs(); - } else { - return std::vector(); + default: + return GPUCommonHW::DebugGetShaderIDs(type); } } std::string GPU_Vulkan::DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) { - if (type == SHADER_TYPE_VERTEXLOADER) { - return drawEngine_.DebugGetVertexLoaderString(id, stringType); - } else if (type == SHADER_TYPE_PIPELINE) { + switch (type) { + case SHADER_TYPE_PIPELINE: return pipelineManager_->DebugGetObjectString(id, type, stringType, shaderManagerVulkan_); - } else if (type == SHADER_TYPE_TEXTURE) { - return textureCache_->GetTextureShaderCache()->DebugGetShaderString(id, type, stringType); - } else if (type == SHADER_TYPE_SAMPLER) { + case SHADER_TYPE_SAMPLER: return textureCacheVulkan_->DebugGetSamplerString(id, stringType); - } else if (type == SHADER_TYPE_VERTEX || type == SHADER_TYPE_FRAGMENT || type == SHADER_TYPE_GEOMETRY) { - return shaderManagerVulkan_->DebugGetShaderString(id, type, stringType); - } else { - return std::string(); + default: + return GPUCommonHW::DebugGetShaderString(id, type, stringType); } } From d22a22569a72a5b44944fa3bf124eada4386f67a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 17:17:09 +0100 Subject: [PATCH 166/424] Move the drawing commands to GPUCommonHW --- GPU/GPUCommon.cpp | 453 +----------------------------------------- GPU/GPUCommon.h | 12 -- GPU/GPUCommonHW.cpp | 472 +++++++++++++++++++++++++++++++++++++++++++- GPU/GPUCommonHW.h | 11 +- 4 files changed, 478 insertions(+), 470 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a59e348d4c..7338d29d3e 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -42,6 +42,7 @@ #include "Core/HW/Display.h" #include "Core/MemMapHelpers.h" #include "Core/Util/PPGeDraw.h" +#include "GPU/GPUCommonHW.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/Common/SplineCommon.h" @@ -50,7 +51,7 @@ #include "GPU/Debugger/Record.h" // TODO: Make class member? -GPUCommon::CommandInfo GPUCommon::cmdInfo_[256]; +GPUCommonHW::CommandInfo GPUCommon::cmdInfo_[256]; void GPUCommon::Flush() { drawEngineCommon_->DispatchFlush(); @@ -1380,444 +1381,6 @@ void GPUCommon::Execute_VertexTypeSkinning(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_CULLRANGE | DIRTY_FOGCOEFENABLE); } -void GPUCommon::CheckDepthUsage(VirtualFramebuffer *vfb) { - if (!gstate_c.usingDepth) { - bool isReadingDepth = false; - bool isClearingDepth = false; - bool isWritingDepth = false; - if (gstate.isModeClear()) { - isClearingDepth = gstate.isClearModeDepthMask(); - isWritingDepth = isClearingDepth; - } else if (gstate.isDepthTestEnabled()) { - isWritingDepth = gstate.isDepthWriteEnabled(); - isReadingDepth = gstate.getDepthTestFunction() > GE_COMP_ALWAYS; - } - - if (isWritingDepth || isReadingDepth) { - gstate_c.usingDepth = true; - gstate_c.clearingDepth = isClearingDepth; - vfb->last_frame_depth_render = gpuStats.numFlips; - if (isWritingDepth) { - vfb->last_frame_depth_updated = gpuStats.numFlips; - } - framebufferManager_->SetDepthFrameBuffer(isClearingDepth); - } - } -} - -void GPUCommon::Execute_Prim(u32 op, u32 diff) { - // This drives all drawing. All other state we just buffer up, then we apply it only - // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. - - PROFILE_THIS_SCOPE("execprim"); - - u32 data = op & 0xFFFFFF; - u32 count = data & 0xFFFF; - if (count == 0) - return; - FlushImm(); - - // Upper bits are ignored. - GEPrimitiveType prim = static_cast((data >> 16) & 7); - SetDrawType(DRAW_PRIM, prim); - - // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. - if (gstate.isAntiAliasEnabled()) { - // Heuristic derived from discussions in #6483 and #12588. - // Discard AA lines in Persona 3 Portable, DOA Paradise and Summon Night 5, while still keeping AA lines in Echochrome. - if ((prim == GE_PRIM_LINE_STRIP || prim == GE_PRIM_LINES) && gstate.getTextureFunction() == GE_TEXFUNC_REPLACE) - return; - } - - // Update cached framebuffer format. - // We store it in the cache so it can be modified for blue-to-alpha, next. - gstate_c.framebufFormat = gstate.FrameBufFormat(); - - if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { - ERROR_LOG(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); - return; - } - - // See the documentation for gstate_c.blueToAlpha. - bool blueToAlpha = false; - if (PSP_CoreParameter().compat.flags().BlueToAlpha) { - if (gstate_c.framebufFormat == GEBufferFormat::GE_FORMAT_565 && gstate.getColorMask() == 0x0FFFFF && !gstate.isLogicOpEnabled()) { - blueToAlpha = true; - gstate_c.framebufFormat = GEBufferFormat::GE_FORMAT_4444; - } - if (blueToAlpha != gstate_c.blueToAlpha) { - gstate_c.blueToAlpha = blueToAlpha; - gstate_c.Dirty(DIRTY_FRAMEBUF | DIRTY_FRAGMENTSHADER_STATE | DIRTY_BLEND_STATE); - } - } - - if (PSP_CoreParameter().compat.flags().SplitFramebufferMargin) { - switch (gstate.vertType & 0xFFFFFF) { - case 0x00800102: // through, u16 uv, u16 pos (used for the framebuffer effect in-game) - case 0x0080011c: // through, 8888 color, s16 pos (used for clearing in the margin of the title screen) - case 0x00000183: // float uv, float pos (used for drawing in the margin of the title screen) - // Need to re-check the framebuffer every one of these draws, to update the split if needed. - gstate_c.Dirty(DIRTY_FRAMEBUF); - } - } - - // This also makes skipping drawing very effective. - VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - if (blueToAlpha) { - vfb->usageFlags |= FB_USAGE_BLUE_TO_ALPHA; - } - - // Must check this after SetRenderFrameBuffer so we know SKIPDRAW_NON_DISPLAYED_FB. - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - // Rough estimate, not sure what's correct. - cyclesExecuted += EstimatePerVertexCost() * count; - if (gstate.isModeClear()) { - gpuStats.numClears++; - } - return; - } - - CheckDepthUsage(vfb); - - const void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); - const void *inds = nullptr; - u32 vertexType = gstate.vertType; - if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - u32 indexAddr = gstate_c.indexAddr; - if (!Memory::IsValidAddress(indexAddr)) { - ERROR_LOG(G3D, "Bad index address %08x!", indexAddr); - return; - } - inds = Memory::GetPointerUnchecked(indexAddr); - } - - if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { - vertexCost_ = EstimatePerVertexCost(); - } - - int bytesRead = 0; - UpdateUVScaleOffset(); - - // cull mode - int cullMode = gstate.getCullMode(); - - uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); - drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, cullMode, &bytesRead); - // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). - // Some games rely on this, they don't bother reloading VADDR and IADDR. - // The VADDR/IADDR registers are NOT updated. - AdvanceVerts(vertexType, count, bytesRead); - int totalVertCount = count; - - // PRIMs are often followed by more PRIMs. Save some work and submit them immediately. - const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - const u32_le *stall = currentList->stall ? (const u32_le *)Memory::GetPointerUnchecked(currentList->stall) : 0; - int cmdCount = 0; - - // Optimized submission of sequences of PRIM. Allows us to avoid going through all the mess - // above for each one. This can be expanded to support additional games that intersperse - // PRIM commands with other commands. A special case is Earth Defence Force 2 that changes culling mode - // between each prim, we just change the triangle winding right here to still be able to join draw calls. - - uint32_t vtypeCheckMask = ~GE_VTYPE_WEIGHTCOUNT_MASK; - if (!g_Config.bSoftwareSkinning) - vtypeCheckMask = 0xFFFFFFFF; - - if (debugRecording_) - goto bail; - - while (src != stall) { - uint32_t data = *src; - switch (data >> 24) { - case GE_CMD_PRIM: - { - u32 count = data & 0xFFFF; - if (count == 0) { - // Ignore. - break; - } - - GEPrimitiveType newPrim = static_cast((data >> 16) & 7); - SetDrawType(DRAW_PRIM, newPrim); - // TODO: more efficient updating of verts/inds - verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); - inds = nullptr; - if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - inds = Memory::GetPointerUnchecked(gstate_c.indexAddr); - } - - drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertTypeID, cullMode, &bytesRead); - AdvanceVerts(vertexType, count, bytesRead); - totalVertCount += count; - break; - } - case GE_CMD_VERTEXTYPE: - { - uint32_t diff = data ^ vertexType; - // don't mask upper bits, vertexType is unmasked - if (diff & vtypeCheckMask) { - goto bail; - } else { - vertexType = data; - vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); - } - break; - } - case GE_CMD_VADDR: - gstate.cmdmem[GE_CMD_VADDR] = data; - gstate_c.vertexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); - break; - case GE_CMD_IADDR: - gstate.cmdmem[GE_CMD_IADDR] = data; - gstate_c.indexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); - break; - case GE_CMD_OFFSETADDR: - gstate.cmdmem[GE_CMD_OFFSETADDR] = data; - gstate_c.offsetAddr = data << 8; - break; - case GE_CMD_BASE: - gstate.cmdmem[GE_CMD_BASE] = data; - break; - case GE_CMD_CULLFACEENABLE: - // Earth Defence Force 2 - if (gstate.cmdmem[GE_CMD_CULLFACEENABLE] != data) { - goto bail; - } - break; - case GE_CMD_CULL: - // flip face by indices for triangles - cullMode = data & 1; - break; - case GE_CMD_TEXFLUSH: - case GE_CMD_NOP: - case GE_CMD_NOP_FF: - gstate.cmdmem[data >> 24] = data; - break; - case GE_CMD_BONEMATRIXNUMBER: - gstate.cmdmem[GE_CMD_BONEMATRIXNUMBER] = data; - break; - case GE_CMD_TEXSCALEU: - gstate.cmdmem[GE_CMD_TEXSCALEU] = data; - gstate_c.uv.uScale = getFloat24(data); - break; - case GE_CMD_TEXSCALEV: - gstate.cmdmem[GE_CMD_TEXSCALEV] = data; - gstate_c.uv.vScale = getFloat24(data); - break; - case GE_CMD_TEXOFFSETU: - gstate.cmdmem[GE_CMD_TEXOFFSETU] = data; - gstate_c.uv.uOff = getFloat24(data); - break; - case GE_CMD_TEXOFFSETV: - gstate.cmdmem[GE_CMD_TEXOFFSETV] = data; - gstate_c.uv.vOff = getFloat24(data); - break; - case GE_CMD_TEXLEVEL: - // Same Gran Turismo hack from Execute_TexLevel - if ((data & 3) != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & data) != 0) { - goto bail; - } - gstate.cmdmem[GE_CMD_TEXLEVEL] = data; - break; - case GE_CMD_CALL: - { - // A bone matrix probably. If not we bail. - const u32 target = gstate_c.getRelativeAddress(data & 0x00FFFFFC); - if ((Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA && - (Memory::ReadUnchecked_U32(target + 11 * 4) >> 24) == GE_CMD_BONEMATRIXDATA && - (Memory::ReadUnchecked_U32(target + 12 * 4) >> 24) == GE_CMD_RET && - (target > currentList->stall || target + 12 * 4 < currentList->stall) && - (gstate.boneMatrixNumber & 0x00FFFFFF) <= 96 - 12) { - FastLoadBoneMatrix(target); - } else { - goto bail; - } - break; - } - - case GE_CMD_TEXBUFWIDTH0: - case GE_CMD_TEXADDR0: - if (data != gstate.cmdmem[data >> 24]) - goto bail; - break; - - default: - // All other commands might need a flush or something, stop this inner loop. - goto bail; - } - cmdCount++; - src++; - } - -bail: - gstate.cmdmem[GE_CMD_VERTEXTYPE] = vertexType; - // Skip over the commands we just read out manually. - if (cmdCount > 0) { - UpdatePC(currentList->pc, currentList->pc + cmdCount * 4); - currentList->pc += cmdCount * 4; - // flush back cull mode - if (cullMode != gstate.getCullMode()) { - // We rewrote everything to the old cull mode, so flush first. - drawEngineCommon_->DispatchFlush(); - - // Now update things for next time. - gstate.cmdmem[GE_CMD_CULL] ^= 1; - gstate_c.Dirty(DIRTY_RASTER_STATE); - } - } - - gpuStats.vertexGPUCycles += vertexCost_ * totalVertCount; - cyclesExecuted += vertexCost_ * totalVertCount; -} - -void GPUCommon::Execute_Bezier(u32 op, u32 diff) { - // We don't dirty on normal changes anymore as we prescale, but it's needed for splines/bezier. - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - - gstate_c.framebufFormat = gstate.FrameBufFormat(); - - // This also make skipping drawing very effective. - VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - // TODO: Should this eat some cycles? Probably yes. Not sure if important. - return; - } - - CheckDepthUsage(vfb); - - if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); - return; - } - - const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr); - const void *indices = NULL; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - if (!Memory::IsValidAddress(gstate_c.indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr); - return; - } - indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); - } - - if (vertTypeIsSkinningEnabled(gstate.vertType)) { - DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); - } - - // Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already. - if (flushOnParams_) - drawEngineCommon_->DispatchFlush(); - - Spline::BezierSurface surface; - surface.tess_u = gstate.getPatchDivisionU(); - surface.tess_v = gstate.getPatchDivisionV(); - surface.num_points_u = op & 0xFF; - surface.num_points_v = (op >> 8) & 0xFF; - surface.num_patches_u = (surface.num_points_u - 1) / 3; - surface.num_patches_v = (surface.num_points_v - 1) / 3; - surface.primType = gstate.getPatchPrimitiveType(); - surface.patchFacing = gstate.patchfacing & 1; - - SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); - - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); - if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { - gstate_c.submitType = SubmitType::HW_BEZIER; - if (gstate_c.spline_num_points_u != surface.num_points_u) { - gstate_c.Dirty(DIRTY_BEZIERSPLINE); - gstate_c.spline_num_points_u = surface.num_points_u; - } - } else { - gstate_c.submitType = SubmitType::BEZIER; - } - - int bytesRead = 0; - UpdateUVScaleOffset(); - drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); - - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); - gstate_c.submitType = SubmitType::DRAW; - - // After drawing, we advance pointers - see SubmitPrim which does the same. - int count = surface.num_points_u * surface.num_points_v; - AdvanceVerts(gstate.vertType, count, bytesRead); -} - -void GPUCommon::Execute_Spline(u32 op, u32 diff) { - // We don't dirty on normal changes anymore as we prescale, but it's needed for splines/bezier. - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - - gstate_c.framebufFormat = gstate.FrameBufFormat(); - - // This also make skipping drawing very effective. - VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); - if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { - // TODO: Should this eat some cycles? Probably yes. Not sure if important. - return; - } - - CheckDepthUsage(vfb); - - if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); - return; - } - - const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr); - const void *indices = NULL; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { - if (!Memory::IsValidAddress(gstate_c.indexAddr)) { - ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr); - return; - } - indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); - } - - if (vertTypeIsSkinningEnabled(gstate.vertType)) { - DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); - } - - // Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already. - if (flushOnParams_) - drawEngineCommon_->DispatchFlush(); - - Spline::SplineSurface surface; - surface.tess_u = gstate.getPatchDivisionU(); - surface.tess_v = gstate.getPatchDivisionV(); - surface.type_u = (op >> 16) & 0x3; - surface.type_v = (op >> 18) & 0x3; - surface.num_points_u = op & 0xFF; - surface.num_points_v = (op >> 8) & 0xFF; - surface.num_patches_u = surface.num_points_u - 3; - surface.num_patches_v = surface.num_points_v - 3; - surface.primType = gstate.getPatchPrimitiveType(); - surface.patchFacing = gstate.patchfacing & 1; - - SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); - - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); - if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { - gstate_c.submitType = SubmitType::HW_SPLINE; - if (gstate_c.spline_num_points_u != surface.num_points_u) { - gstate_c.Dirty(DIRTY_BEZIERSPLINE); - gstate_c.spline_num_points_u = surface.num_points_u; - } - } else { - gstate_c.submitType = SubmitType::SPLINE; - } - - int bytesRead = 0; - UpdateUVScaleOffset(); - drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); - - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); - gstate_c.submitType = SubmitType::DRAW; - - // After drawing, we advance pointers - see SubmitPrim which does the same. - int count = surface.num_points_u * surface.num_points_v; - AdvanceVerts(gstate.vertType, count, bytesRead); -} - void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) { // Just resetting, nothing to check bounds for. const u32 count = op & 0xFFFF; @@ -1872,18 +1435,6 @@ void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) { } } -void GPUCommon::Execute_BlockTransferStart(u32 op, u32 diff) { - Flush(); - - PROFILE_THIS_SCOPE("block"); // don't include the flush in the profile, would be misleading. - - gstate_c.framebufFormat = gstate.FrameBufFormat(); - - // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. - // Can we skip this on SkipDraw? - DoBlockTransfer(gstate_c.skipDrawReason); -} - void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) { if (!currentList) { gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | (op & 0xF); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index eecfaa68da..f234f2faa3 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -155,11 +155,7 @@ public: void Execute_VertexType(u32 op, u32 diff); void Execute_VertexTypeSkinning(u32 op, u32 diff); - void Execute_Prim(u32 op, u32 diff); - void Execute_Bezier(u32 op, u32 diff); - void Execute_Spline(u32 op, u32 diff); void Execute_BoundingBox(u32 op, u32 diff); - void Execute_BlockTransferStart(u32 op, u32 diff); void Execute_LoadClut(u32 op, u32 diff); @@ -415,7 +411,6 @@ protected: std::string reportingFullInfo_; private: - void CheckDepthUsage(VirtualFramebuffer *vfb); void DoExecuteCall(u32 target); void PopDLQueue(); void CheckDrawSync(); @@ -427,10 +422,3 @@ private: int lastVsync_ = -1; }; - -struct CommonCommandTableEntry { - uint8_t cmd; - uint8_t flags; - uint64_t dirty; - GPUCommon::CmdFunc func; -}; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 2f5029d5f7..eb62e1ff60 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1,3 +1,5 @@ +#include "Common/Profiler/Profiler.h" + #include "Common/GPU/thin3d.h" #include "Common/Serialize/Serializer.h" #include "Common/System/System.h" @@ -6,10 +8,18 @@ #include "Core/Config.h" #include "GPU/GPUCommonHW.h" +#include "GPU/Common/SplineCommon.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/TextureCacheCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" +struct CommonCommandTableEntry { + uint8_t cmd; + uint8_t flags; + uint64_t dirty; + GPUCommonHW::CmdFunc func; +}; + const CommonCommandTableEntry commonCommandTable[] = { // From Common. No flushing but definitely need execute. { GE_CMD_OFFSETADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_OffsetAddr }, @@ -21,11 +31,11 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_VADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_Vaddr }, { GE_CMD_IADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_Iaddr }, { GE_CMD_BJUMP, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BJump }, // EXECUTE - { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoundingBox }, // Shouldn't need to FLUSHBEFORE. + { GE_CMD_BOUNDINGBOX, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_BoundingBox }, // Shouldn't need to FLUSHBEFORE. - { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPUCommon::Execute_Prim }, - { GE_CMD_BEZIER, FLAG_EXECUTE, 0, &GPUCommon::Execute_Bezier }, - { GE_CMD_SPLINE, FLAG_EXECUTE, 0, &GPUCommon::Execute_Spline }, + { GE_CMD_PRIM, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_Prim }, + { GE_CMD_BEZIER, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_Bezier }, + { GE_CMD_SPLINE, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_Spline }, // Changing the vertex type requires us to flush. { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, @@ -274,7 +284,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_TRANSFERSRCPOS, 0 }, { GE_CMD_TRANSFERDSTPOS, 0 }, { GE_CMD_TRANSFERSIZE, 0 }, - { GE_CMD_TRANSFERSTART, FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommon::Execute_BlockTransferStart }, + { GE_CMD_TRANSFERSTART, FLAG_EXECUTE | FLAG_READS_PC, 0, &GPUCommonHW::Execute_BlockTransferStart }, // We don't use the dither table. { GE_CMD_DITH0 }, @@ -346,7 +356,7 @@ GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPU dupeCheck.insert(cmd); } cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = commonCommandTable[i].func; + cmdInfo_[cmd].func = (GPUCommon::CmdFunc)commonCommandTable[i].func; if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { // Can't have FLAG_EXECUTE commands without a function pointer to execute. Crash(); @@ -568,3 +578,453 @@ std::string GPUCommonHW::DebugGetShaderString(std::string id, DebugShaderType ty return shaderManager_->DebugGetShaderString(id, type, stringType); } } + +void GPUCommonHW::CheckDepthUsage(VirtualFramebuffer *vfb) { + if (!gstate_c.usingDepth) { + bool isReadingDepth = false; + bool isClearingDepth = false; + bool isWritingDepth = false; + if (gstate.isModeClear()) { + isClearingDepth = gstate.isClearModeDepthMask(); + isWritingDepth = isClearingDepth; + } else if (gstate.isDepthTestEnabled()) { + isWritingDepth = gstate.isDepthWriteEnabled(); + isReadingDepth = gstate.getDepthTestFunction() > GE_COMP_ALWAYS; + } + + if (isWritingDepth || isReadingDepth) { + gstate_c.usingDepth = true; + gstate_c.clearingDepth = isClearingDepth; + vfb->last_frame_depth_render = gpuStats.numFlips; + if (isWritingDepth) { + vfb->last_frame_depth_updated = gpuStats.numFlips; + } + framebufferManager_->SetDepthFrameBuffer(isClearingDepth); + } + } +} + +void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { + // This drives all drawing. All other state we just buffer up, then we apply it only + // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. + + PROFILE_THIS_SCOPE("execprim"); + + u32 data = op & 0xFFFFFF; + u32 count = data & 0xFFFF; + if (count == 0) + return; + FlushImm(); + + // Upper bits are ignored. + GEPrimitiveType prim = static_cast((data >> 16) & 7); + SetDrawType(DRAW_PRIM, prim); + + // Discard AA lines as we can't do anything that makes sense with these anyway. The SW plugin might, though. + if (gstate.isAntiAliasEnabled()) { + // Heuristic derived from discussions in #6483 and #12588. + // Discard AA lines in Persona 3 Portable, DOA Paradise and Summon Night 5, while still keeping AA lines in Echochrome. + if ((prim == GE_PRIM_LINE_STRIP || prim == GE_PRIM_LINES) && gstate.getTextureFunction() == GE_TEXFUNC_REPLACE) + return; + } + + // Update cached framebuffer format. + // We store it in the cache so it can be modified for blue-to-alpha, next. + gstate_c.framebufFormat = gstate.FrameBufFormat(); + + if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { + ERROR_LOG(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); + return; + } + + // See the documentation for gstate_c.blueToAlpha. + bool blueToAlpha = false; + if (PSP_CoreParameter().compat.flags().BlueToAlpha) { + if (gstate_c.framebufFormat == GEBufferFormat::GE_FORMAT_565 && gstate.getColorMask() == 0x0FFFFF && !gstate.isLogicOpEnabled()) { + blueToAlpha = true; + gstate_c.framebufFormat = GEBufferFormat::GE_FORMAT_4444; + } + if (blueToAlpha != gstate_c.blueToAlpha) { + gstate_c.blueToAlpha = blueToAlpha; + gstate_c.Dirty(DIRTY_FRAMEBUF | DIRTY_FRAGMENTSHADER_STATE | DIRTY_BLEND_STATE); + } + } + + if (PSP_CoreParameter().compat.flags().SplitFramebufferMargin) { + switch (gstate.vertType & 0xFFFFFF) { + case 0x00800102: // through, u16 uv, u16 pos (used for the framebuffer effect in-game) + case 0x0080011c: // through, 8888 color, s16 pos (used for clearing in the margin of the title screen) + case 0x00000183: // float uv, float pos (used for drawing in the margin of the title screen) + // Need to re-check the framebuffer every one of these draws, to update the split if needed. + gstate_c.Dirty(DIRTY_FRAMEBUF); + } + } + + // This also makes skipping drawing very effective. + VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); + if (blueToAlpha) { + vfb->usageFlags |= FB_USAGE_BLUE_TO_ALPHA; + } + + // Must check this after SetRenderFrameBuffer so we know SKIPDRAW_NON_DISPLAYED_FB. + if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { + // Rough estimate, not sure what's correct. + cyclesExecuted += EstimatePerVertexCost() * count; + if (gstate.isModeClear()) { + gpuStats.numClears++; + } + return; + } + + CheckDepthUsage(vfb); + + const void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); + const void *inds = nullptr; + u32 vertexType = gstate.vertType; + if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + u32 indexAddr = gstate_c.indexAddr; + if (!Memory::IsValidAddress(indexAddr)) { + ERROR_LOG(G3D, "Bad index address %08x!", indexAddr); + return; + } + inds = Memory::GetPointerUnchecked(indexAddr); + } + + if (gstate_c.dirty & DIRTY_VERTEXSHADER_STATE) { + vertexCost_ = EstimatePerVertexCost(); + } + + int bytesRead = 0; + UpdateUVScaleOffset(); + + // cull mode + int cullMode = gstate.getCullMode(); + + uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); + drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, cullMode, &bytesRead); + // After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed). + // Some games rely on this, they don't bother reloading VADDR and IADDR. + // The VADDR/IADDR registers are NOT updated. + AdvanceVerts(vertexType, count, bytesRead); + int totalVertCount = count; + + // PRIMs are often followed by more PRIMs. Save some work and submit them immediately. + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); + const u32_le *stall = currentList->stall ? (const u32_le *)Memory::GetPointerUnchecked(currentList->stall) : 0; + int cmdCount = 0; + + // Optimized submission of sequences of PRIM. Allows us to avoid going through all the mess + // above for each one. This can be expanded to support additional games that intersperse + // PRIM commands with other commands. A special case is Earth Defence Force 2 that changes culling mode + // between each prim, we just change the triangle winding right here to still be able to join draw calls. + + uint32_t vtypeCheckMask = ~GE_VTYPE_WEIGHTCOUNT_MASK; + if (!g_Config.bSoftwareSkinning) + vtypeCheckMask = 0xFFFFFFFF; + + if (debugRecording_) + goto bail; + + while (src != stall) { + uint32_t data = *src; + switch (data >> 24) { + case GE_CMD_PRIM: + { + u32 count = data & 0xFFFF; + if (count == 0) { + // Ignore. + break; + } + + GEPrimitiveType newPrim = static_cast((data >> 16) & 7); + SetDrawType(DRAW_PRIM, newPrim); + // TODO: more efficient updating of verts/inds + verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr); + inds = nullptr; + if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + inds = Memory::GetPointerUnchecked(gstate_c.indexAddr); + } + + drawEngineCommon_->SubmitPrim(verts, inds, newPrim, count, vertTypeID, cullMode, &bytesRead); + AdvanceVerts(vertexType, count, bytesRead); + totalVertCount += count; + break; + } + case GE_CMD_VERTEXTYPE: + { + uint32_t diff = data ^ vertexType; + // don't mask upper bits, vertexType is unmasked + if (diff & vtypeCheckMask) { + goto bail; + } else { + vertexType = data; + vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning); + } + break; + } + case GE_CMD_VADDR: + gstate.cmdmem[GE_CMD_VADDR] = data; + gstate_c.vertexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); + break; + case GE_CMD_IADDR: + gstate.cmdmem[GE_CMD_IADDR] = data; + gstate_c.indexAddr = gstate_c.getRelativeAddress(data & 0x00FFFFFF); + break; + case GE_CMD_OFFSETADDR: + gstate.cmdmem[GE_CMD_OFFSETADDR] = data; + gstate_c.offsetAddr = data << 8; + break; + case GE_CMD_BASE: + gstate.cmdmem[GE_CMD_BASE] = data; + break; + case GE_CMD_CULLFACEENABLE: + // Earth Defence Force 2 + if (gstate.cmdmem[GE_CMD_CULLFACEENABLE] != data) { + goto bail; + } + break; + case GE_CMD_CULL: + // flip face by indices for triangles + cullMode = data & 1; + break; + case GE_CMD_TEXFLUSH: + case GE_CMD_NOP: + case GE_CMD_NOP_FF: + gstate.cmdmem[data >> 24] = data; + break; + case GE_CMD_BONEMATRIXNUMBER: + gstate.cmdmem[GE_CMD_BONEMATRIXNUMBER] = data; + break; + case GE_CMD_TEXSCALEU: + gstate.cmdmem[GE_CMD_TEXSCALEU] = data; + gstate_c.uv.uScale = getFloat24(data); + break; + case GE_CMD_TEXSCALEV: + gstate.cmdmem[GE_CMD_TEXSCALEV] = data; + gstate_c.uv.vScale = getFloat24(data); + break; + case GE_CMD_TEXOFFSETU: + gstate.cmdmem[GE_CMD_TEXOFFSETU] = data; + gstate_c.uv.uOff = getFloat24(data); + break; + case GE_CMD_TEXOFFSETV: + gstate.cmdmem[GE_CMD_TEXOFFSETV] = data; + gstate_c.uv.vOff = getFloat24(data); + break; + case GE_CMD_TEXLEVEL: + // Same Gran Turismo hack from Execute_TexLevel + if ((data & 3) != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & data) != 0) { + goto bail; + } + gstate.cmdmem[GE_CMD_TEXLEVEL] = data; + break; + case GE_CMD_CALL: + { + // A bone matrix probably. If not we bail. + const u32 target = gstate_c.getRelativeAddress(data & 0x00FFFFFC); + if ((Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA && + (Memory::ReadUnchecked_U32(target + 11 * 4) >> 24) == GE_CMD_BONEMATRIXDATA && + (Memory::ReadUnchecked_U32(target + 12 * 4) >> 24) == GE_CMD_RET && + (target > currentList->stall || target + 12 * 4 < currentList->stall) && + (gstate.boneMatrixNumber & 0x00FFFFFF) <= 96 - 12) { + FastLoadBoneMatrix(target); + } else { + goto bail; + } + break; + } + + case GE_CMD_TEXBUFWIDTH0: + case GE_CMD_TEXADDR0: + if (data != gstate.cmdmem[data >> 24]) + goto bail; + break; + + default: + // All other commands might need a flush or something, stop this inner loop. + goto bail; + } + cmdCount++; + src++; + } + +bail: + gstate.cmdmem[GE_CMD_VERTEXTYPE] = vertexType; + // Skip over the commands we just read out manually. + if (cmdCount > 0) { + UpdatePC(currentList->pc, currentList->pc + cmdCount * 4); + currentList->pc += cmdCount * 4; + // flush back cull mode + if (cullMode != gstate.getCullMode()) { + // We rewrote everything to the old cull mode, so flush first. + drawEngineCommon_->DispatchFlush(); + + // Now update things for next time. + gstate.cmdmem[GE_CMD_CULL] ^= 1; + gstate_c.Dirty(DIRTY_RASTER_STATE); + } + } + + gpuStats.vertexGPUCycles += vertexCost_ * totalVertCount; + cyclesExecuted += vertexCost_ * totalVertCount; +} + +void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) { + // We don't dirty on normal changes anymore as we prescale, but it's needed for splines/bezier. + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + + gstate_c.framebufFormat = gstate.FrameBufFormat(); + + // This also make skipping drawing very effective. + VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); + if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { + // TODO: Should this eat some cycles? Probably yes. Not sure if important. + return; + } + + CheckDepthUsage(vfb); + + if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); + return; + } + + const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr); + const void *indices = NULL; + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + if (!Memory::IsValidAddress(gstate_c.indexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr); + return; + } + indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); + } + + if (vertTypeIsSkinningEnabled(gstate.vertType)) { + DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); + } + + // Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already. + if (flushOnParams_) + drawEngineCommon_->DispatchFlush(); + + Spline::BezierSurface surface; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.num_points_u = op & 0xFF; + surface.num_points_v = (op >> 8) & 0xFF; + surface.num_patches_u = (surface.num_points_u - 1) / 3; + surface.num_patches_v = (surface.num_points_v - 1) / 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = gstate.patchfacing & 1; + + SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType)); + + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { + gstate_c.submitType = SubmitType::HW_BEZIER; + if (gstate_c.spline_num_points_u != surface.num_points_u) { + gstate_c.Dirty(DIRTY_BEZIERSPLINE); + gstate_c.spline_num_points_u = surface.num_points_u; + } + } else { + gstate_c.submitType = SubmitType::BEZIER; + } + + int bytesRead = 0; + UpdateUVScaleOffset(); + drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier"); + + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.submitType = SubmitType::DRAW; + + // After drawing, we advance pointers - see SubmitPrim which does the same. + int count = surface.num_points_u * surface.num_points_v; + AdvanceVerts(gstate.vertType, count, bytesRead); +} + +void GPUCommonHW::Execute_Spline(u32 op, u32 diff) { + // We don't dirty on normal changes anymore as we prescale, but it's needed for splines/bezier. + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + + gstate_c.framebufFormat = gstate.FrameBufFormat(); + + // This also make skipping drawing very effective. + VirtualFramebuffer *vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); + if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { + // TODO: Should this eat some cycles? Probably yes. Not sure if important. + return; + } + + CheckDepthUsage(vfb); + + if (!Memory::IsValidAddress(gstate_c.vertexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad vertex address %08x!", gstate_c.vertexAddr); + return; + } + + const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr); + const void *indices = NULL; + if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { + if (!Memory::IsValidAddress(gstate_c.indexAddr)) { + ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr); + return; + } + indices = Memory::GetPointerUnchecked(gstate_c.indexAddr); + } + + if (vertTypeIsSkinningEnabled(gstate.vertType)) { + DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType)); + } + + // Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already. + if (flushOnParams_) + drawEngineCommon_->DispatchFlush(); + + Spline::SplineSurface surface; + surface.tess_u = gstate.getPatchDivisionU(); + surface.tess_v = gstate.getPatchDivisionV(); + surface.type_u = (op >> 16) & 0x3; + surface.type_v = (op >> 18) & 0x3; + surface.num_points_u = op & 0xFF; + surface.num_points_v = (op >> 8) & 0xFF; + surface.num_patches_u = surface.num_points_u - 3; + surface.num_patches_v = surface.num_points_v - 3; + surface.primType = gstate.getPatchPrimitiveType(); + surface.patchFacing = gstate.patchfacing & 1; + + SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType)); + + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + if (drawEngineCommon_->CanUseHardwareTessellation(surface.primType)) { + gstate_c.submitType = SubmitType::HW_SPLINE; + if (gstate_c.spline_num_points_u != surface.num_points_u) { + gstate_c.Dirty(DIRTY_BEZIERSPLINE); + gstate_c.spline_num_points_u = surface.num_points_u; + } + } else { + gstate_c.submitType = SubmitType::SPLINE; + } + + int bytesRead = 0; + UpdateUVScaleOffset(); + drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline"); + + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE); + gstate_c.submitType = SubmitType::DRAW; + + // After drawing, we advance pointers - see SubmitPrim which does the same. + int count = surface.num_points_u * surface.num_points_v; + AdvanceVerts(gstate.vertType, count, bytesRead); +} + +void GPUCommonHW::Execute_BlockTransferStart(u32 op, u32 diff) { + Flush(); + + PROFILE_THIS_SCOPE("block"); // don't include the flush in the profile, would be misleading. + + gstate_c.framebufFormat = gstate.FrameBufFormat(); + + // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. + // Can we skip this on SkipDraw? + DoBlockTransfer(gstate_c.skipDrawReason); +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index f059d93fc0..11cadb0d0a 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -19,6 +19,13 @@ public: std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; + void Execute_Prim(u32 op, u32 diff); + void Execute_Bezier(u32 op, u32 diff); + void Execute_Spline(u32 op, u32 diff); + void Execute_BlockTransferStart(u32 op, u32 diff); + + typedef void (GPUCommonHW::*CmdFunc)(u32 op, u32 diff); + protected: void UpdateCmdInfo() override; @@ -32,5 +39,7 @@ protected: void CheckRenderResized() override; int msaaLevel_ = 0; -}; +private: + void CheckDepthUsage(VirtualFramebuffer *vfb); +}; From bcd38bc9e8bfbb1c1996424e4ccc096b15313a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 17:37:57 +0100 Subject: [PATCH 167/424] Move some more commands to GPUCommonHW. Get rid of ugly cast. --- GPU/GPUCommon.cpp | 180 +--------------------------------------- GPU/GPUCommon.h | 32 +------ GPU/GPUCommonHW.cpp | 198 ++++++++++++++++++++++++++++++++++++++++++-- GPU/GPUCommonHW.h | 14 +++- 4 files changed, 207 insertions(+), 217 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 7338d29d3e..976392b818 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -50,9 +50,6 @@ #include "GPU/Debugger/Debugger.h" #include "GPU/Debugger/Record.h" -// TODO: Make class member? -GPUCommonHW::CommandInfo GPUCommon::cmdInfo_[256]; - void GPUCommon::Flush() { drawEngineCommon_->DispatchFlush(); } @@ -797,53 +794,6 @@ bool GPUCommon::InterpretList(DisplayList &list) { return gpuState == GPUSTATE_DONE || gpuState == GPUSTATE_ERROR; } -// Maybe should write this in ASM... -void GPUCommon::FastRunLoop(DisplayList &list) { - PROFILE_THIS_SCOPE("gpuloop"); - - if (!Memory::IsValidAddress(list.pc)) { - // We're having some serious problems here, just bail and try to limp along and not crash the app. - downcount = 0; - return; - } - - const CommandInfo *cmdInfo = cmdInfo_; - int dc = downcount; - for (; dc > 0; --dc) { - // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer - const u32 op = *(const u32_le *)(Memory::base + list.pc); - const u32 cmd = op >> 24; - const CommandInfo &info = cmdInfo[cmd]; - const u32 diff = op ^ gstate.cmdmem[cmd]; - if (diff == 0) { - if (info.flags & FLAG_EXECUTE) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } - } else { - uint64_t flags = info.flags; - if (flags & FLAG_FLUSHBEFOREONCHANGE) { - if (drawEngineCommon_->GetNumDrawCalls()) { - drawEngineCommon_->DispatchFlush(); - } - } - gstate.cmdmem[cmd] = op; - if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { - downcount = dc; - (this->*info.func)(op, diff); - dc = downcount; - } else { - uint64_t dirty = flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } - } - list.pc += 4; - } - downcount = 0; -} - void GPUCommon::BeginFrame() { immCount_ = 0; if (dumpNextFrame_) { @@ -862,11 +812,9 @@ void GPUCommon::BeginFrame() { } } -void GPUCommon::SlowRunLoop(DisplayList &list) -{ +void GPUCommon::SlowRunLoop(DisplayList &list) { const bool dumpThisFrame = dumpThisFrame_; - while (downcount > 0) - { + while (downcount > 0) { bool process = GPUDebug::NotifyCommand(list.pc); if (process) { GPURecord::NotifyCommand(list.pc); @@ -1312,75 +1260,6 @@ void GPUCommon::Execute_End(u32 op, u32 diff) { } } -void GPUCommon::Execute_TexLevel(u32 op, u32 diff) { - // TODO: If you change the rules here, don't forget to update the inner interpreter in Execute_Prim. - if (diff == 0xFFFFFFFF) - return; - - gstate.texlevel ^= diff; - - if (diff & 0xFF0000) { - // Piggyback on this flag for 3D textures. - gstate_c.Dirty(DIRTY_MIPBIAS); - } - if (gstate.getTexLevelMode() != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & gstate.texlevel) != 0) { - Flush(); - } - - gstate.texlevel ^= diff; - - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE); -} - -void GPUCommon::Execute_TexSize0(u32 op, u32 diff) { - // Render to texture may have overridden the width/height. - // Don't reset it unless the size is different / the texture has changed. - if (diff || gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS)) { - gstate_c.curTextureWidth = gstate.getTextureWidth(0); - gstate_c.curTextureHeight = gstate.getTextureHeight(0); - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - // We will need to reset the texture now. - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - } -} - -void GPUCommon::Execute_VertexType(u32 op, u32 diff) { - if (diff) - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); - if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) { - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - // Switching between through and non-through, we need to invalidate a bunch of stuff. - if (diff & GE_VTYPE_THROUGH_MASK) - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_CULLRANGE | DIRTY_FOGCOEFENABLE); - } -} - -void GPUCommon::Execute_LoadClut(u32 op, u32 diff) { - gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); - textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); -} - -void GPUCommon::Execute_VertexTypeSkinning(u32 op, u32 diff) { - // Don't flush when weight count changes. - if (diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) { - // Restore and flush - gstate.vertType ^= diff; - Flush(); - gstate.vertType ^= diff; - if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) - gstate_c.Dirty(DIRTY_UVSCALEOFFSET); - // In this case, we may be doing weights and morphs. - // Update any bone matrix uniforms so it uses them correctly. - if ((op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { - gstate_c.Dirty(gstate_c.deferredVertTypeDirty); - gstate_c.deferredVertTypeDirty = 0; - } - gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); - } - if (diff & GE_VTYPE_THROUGH_MASK) - gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_CULLRANGE | DIRTY_FOGCOEFENABLE); -} - void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) { // Just resetting, nothing to check bounds for. const u32 count = op & 0xFFFF; @@ -1849,19 +1728,6 @@ void GPUCommon::FlushImm() { } } -void GPUCommon::ExecuteOp(u32 op, u32 diff) { - const u8 cmd = op >> 24; - const CommandInfo info = cmdInfo_[cmd]; - const u8 cmdFlags = info.flags; - if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { - (this->*info.func)(op, diff); - } else if (diff) { - uint64_t dirty = info.flags >> 8; - if (dirty) - gstate_c.Dirty(dirty); - } -} - void GPUCommon::Execute_Unknown(u32 op, u32 diff) { if ((op & 0xFFFFFF) != 0) WARN_LOG_REPORT_ONCE(unknowncmd, G3D, "Unknown GE command : %08x ", op); @@ -2613,45 +2479,3 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { vertexAverageCycles ); } - - -u32 GPUCommon::CheckGPUFeaturesLate(u32 features) const { - // If we already have a 16-bit depth buffer, we don't need to round. - bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; - bool prefer16 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D16; - if (!prefer16) { - if (sawExactEqualDepth_ && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - // Exact equal tests tend to have issues unless we use the PSP's depth range. - // We use 24-bit depth virtually everwhere, the fallback is just for safety. - if (prefer24) - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - else - features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; - } else if (!g_Config.bHighQualityDepth && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { - if (prefer24 && (features & GPU_USE_ACCURATE_DEPTH) != 0) { - // Here we can simulate a 16 bit depth buffer by scaling. - // Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good. - features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; - } else { - // Use fragment rounding on where available otherwise. - features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; - } - } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { - features |= GPU_ROUND_DEPTH_TO_16BIT; - } - } - - return features; -} - -void GPUCommon::CheckFlushOp(int cmd, u32 diff) { - const u8 cmdFlags = cmdInfo_[cmd].flags; - if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { - if (dumpThisFrame_) { - NOTICE_LOG(G3D, "================ FLUSH ================"); - } - drawEngineCommon_->DispatchFlush(); - } -} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index f234f2faa3..8407c6a520 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -60,7 +60,6 @@ struct TransformedVertex { u32 color1_32; }; - void CopyFromWithOffset(const TransformedVertex &other, float xoff, float yoff) { this->x = other.x + xoff; this->y = other.y + yoff; @@ -108,7 +107,6 @@ public: void DumpNextFrame() override; - void ExecuteOp(u32 op, u32 diff) override; virtual void PreExecuteOp(u32 op, u32 diff) {} bool InterpretList(DisplayList &list); @@ -152,16 +150,8 @@ public: void Execute_Ret(u32 op, u32 diff); void Execute_End(u32 op, u32 diff); - void Execute_VertexType(u32 op, u32 diff); - void Execute_VertexTypeSkinning(u32 op, u32 diff); - void Execute_BoundingBox(u32 op, u32 diff); - void Execute_LoadClut(u32 op, u32 diff); - - void Execute_TexSize0(u32 op, u32 diff); - void Execute_TexLevel(u32 op, u32 diff); - void Execute_WorldMtxNum(u32 op, u32 diff); void Execute_WorldMtxData(u32 op, u32 diff); void Execute_ViewMtxNum(u32 op, u32 diff); @@ -267,9 +257,6 @@ protected: virtual void CheckRenderResized() {} - // Add additional common features dependent on other features, which may be backend-determined. - u32 CheckGPUFeaturesLate(u32 features) const; - inline bool IsTrianglePrim(GEPrimitiveType prim) const { return prim != GE_PRIM_RECTANGLES && prim > GE_PRIM_LINE_STRIP; } @@ -292,7 +279,7 @@ protected: void BeginFrame() override; void UpdateVsyncInterval(bool force); - virtual void FastRunLoop(DisplayList &list); + virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); void UpdatePC(u32 currentPC, u32 newPC); @@ -304,8 +291,6 @@ protected: // TODO: Unify this. The only backend that differs is Vulkan. virtual void FinishDeferred() {} - void CheckFlushOp(int cmd, u32 diff); - void AdvanceVerts(u32 vertType, int count, int bytesRead) { if ((vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) { int indexShift = ((vertType & GE_VTYPE_IDX_MASK) >> GE_VTYPE_IDX_SHIFT) - 1; @@ -333,21 +318,6 @@ protected: GraphicsContext *gfxCtx_; Draw::DrawContext *draw_; - struct CommandInfo { - uint64_t flags; - GPUCommon::CmdFunc func; - - // Dirty flags are mashed into the regular flags by a left shift of 8. - void AddDirty(u64 dirty) { - flags |= dirty << 8; - } - void RemoveDirty(u64 dirty) { - flags &= ~(dirty << 8); - } - }; - - static CommandInfo cmdInfo_[256]; - typedef std::list DisplayListQueue; int nextListID; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index eb62e1ff60..41f0a34c44 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -20,6 +20,21 @@ struct CommonCommandTableEntry { GPUCommonHW::CmdFunc func; }; +struct CommandInfo { + uint64_t flags; + GPUCommonHW::CmdFunc func; + + // Dirty flags are mashed into the regular flags by a left shift of 8. + void AddDirty(u64 dirty) { + flags |= dirty << 8; + } + void RemoveDirty(u64 dirty) { + flags &= ~(dirty << 8); + } +}; + +static CommandInfo cmdInfo_[256]; + const CommonCommandTableEntry commonCommandTable[] = { // From Common. No flushing but definitely need execute. { GE_CMD_OFFSETADDR, FLAG_EXECUTE, 0, &GPUCommon::Execute_OffsetAddr }, @@ -38,9 +53,9 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_SPLINE, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_Spline }, // Changing the vertex type requires us to flush. - { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommon::Execute_VertexType }, + { GE_CMD_VERTEXTYPE, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, 0, &GPUCommonHW::Execute_VertexType }, - { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_LoadClut }, + { GE_CMD_LOADCLUT, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommonHW::Execute_LoadClut}, // These two are actually processed in CMD_END. { GE_CMD_SIGNAL }, @@ -122,7 +137,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_TEXOFFSETU }, { GE_CMD_TEXOFFSETV }, - { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommon::Execute_TexSize0 }, + { GE_CMD_TEXSIZE0, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTE, 0, &GPUCommonHW::Execute_TexSize0 }, { GE_CMD_TEXSIZE1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXSIZE2, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXSIZE3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, @@ -131,7 +146,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_TEXSIZE6, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXSIZE7, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXFORMAT, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE }, - { GE_CMD_TEXLEVEL, FLAG_EXECUTEONCHANGE, DIRTY_TEXTURE_PARAMS, &GPUCommon::Execute_TexLevel }, + { GE_CMD_TEXLEVEL, FLAG_EXECUTEONCHANGE, DIRTY_TEXTURE_PARAMS, &GPUCommonHW::Execute_TexLevel }, { GE_CMD_TEXLODSLOPE, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, { GE_CMD_TEXADDR0, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_IMAGE | DIRTY_UVSCALEOFFSET }, { GE_CMD_TEXADDR1, FLAG_FLUSHBEFOREONCHANGE, DIRTY_TEXTURE_PARAMS }, @@ -356,7 +371,7 @@ GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPU dupeCheck.insert(cmd); } cmdInfo_[cmd].flags |= (uint64_t)commonCommandTable[i].flags | (commonCommandTable[i].dirty << 8); - cmdInfo_[cmd].func = (GPUCommon::CmdFunc)commonCommandTable[i].func; + cmdInfo_[cmd].func = commonCommandTable[i].func; if ((cmdInfo_[cmd].flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) && !cmdInfo_[cmd].func) { // Can't have FLAG_EXECUTE commands without a function pointer to execute. Crash(); @@ -402,10 +417,10 @@ void GPUCommonHW::DeviceLost() { void GPUCommonHW::UpdateCmdInfo() { if (g_Config.bSoftwareSkinning) { cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning; + cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommonHW::Execute_VertexTypeSkinning; } else { cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE; - cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType; + cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommonHW::Execute_VertexType; } if (g_Config.bFastMemory) { @@ -442,6 +457,16 @@ void GPUCommonHW::UpdateCmdInfo() { } } +void GPUCommonHW::CheckFlushOp(int cmd, u32 diff) { + const u8 cmdFlags = cmdInfo_[cmd].flags; + if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { + if (dumpThisFrame_) { + NOTICE_LOG(G3D, "================ FLUSH ================"); + } + drawEngineCommon_->DispatchFlush(); + } +} + void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) { CheckFlushOp(op >> 24, diff); } @@ -547,6 +572,37 @@ u32 GPUCommonHW::CheckGPUFeatures() const { return features; } +u32 GPUCommonHW::CheckGPUFeaturesLate(u32 features) const { + // If we already have a 16-bit depth buffer, we don't need to round. + bool prefer24 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D24_S8; + bool prefer16 = draw_->GetDeviceCaps().preferredDepthBufferFormat == Draw::DataFormat::D16; + if (!prefer16) { + if (sawExactEqualDepth_ && (features & GPU_USE_ACCURATE_DEPTH) != 0) { + // Exact equal tests tend to have issues unless we use the PSP's depth range. + // We use 24-bit depth virtually everwhere, the fallback is just for safety. + if (prefer24) + features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; + else + features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; + } else if (!g_Config.bHighQualityDepth && (features & GPU_USE_ACCURATE_DEPTH) != 0) { + features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; + } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { + if (prefer24 && (features & GPU_USE_ACCURATE_DEPTH) != 0) { + // Here we can simulate a 16 bit depth buffer by scaling. + // Note that the depth buffer is fixed point, not floating, so dividing by 256 is pretty good. + features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; + } else { + // Use fragment rounding on where available otherwise. + features |= GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT; + } + } else if (PSP_CoreParameter().compat.flags().VertexDepthRounding) { + features |= GPU_ROUND_DEPTH_TO_16BIT; + } + } + + return features; +} + void GPUCommonHW::UpdateMSAALevel(Draw::DrawContext *draw) { int level = g_Config.iMultiSampleLevel; if (draw && draw->GetDeviceCaps().multiSampleLevelsMask & (1 << level)) { @@ -604,6 +660,97 @@ void GPUCommonHW::CheckDepthUsage(VirtualFramebuffer *vfb) { } } +void GPUCommonHW::ExecuteOp(u32 op, u32 diff) { + const u8 cmd = op >> 24; + const CommandInfo info = cmdInfo_[cmd]; + const u8 cmdFlags = info.flags; + if ((cmdFlags & FLAG_EXECUTE) || (diff && (cmdFlags & FLAG_EXECUTEONCHANGE))) { + (this->*info.func)(op, diff); + } else if (diff) { + uint64_t dirty = info.flags >> 8; + if (dirty) + gstate_c.Dirty(dirty); + } +} + +void GPUCommonHW::FastRunLoop(DisplayList &list) { + PROFILE_THIS_SCOPE("gpuloop"); + + if (!Memory::IsValidAddress(list.pc)) { + // We're having some serious problems here, just bail and try to limp along and not crash the app. + downcount = 0; + return; + } + + const CommandInfo *cmdInfo = cmdInfo_; + int dc = downcount; + for (; dc > 0; --dc) { + // We know that display list PCs have the upper nibble == 0 - no need to mask the pointer + const u32 op = *(const u32_le *)(Memory::base + list.pc); + const u32 cmd = op >> 24; + const CommandInfo &info = cmdInfo[cmd]; + const u32 diff = op ^ gstate.cmdmem[cmd]; + if (diff == 0) { + if (info.flags & FLAG_EXECUTE) { + downcount = dc; + (this->*info.func)(op, diff); + dc = downcount; + } + } else { + uint64_t flags = info.flags; + if (flags & FLAG_FLUSHBEFOREONCHANGE) { + if (drawEngineCommon_->GetNumDrawCalls()) { + drawEngineCommon_->DispatchFlush(); + } + } + gstate.cmdmem[cmd] = op; + if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) { + downcount = dc; + (this->*info.func)(op, diff); + dc = downcount; + } else { + uint64_t dirty = flags >> 8; + if (dirty) + gstate_c.Dirty(dirty); + } + } + list.pc += 4; + } + downcount = 0; +} + +void GPUCommonHW::Execute_VertexType(u32 op, u32 diff) { + if (diff) + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) { + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + // Switching between through and non-through, we need to invalidate a bunch of stuff. + if (diff & GE_VTYPE_THROUGH_MASK) + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_CULLRANGE | DIRTY_FOGCOEFENABLE); + } +} + +void GPUCommonHW::Execute_VertexTypeSkinning(u32 op, u32 diff) { + // Don't flush when weight count changes. + if (diff & ~GE_VTYPE_WEIGHTCOUNT_MASK) { + // Restore and flush + gstate.vertType ^= diff; + Flush(); + gstate.vertType ^= diff; + if (diff & (GE_VTYPE_TC_MASK | GE_VTYPE_THROUGH_MASK)) + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + // In this case, we may be doing weights and morphs. + // Update any bone matrix uniforms so it uses them correctly. + if ((op & GE_VTYPE_MORPHCOUNT_MASK) != 0) { + gstate_c.Dirty(gstate_c.deferredVertTypeDirty); + gstate_c.deferredVertTypeDirty = 0; + } + gstate_c.Dirty(DIRTY_VERTEXSHADER_STATE); + } + if (diff & GE_VTYPE_THROUGH_MASK) + gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE | DIRTY_CULLRANGE | DIRTY_FOGCOEFENABLE); +} + void GPUCommonHW::Execute_Prim(u32 op, u32 diff) { // This drives all drawing. All other state we just buffer up, then we apply it only // when it's time to draw. As most PSP games set state redundantly ALL THE TIME, this is a huge optimization. @@ -1028,3 +1175,40 @@ void GPUCommonHW::Execute_BlockTransferStart(u32 op, u32 diff) { // Can we skip this on SkipDraw? DoBlockTransfer(gstate_c.skipDrawReason); } + +void GPUCommonHW::Execute_TexSize0(u32 op, u32 diff) { + // Render to texture may have overridden the width/height. + // Don't reset it unless the size is different / the texture has changed. + if (diff || gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS)) { + gstate_c.curTextureWidth = gstate.getTextureWidth(0); + gstate_c.curTextureHeight = gstate.getTextureHeight(0); + gstate_c.Dirty(DIRTY_UVSCALEOFFSET); + // We will need to reset the texture now. + gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); + } +} + +void GPUCommonHW::Execute_TexLevel(u32 op, u32 diff) { + // TODO: If you change the rules here, don't forget to update the inner interpreter in Execute_Prim. + if (diff == 0xFFFFFFFF) + return; + + gstate.texlevel ^= diff; + + if (diff & 0xFF0000) { + // Piggyback on this flag for 3D textures. + gstate_c.Dirty(DIRTY_MIPBIAS); + } + if (gstate.getTexLevelMode() != GE_TEXLEVEL_MODE_AUTO && (0x00FF0000 & gstate.texlevel) != 0) { + Flush(); + } + + gstate.texlevel ^= diff; + + gstate_c.Dirty(DIRTY_TEXTURE_PARAMS | DIRTY_FRAGMENTSHADER_STATE); +} + +void GPUCommonHW::Execute_LoadClut(u32 op, u32 diff) { + gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); + textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 11cadb0d0a..4f02ab15ee 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -19,17 +19,27 @@ public: std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; + void Execute_VertexType(u32 op, u32 diff); + void Execute_VertexTypeSkinning(u32 op, u32 diff); + void Execute_Prim(u32 op, u32 diff); void Execute_Bezier(u32 op, u32 diff); void Execute_Spline(u32 op, u32 diff); void Execute_BlockTransferStart(u32 op, u32 diff); + void Execute_TexSize0(u32 op, u32 diff); + void Execute_TexLevel(u32 op, u32 diff); + void Execute_LoadClut(u32 op, u32 diff); + typedef void (GPUCommonHW::*CmdFunc)(u32 op, u32 diff); + void FastRunLoop(DisplayList &list) override; + void ExecuteOp(u32 op, u32 diff) override; + protected: void UpdateCmdInfo() override; - void PreExecuteOp(u32 op, u32 diff); + void PreExecuteOp(u32 op, u32 diff) override; void ClearCacheNextFrame() override; // Needs to be called on GPU thread, not reporting thread. @@ -37,9 +47,11 @@ protected: void UpdateMSAALevel(Draw::DrawContext *draw) override; void CheckRenderResized() override; + u32 CheckGPUFeaturesLate(u32 features) const; int msaaLevel_ = 0; private: void CheckDepthUsage(VirtualFramebuffer *vfb); + void CheckFlushOp(int cmd, u32 diff); }; From 71ed265c576c87e4fa8cf56668115d8c717272e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 17:40:11 +0100 Subject: [PATCH 168/424] Move sawExactEqualDepth to GPUCommonHW --- GPU/GPUCommon.cpp | 5 ----- GPU/GPUCommon.h | 3 +-- GPU/GPUCommonHW.cpp | 9 +++++++++ GPU/GPUCommonHW.h | 3 +++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 976392b818..f2f8c3c335 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -805,11 +805,6 @@ void GPUCommon::BeginFrame() { } GPUDebug::NotifyBeginFrame(); GPURecord::NotifyBeginFrame(); - - if (drawEngineCommon_->EverUsedExactEqualDepth() && !sawExactEqualDepth_) { - sawExactEqualDepth_ = true; - gstate_c.SetUseFlags(CheckGPUFeatures()); - } } void GPUCommon::SlowRunLoop(DisplayList &list) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 8407c6a520..c4d0a97a35 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -343,7 +343,6 @@ protected: bool displayResized_ = false; bool renderResized_ = false; bool configChanged_ = false; - bool sawExactEqualDepth_ = false; DrawType lastDraw_ = DRAW_UNKNOWN; GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; @@ -362,7 +361,7 @@ protected: uint32_t edramTranslation_ = 0x400; - // Whe matrix data overflows, the CPU visible values wrap and bleed between matrices. + // When matrix data overflows, the CPU visible values wrap and bleed between matrices. // But this doesn't actually change the values used by rendering. // The CPU visible values affect the GPU when list contexts are restored. // Note: not maintained by all backends, here for save stating. diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 41f0a34c44..6ae48c3c5b 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -457,6 +457,15 @@ void GPUCommonHW::UpdateCmdInfo() { } } +void GPUCommonHW::BeginFrame() { + GPUCommon::BeginFrame(); + + if (drawEngineCommon_->EverUsedExactEqualDepth() && !sawExactEqualDepth_) { + sawExactEqualDepth_ = true; + gstate_c.SetUseFlags(CheckGPUFeatures()); + } +} + void GPUCommonHW::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 4f02ab15ee..a51d349868 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -13,6 +13,8 @@ public: void DoState(PointerWrap &p) override; void DeviceLost() override; + void BeginFrame() override; + u32 CheckGPUFeatures() const override; // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. @@ -50,6 +52,7 @@ protected: u32 CheckGPUFeaturesLate(u32 features) const; int msaaLevel_ = 0; + bool sawExactEqualDepth_ = false; private: void CheckDepthUsage(VirtualFramebuffer *vfb); From 8520e1dec59ca217c9e72387fc7615482ee9ce46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 17:42:46 +0100 Subject: [PATCH 169/424] Move SetDisplayFramebuffer to GPUCommonHW --- GPU/GPUCommon.cpp | 4 ---- GPU/GPUCommon.h | 1 - GPU/GPUCommonHW.cpp | 4 ++++ GPU/GPUCommonHW.h | 2 ++ 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index f2f8c3c335..f7e5864cf3 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2031,10 +2031,6 @@ void GPUCommon::SetCmdValue(u32 op) { downcount = 0; } -void GPUCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { - framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format); -} - void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { u32 srcBasePtr = gstate.getTransferSrcAddress(); u32 srcStride = gstate.getTransferSrcStride(); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index c4d0a97a35..b1367275d4 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -127,7 +127,6 @@ public: uint32_t SetAddrTranslation(uint32_t value) override; uint32_t GetAddrTranslation() override; - void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput(bool reallyDirty) override = 0; bool PerformMemoryCopy(u32 dest, u32 src, int size, GPUCopyFlag flags = GPUCopyFlag::NONE) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 6ae48c3c5b..b51e552543 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -466,6 +466,10 @@ void GPUCommonHW::BeginFrame() { } } +void GPUCommonHW::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { + framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format); +} + void GPUCommonHW::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE)) { diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index a51d349868..d57f8619b4 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -17,6 +17,8 @@ public: u32 CheckGPUFeatures() const override; + void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; + // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; From 807d40e09531d27a4a9b268f3b2ccd0830e954fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 17:48:37 +0100 Subject: [PATCH 170/424] Move the matrix loading exec functions too --- GPU/GPUCommon.cpp | 293 ----------------------------------------- GPU/GPUCommon.h | 11 -- GPU/GPUCommonHW.cpp | 314 ++++++++++++++++++++++++++++++++++++++++++-- GPU/GPUCommonHW.h | 11 ++ 4 files changed, 315 insertions(+), 314 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index f7e5864cf3..09b4278c7e 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1309,299 +1309,6 @@ void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) { } } -void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) { - if (!currentList) { - gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | (op & 0xF); - return; - } - - // This is almost always followed by GE_CMD_WORLDMATRIXDATA. - const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - u32 *dst = (u32 *)(gstate.worldMatrix + (op & 0xF)); - const int end = 12 - (op & 0xF); - int i = 0; - - // We must record the individual data commands while debugRecording_. - bool fastLoad = !debugRecording_ && end > 0; - // Stalling in the middle of a matrix would be stupid, I doubt this check is necessary. - if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { - fastLoad = false; - } - - if (fastLoad) { - while ((src[i] >> 24) == GE_CMD_WORLDMATRIXDATA) { - const u32 newVal = src[i] << 8; - if (dst[i] != newVal) { - Flush(); - dst[i] = newVal; - gstate_c.Dirty(DIRTY_WORLDMATRIX); - } - if (++i >= end) { - break; - } - } - } - - const int count = i; - gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | ((op & 0xF) + count); - - // Skip over the loaded data, it's done now. - UpdatePC(currentList->pc, currentList->pc + count * 4); - currentList->pc += count * 4; -} - -void GPUCommon::Execute_WorldMtxData(u32 op, u32 diff) { - // Note: it's uncommon to get here now, see above. - int num = gstate.worldmtxnum & 0x00FFFFFF; - u32 newVal = op << 8; - if (num < 12 && newVal != ((const u32 *)gstate.worldMatrix)[num]) { - Flush(); - ((u32 *)gstate.worldMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_WORLDMATRIX); - } - num++; - gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | (num & 0x00FFFFFF); - gstate.worldmtxdata = GE_CMD_WORLDMATRIXDATA << 24; -} - -void GPUCommon::Execute_ViewMtxNum(u32 op, u32 diff) { - if (!currentList) { - gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | (op & 0xF); - return; - } - - // This is almost always followed by GE_CMD_VIEWMATRIXDATA. - const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - u32 *dst = (u32 *)(gstate.viewMatrix + (op & 0xF)); - const int end = 12 - (op & 0xF); - int i = 0; - - bool fastLoad = !debugRecording_ && end > 0; - if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { - fastLoad = false; - } - - if (fastLoad) { - while ((src[i] >> 24) == GE_CMD_VIEWMATRIXDATA) { - const u32 newVal = src[i] << 8; - if (dst[i] != newVal) { - Flush(); - dst[i] = newVal; - gstate_c.Dirty(DIRTY_VIEWMATRIX); - } - if (++i >= end) { - break; - } - } - } - - const int count = i; - gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | ((op & 0xF) + count); - - // Skip over the loaded data, it's done now. - UpdatePC(currentList->pc, currentList->pc + count * 4); - currentList->pc += count * 4; -} - -void GPUCommon::Execute_ViewMtxData(u32 op, u32 diff) { - // Note: it's uncommon to get here now, see above. - int num = gstate.viewmtxnum & 0x00FFFFFF; - u32 newVal = op << 8; - if (num < 12 && newVal != ((const u32 *)gstate.viewMatrix)[num]) { - Flush(); - ((u32 *)gstate.viewMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_VIEWMATRIX); - } - num++; - gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | (num & 0x00FFFFFF); - gstate.viewmtxdata = GE_CMD_VIEWMATRIXDATA << 24; -} - -void GPUCommon::Execute_ProjMtxNum(u32 op, u32 diff) { - if (!currentList) { - gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | (op & 0xF); - return; - } - - // This is almost always followed by GE_CMD_PROJMATRIXDATA. - const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - u32 *dst = (u32 *)(gstate.projMatrix + (op & 0xF)); - const int end = 16 - (op & 0xF); - int i = 0; - - bool fastLoad = !debugRecording_; - if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { - fastLoad = false; - } - - if (fastLoad) { - while ((src[i] >> 24) == GE_CMD_PROJMATRIXDATA) { - const u32 newVal = src[i] << 8; - if (dst[i] != newVal) { - Flush(); - dst[i] = newVal; - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - if (++i >= end) { - break; - } - } - } - - const int count = i; - gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | ((op & 0xF) + count); - - // Skip over the loaded data, it's done now. - UpdatePC(currentList->pc, currentList->pc + count * 4); - currentList->pc += count * 4; -} - -void GPUCommon::Execute_ProjMtxData(u32 op, u32 diff) { - // Note: it's uncommon to get here now, see above. - int num = gstate.projmtxnum & 0x00FFFFFF; - u32 newVal = op << 8; - if (num < 16 && newVal != ((const u32 *)gstate.projMatrix)[num]) { - Flush(); - ((u32 *)gstate.projMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - num++; - if (num <= 16) - gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | (num & 0x00FFFFFF); - gstate.projmtxdata = GE_CMD_PROJMATRIXDATA << 24; -} - -void GPUCommon::Execute_TgenMtxNum(u32 op, u32 diff) { - if (!currentList) { - gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | (op & 0xF); - return; - } - - // This is almost always followed by GE_CMD_TGENMATRIXDATA. - const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - u32 *dst = (u32 *)(gstate.tgenMatrix + (op & 0xF)); - const int end = 12 - (op & 0xF); - int i = 0; - - bool fastLoad = !debugRecording_ && end > 0; - if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { - fastLoad = false; - } - - if (fastLoad) { - while ((src[i] >> 24) == GE_CMD_TGENMATRIXDATA) { - const u32 newVal = src[i] << 8; - if (dst[i] != newVal) { - Flush(); - dst[i] = newVal; - // We check the matrix to see if we need projection. - gstate_c.Dirty(DIRTY_TEXMATRIX | DIRTY_FRAGMENTSHADER_STATE); - } - if (++i >= end) { - break; - } - } - } - - const int count = i; - gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | ((op & 0xF) + count); - - // Skip over the loaded data, it's done now. - UpdatePC(currentList->pc, currentList->pc + count * 4); - currentList->pc += count * 4; -} - -void GPUCommon::Execute_TgenMtxData(u32 op, u32 diff) { - // Note: it's uncommon to get here now, see above. - int num = gstate.texmtxnum & 0x00FFFFFF; - u32 newVal = op << 8; - if (num < 12 && newVal != ((const u32 *)gstate.tgenMatrix)[num]) { - Flush(); - ((u32 *)gstate.tgenMatrix)[num] = newVal; - gstate_c.Dirty(DIRTY_TEXMATRIX | DIRTY_FRAGMENTSHADER_STATE); // We check the matrix to see if we need projection - } - num++; - gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | (num & 0x00FFFFFF); - gstate.texmtxdata = GE_CMD_TGENMATRIXDATA << 24; -} - -void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { - if (!currentList) { - gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (op & 0x7F); - return; - } - - // This is almost always followed by GE_CMD_BONEMATRIXDATA. - const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); - u32 *dst = (u32 *)(gstate.boneMatrix + (op & 0x7F)); - const int end = 12 * 8 - (op & 0x7F); - int i = 0; - - bool fastLoad = !debugRecording_ && end > 0; - if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { - fastLoad = false; - } - - if (fastLoad) { - // If we can't use software skinning, we have to flush and dirty. - if (!g_Config.bSoftwareSkinning) { - while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { - const u32 newVal = src[i] << 8; - if (dst[i] != newVal) { - Flush(); - dst[i] = newVal; - } - if (++i >= end) { - break; - } - } - - const unsigned int numPlusCount = (op & 0x7F) + i; - for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { - gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); - } - } else { - while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { - dst[i] = src[i] << 8; - if (++i >= end) { - break; - } - } - - const unsigned int numPlusCount = (op & 0x7F) + i; - for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { - gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); - } - } - } - - const int count = i; - gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | ((op & 0x7F) + count); - - // Skip over the loaded data, it's done now. - UpdatePC(currentList->pc, currentList->pc + count * 4); - currentList->pc += count * 4; -} - -void GPUCommon::Execute_BoneMtxData(u32 op, u32 diff) { - // Note: it's uncommon to get here now, see above. - int num = gstate.boneMatrixNumber & 0x00FFFFFF; - u32 newVal = op << 8; - if (num < 96 && newVal != ((const u32 *)gstate.boneMatrix)[num]) { - // Bone matrices should NOT flush when software skinning is enabled! - if (!g_Config.bSoftwareSkinning) { - Flush(); - gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); - } else { - gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); - } - ((u32 *)gstate.boneMatrix)[num] = newVal; - } - num++; - gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x00FFFFFF); - gstate.boneMatrixData = GE_CMD_BONEMATRIXDATA << 24; -} - void GPUCommon::Execute_MorphWeight(u32 op, u32 diff) { gstate_c.morphWeights[(op >> 24) - GE_CMD_MORPHWEIGHT0] = getFloat24(op); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index b1367275d4..cb84369d93 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -151,17 +151,6 @@ public: void Execute_BoundingBox(u32 op, u32 diff); - void Execute_WorldMtxNum(u32 op, u32 diff); - void Execute_WorldMtxData(u32 op, u32 diff); - void Execute_ViewMtxNum(u32 op, u32 diff); - void Execute_ViewMtxData(u32 op, u32 diff); - void Execute_ProjMtxNum(u32 op, u32 diff); - void Execute_ProjMtxData(u32 op, u32 diff); - void Execute_TgenMtxNum(u32 op, u32 diff); - void Execute_TgenMtxData(u32 op, u32 diff); - void Execute_BoneMtxNum(u32 op, u32 diff); - void Execute_BoneMtxData(u32 op, u32 diff); - void Execute_MorphWeight(u32 op, u32 diff); void Execute_ImmVertexAlphaPrim(u32 op, u32 diff); diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index b51e552543..319ca86dcc 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -308,16 +308,16 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_DITH3 }, // These handle their own flushing. - { GE_CMD_WORLDMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_WorldMtxNum }, - { GE_CMD_WORLDMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_WorldMtxData }, - { GE_CMD_VIEWMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_ViewMtxNum }, - { GE_CMD_VIEWMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_ViewMtxData }, - { GE_CMD_PROJMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_ProjMtxNum }, - { GE_CMD_PROJMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_ProjMtxData }, - { GE_CMD_TGENMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_TgenMtxNum }, - { GE_CMD_TGENMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_TgenMtxData }, - { GE_CMD_BONEMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommon::Execute_BoneMtxNum }, - { GE_CMD_BONEMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommon::Execute_BoneMtxData }, + { GE_CMD_WORLDMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommonHW::Execute_WorldMtxNum }, + { GE_CMD_WORLDMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_WorldMtxData }, + { GE_CMD_VIEWMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommonHW::Execute_ViewMtxNum }, + { GE_CMD_VIEWMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_ViewMtxData }, + { GE_CMD_PROJMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommonHW::Execute_ProjMtxNum }, + { GE_CMD_PROJMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_ProjMtxData }, + { GE_CMD_TGENMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommonHW::Execute_TgenMtxNum }, + { GE_CMD_TGENMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_TgenMtxData }, + { GE_CMD_BONEMATRIXNUMBER, FLAG_EXECUTE | FLAG_READS_PC | FLAG_WRITES_PC, 0, &GPUCommonHW::Execute_BoneMtxNum }, + { GE_CMD_BONEMATRIXDATA, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_BoneMtxData }, // Vertex Screen/Texture/Color { GE_CMD_VSCX }, @@ -1225,3 +1225,297 @@ void GPUCommonHW::Execute_LoadClut(u32 op, u32 diff) { gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); textureCache_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); } + + +void GPUCommonHW::Execute_WorldMtxNum(u32 op, u32 diff) { + if (!currentList) { + gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | (op & 0xF); + return; + } + + // This is almost always followed by GE_CMD_WORLDMATRIXDATA. + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); + u32 *dst = (u32 *)(gstate.worldMatrix + (op & 0xF)); + const int end = 12 - (op & 0xF); + int i = 0; + + // We must record the individual data commands while debugRecording_. + bool fastLoad = !debugRecording_ && end > 0; + // Stalling in the middle of a matrix would be stupid, I doubt this check is necessary. + if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { + fastLoad = false; + } + + if (fastLoad) { + while ((src[i] >> 24) == GE_CMD_WORLDMATRIXDATA) { + const u32 newVal = src[i] << 8; + if (dst[i] != newVal) { + Flush(); + dst[i] = newVal; + gstate_c.Dirty(DIRTY_WORLDMATRIX); + } + if (++i >= end) { + break; + } + } + } + + const int count = i; + gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | ((op & 0xF) + count); + + // Skip over the loaded data, it's done now. + UpdatePC(currentList->pc, currentList->pc + count * 4); + currentList->pc += count * 4; +} + +void GPUCommonHW::Execute_WorldMtxData(u32 op, u32 diff) { + // Note: it's uncommon to get here now, see above. + int num = gstate.worldmtxnum & 0x00FFFFFF; + u32 newVal = op << 8; + if (num < 12 && newVal != ((const u32 *)gstate.worldMatrix)[num]) { + Flush(); + ((u32 *)gstate.worldMatrix)[num] = newVal; + gstate_c.Dirty(DIRTY_WORLDMATRIX); + } + num++; + gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | (num & 0x00FFFFFF); + gstate.worldmtxdata = GE_CMD_WORLDMATRIXDATA << 24; +} + +void GPUCommonHW::Execute_ViewMtxNum(u32 op, u32 diff) { + if (!currentList) { + gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | (op & 0xF); + return; + } + + // This is almost always followed by GE_CMD_VIEWMATRIXDATA. + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); + u32 *dst = (u32 *)(gstate.viewMatrix + (op & 0xF)); + const int end = 12 - (op & 0xF); + int i = 0; + + bool fastLoad = !debugRecording_ && end > 0; + if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { + fastLoad = false; + } + + if (fastLoad) { + while ((src[i] >> 24) == GE_CMD_VIEWMATRIXDATA) { + const u32 newVal = src[i] << 8; + if (dst[i] != newVal) { + Flush(); + dst[i] = newVal; + gstate_c.Dirty(DIRTY_VIEWMATRIX); + } + if (++i >= end) { + break; + } + } + } + + const int count = i; + gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | ((op & 0xF) + count); + + // Skip over the loaded data, it's done now. + UpdatePC(currentList->pc, currentList->pc + count * 4); + currentList->pc += count * 4; +} + +void GPUCommonHW::Execute_ViewMtxData(u32 op, u32 diff) { + // Note: it's uncommon to get here now, see above. + int num = gstate.viewmtxnum & 0x00FFFFFF; + u32 newVal = op << 8; + if (num < 12 && newVal != ((const u32 *)gstate.viewMatrix)[num]) { + Flush(); + ((u32 *)gstate.viewMatrix)[num] = newVal; + gstate_c.Dirty(DIRTY_VIEWMATRIX); + } + num++; + gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | (num & 0x00FFFFFF); + gstate.viewmtxdata = GE_CMD_VIEWMATRIXDATA << 24; +} + +void GPUCommonHW::Execute_ProjMtxNum(u32 op, u32 diff) { + if (!currentList) { + gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | (op & 0xF); + return; + } + + // This is almost always followed by GE_CMD_PROJMATRIXDATA. + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); + u32 *dst = (u32 *)(gstate.projMatrix + (op & 0xF)); + const int end = 16 - (op & 0xF); + int i = 0; + + bool fastLoad = !debugRecording_; + if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { + fastLoad = false; + } + + if (fastLoad) { + while ((src[i] >> 24) == GE_CMD_PROJMATRIXDATA) { + const u32 newVal = src[i] << 8; + if (dst[i] != newVal) { + Flush(); + dst[i] = newVal; + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + if (++i >= end) { + break; + } + } + } + + const int count = i; + gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | ((op & 0xF) + count); + + // Skip over the loaded data, it's done now. + UpdatePC(currentList->pc, currentList->pc + count * 4); + currentList->pc += count * 4; +} + +void GPUCommonHW::Execute_ProjMtxData(u32 op, u32 diff) { + // Note: it's uncommon to get here now, see above. + int num = gstate.projmtxnum & 0x00FFFFFF; + u32 newVal = op << 8; + if (num < 16 && newVal != ((const u32 *)gstate.projMatrix)[num]) { + Flush(); + ((u32 *)gstate.projMatrix)[num] = newVal; + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + num++; + if (num <= 16) + gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | (num & 0x00FFFFFF); + gstate.projmtxdata = GE_CMD_PROJMATRIXDATA << 24; +} + +void GPUCommonHW::Execute_TgenMtxNum(u32 op, u32 diff) { + if (!currentList) { + gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | (op & 0xF); + return; + } + + // This is almost always followed by GE_CMD_TGENMATRIXDATA. + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); + u32 *dst = (u32 *)(gstate.tgenMatrix + (op & 0xF)); + const int end = 12 - (op & 0xF); + int i = 0; + + bool fastLoad = !debugRecording_ && end > 0; + if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { + fastLoad = false; + } + + if (fastLoad) { + while ((src[i] >> 24) == GE_CMD_TGENMATRIXDATA) { + const u32 newVal = src[i] << 8; + if (dst[i] != newVal) { + Flush(); + dst[i] = newVal; + // We check the matrix to see if we need projection. + gstate_c.Dirty(DIRTY_TEXMATRIX | DIRTY_FRAGMENTSHADER_STATE); + } + if (++i >= end) { + break; + } + } + } + + const int count = i; + gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | ((op & 0xF) + count); + + // Skip over the loaded data, it's done now. + UpdatePC(currentList->pc, currentList->pc + count * 4); + currentList->pc += count * 4; +} + +void GPUCommonHW::Execute_TgenMtxData(u32 op, u32 diff) { + // Note: it's uncommon to get here now, see above. + int num = gstate.texmtxnum & 0x00FFFFFF; + u32 newVal = op << 8; + if (num < 12 && newVal != ((const u32 *)gstate.tgenMatrix)[num]) { + Flush(); + ((u32 *)gstate.tgenMatrix)[num] = newVal; + gstate_c.Dirty(DIRTY_TEXMATRIX | DIRTY_FRAGMENTSHADER_STATE); // We check the matrix to see if we need projection + } + num++; + gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | (num & 0x00FFFFFF); + gstate.texmtxdata = GE_CMD_TGENMATRIXDATA << 24; +} + +void GPUCommonHW::Execute_BoneMtxNum(u32 op, u32 diff) { + if (!currentList) { + gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (op & 0x7F); + return; + } + + // This is almost always followed by GE_CMD_BONEMATRIXDATA. + const u32_le *src = (const u32_le *)Memory::GetPointerUnchecked(currentList->pc + 4); + u32 *dst = (u32 *)(gstate.boneMatrix + (op & 0x7F)); + const int end = 12 * 8 - (op & 0x7F); + int i = 0; + + bool fastLoad = !debugRecording_ && end > 0; + if (currentList->pc < currentList->stall && currentList->pc + end * 4 >= currentList->stall) { + fastLoad = false; + } + + if (fastLoad) { + // If we can't use software skinning, we have to flush and dirty. + if (!g_Config.bSoftwareSkinning) { + while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { + const u32 newVal = src[i] << 8; + if (dst[i] != newVal) { + Flush(); + dst[i] = newVal; + } + if (++i >= end) { + break; + } + } + + const unsigned int numPlusCount = (op & 0x7F) + i; + for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { + gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); + } + } else { + while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) { + dst[i] = src[i] << 8; + if (++i >= end) { + break; + } + } + + const unsigned int numPlusCount = (op & 0x7F) + i; + for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) { + gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); + } + } + } + + const int count = i; + gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | ((op & 0x7F) + count); + + // Skip over the loaded data, it's done now. + UpdatePC(currentList->pc, currentList->pc + count * 4); + currentList->pc += count * 4; +} + +void GPUCommonHW::Execute_BoneMtxData(u32 op, u32 diff) { + // Note: it's uncommon to get here now, see above. + int num = gstate.boneMatrixNumber & 0x00FFFFFF; + u32 newVal = op << 8; + if (num < 96 && newVal != ((const u32 *)gstate.boneMatrix)[num]) { + // Bone matrices should NOT flush when software skinning is enabled! + if (!g_Config.bSoftwareSkinning) { + Flush(); + gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12)); + } else { + gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12); + } + ((u32 *)gstate.boneMatrix)[num] = newVal; + } + num++; + gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x00FFFFFF); + gstate.boneMatrixData = GE_CMD_BONEMATRIXDATA << 24; +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index d57f8619b4..983712f48f 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -35,6 +35,17 @@ public: void Execute_TexLevel(u32 op, u32 diff); void Execute_LoadClut(u32 op, u32 diff); + void Execute_WorldMtxNum(u32 op, u32 diff); + void Execute_WorldMtxData(u32 op, u32 diff); + void Execute_ViewMtxNum(u32 op, u32 diff); + void Execute_ViewMtxData(u32 op, u32 diff); + void Execute_ProjMtxNum(u32 op, u32 diff); + void Execute_ProjMtxData(u32 op, u32 diff); + void Execute_TgenMtxNum(u32 op, u32 diff); + void Execute_TgenMtxData(u32 op, u32 diff); + void Execute_BoneMtxNum(u32 op, u32 diff); + void Execute_BoneMtxData(u32 op, u32 diff); + typedef void (GPUCommonHW::*CmdFunc)(u32 op, u32 diff); void FastRunLoop(DisplayList &list) override; From c3ceb9bf708827df404722dce05a68baec6dc44c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 18:17:28 +0100 Subject: [PATCH 171/424] Move assorted debug functions and similar to GPUCommonHW --- GPU/GPUCommon.cpp | 77 --------------------------------------------- GPU/GPUCommon.h | 12 ------- GPU/GPUCommonHW.cpp | 76 ++++++++++++++++++++++++++++++++++++++++++++ GPU/GPUCommonHW.h | 14 ++++++++- 4 files changed, 89 insertions(+), 90 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 09b4278c7e..562c93e52d 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -42,7 +42,6 @@ #include "Core/HW/Display.h" #include "Core/MemMapHelpers.h" #include "Core/Util/PPGeDraw.h" -#include "GPU/GPUCommonHW.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" #include "GPU/Common/SplineCommon.h" @@ -2011,21 +2010,6 @@ bool GPUCommon::PerformWriteColorFromMemory(u32 dest, int size) { return false; } -void GPUCommon::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCache_->Invalidate(addr, size, type); - else - textureCache_->InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { - // Vempire invalidates (with writeback) after drawing, but before blitting. - // TODO: Investigate whether we can get this to work some other way. - if (type == GPU_INVALIDATE_SAFE) { - framebufferManager_->UpdateFromMemory(addr, size); - } - } -} - void GPUCommon::PerformWriteFormattedFromMemory(u32 addr, int size, int frameWidth, GEBufferFormat format) { if (Memory::IsVRAMAddress(addr)) { framebufferManager_->PerformWriteFormattedFromMemory(addr, size, frameWidth, format); @@ -2042,36 +2026,6 @@ bool GPUCommon::PerformWriteStencilFromMemory(u32 dest, int size, WriteStencil f return false; } -bool GPUCommon::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? (gstate.getFrameBufRawAddress() | 0x04000000) : framebufferManager_->DisplayFramebufAddr(); - int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride(); - GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate_c.framebufFormat : framebufferManager_->DisplayFramebufFormat(); - return framebufferManager_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); -} - -bool GPUCommon::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress() | 0x04000000; - int fb_stride = gstate.FrameBufStride(); - - u32 z_address = gstate.getDepthBufRawAddress() | 0x04000000; - int z_stride = gstate.DepthBufStride(); - - return framebufferManager_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); -} - -bool GPUCommon::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress() | 0x04000000; - int fb_stride = gstate.FrameBufStride(); - - return framebufferManager_->GetStencilbuffer(fb_address, fb_stride, buffer); -} - -bool GPUCommon::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - // framebufferManager_ can be null here when taking screens in software rendering mode. - // TODO: Actually grab the framebuffer anyway. - return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false; -} - std::vector GPUCommon::GetFramebufferList() const { return framebufferManager_->GetFramebufferList(); } @@ -2081,17 +2035,6 @@ bool GPUCommon::GetCurrentSimpleVertices(int count, std::vector return drawEngineCommon_->GetCurrentSimpleVertices(count, vertices, indices); } -bool GPUCommon::GetCurrentClut(GPUDebugBuffer &buffer) { - return textureCache_->GetCurrentClutBuffer(buffer); -} - -bool GPUCommon::GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) { - if (!gstate.isTextureMapEnabled()) { - return false; - } - return textureCache_->GetCurrentTextureDebug(buffer, level, isFramebuffer); -} - bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) { if (drawEngineCommon_->IsCodePtrVertexDecoder(ptr)) { name = "VertexDecoderJit"; @@ -2100,26 +2043,6 @@ bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) { return false; } -bool GPUCommon::FramebufferDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->dirtyAfterDisplay; - vfb->dirtyAfterDisplay = false; - return dirty; - } - return true; -} - -bool GPUCommon::FramebufferReallyDirty() { - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); - if (vfb) { - bool dirty = vfb->reallyDirtyAfterDisplay; - vfb->reallyDirtyAfterDisplay = false; - return dirty; - } - return true; -} - void GPUCommon::UpdateUVScaleOffset() { #ifdef _M_SSE __m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *) & gstate.texscaleu), 8); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index cb84369d93..0927339ab7 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -133,7 +133,6 @@ public: bool PerformReadbackToMemory(u32 dest, int size) override; bool PerformWriteColorFromMemory(u32 dest, int size) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void PerformWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat format) override; bool PerformWriteStencilFromMemory(u32 dest, int size, WriteStencil flags) override; @@ -178,13 +177,7 @@ public: // From GPUDebugInterface. bool GetCurrentDisplayList(DisplayList &list) override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override; - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; - bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; - bool GetCurrentClut(GPUDebugBuffer &buffer) override; bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; - bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; std::vector DebugGetShaderIDs(DebugShaderType shader) override { return std::vector(); }; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override { @@ -227,11 +220,6 @@ public: return -1; } - bool FramebufferDirty() override; - bool FramebufferReallyDirty() override; - - typedef void (GPUCommon::*CmdFunc)(u32 op, u32 diff); - void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) override { primaryInfo = reportingPrimaryInfo_; fullInfo = reportingFullInfo_; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 319ca86dcc..7bea5851be 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -648,6 +648,47 @@ std::string GPUCommonHW::DebugGetShaderString(std::string id, DebugShaderType ty } } +bool GPUCommonHW::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { + u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? (gstate.getFrameBufRawAddress() | 0x04000000) : framebufferManager_->DisplayFramebufAddr(); + int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride(); + GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate_c.framebufFormat : framebufferManager_->DisplayFramebufFormat(); + return framebufferManager_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); +} + +bool GPUCommonHW::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { + u32 fb_address = gstate.getFrameBufRawAddress() | 0x04000000; + int fb_stride = gstate.FrameBufStride(); + + u32 z_address = gstate.getDepthBufRawAddress() | 0x04000000; + int z_stride = gstate.DepthBufStride(); + + return framebufferManager_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); +} + +bool GPUCommonHW::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { + u32 fb_address = gstate.getFrameBufRawAddress() | 0x04000000; + int fb_stride = gstate.FrameBufStride(); + + return framebufferManager_->GetStencilbuffer(fb_address, fb_stride, buffer); +} + +bool GPUCommonHW::GetOutputFramebuffer(GPUDebugBuffer &buffer) { + // framebufferManager_ can be null here when taking screens in software rendering mode. + // TODO: Actually grab the framebuffer anyway. + return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false; +} + +bool GPUCommonHW::GetCurrentClut(GPUDebugBuffer &buffer) { + return textureCache_->GetCurrentClutBuffer(buffer); +} + +bool GPUCommonHW::GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) { + if (!gstate.isTextureMapEnabled()) { + return false; + } + return textureCache_->GetCurrentTextureDebug(buffer, level, isFramebuffer); +} + void GPUCommonHW::CheckDepthUsage(VirtualFramebuffer *vfb) { if (!gstate_c.usingDepth) { bool isReadingDepth = false; @@ -673,6 +714,41 @@ void GPUCommonHW::CheckDepthUsage(VirtualFramebuffer *vfb) { } } +void GPUCommonHW::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { + if (size > 0) + textureCache_->Invalidate(addr, size, type); + else + textureCache_->InvalidateAll(type); + + if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { + // Vempire invalidates (with writeback) after drawing, but before blitting. + // TODO: Investigate whether we can get this to work some other way. + if (type == GPU_INVALIDATE_SAFE) { + framebufferManager_->UpdateFromMemory(addr, size); + } + } +} + +bool GPUCommonHW::FramebufferDirty() { + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); + if (vfb) { + bool dirty = vfb->dirtyAfterDisplay; + vfb->dirtyAfterDisplay = false; + return dirty; + } + return true; +} + +bool GPUCommonHW::FramebufferReallyDirty() { + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); + if (vfb) { + bool dirty = vfb->reallyDirtyAfterDisplay; + vfb->reallyDirtyAfterDisplay = false; + return dirty; + } + return true; +} + void GPUCommonHW::ExecuteOp(u32 op, u32 diff) { const u8 cmd = op >> 24; const CommandInfo info = cmdInfo_[cmd]; diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 983712f48f..97276e0116 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -17,12 +17,24 @@ public: u32 CheckGPUFeatures() const override; - void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; + // From GPUDebugInterface. + bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override; + bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; + bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; + bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; + bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; + bool GetCurrentClut(GPUDebugBuffer &buffer) override; // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) override; + void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; + void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; + + bool FramebufferDirty() override; + bool FramebufferReallyDirty() override; + void Execute_VertexType(u32 op, u32 diff); void Execute_VertexTypeSkinning(u32 op, u32 diff); From 526ba74d059a8a21d50d18e9e94624518281d9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 18:27:16 +0100 Subject: [PATCH 172/424] Move the shaderManager_ to GPUCommonHW --- GPU/GPUCommon.h | 1 - GPU/GPUCommonHW.h | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 0927339ab7..05fedca897 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -287,7 +287,6 @@ protected: // TODO: These should live in GPUCommonHW. FramebufferManagerCommon *framebufferManager_ = nullptr; TextureCacheCommon *textureCache_ = nullptr; - ShaderManagerCommon *shaderManager_ = nullptr; bool flushOnParams_ = true; diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 97276e0116..b6e1454c19 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -63,6 +63,10 @@ public: void FastRunLoop(DisplayList &list) override; void ExecuteOp(u32 op, u32 diff) override; +private: + void CheckDepthUsage(VirtualFramebuffer *vfb); + void CheckFlushOp(int cmd, u32 diff); + protected: void UpdateCmdInfo() override; @@ -78,8 +82,5 @@ protected: int msaaLevel_ = 0; bool sawExactEqualDepth_ = false; - -private: - void CheckDepthUsage(VirtualFramebuffer *vfb); - void CheckFlushOp(int cmd, u32 diff); + ShaderManagerCommon *shaderManager_ = nullptr; }; From af2fd7b038aa58c297b9176752d2b6f2758a0544 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 18:31:13 +0100 Subject: [PATCH 173/424] Move Vulkan clear detection logic into DrawEngine like the other backends. --- GPU/Vulkan/DrawEngineVulkan.cpp | 20 +++++++++++++++----- GPU/Vulkan/FramebufferManagerVulkan.cpp | 19 ------------------- GPU/Vulkan/FramebufferManagerVulkan.h | 4 ---- 3 files changed, 15 insertions(+), 28 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index c4a3be72de..78f561376e 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -983,11 +983,21 @@ void DrawEngineVulkan::DoFlush() { } } else if (result.action == SW_CLEAR) { // Note: we won't get here if the clear is alpha but not color, or color but not alpha. - - // We let the framebuffer manager handle the clear. It can use renderpasses to optimize on tilers. - // If non-buffered though, it'll just do a plain clear. - framebufferManager_->NotifyClear(gstate.isClearModeColorMask(), gstate.isClearModeAlphaMask(), gstate.isClearModeDepthMask(), result.color, result.depth); - + bool clearColor = gstate.isClearModeColorMask(); + bool clearAlpha = gstate.isClearModeAlphaMask(); // and stencil + bool clearDepth = gstate.isClearModeDepthMask(); + int mask = 0; + // The Clear detection takes care of doing a regular draw instead if separate masking + // of color and alpha is needed, so we can just treat them as the same. + if (clearColor || clearAlpha) mask |= Draw::FBChannel::FB_COLOR_BIT; + if (clearDepth) mask |= Draw::FBChannel::FB_DEPTH_BIT; + if (clearAlpha) mask |= Draw::FBChannel::FB_STENCIL_BIT; + // Note that since the alpha channel and the stencil channel are shared on the PSP, + // when we clear alpha, we also clear stencil to the same value. + draw_->Clear(mask, result.color, result.depth, result.color >> 24); + if (clearColor || clearAlpha) { + framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason); + } if (gstate_c.Use(GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) { int scissorX1 = gstate.getScissorX1(); int scissorY1 = gstate.getScissorY1(); diff --git a/GPU/Vulkan/FramebufferManagerVulkan.cpp b/GPU/Vulkan/FramebufferManagerVulkan.cpp index d5d4bdae50..0cc7c5c9ac 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.cpp +++ b/GPU/Vulkan/FramebufferManagerVulkan.cpp @@ -26,22 +26,3 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw) : FramebufferManagerCommon(draw) { presentation_->SetLanguage(GLSL_VULKAN); } - -void FramebufferManagerVulkan::NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth) { - int mask = 0; - // The Clear detection takes care of doing a regular draw instead if separate masking - // of color and alpha is needed, so we can just treat them as the same. - if (clearColor || clearAlpha) - mask |= Draw::FBChannel::FB_COLOR_BIT; - if (clearDepth) - mask |= Draw::FBChannel::FB_DEPTH_BIT; - if (clearAlpha) - mask |= Draw::FBChannel::FB_STENCIL_BIT; - - // Note that since the alpha channel and the stencil channel are shared on the PSP, - // when we clear alpha, we also clear stencil to the same value. - draw_->Clear(mask, color, depth, color >> 24); - if (clearColor || clearAlpha) { - SetColorUpdated(gstate_c.skipDrawReason); - } -} diff --git a/GPU/Vulkan/FramebufferManagerVulkan.h b/GPU/Vulkan/FramebufferManagerVulkan.h index c2e575f0b2..2abb6008ce 100644 --- a/GPU/Vulkan/FramebufferManagerVulkan.h +++ b/GPU/Vulkan/FramebufferManagerVulkan.h @@ -25,8 +25,4 @@ class FramebufferManagerVulkan : public FramebufferManagerCommon { public: explicit FramebufferManagerVulkan(Draw::DrawContext *draw); - - // If within a render pass, this will just issue a regular clear. If beginning a new render pass, - // do that. - void NotifyClear(bool clearColor, bool clearAlpha, bool clearDepth, uint32_t color, float depth); }; From 4c45f8a4b006c6bf5ef2d18ffbd27d3875a971b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 23:04:27 +0100 Subject: [PATCH 174/424] Pass in draw directly in GPUCommon::DeviceRestore, instead of awkwardly fetching it --- GPU/D3D11/GPU_D3D11.cpp | 4 ++-- GPU/D3D11/GPU_D3D11.h | 2 +- GPU/GLES/GPU_GLES.cpp | 4 ++-- GPU/GLES/GPU_GLES.h | 2 +- GPU/GPUCommon.cpp | 8 ++------ GPU/GPUCommon.h | 3 +-- GPU/GPUCommonHW.cpp | 4 ++++ GPU/GPUCommonHW.h | 1 + GPU/GPUInterface.h | 2 +- GPU/Software/SoftGpu.cpp | 5 ++--- GPU/Software/SoftGpu.h | 3 ++- GPU/Vulkan/GPU_Vulkan.cpp | 4 ++-- GPU/Vulkan/GPU_Vulkan.h | 2 +- GPU/Vulkan/TextureCacheVulkan.h | 4 ++-- UI/NativeApp.cpp | 2 +- libretro/LibretroGraphicsContext.cpp | 2 +- 16 files changed, 26 insertions(+), 26 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 28043a1d68..c92b8ad2f5 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -122,8 +122,8 @@ void GPU_D3D11::DeviceLost() { GPUCommonHW::DeviceLost(); } -void GPU_D3D11::DeviceRestore() { - GPUCommonHW::DeviceRestore(); +void GPU_D3D11::DeviceRestore(Draw::DrawContext *draw) { + GPUCommonHW::DeviceRestore(draw); // Nothing needed. } diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index 782ef7f029..a2e374c6f0 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -38,7 +38,7 @@ public: void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. - void DeviceRestore() override; + void DeviceRestore(Draw::DrawContext *draw) override; protected: void FinishDeferred() override; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 756cf81937..7e362b0697 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -244,8 +244,8 @@ void GPU_GLES::DeviceLost() { GPUCommonHW::DeviceLost(); } -void GPU_GLES::DeviceRestore() { - GPUCommonHW::DeviceRestore(); +void GPU_GLES::DeviceRestore(Draw::DrawContext *draw) { + GPUCommonHW::DeviceRestore(draw); UpdateCmdInfo(); UpdateVsyncInterval(true); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index a56765a580..9e03285ee9 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -46,7 +46,7 @@ public: void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. - void DeviceRestore() override; + void DeviceRestore(Draw::DrawContext *draw) override; void BeginHostFrame() override; void EndHostFrame() override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 562c93e52d..40990eb41b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -133,8 +133,8 @@ void GPUCommon::DeviceLost() { } // Call at the start of the GPU implementation's DeviceRestore -void GPUCommon::DeviceRestore() { - draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext(); +void GPUCommon::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; framebufferManager_->DeviceRestore(draw_); PPGeSetDrawContext(draw_); } @@ -2026,10 +2026,6 @@ bool GPUCommon::PerformWriteStencilFromMemory(u32 dest, int size, WriteStencil f return false; } -std::vector GPUCommon::GetFramebufferList() const { - return framebufferManager_->GetFramebufferList(); -} - bool GPUCommon::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { UpdateUVScaleOffset(); return drawEngineCommon_->GetCurrentSimpleVertices(count, vertices, indices); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 05fedca897..b58923013e 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -211,7 +211,6 @@ public: const std::list& GetDisplayLists() override { return dlQueue; } - std::vector GetFramebufferList() const override; s64 GetListTicks(int listid) const override { if (listid >= 0 && listid < DisplayListMaxCount) { @@ -227,7 +226,7 @@ public: protected: void DeviceLost() override; - void DeviceRestore() override; + void DeviceRestore(Draw::DrawContext *draw) override; void ClearCacheNextFrame() override {} diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 7bea5851be..6a1771875d 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -678,6 +678,10 @@ bool GPUCommonHW::GetOutputFramebuffer(GPUDebugBuffer &buffer) { return framebufferManager_ ? framebufferManager_->GetOutputFramebuffer(buffer) : false; } +std::vector GPUCommonHW::GetFramebufferList() const { + return framebufferManager_->GetFramebufferList(); +} + bool GPUCommonHW::GetCurrentClut(GPUDebugBuffer &buffer) { return textureCache_->GetCurrentClutBuffer(buffer); } diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index b6e1454c19..ca3fe1780d 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -22,6 +22,7 @@ public: bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override; bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override; bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override; + std::vector GetFramebufferList() const override; bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; bool GetCurrentClut(GPUDebugBuffer &buffer) override; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 6bf3856e16..6788e595d7 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -251,7 +251,7 @@ public: virtual void EnableInterrupts(bool enable) = 0; virtual void DeviceLost() = 0; - virtual void DeviceRestore() = 0; + virtual void DeviceRestore(Draw::DrawContext *draw) = 0; virtual void ReapplyGfxState() = 0; virtual void DoState(PointerWrap &p) = 0; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 56e9a3b60a..2a3bf685f7 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -466,9 +466,8 @@ void SoftGPU::DeviceLost() { } } -void SoftGPU::DeviceRestore() { - if (PSP_CoreParameter().graphicsContext) - draw_ = (Draw::DrawContext *)PSP_CoreParameter().graphicsContext->GetDrawContext(); +void SoftGPU::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; if (presentation_) presentation_->DeviceRestore(draw_); PPGeSetDrawContext(draw_); diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 61104a04bd..0377ca7c1b 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -138,6 +138,7 @@ public: void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput(bool reallyDirty) override; void GetStats(char *buffer, size_t bufsize) override; + std::vector GetFramebufferList() const override { return std::vector(); } void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void PerformWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat format) override; bool PerformMemoryCopy(u32 dest, u32 src, int size, GPUCopyFlag flags = GPUCopyFlag::NONE) override; @@ -147,7 +148,7 @@ public: bool PerformWriteStencilFromMemory(u32 dest, int size, WriteStencil flags) override; void DeviceLost() override; - void DeviceRestore() override; + void DeviceRestore(Draw::DrawContext *draw) override; void NotifyRenderResized() override; void NotifyDisplayResized() override; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 532811f365..ee7500ea96 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -460,8 +460,8 @@ void GPU_Vulkan::DeviceLost() { GPUCommonHW::DeviceLost(); } -void GPU_Vulkan::DeviceRestore() { - GPUCommonHW::DeviceRestore(); +void GPU_Vulkan::DeviceRestore(Draw::DrawContext *draw) { + GPUCommonHW::DeviceRestore(draw); InitDeviceObjects(); gstate_c.SetUseFlags(CheckGPUFeatures()); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 1e52e8e0de..1fad919ab1 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -49,7 +49,7 @@ public: void GetStats(char *buffer, size_t bufsize) override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. - void DeviceRestore() override; + void DeviceRestore(Draw::DrawContext *draw) override; // Using string because it's generic - makes no assumptions on the size of the shader IDs of this backend. std::vector DebugGetShaderIDs(DebugShaderType shader) override; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 2c7c149ef6..2a6fb5d2a9 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -59,8 +59,8 @@ public: void StartFrame() override; - void DeviceLost(); - void DeviceRestore(Draw::DrawContext *draw); + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void SetFramebufferManager(FramebufferManagerVulkan *fbManager); void SetDrawEngine(DrawEngineVulkan *td) { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 65fd9fac70..c89c7ec122 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -914,7 +914,7 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { g_gameInfoCache = new GameInfoCache(); if (gpu) { - gpu->DeviceRestore(); + gpu->DeviceRestore(g_draw); } INFO_LOG(SYSTEM, "NativeInitGraphics completed"); diff --git a/libretro/LibretroGraphicsContext.cpp b/libretro/LibretroGraphicsContext.cpp index ca11400491..afd93be889 100644 --- a/libretro/LibretroGraphicsContext.cpp +++ b/libretro/LibretroGraphicsContext.cpp @@ -58,7 +58,7 @@ void LibretroHWRenderContext::ContextReset() { GotBackbuffer(); if (gpu) { - gpu->DeviceRestore(); + gpu->DeviceRestore(draw_); } } From 3dc47c7fef858b5ffd30872b1636f5564ddee741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 25 Feb 2023 23:20:41 +0100 Subject: [PATCH 175/424] Unify TextureCache ::StartFrame as much as possible. Tiny optimization avoiding a Vulkan pool reset on most frames. --- GPU/Common/TextureCacheCommon.cpp | 15 +++++++++++++++ GPU/D3D11/TextureCacheD3D11.cpp | 19 ------------------- GPU/D3D11/TextureCacheD3D11.h | 2 -- GPU/Directx9/TextureCacheDX9.cpp | 16 +--------------- GPU/GLES/TextureCacheGLES.cpp | 15 --------------- GPU/Vulkan/TextureCacheVulkan.cpp | 23 ++--------------------- GPU/Vulkan/VulkanUtil.cpp | 10 +++++++--- GPU/Vulkan/VulkanUtil.h | 1 + 8 files changed, 26 insertions(+), 75 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 5a88a718b0..c7985e82fa 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -139,7 +139,22 @@ TextureCacheCommon::~TextureCacheCommon() { } void TextureCacheCommon::StartFrame() { + ForgetLastTexture(); textureShaderCache_->Decimate(); + timesInvalidatedAllThisFrame_ = 0; + replacementTimeThisFrame_ = 0.0; + + if (texelsScaledThisFrame_) { + VERBOSE_LOG(G3D, "Scaled %d texels", texelsScaledThisFrame_); + } + texelsScaledThisFrame_ = 0; + + if (clearCacheNextFrame_) { + Clear(true); + clearCacheNextFrame_ = false; + } else { + Decimate(false); + } } // Produces a signed 1.23.8 value. diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index c8d6b9194a..047a3504f9 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -185,25 +185,6 @@ void TextureCacheD3D11::ForgetLastTexture() { context_->PSSetShaderResources(0, 4, nullTex); } -void TextureCacheD3D11::StartFrame() { - TextureCacheCommon::StartFrame(); - - lastBoundTexture = INVALID_TEX; - timesInvalidatedAllThisFrame_ = 0; - replacementTimeThisFrame_ = 0.0; - - if (texelsScaledThisFrame_) { - // INFO_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_); - } - texelsScaledThisFrame_ = 0; - if (clearCacheNextFrame_) { - Clear(true); - clearCacheNextFrame_ = false; - } else { - Decimate(); - } -} - void TextureCacheD3D11::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { const u32 clutBaseBytes = clutBase * (clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16)); // Technically, these extra bytes weren't loaded, but hopefully it was loaded earlier. diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 8c2ff77f62..35f14d5a6f 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -46,8 +46,6 @@ public: TextureCacheD3D11(Draw::DrawContext *draw, Draw2D *draw2D); ~TextureCacheD3D11(); - void StartFrame() override; - void SetFramebufferManager(FramebufferManagerD3D11 *fbManager); void ForgetLastTexture() override; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index d615c4e330..4e349fbe73 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -154,22 +154,8 @@ void TextureCacheDX9::ApplySamplingParams(const SamplerCacheKey &key) { void TextureCacheDX9::StartFrame() { TextureCacheCommon::StartFrame(); - lastBoundTexture = nullptr; - timesInvalidatedAllThisFrame_ = 0; - replacementTimeThisFrame_ = 0.0; - - if (texelsScaledThisFrame_) { - VERBOSE_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_); - } - texelsScaledThisFrame_ = 0; - if (clearCacheNextFrame_) { - Clear(true); - clearCacheNextFrame_ = false; - } else { - Decimate(); - } - if (gstate_c.Use(GPU_USE_ANISOTROPY)) { + // Just take the opportunity to set the global aniso level here, once per frame. DWORD aniso = 1 << g_Config.iAnisotropyLevel; DWORD anisotropyLevel = aniso > maxAnisotropyLevel ? maxAnisotropyLevel : aniso; device_->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, anisotropyLevel); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index c4ed59221d..aacba8e3d6 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -143,10 +143,6 @@ static void ConvertColors(void *dstBuf, const void *srcBuf, Draw::DataFormat dst void TextureCacheGLES::StartFrame() { TextureCacheCommon::StartFrame(); - ForgetLastTexture(); - timesInvalidatedAllThisFrame_ = 0; - replacementTimeThisFrame_ = 0.0; - GLRenderManager *renderManager = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); if (!lowMemoryMode_ && renderManager->SawOutOfMemory()) { lowMemoryMode_ = true; @@ -159,17 +155,6 @@ void TextureCacheGLES::StartFrame() { host->NotifyUserMessage(err->T("Warning: Video memory FULL, switching to slow caching mode"), 2.0f); } } - - if (texelsScaledThisFrame_) { - VERBOSE_LOG(G3D, "Scaled %i texels", texelsScaledThisFrame_); - } - texelsScaledThisFrame_ = 0; - if (clearCacheNextFrame_) { - Clear(true); - clearCacheNextFrame_ = false; - } else { - Decimate(); - } } void TextureCacheGLES::UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index d47ed1ee2d..1444c6abca 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -327,27 +327,8 @@ static const VkFilter MagFiltVK[2] = { void TextureCacheVulkan::StartFrame() { TextureCacheCommon::StartFrame(); - - textureShaderCache_->Decimate(); - - timesInvalidatedAllThisFrame_ = 0; - texelsScaledThisFrame_ = 0; - replacementTimeThisFrame_ = 0.0; - - if (clearCacheNextFrame_) { - Clear(true); - clearCacheNextFrame_ = false; - } else { - int slabPressureLimit = TEXCACHE_SLAB_PRESSURE; - if (g_Config.iTexScalingLevel > 1) { - // Since textures are 2D maybe we should square this, but might get too non-aggressive. - slabPressureLimit *= g_Config.iTexScalingLevel; - } - // TODO: Use some indication from VMA. - // Maybe see https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/staying_within_budget.html#staying_within_budget_querying_for_budget . - Decimate(false); - } - + // TODO: For low memory detection, maybe use some indication from VMA. + // Maybe see https://gpuopen-librariesandsdks.github.io/VulkanMemoryAllocator/html/staying_within_budget.html#staying_within_budget_querying_for_budget . computeShaderManager_.BeginFrame(); } diff --git a/GPU/Vulkan/VulkanUtil.cpp b/GPU/Vulkan/VulkanUtil.cpp index 0d87ebc153..d10749b187 100644 --- a/GPU/Vulkan/VulkanUtil.cpp +++ b/GPU/Vulkan/VulkanUtil.cpp @@ -52,8 +52,7 @@ VkShaderModule CompileShaderModule(VulkanContext *vulkan, VkShaderStageFlagBits } } -VulkanComputeShaderManager::VulkanComputeShaderManager(VulkanContext *vulkan) : vulkan_(vulkan), pipelines_(8) { -} +VulkanComputeShaderManager::VulkanComputeShaderManager(VulkanContext *vulkan) : vulkan_(vulkan), pipelines_(8) {} VulkanComputeShaderManager::~VulkanComputeShaderManager() {} void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) { @@ -96,6 +95,7 @@ void VulkanComputeShaderManager::InitDeviceObjects(Draw::DrawContext *draw) { for (int i = 0; i < ARRAY_SIZE(frameData_); i++) { frameData_[i].descPool.Create(vulkan_, dp, dpTypes); + frameData_[i].descPoolUsed = false; } VkPushConstantRange push = {}; @@ -137,6 +137,7 @@ void VulkanComputeShaderManager::DestroyDeviceObjects() { VkDescriptorSet VulkanComputeShaderManager::GetDescriptorSet(VkImageView image, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range, VkBuffer buffer2, VkDeviceSize offset2, VkDeviceSize range2) { int curFrame = vulkan_->GetCurFrame(); FrameData &frameData = frameData_[curFrame]; + frameData.descPoolUsed = true; VkDescriptorSet desc = frameData.descPool.Allocate(1, &descriptorSetLayout_, "compute_descset"); _assert_(desc != VK_NULL_HANDLE); @@ -206,5 +207,8 @@ VkPipeline VulkanComputeShaderManager::GetPipeline(VkShaderModule cs) { void VulkanComputeShaderManager::BeginFrame() { int curFrame = vulkan_->GetCurFrame(); FrameData &frame = frameData_[curFrame]; - frame.descPool.Reset(); + if (frame.descPoolUsed) { + frame.descPool.Reset(); + frame.descPoolUsed = false; + } } diff --git a/GPU/Vulkan/VulkanUtil.h b/GPU/Vulkan/VulkanUtil.h index 2046f6201f..75ed153ad3 100644 --- a/GPU/Vulkan/VulkanUtil.h +++ b/GPU/Vulkan/VulkanUtil.h @@ -77,6 +77,7 @@ private: } VulkanDescSetPool descPool; + bool descPoolUsed = false; }; FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]; From 231f4efbbb4d59088dbbde51b87377332ede35ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Feb 2023 10:33:11 +0100 Subject: [PATCH 176/424] Move some more stuff to GPUCommonHW --- GPU/GPUCommon.cpp | 68 ---------------------------------------- GPU/GPUCommon.h | 6 ---- GPU/GPUCommonHW.cpp | 57 ++++++++++++++++++++++++++++++++- GPU/GPUCommonHW.h | 2 ++ GPU/Software/SoftGpu.cpp | 2 ++ 5 files changed, 60 insertions(+), 75 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 40990eb41b..884b06816b 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -12,12 +12,9 @@ #endif #include -#include -#include #include "Common/Profiler/Profiler.h" -#include "Common/Data/Convert/ColorConv.h" #include "Common/GraphicsContext.h" #include "Common/LogReporting.h" #include "Common/Serialize/Serializer.h" @@ -41,10 +38,8 @@ #include "Core/HLE/sceGe.h" #include "Core/HW/Display.h" #include "Core/MemMapHelpers.h" -#include "Core/Util/PPGeDraw.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" -#include "GPU/Common/SplineCommon.h" #include "GPU/Common/TextureCacheCommon.h" #include "GPU/Debugger/Debugger.h" #include "GPU/Debugger/Record.h" @@ -74,13 +69,6 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : UpdateVsyncInterval(true); ResetMatrices(); - - PPGeSetDrawContext(draw); -} - -GPUCommon::~GPUCommon() { - // Probably not necessary. - PPGeSetDrawContext(nullptr); } void GPUCommon::BeginHostFrame() { @@ -126,19 +114,6 @@ void GPUCommon::Reinitialize() { framebufferManager_->DestroyAllFBOs(); } -// Call at the END of the GPU implementation's DeviceLost -void GPUCommon::DeviceLost() { - framebufferManager_->DeviceLost(); - draw_ = nullptr; -} - -// Call at the start of the GPU implementation's DeviceRestore -void GPUCommon::DeviceRestore(Draw::DrawContext *draw) { - draw_ = draw; - framebufferManager_->DeviceRestore(draw_); - PPGeSetDrawContext(draw_); -} - void GPUCommon::UpdateVsyncInterval(bool force) { #if !(PPSSPP_PLATFORM(ANDROID) || defined(USING_QT_UI) || PPSSPP_PLATFORM(UWP) || PPSSPP_PLATFORM(IOS)) int desiredVSyncInterval = g_Config.bVSync ? 1 : 0; @@ -2053,46 +2028,3 @@ void GPUCommon::UpdateUVScaleOffset() { gstate_c.uv.vOff = getFloat24(gstate.texoffsetv); #endif } - -size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) { - float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; - return snprintf(buffer, size, - "DL processing time: %0.2f ms, %d drawsync, %d listsync\n" - "Draw calls: %d, flushes %d, clears %d (cached: %d)\n" - "Num Tracked Vertex Arrays: %d\n" - "Vertices: %d cached: %d uncached: %d\n" - "FBOs active: %d (evaluations: %d)\n" - "Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n" - "readbacks %d (%d non-block), uploads %d, depal %d\n" - "Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n" - "GPU cycles executed: %d (%f per vertex)\n", - gpuStats.msProcessingDisplayLists * 1000.0f, - gpuStats.numDrawSyncs, - gpuStats.numListSyncs, - gpuStats.numDrawCalls, - gpuStats.numFlushes, - gpuStats.numClears, - gpuStats.numCachedDrawCalls, - gpuStats.numTrackedVertexArrays, - gpuStats.numVertsSubmitted, - gpuStats.numCachedVertsDrawn, - gpuStats.numUncachedVertsDrawn, - (int)framebufferManager_->NumVFBs(), - gpuStats.numFramebufferEvaluations, - (int)textureCache_->NumLoadedTextures(), - gpuStats.numTexturesDecoded, - gpuStats.numTextureInvalidations, - gpuStats.numTextureDataBytesHashed / 1024, - gpuStats.numBlockingReadbacks, - gpuStats.numReadbacks, - gpuStats.numUploads, - gpuStats.numDepal, - gpuStats.numDepthCopies, - gpuStats.numColorCopies, - gpuStats.numReinterpretCopies, - gpuStats.numCopiesForShaderBlend, - gpuStats.numCopiesForSelfTex, - gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, - vertexAverageCycles - ); -} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index b58923013e..367da7c85b 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -70,7 +70,6 @@ struct TransformedVertex { class GPUCommon : public GPUInterface, public GPUDebugInterface { public: GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); - ~GPUCommon(); Draw::DrawContext *GetDrawContext() override { return draw_; @@ -225,9 +224,6 @@ public: } protected: - void DeviceLost() override; - void DeviceRestore(Draw::DrawContext *draw) override; - void ClearCacheNextFrame() override {} virtual void CheckRenderResized() {} @@ -275,8 +271,6 @@ protected: } } - size_t FormatGPUStatsCommon(char *buf, size_t size); - virtual void BuildReportingInfo() = 0; virtual void UpdateMSAALevel(Draw::DrawContext *draw) {} diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 6a1771875d..2278ceadb2 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -6,6 +6,7 @@ #include "Core/System.h" #include "Core/Config.h" +#include "Core/Util/PPGeDraw.h" #include "GPU/GPUCommonHW.h" #include "GPU/Common/SplineCommon.h" @@ -386,6 +387,8 @@ GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPU UpdateCmdInfo(); UpdateMSAALevel(draw); + + PPGeSetDrawContext(draw); } GPUCommonHW::~GPUCommonHW() { @@ -407,13 +410,22 @@ void GPUCommonHW::CheckRenderResized() { } } +// Call at the END of the GPU implementation's DeviceLost void GPUCommonHW::DeviceLost() { - textureCache_->Clear(false); framebufferManager_->DeviceLost(); + draw_ = nullptr; + textureCache_->Clear(false); textureCache_->DeviceLost(); shaderManager_->DeviceLost(); } +// Call at the start of the GPU implementation's DeviceRestore +void GPUCommonHW::DeviceRestore(Draw::DrawContext *draw) { + draw_ = draw; + framebufferManager_->DeviceRestore(draw_); + PPGeSetDrawContext(draw_); +} + void GPUCommonHW::UpdateCmdInfo() { if (g_Config.bSoftwareSkinning) { cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE; @@ -1599,3 +1611,46 @@ void GPUCommonHW::Execute_BoneMtxData(u32 op, u32 diff) { gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x00FFFFFF); gstate.boneMatrixData = GE_CMD_BONEMATRIXDATA << 24; } + +size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { + float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; + return snprintf(buffer, size, + "DL processing time: %0.2f ms, %d drawsync, %d listsync\n" + "Draw calls: %d, flushes %d, clears %d (cached: %d)\n" + "Num Tracked Vertex Arrays: %d\n" + "Vertices: %d cached: %d uncached: %d\n" + "FBOs active: %d (evaluations: %d)\n" + "Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n" + "readbacks %d (%d non-block), uploads %d, depal %d\n" + "Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n" + "GPU cycles executed: %d (%f per vertex)\n", + gpuStats.msProcessingDisplayLists * 1000.0f, + gpuStats.numDrawSyncs, + gpuStats.numListSyncs, + gpuStats.numDrawCalls, + gpuStats.numFlushes, + gpuStats.numClears, + gpuStats.numCachedDrawCalls, + gpuStats.numTrackedVertexArrays, + gpuStats.numVertsSubmitted, + gpuStats.numCachedVertsDrawn, + gpuStats.numUncachedVertsDrawn, + (int)framebufferManager_->NumVFBs(), + gpuStats.numFramebufferEvaluations, + (int)textureCache_->NumLoadedTextures(), + gpuStats.numTexturesDecoded, + gpuStats.numTextureInvalidations, + gpuStats.numTextureDataBytesHashed / 1024, + gpuStats.numBlockingReadbacks, + gpuStats.numReadbacks, + gpuStats.numUploads, + gpuStats.numDepal, + gpuStats.numDepthCopies, + gpuStats.numColorCopies, + gpuStats.numReinterpretCopies, + gpuStats.numCopiesForShaderBlend, + gpuStats.numCopiesForSelfTex, + gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles, + vertexAverageCycles + ); +} diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index ca3fe1780d..2e13a11738 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -12,6 +12,7 @@ public: void CopyDisplayToOutput(bool reallyDirty) override; void DoState(PointerWrap &p) override; void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void BeginFrame() override; @@ -69,6 +70,7 @@ private: void CheckFlushOp(int cmd, u32 diff); protected: + size_t FormatGPUStatsCommon(char *buf, size_t size); void UpdateCmdInfo() override; void PreExecuteOp(u32 op, u32 diff) override; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2a3bf685f7..bf54743958 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -454,6 +454,8 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw) NotifyConfigChanged(); NotifyRenderResized(); NotifyDisplayResized(); + + PPGeSetDrawContext(draw); } void SoftGPU::DeviceLost() { From 72bed6f2b596b90f7ddd31584b65fa5440567c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Feb 2023 11:05:52 +0100 Subject: [PATCH 177/424] Some DeviceLost/DeviceRestore cleanup --- GPU/Common/DrawEngineCommon.h | 2 ++ GPU/D3D11/DrawEngineD3D11.h | 3 +++ GPU/D3D11/ShaderManagerD3D11.h | 2 +- GPU/D3D11/TextureCacheD3D11.h | 2 +- GPU/Directx9/DrawEngineDX9.h | 3 +++ GPU/Directx9/GPU_DX9.cpp | 8 ++++++++ GPU/Directx9/GPU_DX9.h | 3 +++ GPU/Directx9/ShaderManagerDX9.h | 2 +- GPU/Directx9/TextureCacheDX9.h | 2 +- GPU/GLES/DrawEngineGLES.h | 4 ++-- GPU/GLES/GPU_GLES.cpp | 8 +------- GPU/GPUCommonHW.cpp | 9 +++++++++ GPU/Software/TransformUnit.h | 3 +++ GPU/Vulkan/DrawEngineVulkan.cpp | 1 - GPU/Vulkan/DrawEngineVulkan.h | 4 ++-- GPU/Vulkan/GPU_Vulkan.cpp | 11 ++--------- 16 files changed, 42 insertions(+), 25 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index 78473c3cf3..d5f8056417 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -74,6 +74,8 @@ public: virtual ~DrawEngineCommon(); void Init(); + virtual void DeviceLost() = 0; + virtual void DeviceRestore(Draw::DrawContext *draw) = 0; bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices); diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 2703828516..7c9b46ac5e 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -119,6 +119,9 @@ public: DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context); ~DrawEngineD3D11(); + void DeviceLost() override { draw_ = nullptr; } + void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + void SetShaderManager(ShaderManagerD3D11 *shaderManager) { shaderManager_ = shaderManager; } diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 5dacd408a5..9f8de499a9 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -89,7 +89,7 @@ public: void ClearShaders() override; void DirtyLastShader() override; - void DeviceLost() override {} + void DeviceLost() override { draw_ = nullptr; } void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 35f14d5a6f..53c150a9e4 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -52,7 +52,7 @@ public: bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; - void DeviceLost() override {} + void DeviceLost() override { draw_ = nullptr; } void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } protected: diff --git a/GPU/Directx9/DrawEngineDX9.h b/GPU/Directx9/DrawEngineDX9.h index e8bb1fbf42..1cea91376b 100644 --- a/GPU/Directx9/DrawEngineDX9.h +++ b/GPU/Directx9/DrawEngineDX9.h @@ -107,6 +107,9 @@ public: DrawEngineDX9(Draw::DrawContext *draw); ~DrawEngineDX9(); + void DeviceLost() override { draw_ = nullptr; } + void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } + void SetShaderManager(ShaderManagerDX9 *shaderManager) { shaderManager_ = shaderManager; } diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 1c748980c0..cc099aa52a 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -105,6 +105,14 @@ u32 GPU_DX9::CheckGPUFeatures() const { return CheckGPUFeaturesLate(features); } +void GPU_DX9::DeviceLost() { + GPUCommonHW::DeviceLost(); +} + +void GPU_DX9::DeviceRestore(Draw::DrawContext *draw) { + GPUCommonHW::DeviceRestore(draw); +} + void GPU_DX9::ReapplyGfxState() { dxstate.Restore(); GPUCommonHW::ReapplyGfxState(); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 1da17b2e3e..f18ffeb77e 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -36,6 +36,9 @@ public: u32 CheckGPUFeatures() const override; + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; + void ReapplyGfxState() override; void GetStats(char *buffer, size_t bufsize) override; diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index a0ccce98ed..99773c69dc 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -85,7 +85,7 @@ public: int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } - void DeviceLost() override {} + void DeviceLost() override { draw_ = nullptr; } void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } std::vector DebugGetShaderIDs(DebugShaderType type); diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index 8b2a9eaec8..0b41c92a71 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -42,7 +42,7 @@ public: bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override; - void DeviceLost() override {} + void DeviceLost() override { draw_ = nullptr; } void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } protected: diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index 9352291c29..17f773c0b2 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -76,8 +76,8 @@ public: fragmentTestCache_ = testCache; } - void DeviceLost(); - void DeviceRestore(Draw::DrawContext *draw); + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; void ClearTrackedVertexArrays() override {} diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 7e362b0697..20ac03129b 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -239,7 +239,6 @@ void GPU_GLES::DeviceLost() { // TransformDraw has registered as a GfxResourceHolder. CancelReady(); fragmentTestCache_.DeviceLost(); - drawEngine_.DeviceLost(); GPUCommonHW::DeviceLost(); } @@ -247,13 +246,8 @@ void GPU_GLES::DeviceLost() { void GPU_GLES::DeviceRestore(Draw::DrawContext *draw) { GPUCommonHW::DeviceRestore(draw); - UpdateCmdInfo(); - UpdateVsyncInterval(true); - - shaderManager_->DeviceRestore(draw_); - textureCache_->DeviceRestore(draw_); - drawEngine_.DeviceRestore(draw_); fragmentTestCache_.DeviceRestore(draw_); + UpdateVsyncInterval(true); } void GPU_GLES::BeginHostFrame() { diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 2278ceadb2..1dbf9c10df 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -417,13 +417,22 @@ void GPUCommonHW::DeviceLost() { textureCache_->Clear(false); textureCache_->DeviceLost(); shaderManager_->DeviceLost(); + drawEngineCommon_->DeviceLost(); } // Call at the start of the GPU implementation's DeviceRestore void GPUCommonHW::DeviceRestore(Draw::DrawContext *draw) { draw_ = draw; framebufferManager_->DeviceRestore(draw_); + textureCache_->DeviceRestore(draw_); + shaderManager_->DeviceRestore(draw_); + drawEngineCommon_->DeviceRestore(draw_); + PPGeSetDrawContext(draw_); + + gstate_c.SetUseFlags(CheckGPUFeatures()); + BuildReportingInfo(); + UpdateCmdInfo(); } void GPUCommonHW::UpdateCmdInfo() { diff --git a/GPU/Software/TransformUnit.h b/GPU/Software/TransformUnit.h index b1dd318540..895c023a92 100644 --- a/GPU/Software/TransformUnit.h +++ b/GPU/Software/TransformUnit.h @@ -173,6 +173,9 @@ public: SoftwareDrawEngine(); ~SoftwareDrawEngine(); + void DeviceLost() override {} + void DeviceRestore(Draw::DrawContext *draw) override {} + void NotifyConfigChanged() override; void DispatchFlush() override; void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int cullMode, int *bytesRead) override; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 78f561376e..11907c13b7 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -287,7 +287,6 @@ void DrawEngineVulkan::DeviceLost() { void DrawEngineVulkan::DeviceRestore(Draw::DrawContext *draw) { draw_ = draw; - InitDeviceObjects(); } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 6c21b7609d..b0e99a7c24 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -158,8 +158,8 @@ public: framebufferManager_ = fbManager; } - void DeviceLost(); - void DeviceRestore(Draw::DrawContext *draw); + void DeviceLost() override; + void DeviceRestore(Draw::DrawContext *draw) override; // So that this can be inlined void Flush() { diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index ee7500ea96..ed9a15c99d 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -454,7 +454,6 @@ void GPU_Vulkan::DeviceLost() { SaveCache(shaderCachePath_); } DestroyDeviceObjects(); - drawEngine_.DeviceLost(); pipelineManager_->DeviceLost(); GPUCommonHW::DeviceLost(); @@ -462,17 +461,11 @@ void GPU_Vulkan::DeviceLost() { void GPU_Vulkan::DeviceRestore(Draw::DrawContext *draw) { GPUCommonHW::DeviceRestore(draw); - InitDeviceObjects(); - - gstate_c.SetUseFlags(CheckGPUFeatures()); - BuildReportingInfo(); - UpdateCmdInfo(); VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - drawEngine_.DeviceRestore(draw_); pipelineManager_->DeviceRestore(vulkan); - textureCacheVulkan_->DeviceRestore(draw_); - shaderManagerVulkan_->DeviceRestore(draw_); + + InitDeviceObjects(); } void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { From b3ce31c61eee3d8ac8996115e0f013a89ded7d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Feb 2023 19:54:30 +0100 Subject: [PATCH 178/424] Address feedback --- GPU/GPUCommon.cpp | 2 ++ GPU/GPUCommonHW.cpp | 2 -- GPU/Software/SoftGpu.cpp | 2 -- GPU/Vulkan/GPU_Vulkan.cpp | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 884b06816b..802219472c 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -37,6 +37,7 @@ #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceGe.h" #include "Core/HW/Display.h" +#include "Core/Util/PPGeDraw.h" #include "Core/MemMapHelpers.h" #include "GPU/Common/DrawEngineCommon.h" #include "GPU/Common/FramebufferManagerCommon.h" @@ -68,6 +69,7 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : gpuStats.Reset(); UpdateVsyncInterval(true); + PPGeSetDrawContext(draw); ResetMatrices(); } diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 1dbf9c10df..5c51cf5e8a 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -387,8 +387,6 @@ GPUCommonHW::GPUCommonHW(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : GPU UpdateCmdInfo(); UpdateMSAALevel(draw); - - PPGeSetDrawContext(draw); } GPUCommonHW::~GPUCommonHW() { diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index bf54743958..2a3bf685f7 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -454,8 +454,6 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw) NotifyConfigChanged(); NotifyRenderResized(); NotifyDisplayResized(); - - PPGeSetDrawContext(draw); } void SoftGPU::DeviceLost() { diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index ed9a15c99d..065dc5b1c5 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -438,8 +438,8 @@ void GPU_Vulkan::DestroyDeviceObjects() { } void GPU_Vulkan::CheckRenderResized() { - GPUCommonHW::CheckRenderResized(); if (renderResized_) { + GPUCommonHW::CheckRenderResized(); pipelineManager_->InvalidateMSAAPipelines(); framebufferManager_->ReleasePipelines(); } From 0943bebc481854f31f7a7c225beecb8013f2344b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 26 Feb 2023 11:18:56 -0800 Subject: [PATCH 179/424] Build: Fix an MSVC warning, normalize a bit. --- ext/cpu_features.vcxproj | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ext/cpu_features.vcxproj b/ext/cpu_features.vcxproj index 0588cb55a9..5481dad5db 100644 --- a/ext/cpu_features.vcxproj +++ b/ext/cpu_features.vcxproj @@ -198,6 +198,9 @@ stdcpp17 cpu_features/include STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + false + Size + true Windows @@ -216,6 +219,9 @@ stdcpp17 cpu_features/include STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + false + Size + true Windows @@ -234,6 +240,9 @@ stdcpp17 cpu_features/include STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + false + Size + true Windows @@ -308,6 +317,10 @@ stdcpp17 cpu_features/include STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions) + false + Size + StreamingSIMDExtensions2 + true Windows From c062b78b556586baa45cac9051bbb4ef48227bab Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 26 Feb 2023 11:27:46 -0800 Subject: [PATCH 180/424] Build: Cleanup some MSVC optimization settings. --- UI/UI.vcxproj | 1 + ext/SPIRV-Cross.vcxproj | 1 + ext/cpu_features.vcxproj | 8 ++++---- ext/discord-rpc-build/discord-rpc.vcxproj | 13 +++++++++---- ext/glslang.vcxproj | 5 +++++ ext/libarmips.vcxproj | 13 +++++++++---- ext/libzstd.vcxproj | 1 + ext/miniupnpc.vcxproj | 3 +++ unittest/UnitTests.vcxproj | 1 + 9 files changed, 34 insertions(+), 12 deletions(-) diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index be370e4ef1..f4c85a7185 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -302,6 +302,7 @@ MultiThreaded $(EXTERNAL_COMPILE_OPTIONS) ProgramDatabase + StreamingSIMDExtensions2 Windows diff --git a/ext/SPIRV-Cross.vcxproj b/ext/SPIRV-Cross.vcxproj index b6369489d7..467cb84cf1 100644 --- a/ext/SPIRV-Cross.vcxproj +++ b/ext/SPIRV-Cross.vcxproj @@ -240,6 +240,7 @@ false true ProgramDatabase + StreamingSIMDExtensions2 Windows diff --git a/ext/cpu_features.vcxproj b/ext/cpu_features.vcxproj index 5481dad5db..a0eddbd869 100644 --- a/ext/cpu_features.vcxproj +++ b/ext/cpu_features.vcxproj @@ -190,7 +190,7 @@ Level3 - MaxSpeed + MinSpace true true MultiThreaded @@ -211,7 +211,7 @@ Level3 - MaxSpeed + MinSpace true true MultiThreaded @@ -232,7 +232,7 @@ Level3 - MaxSpeed + MinSpace true true MultiThreaded @@ -309,7 +309,7 @@ Level3 - MaxSpeed + MinSpace true true MultiThreaded diff --git a/ext/discord-rpc-build/discord-rpc.vcxproj b/ext/discord-rpc-build/discord-rpc.vcxproj index 5fc9b0f697..e1b7c7d435 100644 --- a/ext/discord-rpc-build/discord-rpc.vcxproj +++ b/ext/discord-rpc-build/discord-rpc.vcxproj @@ -178,7 +178,7 @@ Level3 - MaxSpeed + MinSpace true true NDEBUG;_LIB;%(PreprocessorDefinitions) @@ -189,6 +189,7 @@ false false ProgramDatabase + Size Windows @@ -200,7 +201,7 @@ Level3 - MaxSpeed + MinSpace true true NDEBUG;_LIB;%(PreprocessorDefinitions) @@ -211,6 +212,7 @@ false false ProgramDatabase + Size Windows @@ -222,7 +224,7 @@ Level3 - MaxSpeed + MinSpace true true NDEBUG;_LIB;%(PreprocessorDefinitions) @@ -233,6 +235,7 @@ false false ProgramDatabase + Size Windows @@ -308,7 +311,7 @@ Level3 - MaxSpeed + MinSpace true true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) @@ -318,6 +321,8 @@ true false ProgramDatabase + Size + StreamingSIMDExtensions2 Windows diff --git a/ext/glslang.vcxproj b/ext/glslang.vcxproj index 6d8e742a70..2accb51d6e 100644 --- a/ext/glslang.vcxproj +++ b/ext/glslang.vcxproj @@ -222,6 +222,8 @@ false true ProgramDatabase + true + StreamingSIMDExtensions2 Windows @@ -245,6 +247,7 @@ true false ProgramDatabase + true Windows @@ -268,6 +271,7 @@ true false ProgramDatabase + true Windows @@ -291,6 +295,7 @@ true false ProgramDatabase + true Windows diff --git a/ext/libarmips.vcxproj b/ext/libarmips.vcxproj index fa5fa59c2c..47ed57ae3c 100644 --- a/ext/libarmips.vcxproj +++ b/ext/libarmips.vcxproj @@ -395,7 +395,7 @@ Level3 - MaxSpeed + MinSpace true true WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) @@ -405,6 +405,8 @@ false ProgramDatabase stdcpp17 + Size + StreamingSIMDExtensions2 Windows @@ -416,7 +418,7 @@ Level3 - MaxSpeed + MinSpace true true WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) @@ -428,6 +430,7 @@ false ProgramDatabase stdcpp17 + Size Windows @@ -439,7 +442,7 @@ Level3 - MaxSpeed + MinSpace true true WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) @@ -451,6 +454,7 @@ false ProgramDatabase stdcpp17 + Size Windows @@ -462,7 +466,7 @@ Level3 - MaxSpeed + MinSpace true true WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) @@ -474,6 +478,7 @@ false ProgramDatabase stdcpp17 + Size Windows diff --git a/ext/libzstd.vcxproj b/ext/libzstd.vcxproj index 68dadeded9..bb93a9b3f8 100644 --- a/ext/libzstd.vcxproj +++ b/ext/libzstd.vcxproj @@ -313,6 +313,7 @@ Speed true false + StreamingSIMDExtensions2 Windows diff --git a/ext/miniupnpc.vcxproj b/ext/miniupnpc.vcxproj index ee83b4495c..f69e726242 100644 --- a/ext/miniupnpc.vcxproj +++ b/ext/miniupnpc.vcxproj @@ -287,6 +287,7 @@ cd..\..\.. true false MultiThreaded + StreamingSIMDExtensions2 Windows @@ -320,6 +321,7 @@ cd..\..\.. MultiThreaded false false + false Windows @@ -412,6 +414,7 @@ cd..\..\.. true false false + true iphlpapi.lib diff --git a/unittest/UnitTests.vcxproj b/unittest/UnitTests.vcxproj index 057c5fe52b..bd29c69cd0 100644 --- a/unittest/UnitTests.vcxproj +++ b/unittest/UnitTests.vcxproj @@ -271,6 +271,7 @@ false MultiThreaded ProgramDatabase + StreamingSIMDExtensions2 Console From 0981c28224ee1a1e5c1e727c54bc59e80183e312 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 26 Feb 2023 15:58:40 -0800 Subject: [PATCH 181/424] Build: Skip install of list_cpu_features. --- ext/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/CMakeLists.txt b/ext/CMakeLists.txt index 8205fe4054..e2b0f44a80 100644 --- a/ext/CMakeLists.txt +++ b/ext/CMakeLists.txt @@ -22,7 +22,7 @@ endif() # This works around a bug in cpu_features when ${CMAKE_BINARY_DIR} != ${CMAKE_CURRENT_BINRARY_DIR}. # We also disable the list_cpu_features binary. -add_subdirectory(cmake/cpu_features) +add_subdirectory(cmake/cpu_features EXCLUDE_FROM_ALL) set(SKIP_GLSLANG_INSTALL ON CACHE BOOL "" FORCE) set(ENABLE_GLSLANG_INSTALL OFF) From 9e46a30c131ae22d06f641ccec6276faf40c83c5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 26 Feb 2023 15:58:58 -0800 Subject: [PATCH 182/424] GPU: Correct some missing override specifiers. --- GPU/D3D11/ShaderManagerD3D11.h | 4 ++-- GPU/Directx9/ShaderManagerDX9.h | 4 ++-- GPU/GLES/ShaderManagerGLES.h | 4 ++-- GPU/Vulkan/ShaderManagerVulkan.h | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h index 9f8de499a9..ffdd65ffe7 100644 --- a/GPU/D3D11/ShaderManagerD3D11.h +++ b/GPU/D3D11/ShaderManagerD3D11.h @@ -94,8 +94,8 @@ public: int GetNumVertexShaders() const { return (int)vsCache_.size(); } int GetNumFragmentShaders() const { return (int)fsCache_.size(); } - std::vector DebugGetShaderIDs(DebugShaderType type); - std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); + std::vector DebugGetShaderIDs(DebugShaderType type) override; + std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) override; uint64_t UpdateUniforms(bool useBufferedRendering); void BindUniforms(); diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h index 99773c69dc..68337503b4 100644 --- a/GPU/Directx9/ShaderManagerDX9.h +++ b/GPU/Directx9/ShaderManagerDX9.h @@ -88,8 +88,8 @@ public: void DeviceLost() override { draw_ = nullptr; } void DeviceRestore(Draw::DrawContext *draw) override { draw_ = draw; } - std::vector DebugGetShaderIDs(DebugShaderType type); - std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); + std::vector DebugGetShaderIDs(DebugShaderType type) override; + std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) override; private: void PSUpdateUniforms(u64 dirtyUniforms); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index 6435b44d7d..027c7def9f 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -182,8 +182,8 @@ public: int GetNumFragmentShaders() const { return (int)fsCache_.size(); } int GetNumPrograms() const { return (int)linkedShaderCache_.size(); } - std::vector DebugGetShaderIDs(DebugShaderType type); - std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); + std::vector DebugGetShaderIDs(DebugShaderType type) override; + std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) override; bool LoadCacheFlags(File::IOFile &f, DrawEngineGLES *drawEngine); bool LoadCache(File::IOFile &f); diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index a29ea06be3..38b4b2e1e1 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -118,7 +118,7 @@ public: void DeviceRestore(Draw::DrawContext *draw) override; void GetShaders(int prim, VertexDecoder *decoder, VulkanVertexShader **vshader, VulkanFragmentShader **fshader, VulkanGeometryShader **gshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); - void ClearShaders(); + void ClearShaders() override; void DirtyShader(); void DirtyLastShader() override; @@ -134,8 +134,8 @@ public: VulkanFragmentShader *GetFragmentShaderFromModule(VkShaderModule module); VulkanGeometryShader *GetGeometryShaderFromModule(VkShaderModule module); - std::vector DebugGetShaderIDs(DebugShaderType type); - std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType); + std::vector DebugGetShaderIDs(DebugShaderType type) override; + std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) override; uint64_t UpdateUniforms(bool useBufferedRendering); From ef4f17e9985c6315cb66fde0e50b1c2342ac2e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Feb 2023 15:12:46 +0100 Subject: [PATCH 183/424] Resurrect the Vulkan memory visualizer, but now it's global stats and pushbuffer stats. --- Common/GPU/Vulkan/VulkanMemory.cpp | 31 +++++++++++++++ Common/GPU/Vulkan/VulkanMemory.h | 7 +++- GPU/Vulkan/DebugVisVulkan.cpp | 62 +++++++++++++++++++++++++++++- UI/DevScreens.cpp | 3 +- 4 files changed, 98 insertions(+), 5 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index d8184098a5..9a25e5cbb0 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -18,6 +18,9 @@ // Additionally, Common/Vulkan/* , including this file, are also licensed // under the public domain. +#include +#include + #include "Common/Math/math_util.h" #include "Common/Log.h" @@ -26,17 +29,41 @@ using namespace PPSSPP_VK; +// Global push buffer tracker for vulkan memory profiling. +// Don't want to manually dig up all the active push buffers. +static std::mutex g_pushBufferListMutex; +static std::set g_pushBuffers; + VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage, PushBufferType type) : vulkan_(vulkan), name_(name), size_(size), usage_(usage), type_(type) { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.insert(this); + } + bool res = AddBuffer(); _assert_(res); } VulkanPushBuffer::~VulkanPushBuffer() { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.erase(this); + } + _dbg_assert_(!writePtr_); _assert_(buffers_.empty()); } +std::vector VulkanPushBuffer::GetAllActive() { + std::vector buffers; + std::lock_guard guard(g_pushBufferListMutex); + for (auto iter : g_pushBuffers) { + buffers.push_back(iter); + } + return buffers; +} + bool VulkanPushBuffer::AddBuffer() { BufInfo info; VkDevice device = vulkan_->GetDevice(); @@ -122,6 +149,10 @@ size_t VulkanPushBuffer::GetTotalSize() const { return sum; } +size_t VulkanPushBuffer::GetTotalCapacity() const { + return size_ * buffers_.size(); +} + void VulkanPushBuffer::Map() { _dbg_assert_(!writePtr_); VkResult res = vmaMapMemory(vulkan_->Allocator(), buffers_[buf_].allocation, (void **)(&writePtr_)); diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index 275ca4bb78..863e4f965e 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -131,7 +131,10 @@ public: info->range = sizeof(T); } - size_t GetTotalSize() const; + size_t GetTotalSize() const; // Used size + size_t GetTotalCapacity() const; + + static std::vector GetAllActive(); private: bool AddBuffer(); @@ -173,7 +176,7 @@ private: const char *tag_; VulkanContext *vulkan_ = nullptr; VkDescriptorPool descPool_ = VK_NULL_HANDLE; - VkDescriptorPoolCreateInfo info_; + VkDescriptorPoolCreateInfo info_{}; std::vector sizes_; std::function clear_; uint32_t usage_ = 0; diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index 82acb8c0fd..ff03218efd 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -15,24 +15,84 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include +#include +#include + #include "Common/Render/DrawBuffer.h" #include "Common/GPU/thin3d.h" +#include "Common/GPU/Vulkan/VulkanContext.h" #include "Common/UI/Context.h" #include "Common/UI/View.h" #include "Common/System/Display.h" #include "Common/System/System.h" +#include "ext/vma/vk_mem_alloc.h" + #include "DebugVisVulkan.h" #include "Common/GPU/Vulkan/VulkanMemory.h" #include "Common/GPU/Vulkan/VulkanImage.h" +#include "Common/Data/Text/Parsers.h" #include "GPU/Vulkan/GPU_Vulkan.h" #include "GPU/Vulkan/VulkanUtil.h" #include "GPU/Vulkan/TextureCacheVulkan.h" #undef DrawText +bool comparePushBufferNames(const VulkanPushBuffer *a, const VulkanPushBuffer *b) { + return strcmp(a->Name(), b->Name()) < 0; +} + void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { - // TODO: Make a new allocator visualizer for VMA. + // This one will simply display stats. + Draw::DrawContext *draw = ui->GetDrawContext(); + + VulkanContext *vulkan = (VulkanContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); + if (!vulkan) { + return; + } + + VmaTotalStatistics vmaStats; + vmaCalculateStatistics(vulkan->Allocator(), &vmaStats); + + std::vector budgets; + budgets.resize(vulkan->GetMemoryProperties().memoryHeapCount); + vmaGetHeapBudgets(vulkan->Allocator(), &budgets[0]); + + size_t totalBudget = 0; + size_t totalUsedBytes = 0; + for (auto &budget : budgets) { + totalBudget += budget.budget; + totalUsedBytes += budget.usage; + } + + std::stringstream str; + str << vulkan->GetPhysicalDeviceProperties().properties.deviceName << std::endl; + str << "Allocated " << NiceSizeFormat(vmaStats.total.statistics.allocationBytes) << " in " << vmaStats.total.statistics.allocationCount << " allocs" << std::endl; + // Note: The overall number includes stuff like descriptor sets pools and other things that are not directly visible as allocations. + str << "Overall " << NiceSizeFormat(totalUsedBytes) << " used out of " << NiceSizeFormat(totalBudget) << " available" << std::endl; + + str << "Push buffers:" << std::endl; + + // Now list the various push buffers. + auto pushBuffers = VulkanPushBuffer::GetAllActive(); + std::sort(pushBuffers.begin(), pushBuffers.end(), comparePushBufferNames); + + for (auto push : pushBuffers) { + str << " " << push->Name() << " " + << NiceSizeFormat(push->GetTotalCapacity()) << ", used: " + << NiceSizeFormat(push->GetTotalSize()) << std::endl; + } + + const int padding = 10 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT); + const int starty = 50 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_TOP); + int x = padding; + int y = starty; + + ui->SetFontScale(0.7f, 0.7f); + ui->DrawTextShadow(str.str().c_str(), x, y, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); + ui->SetFontScale(1.0f, 1.0f); + ui->Flush(); } void DrawGPUProfilerVis(UIContext *ui, GPUInterface *gpu) { diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index eb3de25579..82cb3c159e 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -101,8 +101,7 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) { items->Add(new Choice(dev->T("Jit Compare")))->OnClick.Handle(this, &DevMenuScreen::OnJitCompare); items->Add(new Choice(dev->T("Shader Viewer")))->OnClick.Handle(this, &DevMenuScreen::OnShaderView); if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) { - // TODO: Make a new allocator visualizer for VMA. - // items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer"))); + items->Add(new CheckBox(&g_Config.bShowAllocatorDebug, dev->T("Allocator Viewer"))); items->Add(new CheckBox(&g_Config.bShowGpuProfile, dev->T("GPU Profile"))); } items->Add(new Choice(dev->T("Toggle Freeze")))->OnClick.Handle(this, &DevMenuScreen::OnFreezeFrame); From 5d5e02d94958dfdb81bd31287bc30f0ccef27af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 01:10:30 +0100 Subject: [PATCH 184/424] Attempted buildfix --- Common/GPU/Vulkan/VulkanLoader.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Common/GPU/Vulkan/VulkanLoader.h b/Common/GPU/Vulkan/VulkanLoader.h index 85b4bb5510..f85a09f558 100644 --- a/Common/GPU/Vulkan/VulkanLoader.h +++ b/Common/GPU/Vulkan/VulkanLoader.h @@ -33,6 +33,11 @@ #include "ext/vulkan/vulkan.h" +// Hacky X11 header workaround +#ifdef Opposite +#undef Opposite +#endif + namespace PPSSPP_VK { // Putting our own Vulkan function pointers in a namespace ensures that ppsspp_libretro.so doesn't collide with libvulkan.so. extern PFN_vkCreateInstance vkCreateInstance; From c5383151349ba2107789399daa2c9fde53af3d97 Mon Sep 17 00:00:00 2001 From: GABO1423 <35014183+GABO1423@users.noreply.github.com> Date: Sun, 26 Feb 2023 19:19:05 -0400 Subject: [PATCH 185/424] (UWP) Small Build Overhaul --- UWP/UWP.vcxproj | 1180 +++++++-------------------------------- UWP/UWP.vcxproj.filters | 187 ++++++- 2 files changed, 377 insertions(+), 990 deletions(-) diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 1cd5d12174..d3f35bd6d8 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -212,7 +212,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -237,7 +237,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -262,7 +262,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -287,7 +287,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -312,7 +312,7 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsGold\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -337,7 +337,7 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsGold\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -362,7 +362,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -387,7 +387,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -412,7 +412,7 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsGold\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -437,7 +437,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -462,7 +462,7 @@ copy PackageNormal.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsNormal\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -487,7 +487,7 @@ copy PackageGold.appxmanifest Package.appxmanifest /Y mkdir Assets copy AssetsGold\*.* Assets /Y - robocopy "..\Assets\." "Content\." /xf *.vsh /E /R:0 /W:0 + robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 @@ -521,6 +521,9 @@ true + + true + true @@ -544,18 +547,7 @@ - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing @@ -564,18 +556,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create @@ -596,283 +577,123 @@ true Document + + true + Document + true - + true - - true - true - true - true - true - true - true - true - true - true - true - true + + true - + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + true true + + true + + + true + + + true + + + true + + + true + - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true true @@ -881,819 +702,247 @@ true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true true - true - true - true - true - true - true - true - true - true - true - true - true + true - - true - true - true - true - true - true - true - true - true - true - true - true + + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true + + + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true + + + true - true - true - true - true - true - true - true - true - true - true - true - true + true - true - true - true - true - true - true - true - true - true - true - true - true + true @@ -1730,6 +979,9 @@ + + true + true diff --git a/UWP/UWP.vcxproj.filters b/UWP/UWP.vcxproj.filters index 15c471b062..b03d9592a8 100644 --- a/UWP/UWP.vcxproj.filters +++ b/UWP/UWP.vcxproj.filters @@ -53,6 +53,21 @@ {da2113a6-e616-4fc9-8be3-ff75b963664b} + + {55147387-68fc-487e-abed-7a763f850ef1} + + + {e5d2759b-3511-4ab9-a9ca-070dd9715f3b} + + + {0fb972a9-20a9-4eba-be70-c408f9306939} + + + {47d54a48-ca53-4d57-8bfd-9c86fd97d84b} + + + {83476056-57b8-409f-b729-754d6401e3d5} + @@ -102,6 +117,12 @@ Content + + Content + + + Content\debugger + @@ -171,9 +192,15 @@ Content\lang + + Content\lang + Content\lang + + Content\lang + Content\lang @@ -246,21 +273,33 @@ Content\shaders + + Content\shaders + Content\shaders - + Content\shaders Content\shaders + + Content\shaders + Content\shaders Content\shaders + + Content\shaders + + + Content\shaders + Content\shaders @@ -270,9 +309,72 @@ Content\shaders + + Content\shaders + Content\shaders + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + + + Content\shaders + Content\flash0\font @@ -327,48 +429,81 @@ Content\flash0\font - - Content\shaders - - - Content\shaders - - - Content\shaders - - - Content\shaders - - - Content\shaders - - - Content\shaders - - - Content\shaders - - + Content - + Content - + Content\themes Content + + Content + + + Content + + + Content + + + Content + + + Content + + + Content + + + Content\shaders + + + Content\shaders + + + Content\debugger + + + Content\debugger + + + Content\debugger + + + Content\debugger + + + Content\debugger\static\css + + + Content\debugger\static\css + + + Content\debugger\static\js + + + Content\debugger\static\js + + + Content\debugger\static\media + Content + + Content\debugger\static\js + Content - + \ No newline at end of file From 15f087b71abb41b4bd9030cf462b08f770226086 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 26 Feb 2023 23:59:48 -0800 Subject: [PATCH 186/424] D3D11: Correct equal clear check. --- GPU/D3D11/DrawEngineD3D11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 81692d3ec5..df5eeb0284 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -634,8 +634,8 @@ rotateVBO: swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result); // Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values. // Games sometimes expect exact matches (see #12626, for example) for equal comparisons. - if (result.action == SW_NOT_READY && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f) - result.action = SW_DRAW_PRIMITIVES; + if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f) + result.action = SW_NOT_READY; if (result.action == SW_NOT_READY) { swTransform.DetectOffsetTexture(maxIndex); } From ca8af6f4c7076f0c253e2afc0886328e1a5e6d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 10:39:49 +0100 Subject: [PATCH 187/424] Fix "DebugAnnotate" (not used, but I used it temporarily to investigate #17014) See #17014 --- Common/GPU/Vulkan/VulkanRenderManager.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Common/GPU/Vulkan/VulkanRenderManager.h b/Common/GPU/Vulkan/VulkanRenderManager.h index 812128b906..3cad859e8d 100644 --- a/Common/GPU/Vulkan/VulkanRenderManager.h +++ b/Common/GPU/Vulkan/VulkanRenderManager.h @@ -416,8 +416,10 @@ public: // These can be useful both when inspecting in RenderDoc, and when manually inspecting recorded commands // in the debugger. void DebugAnnotate(const char *annotation) { + _dbg_assert_(curRenderStep_); VkRenderData data{ VKRRenderCommand::DEBUG_ANNOTATION }; data.debugAnnotation.annotation = annotation; + curRenderStep_->commands.push_back(data); } VkCommandBuffer GetInitCmd(); From 1071d0808c5b0bb6578f44b767070d100a591182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 11:10:47 +0100 Subject: [PATCH 188/424] Undo Daxter's rotation of the analog input. See #17015 I think this is quite a bit better actually. Appears to be exactly 15 degrees. --- Core/Compatibility.cpp | 1 + Core/Compatibility.h | 1 + Core/HLE/sceCtrl.cpp | 16 ++++++++++++++++ assets/compat.ini | 7 +++++++ 4 files changed, 25 insertions(+) diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index f6cf4a644c..a40a62bf4d 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -127,6 +127,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) { CheckSetting(iniFile, gameID, "RockmanDash2SoundFix", &flags_.RockmanDash2SoundFix); CheckSetting(iniFile, gameID, "ReadbackDepth", &flags_.ReadbackDepth); CheckSetting(iniFile, gameID, "BlockTransferDepth", &flags_.BlockTransferDepth); + CheckSetting(iniFile, gameID, "DaxterRotatedAnalogStick", &flags_.DaxterRotatedAnalogStick); } void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) { diff --git a/Core/Compatibility.h b/Core/Compatibility.h index d34722f4fa..021518ddf6 100644 --- a/Core/Compatibility.h +++ b/Core/Compatibility.h @@ -98,6 +98,7 @@ struct CompatFlags { bool RockmanDash2SoundFix; bool ReadbackDepth; bool BlockTransferDepth; + bool DaxterRotatedAnalogStick; }; struct VRCompat { diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index ab9d15bf9d..898ba6e37b 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -20,6 +20,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" +#include "Common/Math/math_util.h" #include "Core/CoreTiming.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" @@ -28,6 +29,7 @@ #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HW/Display.h" +#include "Core/System.h" #include "Core/MemMapHelpers.h" #include "Core/MIPS/MIPS.h" #include "Core/Replay.h" @@ -118,6 +120,20 @@ static void __CtrlUpdateLatch() // Copy in the current data to the current buffer. ctrlBufs[ctrlBuf] = ctrlCurrent; + + if (PSP_CoreParameter().compat.flags().DaxterRotatedAnalogStick) { + // For some reason, Daxter rotates the analog input. See #17015 + float angle = (15.0f / 360.0f) * (2.0f * M_PI); + float cosAngle = cosf(angle); + float sinAngle = sinf(angle); + float x = ctrlBufs[ctrlBuf].analog[0][0] - 128; + float y = ctrlBufs[ctrlBuf].analog[0][1] - 128; + float rX = x * cosAngle - y * sinAngle; + float rY = x * sinAngle + y * cosAngle; + ctrlBufs[ctrlBuf].analog[0][0] = (u8)Clamp(rX + 128, 0.0f, 255.0f); + ctrlBufs[ctrlBuf].analog[0][1] = (u8)Clamp(rY + 128, 0.0f, 255.0f); + } + ctrlBufs[ctrlBuf].buttons = buttons; u32 changed = buttons ^ ctrlOldButtons; diff --git a/assets/compat.ini b/assets/compat.ini index 91b673fb7a..1828319a3b 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -1479,3 +1479,10 @@ NPEG00004 = true ULES01070 = true ULES01071 = true ULUS10347 = true + +[DaxterRotatedAnalogStick] +# Daxter (see issue #17015) +UCUS98618 = true +UCES00044 = true +NPUG80329 = true +NPEG00025 = true From 7b06ec7469b576124a0e5a641af5d3f142a377c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 11:15:36 +0100 Subject: [PATCH 189/424] Add more Daxter game IDs --- assets/compat.ini | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/compat.ini b/assets/compat.ini index 1828319a3b..14ee5a4bbb 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -328,9 +328,11 @@ UCED00971 = true UCUS98713 = true # Daxter UCUS98618 = true +UCUS98654 = true UCES00044 = true NPUG80329 = true NPEG00025 = true +UCKS45025 = true # Ys Seven ULUS10551 = true ULJM05475 = true @@ -1483,6 +1485,8 @@ ULUS10347 = true [DaxterRotatedAnalogStick] # Daxter (see issue #17015) UCUS98618 = true +UCUS98654 = true UCES00044 = true NPUG80329 = true NPEG00025 = true +UCKS45025 = true From 3aa0a9e17b6c9ad6a4ae0bed18bc6062c7d68439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 15:21:58 +0100 Subject: [PATCH 190/424] Fix blackscreen, better debug print of display parameters --- Common/System/Display.cpp | 20 ++++++++++++++++++++ Common/System/Display.h | 3 +++ SDL/SDLMain.cpp | 4 +--- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 90644a592a..7f79cc5041 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -1,3 +1,5 @@ +#include + #include "Common/System/Display.h" #include "Common/Math/math_util.h" @@ -46,3 +48,21 @@ void RotateRectToDisplay(DisplayRect &rect, int curRTWidth, int curRTHeight void RotateRectToDisplay(DisplayRect &rect, float curRTWidth, float curRTHeight) { RotateRectToDisplayImpl(rect, curRTWidth, curRTHeight); } + +DisplayProperties::DisplayProperties() { + rot_matrix.setIdentity(); +} + +void DisplayProperties::Print() { + printf("dp_xres/yres: %d, %d\n", dp_xres, dp_yres); + printf("pixel_xres/yres: %d, %d\n", pixel_xres, pixel_yres); + + printf("dpi, x, y: %f, %f, %f\n", dpi, dpi_scale_x, dpi_scale_y); + printf("pixel_in_dps: %f, %f\n", pixel_in_dps_x, pixel_in_dps_y); + + printf("dpi_real: %f, %f\n", dpi_scale_real_x, dpi_scale_real_y); + printf("display_hz: %f\n", display_hz); + + printf("rotation: %d\n", rotation); + rot_matrix.print(); +} diff --git a/Common/System/Display.h b/Common/System/Display.h index c7e826394c..0bea49542a 100644 --- a/Common/System/Display.h +++ b/Common/System/Display.h @@ -36,6 +36,9 @@ struct DisplayProperties { DisplayRotation rotation; Lin::Matrix4x4 rot_matrix; + + DisplayProperties(); + void Print(); }; extern DisplayProperties g_display; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index d1e71462a3..1acd96e77a 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -751,9 +751,7 @@ int main(int argc, char *argv[]) { g_display.dpi_scale_y = g_display.dp_yres / (float)g_display.pixel_yres; g_display.dpi_scale_real_x = g_display.dpi_scale_x; g_display.dpi_scale_real_y = g_display.dpi_scale_y; - - printf("Pixels: %i x %i\n", g_display.pixel_xres, g_display.pixel_yres); - printf("Virtual pixels: %i x %i\n", g_display.dp_xres, g_display.dp_yres); + g_display.Print(); GraphicsContext *graphicsContext = nullptr; SDL_Window *window = nullptr; From 970f7993df79518c4ca5c7f3dd20212720dc3c09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 27 Feb 2023 23:59:57 +0100 Subject: [PATCH 191/424] Android: Make font rendering work even absent support for R4G4B4A4 textures. This shouldn't normally happen as conforming drivers are required to support that texture format, but the software driver that we accidentally choose on Poco C40 (see issue #16391) doesn't. That we choose that driver will be fixed separately. This fix on its own at least lets the user comfortably navigate to settings and switch to OpenGL. --- Common/GPU/Vulkan/VulkanContext.cpp | 4 ++-- Common/GPU/Vulkan/VulkanLoader.cpp | 1 + Common/GPU/Vulkan/thin3d_vulkan.cpp | 4 +++- Common/GPU/thin3d.h | 6 ++++++ Common/Render/Text/draw_text_android.cpp | 9 +++++++-- Common/Render/Text/draw_text_android.h | 1 + GPU/Common/FramebufferManagerCommon.cpp | 1 + 7 files changed, 21 insertions(+), 5 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index fe15710d70..a8e2a1846c 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -535,7 +535,7 @@ int VulkanContext::GetBestPhysicalDevice() { void VulkanContext::ChooseDevice(int physical_device) { physical_device_ = physical_device; - INFO_LOG(G3D, "Chose physical device %d: %p", physical_device, physical_devices_[physical_device]); + INFO_LOG(G3D, "Chose physical device %d: %s", physical_device, physicalDeviceProperties_[physical_device].properties.deviceName); GetDeviceLayerProperties(); if (!CheckLayers(device_layer_properties_, device_layer_names_)) { @@ -711,7 +711,7 @@ VkResult VulkanContext::CreateDevice() { } else { VulkanLoadDeviceFunctions(device_, extensionsLookup_); } - INFO_LOG(G3D, "Vulkan Device created"); + INFO_LOG(G3D, "Vulkan Device created: %s", physicalDeviceProperties_[physical_device_].properties.deviceName); VulkanSetAvailable(true); VmaAllocatorCreateInfo allocatorInfo = {}; diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 2a00ed9622..2a37785544 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -470,6 +470,7 @@ bool VulkanMayBeAvailable() { case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: anyGood = true; + INFO_LOG(G3D, "VulkanMayBeAvailable: Eligible device found: '%s'", props.deviceName); break; default: INFO_LOG(G3D, "VulkanMayBeAvailable: Ineligible device found and ignored: '%s'", props.deviceName); diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index b0c74c5c76..2d58bebdc8 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -742,7 +742,9 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const Textur usageBits |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT; } - if (!vkTex_->CreateDirect(cmd, width_, height_, 1, mipLevels_, vulkanFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, usageBits)) { + VkComponentMapping r8AsAlpha[4] = { VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_R }; + + if (!vkTex_->CreateDirect(cmd, width_, height_, 1, mipLevels_, vulkanFormat, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, usageBits, desc.swizzle == TextureSwizzle::R8_AS_ALPHA ? r8AsAlpha : nullptr)) { ERROR_LOG(G3D, "Failed to create VulkanTexture: %dx%dx%d fmt %d, %d levels", width_, height_, depth_, (int)vulkanFormat, mipLevels_); return false; } diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 9a427027a9..3013470e95 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -598,6 +598,11 @@ struct DeviceCaps { // Important: only write to the provided pointer, don't read from it. typedef std::function TextureCallback; +enum class TextureSwizzle { + DEFAULT, + R8_AS_ALPHA, +}; + struct TextureDesc { TextureType type; DataFormat format; @@ -607,6 +612,7 @@ struct TextureDesc { int depth; int mipLevels; bool generateMips; + TextureSwizzle swizzle; // Optional, for tracking memory usage and graphcis debuggers. const char *tag; // Does not take ownership over pointed-to data. diff --git a/Common/Render/Text/draw_text_android.cpp b/Common/Render/Text/draw_text_android.cpp index b6ada98a94..1cc3dc9d1e 100644 --- a/Common/Render/Text/draw_text_android.cpp +++ b/Common/Render/Text/draw_text_android.cpp @@ -27,7 +27,10 @@ TextDrawerAndroid::TextDrawerAndroid(Draw::DrawContext *draw) : TextDrawer(draw) ERROR_LOG(G3D, "Failed to find class: '%s'", textRendererClassName); } dpiScale_ = CalculateDPIScale(); - INFO_LOG(G3D, "Initializing TextDrawerAndroid with DPI scale %f", dpiScale_); + + use4444Format_ = (draw->GetDataFormatSupport(Draw::DataFormat::R4G4B4A4_UNORM_PACK16) & Draw::FMT_TEXTURE) != 0; + + INFO_LOG(G3D, "Initializing TextDrawerAndroid with DPI scale %f, use4444=%d", dpiScale_, (int)use4444Format_); } TextDrawerAndroid::~TextDrawerAndroid() { @@ -244,7 +247,8 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, entry = iter->second.get(); entry->lastUsedFrame = frameCount_; } else { - DataFormat texFormat = Draw::DataFormat::R4G4B4A4_UNORM_PACK16; + // Actually, I don't know why we don't always use R8_UNORM.. + DataFormat texFormat = use4444Format_ ? Draw::DataFormat::R4G4B4A4_UNORM_PACK16 : Draw::DataFormat::R8_UNORM; entry = new TextStringEntry(); @@ -260,6 +264,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x, desc.depth = 1; desc.mipLevels = 1; desc.generateMips = false; + desc.swizzle = use4444Format_ ? Draw::TextureSwizzle::DEFAULT : Draw::TextureSwizzle::R8_AS_ALPHA, desc.tag = "TextDrawer"; entry->texture = draw_->CreateTexture(desc); cache_[key] = std::unique_ptr(entry); diff --git a/Common/Render/Text/draw_text_android.h b/Common/Render/Text/draw_text_android.h index 4b95bdeb75..f4b7e431e6 100644 --- a/Common/Render/Text/draw_text_android.h +++ b/Common/Render/Text/draw_text_android.h @@ -40,6 +40,7 @@ private: jmethodID method_renderText; uint32_t fontHash_; + bool use4444Format_ = false; std::map fontMap_; diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index deba2f8d39..91005fd71c 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1384,6 +1384,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G 1, 1, false, + Draw::TextureSwizzle::DEFAULT, "DrawPixels", { (uint8_t *)srcPixels }, generateTexture, From 051039b69641147d215ec354611e1c155540f751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Moraz=C3=A1n?= <35014183+GABO1423@users.noreply.github.com> Date: Tue, 28 Feb 2023 00:01:26 -0400 Subject: [PATCH 192/424] (UWP) Fix Skipped Asset Files --- UWP/UWP.vcxproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index d3f35bd6d8..561080d0eb 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -598,18 +598,23 @@ true + Content\debugger\static\css\%(Filename)%(Extension) true + Content\debugger\static\css\%(Filename)%(Extension) true + Content\debugger\static\js\%(Filename)%(Extension) true + Content\debugger\static\js\%(Filename)%(Extension) true + Content\debugger\static\media\%(Filename)%(Extension) true @@ -981,6 +986,7 @@ true + Content\debugger\static\js\%(Filename)%(Extension) true From ea5d4a5671a8369ca46e2909478b336cca39dc75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Feb 2023 08:31:25 +0100 Subject: [PATCH 193/424] Rotate the analog stick by 15 degrees in the GoW games too, they do the same thing. --- assets/compat.ini | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/assets/compat.ini b/assets/compat.ini index 14ee5a4bbb..58dff15e54 100644 --- a/assets/compat.ini +++ b/assets/compat.ini @@ -1490,3 +1490,36 @@ UCES00044 = true NPUG80329 = true NPEG00025 = true UCKS45025 = true + +# GOW : Ghost of Sparta +UCUS98737 = true +UCAS40323 = true +NPHG00092 = true +NPEG00044 = true +NPEG00045 = true +NPJG00120 = true +NPUG80508 = true +UCJS10114 = true +UCES01401 = true +UCES01473 = true +# GOW : Ghost of Sparta Demo +NPJG90095 = true +NPEG90035 = true +NPUG70125 = true +# GOW : Chains Of Olympus +UCAS40198 = true +UCUS98653 = true +UCES00842 = true +ULJM05438 = true +ULJM05348 = true +UCKS45084 = true +NPUG80325 = true +NPEG00023 = true +NPHG00027 = true +NPHG00028 = true +NPJH50170 = true +UCET00844 = true +# GOW: Chains of Olympus Demo +UCUS98705 = true +UCED00971 = true +UCUS98713 = true From 8f1b4d6740eaca9b43a3f4928e7c92494dc406d1 Mon Sep 17 00:00:00 2001 From: Halo-Michael <45062120+Halo-Michael@users.noreply.github.com> Date: Tue, 28 Feb 2023 20:47:26 +0800 Subject: [PATCH 194/424] Update PPSSPP-Info.plist First, we are no longer support armv7 then specific CFBundleDevelopmentRegion key will make https://github.com/hrydgard/ppsspp/blob/a11ca4cb9010b6c6ca33d5ec46b369045a43f6f3/ios/main.mm#L109 always return en_XX --- ios/PPSSPP-Info.plist | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ios/PPSSPP-Info.plist b/ios/PPSSPP-Info.plist index 55d219357c..6e72de13ff 100644 --- a/ios/PPSSPP-Info.plist +++ b/ios/PPSSPP-Info.plist @@ -10,8 +10,6 @@ Your camera may be used to emulate Go!Cam, a camera accessory NSMicrophoneUsageDescription Your microphone may be used to emulate Go!Cam/Talkman, a microphone accessory - CFBundleDevelopmentRegion - en CFBundleDisplayName PPSSPP CFBundleExecutable @@ -36,7 +34,7 @@ UIRequiredDeviceCapabilities - armv7 + arm64 UIStatusBarHidden From 891cc49beb71f0ebffcc2e1df3505c8f8aebd07e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 28 Feb 2023 06:57:47 -0800 Subject: [PATCH 195/424] iOS: Allow saving interp when jit was selected. --- Core/Config.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 3cf4d788b6..b82cf41ff3 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1589,15 +1589,16 @@ void Config::PostLoadCleanup(bool gameSpecific) { void Config::PreSaveCleanup(bool gameSpecific) { if (jitForcedOff) { - // if JIT has been forced off, we don't want to screw up the user's ppsspp.ini - g_Config.iCpuCore = (int)CPUCore::JIT; + // If we forced jit off and it's still set to IR, change it back to jit. + if (g_Config.iCpuCore == (int)CPUCore::IR_JIT) + g_Config.iCpuCore = (int)CPUCore::JIT; } } void Config::PostSaveCleanup(bool gameSpecific) { if (jitForcedOff) { - // force JIT off again just in case Config::Save() is called without exiting PPSSPP - if (g_Config.iCpuCore != (int)CPUCore::INTERPRETER) + // Force JIT off again just in case Config::Save() is called without exiting PPSSPP. + if (g_Config.iCpuCore == (int)CPUCore::JIT) g_Config.iCpuCore = (int)CPUCore::IR_JIT; } } From f199a0fee35e9d9720ccbbf5cd3542e2985e2a97 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 28 Feb 2023 06:58:30 -0800 Subject: [PATCH 196/424] UI: Forget jit override on user selection. --- Core/Config.cpp | 7 +++++++ Core/Config.h | 2 ++ UI/GameSettingsScreen.cpp | 4 ++++ 3 files changed, 13 insertions(+) diff --git a/Core/Config.cpp b/Core/Config.cpp index b82cf41ff3..8b4cbe05ab 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1603,6 +1603,13 @@ void Config::PostSaveCleanup(bool gameSpecific) { } } +void Config::NotifyUpdatedCpuCore() { + if (jitForcedOff && g_Config.iCpuCore == (int)CPUCore::IR_JIT) { + // No longer forced off, the user set it to IR jit. + jitForcedOff = false; + } +} + // Use for debugging the version check without messing with the server #if 0 #define PPSSPP_GIT_VERSION "v0.0.1-gaaaaaaaaa" diff --git a/Core/Config.h b/Core/Config.h index a87fbc005d..17f198f920 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -568,6 +568,8 @@ public: bool LoadAppendedConfig(); void SetAppendedConfigIni(const Path &path); + void NotifyUpdatedCpuCore(); + protected: void LoadStandardControllerIni(); void LoadLangValuesMapping(); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 454eec0d03..6c8f8469f3 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1774,6 +1774,10 @@ void DeveloperToolsScreen::CreateViews() { static const char *cpuCores[] = {"Interpreter", "Dynarec (JIT)", "IR Interpreter"}; PopupMultiChoice *core = list->Add(new PopupMultiChoice(&g_Config.iCpuCore, gr->T("CPU Core"), cpuCores, 0, ARRAY_SIZE(cpuCores), sy->GetName(), screenManager())); core->OnChoice.Handle(this, &DeveloperToolsScreen::OnJitAffectingSetting); + core->OnChoice.Add([](UI::EventParams &) { + g_Config.NotifyUpdatedCpuCore(); + return UI::EVENT_DONE; + }); if (!canUseJit) { core->HideChoice(1); } From 9c21184352de57807d5abdf2c967b5c4d9fcbe54 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 28 Feb 2023 07:03:12 -0800 Subject: [PATCH 197/424] vertexjit: Simplify CPU core check. This also avoids allocating the memory we won't use if it's off. --- GPU/Common/DrawEngineCommon.cpp | 7 +++++-- GPU/Common/DrawEngineCommon.h | 4 +++- GPU/Common/VertexDecoderCommon.cpp | 2 +- unittest/TestVertexJit.cpp | 3 --- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/GPU/Common/DrawEngineCommon.cpp b/GPU/Common/DrawEngineCommon.cpp index 139d47613c..59083f5352 100644 --- a/GPU/Common/DrawEngineCommon.cpp +++ b/GPU/Common/DrawEngineCommon.cpp @@ -36,7 +36,9 @@ enum { }; DrawEngineCommon::DrawEngineCommon() : decoderMap_(16) { - decJitCache_ = new VertexDecoderJitCache(); + if (g_Config.bVertexDecoderJit && g_Config.iCpuCore == (int)CPUCore::JIT) { + decJitCache_ = new VertexDecoderJitCache(); + } transformed = (TransformedVertex *)AllocateMemoryPages(TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); transformedExpanded = (TransformedVertex *)AllocateMemoryPages(3 * TRANSFORMED_VERTEX_BUFFER_SIZE, MEM_PROT_READ | MEM_PROT_WRITE); } @@ -169,7 +171,8 @@ static Vec3f ScreenToDrawing(const Vec3f& coords) { } void DrawEngineCommon::NotifyConfigChanged() { - decJitCache_->Clear(); + if (decJitCache_) + decJitCache_->Clear(); lastVType_ = -1; dec_ = nullptr; decoderMap_.Iterate([&](const uint32_t vtype, VertexDecoder *decoder) { diff --git a/GPU/Common/DrawEngineCommon.h b/GPU/Common/DrawEngineCommon.h index d5f8056417..94ce1f35e7 100644 --- a/GPU/Common/DrawEngineCommon.h +++ b/GPU/Common/DrawEngineCommon.h @@ -117,7 +117,9 @@ public: } bool IsCodePtrVertexDecoder(const u8 *ptr) const { - return decJitCache_->IsInSpace(ptr); + if (decJitCache_) + return decJitCache_->IsInSpace(ptr); + return false; } int GetNumDrawCalls() const { return numDrawCalls; diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index 488c1736e9..21b3e76a6f 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -1274,7 +1274,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, // Attempt to JIT as well. But only do that if the main CPU JIT is enabled, in order to aid // debugging attempts - if the main JIT doesn't work, this one won't do any better, probably. - if (jitCache && g_Config.bVertexDecoderJit && g_Config.iCpuCore == (int)CPUCore::JIT) { + if (jitCache) { jitted_ = jitCache->Compile(*this, &jittedSize_); if (!jitted_) { WARN_LOG(G3D, "Vertex decoder JIT failed! fmt = %08x (%s)", fmt_, GetString(SHADER_STRING_SHORT_DESC).c_str()); diff --git a/unittest/TestVertexJit.cpp b/unittest/TestVertexJit.cpp index 12dad2f5aa..e759d64444 100644 --- a/unittest/TestVertexJit.cpp +++ b/unittest/TestVertexJit.cpp @@ -38,9 +38,6 @@ public: dst_ = new u8[BUFFER_SIZE]; cache_ = new VertexDecoderJitCache(); - g_Config.bVertexDecoderJit = true; - // Required for jit to be enabled. - g_Config.iCpuCore = (int)CPUCore::JIT; gstate_c.uv.uScale = 1.0f; gstate_c.uv.vScale = 1.0f; } From 31d796e769139c2379be19e3fb3a80f5e0efc75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Feb 2023 18:18:19 +0100 Subject: [PATCH 198/424] Vulkan on Android: In non-debug mode, avoid devices that were rejected by VulkanMayBeAvailable. Fixes #16931 Can still use these devices in debug builds by modifying the ini. --- Common/GPU/Vulkan/VulkanContext.cpp | 2 ++ Common/GPU/Vulkan/VulkanLoader.cpp | 6 ++++-- android/jni/app-android.cpp | 16 +++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index a8e2a1846c..032fc128f6 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -712,6 +712,8 @@ VkResult VulkanContext::CreateDevice() { VulkanLoadDeviceFunctions(device_, extensionsLookup_); } INFO_LOG(G3D, "Vulkan Device created: %s", physicalDeviceProperties_[physical_device_].properties.deviceName); + + // Since we successfully created a device (however we got here, might be interesting in debug), we force the choice to be visible in the menu. VulkanSetAvailable(true); VmaAllocatorCreateInfo allocatorInfo = {}; diff --git a/Common/GPU/Vulkan/VulkanLoader.cpp b/Common/GPU/Vulkan/VulkanLoader.cpp index 2a37785544..5dd7baf4f6 100644 --- a/Common/GPU/Vulkan/VulkanLoader.cpp +++ b/Common/GPU/Vulkan/VulkanLoader.cpp @@ -310,6 +310,7 @@ static void VulkanFreeLibrary(VulkanLibraryHandle &h) { } void VulkanSetAvailable(bool available) { + INFO_LOG(G3D, "Forcing Vulkan availability to true"); g_vulkanAvailabilityChecked = true; g_vulkanMayBeAvailable = available; } @@ -495,8 +496,9 @@ bail: } if (lib) { VulkanFreeLibrary(lib); - } else { - ERROR_LOG(G3D, "Vulkan with working device not detected."); + } + if (!g_vulkanMayBeAvailable) { + WARN_LOG(G3D, "Vulkan with working device not detected."); } return g_vulkanMayBeAvailable; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 67e2fc9238..42d46cae43 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -73,6 +73,7 @@ struct JNIEnv {}; #include "Common/Math/math_util.h" #include "Common/Data/Text/Parsers.h" #include "Common/VR/PPSSPPVR.h" +#include "Common/GPU/Vulkan/VulkanLoader.h" #include "Common/GraphicsContext.h" #include "Common/StringUtils.h" @@ -677,9 +678,9 @@ static void parse_args(std::vector &args, const std::string value) #define EARLY_LOG(...) __android_log_print(ANDROID_LOG_INFO, "PPSSPP", __VA_ARGS__) extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init - (JNIEnv *env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath, - jstring jdataDir, jstring jexternalStorageDir, jstring jexternalFilesDir, jstring jadditionalStorageDirs, jstring jcacheDir, jstring jshortcutParam, - jint jAndroidVersion, jstring jboard) { +(JNIEnv * env, jclass, jstring jmodel, jint jdeviceType, jstring jlangRegion, jstring japkpath, + jstring jdataDir, jstring jexternalStorageDir, jstring jexternalFilesDir, jstring jadditionalStorageDirs, jstring jcacheDir, jstring jshortcutParam, + jint jAndroidVersion, jstring jboard) { SetCurrentThreadName("androidInit"); // Makes sure we get early permission grants. @@ -754,6 +755,15 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init NativeInit((int)args.size(), &args[0], user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str()); + // In debug mode, don't allow creating software Vulkan devices (reject by VulkaMaybeAvailable). + // Needed for #16931. +#ifdef NDEBUG + if (!VulkanMayBeAvailable()) { + // If VulkanLoader decided on no viable backend, let's force Vulkan off in release builds at least. + g_Config.iGPUBackend = 0; + } +#endif + // No need to use EARLY_LOG anymore. retry: From c6352a262d272468e867138f3d3310234302210b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Feb 2023 23:21:36 +0100 Subject: [PATCH 199/424] Fix crash in SoftGPU when frameskipping, noticed by sum2012 in Daxter Fixes #17021 --- GPU/Software/SoftGpu.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 2a3bf685f7..7fe082b859 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -670,6 +670,9 @@ void SoftGPU::MarkDirty(uint32_t addr, uint32_t bytes, SoftGPUVRAMDirty value) { uint32_t start = ((addr - PSP_GetVidMemBase()) & 0x001FFFFF) >> 10; uint32_t end = start + ((bytes + 1023) >> 10); + if (end > sizeof(vramDirty_)) { + end = sizeof(vramDirty_); + } if (value == SoftGPUVRAMDirty::CLEAR || value == (SoftGPUVRAMDirty::DIRTY | SoftGPUVRAMDirty::REALLY_DIRTY)) { memset(vramDirty_ + start, (uint8_t)value, end - start); } else { From 7a7117f2f70b715df6b3cc0e1829de3e9247b571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 1 Mar 2023 22:38:46 +0100 Subject: [PATCH 200/424] Cache framebuffer copies (for self-texturing) until the next TexFlush instruction. Fixes #17030 , or at least improves on it - for optimal performance that big framebuffer used for bloom should be split like in Killzone, but it's not trivial. The regression in 1.14 is fixed with this, at least. I tried it with a few other games with no issues - it seems games are using TexFlush when needed. But let's see if it really is safe to rely on that... There might also be other places we should call DiscardFramebufferCopy in. --- GPU/Common/FramebufferManagerCommon.cpp | 11 +++++++++++ GPU/Common/FramebufferManagerCommon.h | 6 ++++++ GPU/GPUCommonHW.cpp | 9 ++++++++- GPU/GPUCommonHW.h | 2 ++ 4 files changed, 27 insertions(+), 1 deletion(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index 91005fd71c..cf96977c42 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -546,6 +546,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer // TODO: Is it worth trying to upload the depth buffer (only if it wasn't copied above..?) } + DiscardFramebufferCopy(); + // We already have it! } else if (vfb != currentRenderVfb_) { // Use it as a render target. @@ -562,6 +564,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer NotifyRenderFramebufferSwitched(prev, vfb, params.isClearingDepth); CopyToColorFromOverlappingFramebuffers(vfb); gstate_c.usingDepth = false; // reset depth buffer tracking + + DiscardFramebufferCopy(); } else { // Something changed, but we still got the same framebuffer we were already rendering to. // Might not be a lot to do here, we check in NotifyRenderFramebufferUpdated @@ -1233,6 +1237,12 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF // Self-texturing, need a copy currently (some backends can potentially support it though). WARN_LOG_ONCE(selfTextureCopy, G3D, "Attempting to texture from current render target (src=%08x / target=%08x / flags=%d), making a copy", framebuffer->fb_address, currentRenderVfb_->fb_address, flags); // TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size. + if (currentFramebufferCopy_) { + // We have a copy already that hasn't been invalidated, let's keep using it. + draw_->BindFramebufferAsTexture(currentFramebufferCopy_, stage, Draw::FB_COLOR_BIT, layer); + return true; + } + Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight); if (renderCopy) { VirtualFramebuffer copyInfo = *framebuffer; @@ -1240,6 +1250,7 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF CopyFramebufferForColorTexture(©Info, framebuffer, flags, layer); RebindFramebuffer("After BindFramebufferAsColorTexture"); draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, layer); + currentFramebufferCopy_ = renderCopy; gpuStats.numCopiesForSelfTex++; } else { // Failed to get temp FBO? Weird. diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 672130f7aa..bda9bdc389 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -466,6 +466,10 @@ public: return msaaLevel_; } + void DiscardFramebufferCopy() { + currentFramebufferCopy_ = nullptr; + } + protected: virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode); // Used for when a shader is required, such as GLES. @@ -552,6 +556,8 @@ protected: VirtualFramebuffer *currentRenderVfb_ = nullptr; + Draw::Framebuffer *currentFramebufferCopy_ = nullptr; + // The range of PSP memory that may contain FBOs. So we can skip iterating. u32 framebufRangeEnd_ = 0; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 5c51cf5e8a..01d6dd02c2 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -287,7 +287,7 @@ const CommonCommandTableEntry commonCommandTable[] = { { GE_CMD_LSC3, FLAG_FLUSHBEFOREONCHANGE, DIRTY_LIGHT3 }, // Ignored commands - { GE_CMD_TEXFLUSH, 0 }, + { GE_CMD_TEXFLUSH, FLAG_EXECUTE, 0, &GPUCommonHW::Execute_TexFlush }, { GE_CMD_TEXSYNC, 0 }, // These are just nop or part of other later commands. @@ -1619,6 +1619,13 @@ void GPUCommonHW::Execute_BoneMtxData(u32 op, u32 diff) { gstate.boneMatrixData = GE_CMD_BONEMATRIXDATA << 24; } +void GPUCommonHW::Execute_TexFlush(u32 op, u32 diff) { + // Games call this when they need the effect of drawing to be visible to texturing. + // And for a bunch of other reasons, but either way, this is what we need to do. + // It's possible we could also use this as a hint for the texture cache somehow. + framebufferManager_->DiscardFramebufferCopy(); +} + size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f; return snprintf(buffer, size, diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 2e13a11738..000993be79 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -60,6 +60,8 @@ public: void Execute_BoneMtxNum(u32 op, u32 diff); void Execute_BoneMtxData(u32 op, u32 diff); + void Execute_TexFlush(u32 op, u32 diff); + typedef void (GPUCommonHW::*CmdFunc)(u32 op, u32 diff); void FastRunLoop(DisplayList &list) override; From 4d0fbdb96f34affa43af8070fd3c9cadc44be6c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 1 Mar 2023 22:51:23 +0100 Subject: [PATCH 201/424] Add a safety check - don't cache partial copies. --- GPU/Common/FramebufferManagerCommon.cpp | 19 ++++++++++++++++--- GPU/Common/FramebufferManagerCommon.h | 2 +- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index cf96977c42..e4f3bc0d94 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -1247,10 +1247,17 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF if (renderCopy) { VirtualFramebuffer copyInfo = *framebuffer; copyInfo.fbo = renderCopy; - CopyFramebufferForColorTexture(©Info, framebuffer, flags, layer); + + bool partial = false; + CopyFramebufferForColorTexture(©Info, framebuffer, flags, layer, &partial); RebindFramebuffer("After BindFramebufferAsColorTexture"); draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, layer); - currentFramebufferCopy_ = renderCopy; + + // Only cache the copy if it wasn't a partial copy. + // TODO: Improve on this. + if (!partial) { + currentFramebufferCopy_ = renderCopy; + } gpuStats.numCopiesForSelfTex++; } else { // Failed to get temp FBO? Weird. @@ -1273,14 +1280,17 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF } } -void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags, int layer) { +void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags, int layer, bool *partial) { int x = 0; int y = 0; int w = src->drawnWidth; int h = src->drawnHeight; + *partial = false; + // If max is not > min, we probably could not detect it. Skip. // See the vertex decoder, where this is updated. + // TODO: We're currently not hitting this path in Dante. See #17032 if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) == BINDFBCOLOR_MAY_COPY_WITH_UV && gstate_c.vertBounds.maxU > gstate_c.vertBounds.minU) { x = std::max(gstate_c.vertBounds.minU, (u16)0); y = std::max(gstate_c.vertBounds.minV, (u16)0); @@ -1298,6 +1308,9 @@ void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer } if (x < src->drawnWidth && y < src->drawnHeight && w > 0 && h > 0) { + if (x != 0 || y != 0 || w < src->drawnWidth || h < src->drawnHeight) { + *partial = true; + } BlitFramebuffer(dst, x, y, src, x, y, w, h, 0, RASTER_COLOR, "CopyFBForColorTexture"); } } diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index bda9bdc389..394e5d0593 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -490,7 +490,7 @@ protected: // Used by ReadFramebufferToMemory and later framebuffer block copies void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp, RasterChannel channel, const char *tag); - void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags, int layer); + void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags, int layer, bool *partial); void EstimateDrawingSize(u32 fb_address, int fb_stride, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int &drawing_width, int &drawing_height); From 624e443b5b494b08bbff60de4ad646079b960602 Mon Sep 17 00:00:00 2001 From: huhongwei Date: Thu, 2 Mar 2023 09:13:31 +0800 Subject: [PATCH 202/424] Fix logic error: assign EGLSurface to EGLConfig --- Common/VR/VRBase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/VR/VRBase.cpp b/Common/VR/VRBase.cpp index 284c33aaff..3ada93d754 100644 --- a/Common/VR/VRBase.cpp +++ b/Common/VR/VRBase.cpp @@ -182,7 +182,7 @@ void VR_EnterVR( engine_t* engine, XrGraphicsBindingVulkanKHR* graphicsBindingVu graphicsBindingGL.type = XR_TYPE_GRAPHICS_BINDING_OPENGL_ES_ANDROID_KHR; graphicsBindingGL.next = NULL; graphicsBindingGL.display = eglGetCurrentDisplay(); - graphicsBindingGL.config = eglGetCurrentSurface(EGL_DRAW); + graphicsBindingGL.config = NULL; graphicsBindingGL.context = eglGetCurrentContext(); sessionCreateInfo.next = &graphicsBindingGL; #else From 92a18eed01988db7ea6a55f1549fc919476f0524 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 1 Mar 2023 22:03:56 -0800 Subject: [PATCH 203/424] GPU: Discard framebuffer copy when clearing. This avoids retaining the framebuffer copy any longer than the current framebuffer target. --- GPU/Common/DepthBufferCommon.cpp | 2 +- GPU/Common/FramebufferManagerCommon.cpp | 6 ++++++ GPU/Common/FramebufferManagerCommon.h | 2 ++ GPU/GLES/StencilBufferGLES.cpp | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/GPU/Common/DepthBufferCommon.cpp b/GPU/Common/DepthBufferCommon.cpp index 46a2ecfb6f..a29c995775 100644 --- a/GPU/Common/DepthBufferCommon.cpp +++ b/GPU/Common/DepthBufferCommon.cpp @@ -204,7 +204,7 @@ bool FramebufferManagerCommon::ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x } shaderManager_->DirtyLastShader(); - auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width() * scaleX, fbo->Height() * scaleY); + auto *blitFBO = GetTempFBO(TempFBO::Z_COPY, fbo->Width() * scaleX, fbo->Height() * scaleY); draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackDepthbufferSync"); Draw::Viewport viewport = { 0.0f, 0.0f, (float)destW, (float)destH, 0.0f, 1.0f }; draw_->SetViewport(viewport); diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp index e4f3bc0d94..e21bc35e93 100644 --- a/GPU/Common/FramebufferManagerCommon.cpp +++ b/GPU/Common/FramebufferManagerCommon.cpp @@ -932,6 +932,7 @@ void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) { } // Wipe some pointers + DiscardFramebufferCopy(); if (currentRenderVfb_ == v) currentRenderVfb_ = nullptr; if (displayFramebuf_ == v) @@ -1450,6 +1451,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, int // PresentationCommon sets all kinds of state, we can't rely on anything. gstate_c.Dirty(DIRTY_ALL); + DiscardFramebufferCopy(); currentRenderVfb_ = nullptr; } @@ -1607,10 +1609,12 @@ void FramebufferManagerCommon::CopyDisplayToOutput(bool reallyDirty) { // This may get called mid-draw if the game uses an immediate flip. // PresentationCommon sets all kinds of state, we can't rely on anything. gstate_c.Dirty(DIRTY_ALL); + DiscardFramebufferCopy(); currentRenderVfb_ = nullptr; } void FramebufferManagerCommon::DecimateFBOs() { + DiscardFramebufferCopy(); currentRenderVfb_ = nullptr; for (auto iter : fbosToDelete_) { @@ -1767,6 +1771,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, } else { draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }, "ResizeFramebufFBO"); } + DiscardFramebufferCopy(); currentRenderVfb_ = vfb; if (!vfb->fbo) { @@ -2568,6 +2573,7 @@ void FramebufferManagerCommon::NotifyConfigChanged() { } void FramebufferManagerCommon::DestroyAllFBOs() { + DiscardFramebufferCopy(); currentRenderVfb_ = nullptr; displayFramebuf_ = nullptr; prevDisplayFramebuf_ = nullptr; diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h index 394e5d0593..d0c83b4d6c 100644 --- a/GPU/Common/FramebufferManagerCommon.h +++ b/GPU/Common/FramebufferManagerCommon.h @@ -217,6 +217,8 @@ enum class TempFBO { BLIT, // For copies of framebuffers (e.g. shader blending.) COPY, + // Used for copies when setting color to depth. + Z_COPY, // Used to copy stencil data, means we need a stencil backing. STENCIL, }; diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 763e5a95fe..845cd2b3ac 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -130,7 +130,7 @@ bool FramebufferManagerGLES::ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x } shaderManager_->DirtyLastShader(); - auto *blitFBO = GetTempFBO(TempFBO::COPY, fbo->Width(), fbo->Height()); + auto *blitFBO = GetTempFBO(TempFBO::Z_COPY, fbo->Width(), fbo->Height()); draw_->BindFramebufferAsRenderTarget(blitFBO, { RPAction::DONT_CARE, RPAction::DONT_CARE, RPAction::DONT_CARE }, "ReadbackStencilbufferSync"); Draw::Viewport viewport = { 0.0f, 0.0f, (float)fbo->Width(), (float)fbo->Height(), 0.0f, 1.0f }; draw_->SetViewport(viewport); From 4960c8a07a4f182b31305e1a31faa236e667a629 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 2 Mar 2023 06:20:49 +0000 Subject: [PATCH 204/424] riscv: Add libatomic. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20cd4d0e74..ebd1b151c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1354,7 +1354,7 @@ if(LINUX AND NOT ANDROID) endif() set(ATOMIC_LIB) -if(ANDROID OR (LINUX AND ARM_DEVICE)) +if(ANDROID OR (LINUX AND ARM_DEVICE) OR (LINUX AND RISCV64)) set(ATOMIC_LIB atomic) endif() From 38bbd4b8a7cc21acbda7a63bf5b24bd1feb17950 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Thu, 2 Mar 2023 06:21:06 +0000 Subject: [PATCH 205/424] Common: Fix printf format warning. --- Common/System/Display.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/System/Display.cpp b/Common/System/Display.cpp index 7f79cc5041..15af7de4e3 100644 --- a/Common/System/Display.cpp +++ b/Common/System/Display.cpp @@ -63,6 +63,6 @@ void DisplayProperties::Print() { printf("dpi_real: %f, %f\n", dpi_scale_real_x, dpi_scale_real_y); printf("display_hz: %f\n", display_hz); - printf("rotation: %d\n", rotation); + printf("rotation: %d\n", (int)rotation); rot_matrix.print(); } From 055ac2b697132379a4f4281af5d3758e077cbb98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Mar 2023 11:45:47 +0100 Subject: [PATCH 206/424] Add new default icon --- android/AndroidManifest.xml | 3 +-- android/res/mipmap-anydpi-v26/ic_launcher.xml | 5 +++++ .../res/mipmap-anydpi-v26/ic_launcher_round.xml | 5 +++++ android/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 4218 bytes .../res/mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 8456 bytes android/res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 6731 bytes android/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2581 bytes .../res/mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 5094 bytes android/res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3971 bytes android/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 6191 bytes .../res/mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 12254 bytes android/res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 9908 bytes android/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 10154 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 21824 bytes android/res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 16345 bytes android/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 14281 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 31261 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 23394 bytes android/res/values/ic_launcher_background.xml | 4 ++++ 19 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 android/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 android/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 android/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 android/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 android/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 android/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 android/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 android/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 android/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 android/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 android/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 android/res/values/ic_launcher_background.xml diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index ab8cf74a3b..0d67ad89e4 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,7 +1,6 @@ @@ -43,7 +42,7 @@ + + + + \ No newline at end of file diff --git a/android/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/android/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/res/mipmap-hdpi/ic_launcher.png b/android/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..e4861f3566c7c069c9adc66de2d033f443da3142 GIT binary patch literal 4218 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 Qq5uE@07*qoM6N<$f^%>Et^fc4 literal 0 HcmV?d00001 diff --git a/android/res/mipmap-hdpi/ic_launcher_foreground.png b/android/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd4b7ebadac9b9ead5b7d2e04a62d4eab414b49 GIT binary patch literal 8456 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 literal 0 HcmV?d00001 diff --git a/android/res/mipmap-hdpi/ic_launcher_round.png b/android/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..33e11da64714aa7c3819e1765c971596fe7eec06 GIT binary patch literal 6731 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 literal 0 HcmV?d00001 diff --git a/android/res/mipmap-mdpi/ic_launcher.png b/android/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..78762e0a13e85c5d57c84394aaa8fb809f2742d3 GIT binary patch literal 2581 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 roNWhHA?>Eln2kx00000NkvXXu0mjfng0L{ literal 0 HcmV?d00001 diff --git a/android/res/mipmap-mdpi/ic_launcher_foreground.png b/android/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..00db9645c02693aee68c1c4c07db7a0f213a5555 GIT binary patch literal 5094 zcma)A=QkV<)78taw#w>D^s+ju3#&x$(V`OsAtHLO(W69*y1GQ~qOVTW$S$H2B#4q= z^(Vi-;C=5oGxOzsm@_kH=G=+b*L^|?U;toYVUcR6s~G-^?*ADP!9V}b$#e<}i>g*b zMakIT`sf*MQLdUkIVPyLmi5xLc;GV^dwn2csPPml!N2@O3O+H%q?zaO^kPj zPq##F)hO`hXKfgSkzBC#WhKk3!+c}!MOBL%zwBfmm9&ekbXWgclf6fD_w}qrYj1pf zZu0OebO(~Wv_C?l4m$ynx5ZG3d4cA%8a@}qgRkbtZelcfdh%eg(^#dXyjb=lm_cW3 zs(jk?cxIPk@l0lnQfN+7uKy2-j1z&k8WsluhCZ7LFM2QWtEIy9{HNZD(F)9ECQlWs zbvuDm&)SUO0a;qF&$%h~kKYd~32J=eKA7~)=*XhtXg}gxdVNRyqVu5~(7t{b37vE) zM&}S}7D%_HR5OR{%3!pO!DAs`O(>0n!qqPe9+f+LWK_r&eTw@^bH{f%FXHY16txZ3 z`621(FR@`PwV+{mP8Y@0dd^ebbE~cz{ae@$&C8dgY=7lN_w3mfDZMpm$H@L-e1acQ zBrkB*3Y`C02|w!m_+XBTn=GS;Fp6ProsEN?A?nboLs>Qachl)^9|*lLWi0N%lJ;oS zS>zw#7*{gPh(y>VjPBKQ(C0y?VsfH)+vcjfYW*073D2<;*Zop?_eCD(7gLgSJCPaa zrz-m3vMb0Lu*qtqqN~WrqiayC>6D0ugkj%_uCMQmQM8-kRWiLji%lR?6m%`1shQR9 zDgIL6o>zZj*}BG{K;g60R0J>Kw9!C*`lq7)MVY2cTYdJHTDGQU;j!KyLDoF# zJxO_&!Lrg9wuvk_B3P zC`{eoXns`q#ZlWS7WmiY@F=jyg)SVC5>F#3GUhdV+pA9Dcp4K_hPjnDR0+tYF5EVM zbwOrs)tv~~<*Du_av(PjRi>9|az^3_ct8AoLFQGi@JgrL`}H|#$36Gb0$=68*#>=+ zTcCvStEhi7@k^K|^eIae>t(0`g`>jR7v^+AH?ZiX_!&4p0;x*WkWqF^i8k;bOWwV# zLG{>CVt8Yni(06Dm!+0fje1Cinn~1N}i@OdX1arZl{4UGiz?xe*R4?1j8X; zVb)24c;iZ;uM-`O);RK(1DsmdS*xE2Wt5BJ(up~)iH6Ch2p!!ltI^WQa+>TYUgSsY z^_qeSZxm;`ohaLWP-sMHHd8jyeKL0EMrHoqtz5)x@!i&F7WJ5x6crX!_P)w?*f2

C4LZGLVwx;g3V81gT@{KCBvF{zZ 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 N002ovPDHLkV1hUL3B&*Z literal 0 HcmV?d00001 diff --git a/android/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..1711f0f7b98982df5a9f6c5c27704cc120148ec8 GIT binary patch literal 12254 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 literal 0 HcmV?d00001 diff --git a/android/res/mipmap-xxhdpi/ic_launcher_round.png b/android/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..792f90ca0ae900b471705c2e3f72fbc63a97e7a6 GIT binary patch literal 16345 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 z zsP4n90+^ux-XDUB0*E$pl2}5UAenJr@UO`Ts z;NR%pbiLMuEOU?+I#&z1p^7qNO8W#S=O#+Wxl%Nb4wX<$Bq1q*A(=Ph#LFH`j9ZKB zwxAJ2gGCU+4h2b;?FP2JEwJGE*Lm~3x*kk?h|GBf`$0Nk&=;Q3owds!CokM&-4)Vh}3*<1LN&kL&_?%{@@X&7#n zX#Fur0DmxUz$BLTG!Mvn7KY(J>yio;w}xJaUD5pNoVlSDxhWebN*l+7A8aeU4;z41BQNWRy6(m*|y zAGWRq9f}>gK5=u7v?Pi>c~ZdI=Ja8mdW_;Gvde_!M3!xS4H01Yu{58|_Jy)olgOAv z$hus$kczxQQwp|MmG%KtLJ|MQG={!Vt6zTK(jtl&p0tRmL2Pn-&H-ZR*!ae0oG8Es z9oIi&tFC;=25z+5TRBLmas4NX>+~Ts3l>@AFXl3Pnya9_W^Ff$~&=+dE8;v&d(;8V6<$F)z{I*v~`*1YyHn{>?SKm(Yihl%z0)LTT6+C}~yCa*)+ zAuN9IRF*z&DfurOSi!uVeh(6eAxJT%^u*?898Le&1OhTE&7`WlP|LWCKQ(IIHV`te zRURags_fR*$@vqjQu`<PhM@B~8bk7j#BfxDTDFt%h zo~qrGP$U#{SVVRoR-`TJ;7!kPlVX#@sX@FE!zPCy2C(|7ja3{Uu~n}MtRyVE{5~79 zMK7cZU^fq#ANUfgI}yYQODpDeva~0cu$&nix&P+xTpP3t$TD!l2{wAyS>DRKj?TZA z{JO&*{npiufGqp4t*5N_!%ynmPncAfMl=Cuntld#O8t;zewQZy8#|Qm6P%C}Tb0hU z1IeO85l>XXydBm;VUd?yc*iD)B!`0_R|Omdk;Kpm!a-yNR%lrM3h)7&bo`RTOelaP zE#opRVF|61$3yF~YMFjyj>hkQfh~CM8rwwIv+v!nTx9VC)B`bTtA7@>BCeyfaNc&N zvspmf*e;O$O*zw2h5dp~ys|o&F9iq)W+Hw3GHa3Wq)vV6GLhmV2SL1P5e1zfoFp1i zfMp6Vf54U!=2Fy!sLvEQoK;MZsHQSyvUn>l`61@(6+lE})6wINF2~gu-(~yW`^rU( zvcR04&6%-*ubW@PkKCEgW6e7zZiVb`#*A_G^-yr|Js~M#zN^ZdX9LQSjvqAD;b`_+ zb%c#O^b%Wg>0QzuLW}rI4n>fq6wLukE<3UK@_TH-g}2$z9a`x^0{Ist@me{wk0237 zeoSW=gOFqQJkREl5gi&sFK4`y)tX`%1L40k+ZvL!AZ2A}X zHfmH?@xb6l>4!33E#k9O=Gk?!s)8!4Vn+^7rU9Y#bn+DxF$6gTG2G;MkCS8ZB^!$@ zyvr79m_Siiw`I0q6cV18!A%!0VMy%*VRbAX>I%Ji=A1N5MGin7{NQUg$Ve}EjSM|O z=7btY#N>hlH)O`-n{FdvEv`=H3*Z7u$mQ8sZ{`8Rhr>u)%z6I0AcjU1n;>qI01JSN zz&mWd#4L)spyAB(pe~1N!h$A?azyE8O(908u#wL*eq@Oow#2ky@ z=6bpSGe!?U)Ak7)!GRkgkWyQBQ1o@RIz(R%@FzT%F9;gUeC-9)hy06iM=r2=FTHIO zM3O@%$ovZe^TUHvkMpQ;abpkoJCyXbqq-ACsm_?X+`YP9A=4YWd z+sgUKVkJm~?e#Jyt#rK}SzmhC4?Zj4maa;8;Up%rgk^$Qz1sps%H(r=7xv7G3oa6dWauqqD3Fe=E%_a03 zfyXHleK0`vdy}RcviWIlMu9>CD)-`geG`a7hV#ujBrnLc@)YI@aWVdgN)6sOfr-PHIL?Lio`iR;v5Q4 z?YvWtUf{$jT(pNHZTwQ}nq6ycLi$00QOU2>5`GZx$Z#;l<01W@hCz|_NR@q4DJBe0 zgr-&SJALEt#9_1e4j9w^$MBAy@0;R!wXCfG?H&ZDog0qR-9 z_B_ufoqCl`J$sE!c}`#g`AdD*pK!e%Mb37419)SbGv|}f+bqo2!;D~eG?N@|qIjMr z@kA7xEJokA(d)g49*UyHds)H4-5lAoH)#)~2RUd^#nqsg^zZ6E8rTS&@T*Tqs;XZE zMkTck#r7=a?LZr3QG&-J5-Df>$pMAUl$}`SJ&Zkq)QLbyn`==ed#7hwR=n*FiA6zuYjpRg$ zMG||GL??-(_uI?F$UefFm)|G9?;y)xxQpeJ50p1=JFg+~grX@I16ElhF7x|FEhFN= z3BR(^@E?zqvE9p*nln1u;Kg9v+mmdKMGk>*I7w6G5;k@7n;2g<(RKWG7n`5 zPo_s7TC`2i?~ExDV|qjm3D|=H_QZ&4<=vyT@ostJb2ebZaU#!7mPg2)zk_w^J;tx$ zN9joOR@WwB(SyMWzZ_{vpgYLfnuf&+F01*n$YPqK{;X54(OhF-eu|qTUs}Ncn&+|0 zs#_}vAma-Yf<`PA5h-od8rq1QY!C|D1LNGLw$R}z+YI6%=i{kdfnp^bXCCq3Cjm9C zCFGQQGCK~9B4^U{Su|^cL>m&|MDfz^ZBC1*7G5;ijof{P$g_jx0z{zrVKZga=-Z5e zKrmyxy(2Pq3Fm}A1d=bhlTNb9F9+JtE_fpGHAo!_hp_kolUeGR1-!xAmqY6f2z|$p zDVh7U*ava*YoD;mhc9@{$tXY@#SfWAr0piOk-R2{Hlk2l2;I9ja$+CvJBH>l9cPpX za8BW@+8Dd%EZaxIRl|$EOpjyCNKTMg<3-xk$R0<}w|iQ|(c>+MI4XN6Hjska*Ncqs8`fTapYOs{BWawkfo@IIf69xl@rMkLLivB8RR6nd;U#5Q01#5J3y&!m|eMK?Wsazq~t zFnhhtNfE7u*Bk&?a^Wq~J|NFFj?7sbSa@a+;Rlss#&{$~uW8mX5zY3$l-wxwz>9tv zoSgrLFB66j#%>uf8wg#^qMX%S(5MBYT@P6{b{!8iKAan^G__=$ZR3+O>n zQ4WBpXF6RMX3#tlMW07=jTgCyVrmpOQQZCA&ThbYu9zKWrj_; z>VWKF%9=+dzfYW~Be~%-lt-9$Tdlfv@1-~LuO;wGpd^uX^;9r40e@iNhLddkzVm$3 z@Aa>I!1mMP`9l_8fM(iwnilUGSCqD;{q zmQD`{)VOK7+7}IGx%9a@dGZN^Hl1MGNN~DCYt5r+WZ4NATE(eRw5bteTEsCSqPOl6 z^tN5J?5=tBV>V#(aZa8rA`cKdXp$U$^liqt>}k!KcS`%R);;%Nt6<*VY;Z<9M7`s- zhXR5h2}v&e9ba%y1d>iFSd5U{K^D?5=*bS0N3@3)3){)gvqFAkvf(hsP&Ah_dy^mpIh_c59gcI7=xa`&w1S7m zHg>YEOZT$HFTCL-io-{7njX&@#nvjOMzMRm&E9S=ZM*2iy!tU4z5lErPswJMNl1Kh zzPO)K{2(hA)G7VD`|3A&9Nh42#sqQkeRGyY!^X z#v`r-{6EK;^U3YYvgd5FNQ2NAfc9BOLURl&>Ka8eJ*J;xjuokCk#(9@QG)>bbcmy6 z*J#&Wam8-eEqUQ}mb+*>%b2^7BYox?7FjT$R7YAR6G=P&r9rcnk+u9KP@~Z3P-5TT zd=p6aDfj=0RfKO7hu4Q}`(kW3=p84%t+oZk5Vd=Ur$ zgW(_OUqb-k`zuVLRt3;|v-JEMtoQ1}nz_*-v`FU6b=>!{d?Oxd36o`&Ug-Dj$Z^h` zy-|e3^K4{uY~{c2x8W$8fBw410Y!Z<(ViGFCq+C=iRgXZW>2@?u4}gHYAw3`w;W^X zL>z^<5i?44q^)vB=gjXLHfs?BZuravDFQWV(=Ngv0%1}4*ANVvBFQ6iCm49EO#i1e zz=5Ak+5u)pWn^vG+9YlAa!wNNT0bYwl(i)oTuWNb-HLuj^&ZXArmZ3(A-Yl6Y(+YVdb+RL&!#?onJp)Q zd($XNtC-_MZlah?|3)9T-lA)?=c3bcB018T^ER@y*=spcXRQ&AG%u`rHe(inVl)2s zaFalousdt{ET~EXJrW$zn%?|hzM?R(sKO6IXI{?i%~rJ2ZP@`n3}*_pyy0rDay3>N zmF-WyVY}b`H#TJJNz3f$NE}mwFKXk9>M&mlaJ03ONGSP4@grxkj5!-cgrgy2t^kNM zc>752`V+v74jU1qGMC$hVouCN{Fc143&L{1;uFXGXf>ViZP zvI}cl(4QrZUuZ=+o{+bAI~#lWJX=6Q)-{SgA!3>ytKt75h~m^JqJJB3w&v>XxE!+6 z5>0d6*Y0O2vsPQ^G-!f!q&=H4D~yln@}KuV`Z&J*uoMExPQ7weDe$YA47mg> zI&vm@v@_wrdA~++O*opXJZTiG`%d)Acxt9Hil>qH~Qset`|z`3%clyv;$N&ZB2DbR7ym z$gPF!rn0o}>eOr40^F!2ve8}-P9VaAv`C-g&E85G)=4CRI`$Z0Wn>ZI3|N26XB(&4 zu4(nlcx%(Ni1Llr`rz!3;Y6`|W3-x+tY9xZ|2oTGwB7Pk6q3d*;FA@iTp?N=K$6Zw zrdS#TB!Ib!$dz?9sgXqA5pqW$QW|TM)sw}Knj;-nJL<8qj%Cf?%!chd!)BA9^~n%V z8pWkm&cA8*Z*#IJ!dxf9Tw~)-Tw=rapJjcw9%n_X_OQ$an;fLkkvMrV3(F8)3!coF zRmzA?`I0!%Kyt(9bO!1i*p;DfNOB(k#=%kvBom6^S-n`!+^tqt&&7Ca*R;)# z=N3&zpNwA7_C*xEIQgztYkKEPw&B{xtnd0mRyG!ZkCHZHHIbr^J=-Ns6r!=TnQLrq zBJ(Gy(^j(Req*_IvWUdrW0yqmS?zlaV~GUGcU8z$6jKC_ncxq)*ocKOSZ8tCF?25TI(WP-zVaz>6LrQalR+`D*771d?AvK>tpkvdR$_FCzy|Z2<0U zta7(#dh3yK^v8H2%6q>1VNgCmxnSba7s#RA?D9=I4IFQnt~_q4635NwgmG(-^_&3l zW9Ep(*K$T?-%&_f5sMi*g{6?7QW5#gUSmT#vKbT^4cLByO(7>&p9T>P{?|Fs;6LTe zYi#1PSJ=oSFR=df`rqwrlf;7(}7CT}(Yu{@G3&n$=f(BE*vYn%8 zyLhy7)Ro-uO`wJi8~&1h-cL`{W`77I9BEp(#2l6|a*iWBo^a?qZ>CbFM-jzr%~U>$ zTcc!Ao zF2;0vv@0Mrwx9aqm)^zSkkm* zEPnia)_LR%)}hZR7M9(MwNB3Cduu}@0*D-O&mg!}k@ui|_`Q(qL9ixa9an%8Wg*bL zq_%qUsKZAh(I${cD7MY(&wUHgIDly{n`3%zZBUzE3Zl5n z1u6rKN;IM$Q;Wc~ICs>@=MhQl@M$h{(`D{@Rxf-tP@?ctMuf z5i?jva^l1D`wFsjO63q_=_1L3P6E3a47u2(_D&juKs*Z_6x-$R4>t}>2PXoA59FIb zwM3j>`>y-%ZxWnb@U>rNO!`51qLaoia%5!3A3ksRC|)#*UafXjs+|>Tv){!m51=%# z^zwUb$j*~oP!X`%*nhepME;uesIN8#q1QUs)22CK-v)o0Nq^V0e!D5F`=Mf#Wi!w*hFuFMs zttVRdfJqiV2xCHp@PSb&-`-iL4st-XYl-g`^GP5ai1YE{`s84~6fD^*Z41bm%>buaCp5AzFi3;ULl50UKkK#V zoUz7V0x3TzvS=_%CsUy!oxDZcd5eOl1}V$*NUh?kPAj5Zv5SqW(6~erMOCBqa=@JP zue0LSdtCyB2?&vbQL|C_8Bx%mYYp@Deb*o0IV&>>s(?i4jFT6*mNMUKfk+8*z+u-l zgVU^Kh;B$SL2hSP(=Lg+ITH1`awUy~ionq8)uc_-Zg4?z!e-+~cN>Fddc0{AXYI(`P0U#e7`o?_J9;5Ow(m9E zIbA`52u&+uaTMm7g3nvDg{^(L^v$54jW%8VkPY2Ik>1>OuFp|`Ns8*PCm>aUR+u%e zRSfMS%#pLOYp#1mKsnGLb%PdRW5ET<3BL$*OD*9@-}g|HzzF&<{$22;)x@mADlJaJ zxcOH81QE=W#@i>92q!ZPQ({gck4W^utdOcz~m z$G)S<=UC}_{nX zU$kNuD|zuvNfvKSP|ke`RZk1=XL->{6su0;Nc~^uncOtfjF9O<7S=gkkb!!ZYK`ZuUoe+ z2;`Rot&Usk*RPLAtX{+5_Bn8<{PBgjBTXj`%k0iWQCleM*|gKII!%vNf%e|d;;J~y z8WG4+N zd=J+Jz^SJIMQ9-p>sb}h@<0Eq*R*wSaG)#>v^t=w;0N7L2nbHh`M@77#2x8GasZR_ z_~Ph`HJbb&n<)Nh6roj6NYse}On&Y)HW|gmQ?GL3j5>CKOxGc+w4eY}fjX397gZur zSVniA@;3$AbIo41>+R27L?|oJfgoB`zU5tz8_CHYvHNLWn$XV&(;A-JhZDNGm@!d- zC-c=l{&SLjbIAd4!Ef`0gC`X4yYIdS=;xzB(P@0IM1KgxQ}?8WQ0>(htKZh+ZlV|! z=V?R|5CwfLC@P`?4WakhEIr8`&`Lof>PGvN0K$64lJ zh)AAtJ|N%H7p~uQ7bUcp=xeh3m{368OFq@y=U#Dy{Ls?v$lMEZS3QAr^VK+{!!F4F z-h1!GZuO1E$ZF;V28s!?B z1d>3joCX9@#y#^2k>vs#jEeN;W2}IDDHI${qId$bxK7h0v`++SBv0fSz4uuzbdwPN zLJ>!`)+*wlkgSTwr~ytpdBJgR)UlLybggG4Lz%A@G3o!P+c>B@WPc<6k2+xUcy}Tp zpmki1{|#nDposkb+=Qrw%38RYjXiNmXcLPpL==rIW9aWAj=aPM?mES~Z#cwqmu}}B zbuP!)8_@4U=Y;u;q)=Jpe3a=DIUj`c=KBiiJUia}%tZ=+plclTI;kEfP8{C!Cb|t& z@p#dTuRGc@U`kc_!CcGA2DA^4zS_oPH;!gf_TWI7{2z7ja9*mgN1H}=o~~4!d1A*! zz>Fc=ibK{Fk8z&apmQpJH9nAhmd#I{{bF>I8&##NlS91Dg7cokM>atW@>bi;ZHSa)B8!VuJjKcBC zm)~Or%eLFsKVu~)Ht!1bu%49#nLPXf{$j&c5lbQSI(6!RKxGQw&Eprfga`g`?fV}J zZ=IO?ze-Iiaz99XzdLF>YN22zx|5?jaQ7+JW8)E)w`>PDN2zn{zM9ei;U`X6!b=0u zgD3KeHoE?>eVttbKt)=l|E-KK{S43U<*^rM*v=C^d$&#SKJL$*#Ia137vi9pEN0_B zXKP>knDyOw$Z-vkMFaVoRiz`XWEvQi`0sb$`(Q`Nyq0ibZpeJ8gPXB?#NIGX0;5xQ zsXB>y0Txt3k(eAkc!Fc0pk4eW3(QdxnIjM;e(W69vELXLp5KoMQ%K~@5*6tfNf=d; zCeta}N`%kDeKP5np;t%u$$)G!k6W+%-h$UAj_l|5pm9{|ttaB3pGkEcpn!~m@yLCr z9oK<8l`5~e*0U0zWZEhrn>7yYa1630nLiBKOAg%dA=*2HBh~PsfEHaSL@(8u=J_BJ zW?Rw_ro-wBQ0H)dI}M%8+Vw;WLr;dA;yo{_L5f$TjRq;{LnzYdPqGzx4IJk<7fcrl zp{3<~R7j2?0M*aUCqq=1r9m7t#-Y~CawvTnqd%3^Z0Dfkf^n zI^`b^HfT}^S=V~tf%~}ZZ^C@311jw9+O=!fr=Lw*bV@%}nik@YG!lwgJy@cLQh_21 zoZYxFvsu)j@hqZn0Pm0C?U&Ldi3taH3xnPBQhG(2=ced=aH?@mb$-;W4t(JKYnLqI zsG&tZDFWjB)vB}(Z#ZGq61A+7;pa{voVTa``8ioLL;-G(9Y$D|( z4*H!`j}s@(Rnc|83&^MkUVfkDY1wH+juCnNcn+BJP-ttzXO76*L^5QXht_dmS|;;oZ3Zvk*=m)bi&-sqDnI3 z35y>;&k`E^pAE0t`xx28f!47{k1XQAK{kk^OcgpToy7UnNgUbF1mdWAVBgJ09U2*p zXWa3>nR_iGEbW8DVVjQUAzLY9)jU=%1i}GF>W*4M3qAHwlV%yg@i~9>M+>RWJGZmz z)-E@qVf=yW66k~(Eh#WK^z+WVVhuj3saRJMP~~#uXc6!0_DLM{X4`#Eq6tnB=RGm= ze&HQ9V*hiFltt$e(?!O-68#{heFCGB|EF$)Mn#ZqEunp|h09Gj&*q`DQ0=?#zWY)7 z85r0;em5LH-&#m?{Bg~~VLQ7OMHWxMIYC@F=K52Q-e&Rr6mH@mva*waU-6*;HCn_& za)UT%!&SS8sdigV9N8_YHcLRa0Sd_Dp1SC$jlmzR%!Hy9c@b$FhqOoJ6-cthm#UzM zUM|kFd5FxkVCZANy!XNOEjwrZ9v9*@J1w<}j>;m94iy!m|3`0K?Y43^J3vG+Lvo!s zJLMz^Ck`~uo1Qd|O&m+(NaCPvMRiJ|n5+uOm_*gP2hdpGCfmPnRxS^yvE{%HiU0fV zIuBs;C}^L0T*l?BebgaBdZC5D)Mkyt+RcD(fefa3fz=6?Q%_NzK1ze$A8hxc1|NMV z0lyIYFkeS5$D79afba2R5r?<02#tdd1m2=@4qL6f&WpwvB2?FcAOpT)Wh4|;)){_i zgP@Q_kYz<{A9V;{NR;>+6IwQpPQD^cS;6<_g;pCVe~kRD&cmHu0*lUHvxuWYax;5u z=5iEq(57n>NBB9Ohy$&|_vktIx|nk(@}MTzZ`%pSwV+FY6TJcnB*;_vJs$kWBVyhp z8MczLgiOob_c0GEBCB1y_9OJO=>v~8&2HH_^M7z*K1&=`3^?oXgF5yZ?GW1717}#n;3=x2+7HZe<(F|OVO5`GXG%ya_v+jxi^;?GM1K=H5GI_u%8SWQK68Z)KYD>>XafLAQyIp|lX+N2u0acRfx&TQ_T;cmYv_*Ql(j z0W-$yWciMaG%DjOFTd*|jz|K2!bgy-T#ifv>coMA?1?yh!zbBAIqCFkylrLtvuInn z!p5R?<>bq3#PN$PZ`n=bE`XSG|gB9F;xRG!Bx0o`{3UN+*tLlHA^Ryt&s1ujjh^H>GVaG4AuIrprBvJjwmU}``kq7CMrtRXtyX&5N;vh4UT|+Lz z3U-{m9m=7;PnoiY%|i#a=$y&J!|G_xtb`)3%-cd6clex@JyyhVCjp(r;r-o`IB3xo zk(KasRI{Awd*T|0$OGbxB;pJw;tV@>i48q^k@ehq!r=#X9*J)hl-sU&xQ82oHRlzT z`oqIbf<{7CcM0u-f@y_2&fX4X%20HB@XkB$45Xi}n}l~0j^)3MvHkS}d?Ch~d92Jr~h$F{~BysqJh$0SYoF^4=P7301b4A2?;+RdG zfrnmV0}j5(`t3i@y3DtS5Rp&}&+S_-2}NbPP)ceX(&02@BV~kMpDHt5=Ald(y4PS+ zF$xm;cx30x5LUG!k@SNQD(ij_N(wWdyXr9{x08U8BK{3OoSwcfmbJW4-wUAs9=Phen zUC$cls-;>pJ9dT50lo} z#WEIbW@+dPH`;vBV0NR9w3TTl0+K8770DnLvXC-C$X?}skGDhlL&#{>la5-ed+I%s z7}z24*NQ~u4Ocd-!fH-$N4qWN_h%AOyb_0JkKM#k8b>(D7cJrpgqhlVmUX8nt6p3%|$PfeS-M z6As!#Dl!9!nsrG0qB{6Q%8^E4HDS_XOK6zYntbYtMjRPg$=NlPJ=Qgj3dx6(e>3PH z`7@Yj+kBkmuiDEp7H%%v5P>2OT75|aVE~dl(jM-?6D*&H9*(AMW51N-Q4tr0BK+Q> zuBs1J>fqx*lKrhomBuuUjC)5#XH^yAi^@Fqwa(=^7hQNG55M3F$@N^0BF=DV8qzTR z_ncwfHXdbpD|WNYMO#?<-1RJ_420o(AyU+ZULb7E3$qH%h*72BB++bVUcV>EQ2n21 z2M!32{@|`Ub+D%o$b+><#06PYTB)Ku4n-n(`}OHYg6L=P?YH0FHlS_HrIwvDapV8u zlaL-3q(YG_+HFB(>=>pC6yGo5A`ZfF(lk$yhUvTGX;!@c5XKCU&9(XC16c{%)S`c(HRG|cj#p@n+hMKcnxi=$GEn5H_S#1s zDl${y{Uh>*TGI`N(~Ulb8@5vH9u}t}q5Pn>g##T4#ln?)*w~X~ny^Fs{^wcW?I&3w znWHRd7w+tqZEBX21v{;d#MZoHxOTz3zS=Wd-5mOoKnC^BFvF{uFdKV2U*HM7zNE_{lJ~&$hdDG3}`w6ZhJ*7D^zK6n?nzghGCyXSEpM=q&LUjCu$qERKdikz>h=`&mP>*+H}jp-{v3H*B2OBs}^mw2>MaswlIj#;?P3 zdT~<(vc!&<#ya#H&D!Ml7G#OR5Ty1!6miS`X`PZU$E>|?;$Y9@-<&z}1x_59*Fl7ZHE7l@?)Q&0Yc*d+S)p>R0_56Z z4J*B)u&NJ5BIR5|{WhW}szoiSjgSm$6w>}cU{un7!A$T4h7VAV8i{Km?o4Ofp|oy} zG{TfOQB2qxr;zVEfNKiunD}3fT1Os&ufwA(Xq`LmXvx<~teJ9_e^%sChwc|a{h~^Y z+=Z@UQ5gLU!y-P=ph>Srp&g$O zj7t71H*F9uIhGY+-YOb~nc@#Z%eXAkILUu)9M<970}USQBZ(6x*8si_)&y&VHB#T6 z{Ie#Gewf+_y}GdPk3nV2Bv~6Q>irEG6h0Qx?f^w2-y)mM3yyNzJ!#&mC7BdyxaJfZ zhx=5x2i(hJA(02~YtW!b5(oDRlLd2y9v-X()}%)3lyd045%L*`E}*iT&|+9oRHuekOGfgy|NUSc(k z13w4Tq96|L9czHK_}Th8Wj&NOLP!c#4M!1;P#7Nyz*DK2ws1n^z4aUSe6)4jZI8E& z{eb+3zi~3DRtSwy>giXcQZR+@FZ9n4WGVbX`7??zO4EQe4U^ z9ru8H;rApoPJp~u+%xVSYoNmO8uFCk@J1w|k%W&FT8mUY)IFYHLc0eWJl3~itME-t zB09Ym*fHr3$SI*Om}i6`cqvr)9?}QlfZ!E`IV?0_|6Ox>6)dvg9HMPDo0l`1bx8a} zlZcqBxTgCb4d_qT*j`?18(h28s_=1?#!v8`Obt%+=cc?H)vGLM9i zAKC@JO!KIeKR1o+{3XtXbJDq=tbK3Ybg5}@O}e&079O=L+ym|f_f(^CD)7*W1b+Z& zdnC~inLy>E7SzllldYL7LJ^{n7I^6K=3^Q*4_($cxZOUA?9K*6bh_R&GVYV6?c={D zjqxq{C;v|7=0BTvO8LJW^l$twutUsxnGkLAJW?Va*W84ewsfIX}a3~_dp+rQYv=RiN$b{O^P6G8^6QfBtbe5+G+2%$s#q31adc+P{Fm}nsm}A zGlhG=z0?q=k`FAlsg-mxAybR+7quch@epEj8O?E0-F|y*OGDI>p|b}3O^5Y2yw=um zwZkp4i0BDzq&OGOiF4x`a4kA%Ol?y`oGL!NkqM>&i8o|!;hdsZ297F*>!1ufc2a9=sQyfzQHc; zIHyR&A*TXO0RKr53mO8Z1;U3z3#|b%=)mvrH@pU~#d{P{@LBjwd^XO3bK#sgw{D(l zNb@5+bVBK*QpAF0fWV<8AbbE?!xPls@mjnG?^Q(6$x=g@pZKAKYm!R`$e_dgyH1jy bEm{6Q?2jv-#RW^F00000NkvXXu0mjfz&))9 literal 0 HcmV?d00001 diff --git a/android/res/mipmap-xxxhdpi/ic_launcher.png b/android/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..dc6461c734a50d643a47be730905f2f61178c65e GIT binary patch literal 14281 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 A^#A|> literal 0 HcmV?d00001 diff --git a/android/res/values/ic_launcher_background.xml b/android/res/values/ic_launcher_background.xml new file mode 100644 index 0000000000..eceed3d93c --- /dev/null +++ b/android/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #2D4553 + \ No newline at end of file From ab5172cd6ebe9836624649cab21b9a81171e76d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Mar 2023 12:51:55 +0100 Subject: [PATCH 207/424] Gradle updates --- android/build.gradle | 10 ++++++---- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index c7f80f319c..bd11462d06 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -22,7 +22,7 @@ dependencies { android { flavorDimensions "variant" - + namespace 'org.ppsspp.ppsspp' signingConfigs { debug { storeFile file("debug.keystore") @@ -51,11 +51,11 @@ android { applicationId 'org.ppsspp.ppsspp' if (androidGitVersion.name() != "unknown" && androidGitVersion.code() >= 14000000) { // Start using automatic Android version numbers from version 1.4. - println "Overriding Android Version Name, Code: " + androidGitVersion.name() + " " + androidGitVersion.code(); + println "Overriding Android Version Name, Code: " + androidGitVersion.name() + " " + androidGitVersion.code() versionName androidGitVersion.name() versionCode androidGitVersion.code() } else { - println "(not using these:) Android Version Name, Code: " + androidGitVersion.name() + " " + androidGitVersion.code(); + println "(not using these:) Android Version Name, Code: " + androidGitVersion.name() + " " + androidGitVersion.code() } new File("versionname.txt").write(androidGitVersion.name()) @@ -92,7 +92,9 @@ android { } } packagingOptions { - exclude 'lib/arm64-v8a/libopenxr_loader.so' + jniLibs { + excludes += ['lib/arm64-v8a/libopenxr_loader.so'] + } } sourceSets { main { diff --git a/build.gradle b/build.gradle index d9fc3ebd95..4bf0701175 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.3.1' + classpath 'com.android.tools.build:gradle:7.4.2' } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 86463708b7..b9eead5b1f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,6 +3,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip android.useAndroidX=true android.enableJetifier=true From cf6b00e3aa165c6ea5d109ab17d44b32eb6ce954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Mar 2023 13:13:50 +0100 Subject: [PATCH 208/424] Also add new gold icon --- .../gold/res/mipmap-anydpi-v26/ic_launcher.xml | 5 +++++ .../res/mipmap-anydpi-v26/ic_launcher_round.xml | 5 +++++ android/gold/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 4088 bytes .../res/mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 8215 bytes .../gold/res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 6568 bytes android/gold/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2467 bytes .../res/mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 4781 bytes .../gold/res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3855 bytes android/gold/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 6021 bytes .../res/mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 12189 bytes .../gold/res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 9704 bytes android/gold/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 9989 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 21422 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 16019 bytes android/gold/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 14644 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 32536 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 23603 bytes .../gold/res/values/ic_launcher_background.xml | 4 ++++ 18 files changed, 14 insertions(+) create mode 100644 android/gold/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/gold/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 android/gold/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/gold/res/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 android/gold/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 android/gold/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/gold/res/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 android/gold/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 android/gold/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/gold/res/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 android/gold/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 android/gold/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/gold/res/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 android/gold/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 android/gold/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/gold/res/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 android/gold/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 android/gold/res/values/ic_launcher_background.xml diff --git a/android/gold/res/mipmap-anydpi-v26/ic_launcher.xml b/android/gold/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/android/gold/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/gold/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/gold/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000..036d09bc5f --- /dev/null +++ b/android/gold/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/gold/res/mipmap-hdpi/ic_launcher.png b/android/gold/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..3b6eb448759c6c28cec4350d03336708e5be5bf8 GIT binary patch literal 4088 zcmV~FqM)FtU_nt9OY9{YV`5elqgZ1@v7y-L zh#dTdU12_>pzH@$OaQNnZ-~GSa-ow$+c{|>Yx8v=2 zJ8Jx>Wo~X>_f3LrQZ=$tW62Vo+N$rpDWl4^m7HLdjghUhjnQ&?UGF@s>pFV zuL`A2hOjd2w4H6Oj6ikm2J3Gwo=p8FmB$d{?DP=e-VvWqX^n%QHN}+;4RC*JT|C-d z3#of`1bgQ-g`>4$8K18@>_I}H0iAZRt(6t%dofuR1sXlf024>*B4}I(d>habXI8zB zn;Yxnx9xTCcn^uOuQr~B*2lB3_mLU?33AVL#?u4uAYolY`mDa%e6NBcflNE^WLqmG z&1t31o<1&kp!uek;UMxZK^+7*Ebw3NfDSuZy(M21q~B6xk8&AdNIceoSx3 z69z(Yevsh#;ScfC_w_K*sZ$wqSDiwEh79<07u))m3q%zVCzk&W8FBV_ex?sH&bvTz zD+oE{9eL5+A&WC95~D1#BHH5754G@*ac#AduwT1Cj#h^F(yt|+9&3lZN9Ul({x=j4 zHbQaP4vIuGH9=I7L>k};dE0jZ&4t*i^H-JEE|8P85oWlyLrPd1W6%M(l2kIkobz^Y9qB?(7dF=u*-p)PoTjW$^ogW3oqmxkF^d;lV_Z~rl zDV`l_jO0!4P{q?#o4cx13xP%rH9*vwCX|%xL3Z66isb3)LcD~`@K*SJM{UeM2M|Azb3fa8jvTezh5l`V#YgsiU-^3P|x#`ngHb?i|dE9gAI}N z&AVh|`3)m)SH?SZ!A!S~Sm*x9wh^Y`F9R1a*Bk5gx?@NJF#3qGQ)$b0x#NL`VqSPapj zA8I6$JLj*g6Uy-3FujFZFI9a6q6b?!sg-!p+%uijgm@7-bS-a7ehsOE>7(0<927XF zz3>R-X112dPrN1JuA3W6SzO;zb4a7R(KU5&a{2peIjq_U#MQ^gu_IDwQ_3rxeX2vL zJy%)e$10md_KdBwKZ5;W0}3ZSvEyfP(vLQy@atLbJiMJr3w;;Y|5+bnhIgr+0x=vO zr&ly8I>z7zP#V>hj3_H7nF;~;x=UZZi!rv8d#nwxC9t`8k8_f$r@RdIu-~XiOn2>2 z>Y1vIK)lfu?rp7$wNskomo0ULq3rsZ;U7a5+ozO4xo5kGeDYsPwDUY$!+~;GfLjMq z2|28CPHP^f40~+qfd*JPx%8&@wFxvzBvM@jd$z--fR+^hABYOWE^a@Vs*Xc@gfDGe zluObMHW24OoRsAh5>F{4`29nleL$k>iO`Dvyb+!p`Vi?6y5)wID$?klcy_cULYKBL zm52T!febNbgdY4{I*H@a-NDU7Wx2cg9rA$MV#S%1J+*N0tA;`}CoAe_taP#5rzLLu z^Br+u#vb$hNK<4SQ-;yq&Gq2z&=FI;hT_mSqmgp3IkImCL3YVeO@Q){#q~$VDSaeu z(-T`CtqbI7ucvIp{954%HDZ^)ZlEl+A_>bI?@sFw0_J#cB6b&EPRCv_0 z!yh3njKye%bL;*Ne^)&?3^9PqP+e@F*Pg<)GbLt2toAp+vrGPv-1`c$U%!RoQFtZ1 zM@fF76>=|)#*XFYMVnr&2*i_f9(fY)iQLN`Q2ZFEJS8mSpb4?9EryuUXxqXr-=dH|#s>??eqQun+t1bIn5xVUe0QKHt0 zK+Jgi&bYs)y~qo~?H}$^o)Btqj9QX>N}kz~eUKU1mxM4u^rk*Vf8ycN9_-x>xA&VN zJKh#K=j|Z54yNrfWiEEK

IvypFUYQN zqP9@Zkx&{rZHDFXD#Y=tIpntkke$2)b0?W;SD*>5W{3}+fy@L4caFuhas5To zcBbF24YI<+xIoCclHFTM1!5{>=WU2#)FZh-eti<;cY;WeMI^`yO6Iz8H-KeioQGx(|up6?T^T;y#7P9$FKKaT{)gyGQIPagK&8-mKX0Qm$S= z%s}dcm;p*+%^)KWk^i&^(Yw8b=Xj0mh5J!+p!nBX$ZyT0_JKU?B6-A}c_hLr^bq5b)KzNf%wLe zTOE;i-52=@LyL_sL0)tr{gp&1kx`=MeDJ?Z3*hHrf{7lMIJ|ih39*KHo#T+k*+NR; zD>+Lc9BqO8YZJ+nmI-fpeq%9th6~1!H?cSHSu+bT!a`q&#z|iFVC+R`RUm$ljf*Jm z?*t>CV!zOMMjBa&i4x9L1?0t8QSMj<8HK|pN|tQYvbps6)QeE0MnRSmOB+`cqNBa#1~P$<%_L6&+2c@Op@H^!Md?ZLSD><$ti(ey5MgF=M z83+%`H>%I2DOwkZ#SOLBxUM&30)QL!ew_fs=mQ?xD+8@Xq_ zo5&0DpO+LQQYy8{%Wyw>E@JljV)F_o%4#J}$n+3AXF`=^Mp)5;tU%Z%4~?sqDq0ta zaT(SPzHWWR&)j|XGQr-1QNfiWT_ov-$OKc`L}{d6l10F`??j8#_UyL57QM-iM*s)l*8s@lB;ro zD#~9bP-WppFaE$};R)$S1{E1D_(6r;MuI1W>@q@5%viD43Z87PHn%2Jdx1Cszz9h*j;un4KUjMYR?g|A6FWR8r}BaxfvOC9x6(V5To9;7yRdDIAj zI1hzx7(xwFr`vmC$22jgOxA7*$B ztZ*f*5dv}USUS^6dDs={hNlMxBK?FNa^k(Ij0ZyYWARaGTGC?b(B~j(_e62_6F|Fp z4lNd$n^D!d%j1;@^s2tA@gg`;^L~mOMh=%k@5mwV;0~P+#KJa?#fre8@EhA7F1B5j z4Qaujhbr5HiF+3a^cugbp&7g_xgI`49H3o1G!-GMMq&O`3vtTG$E1ZvrJ8i;6+vlJ z6+MUq`dZsxsAHq~=!CstxP_kZ4(0w${n}Rvdk}x2&az*}Eo^J01hO#c=vg=!tF3yI zR|SiqZ9z(7D87=(p4q!co2hK8v9WPIRUKY7Y7upak8RAl+$fw-sQw1Pwy;f>CY_SW z#?}S4vdx+g7Z>rNCaqgGF&i?lb29&T6=la-v*EC^AEHmfIr%CLx}go}F!ATi7PHt#xai2Bod8 z*r?U2l}?+Mp{cnrzs{lou7d-3qXtR&WX;Yf%%hnKxst5RA}Nx|%+Kmb)jrSO{VgmF5S7L? zlll-9@IDBcUmRCEVI8CN^yS!lACJccgYm;&o!@`W^Uaf{d+YrFA(-Q;%P)CkKA0eKHtIz|t73#gR<4`FZj7^8t zc!>CmH-{|V&mQ=)5b~lIB3x&ux&NS@rk2HxGiO8)$t$xPh2nA$Pq%;FvF1etV`w9& zE}Nusjer?OxQnh5+1+D>?;b3-?AJ0HQp!u3Cv?^l%=z%B2*l0^E;7hy*IOxJ$UiNy zhn&Y@fc;xYRf^BTH9_F2)=3&U&|;%@Y(e028x;6BHz3+2Qh+I8+ktq|-DK$v&&aVTZeo1{8t@3!KA($-VRJFh7j%nZLtX(CK!y2qsX4#p>6B8UEepRB0dnnZ3ATgR z2nGjxC1q%swY3rm?8%Ky<@L4! ztSB20%tXthf4M7tY&|=0R@|(|`;qmhxSzCCGHy|v0OPD!&wZ;Yq9jaq%tM=U(UpFn z^!An|ga95MG!&`zZWr(ChH&?iD5ob7O5NCh9Q-Rny-3C*=P_AHdY+!7n~Bb79o@LW zNfUzu&WfWzVEbr={+8>P+VZ4B#O*4%#|Wwg`!sfpYqy2RIl9qe^)wL2Vxdi_@zVfv1q+TN7WY)jCv02F&(?^V_1a@S|qXZHs zG=2IyC9AF5e$8`$)bXZJA$S|!mhK-=l>~8qsbnFJYm&z$oXureU zdyVCJ9V52>zsb<+q{yLVgs{c}5S}f(MamzSb$=nE`02!fNQf27n){gfCR~6APdt+G ztyXQalHfcvQPm}wfc7+S%#O;f=RVY4{#%%Pb9rZhHiG|vssT;^(0Ct)nlE3tSb6aZ zIAx-+?UbU|xKdVFr$odtothFQGW+Hs&PvijF?H~-4dsxqi=!yU{Kb$>9vj6qn_8cGzKut^AnSQc_g`kf;9bKM#K_ zx>hz4>%tD3a*I73xe!BD4yx)D<&|G!J{~0ol`p;+bHC9GUT#=ZRuF&}|LEPI$;XOd zqLT0t^$zkqkUj9cB+a-m!9P|OMv6S{w9Om_t1Y%LxuytXN2brJtIQ$o_zkzvhCa>x z)-#RsC$n&(sFfFEQr76bkmV-S3;rjkcw0p_HfCS~ zIQ&PoNA-(zP!T`gdSq-}Oe#(N{y2A|2ji8+%EgJ*_aAR-jk1b!q;C5D6TXb}p_rCs zbD_&!V}ysrN;HP?#vOtCuOa?F;FV%VJq9)DwFkRDkH4RUIM7@^q{!(DB~=fsdSh=G z8@7s{*6!tbK}J2NT{>-x_8Q&HWDIpxlTV7_?KIy?Y)}gF}crl{7w7W7!Z3)CcSGiV4(aR4#j%9OG}tf{MF}#w&<7|e?J}{G#`Jr zk~hl8kp*-v(TO0*+2rq-sS+m^#9s(C`b_*f7hige2#DViz0s5MPHXh}df&AllIy>> z;H|H*QR0dZAUzB8hk7Lz1rZ!Y8si1i2>c3mgpywivIa&_9{nb^i`-RU$%J$b_ID<5 zcl?}ml6ufWP4{sXx-!$A-u*;eU%0o>fPNXz4_RffJabvtTmo}Ci_i_zCusRB%>(pL zj8PkCPFdLZ$&!h}%m59k>A4Dw%?{6AXC#p5wKBR0z7A4hK}l+NPGUtR8Ml+Ay!tM4qM({>V07O8O-PD$a8+*>H)p3Y!}D$?IwUbBnZ5v!^%( zx)kvY)kbMk^7w&_!5^m8kPyRcZC-0imbHn~d)3;-$7QDHD$9iiz?@Z^$<3C2#?!uH zOcU2`dlv1q;ME4!5Ko9*YM(Di&|nFVAp{!WOVE>q`Xj;Z9PorEJ@zSd{XT}>{|*_n zwt^x_F7f<*RA*r^v0PI{7q>mPI$x-hns|6ocr7D)%K6S^r&Tf}$B~o>>eAve z%+qQPI6ZW4e`89#XOtykBJrU%azu8N@xc%)p=^pKPgdaR<41Y2_}n`1D7v-L+kC9w z=sWx0z(8oVadPaCn)Cz?c}UdVZ*9@NVlW`@o^+4KF|L)Fifdr(;_dmL zJ?gA{BNI#S#{{Ld4`LE%E~7HvQi2E?K2qAGh0< z?aNJuzP|V-FcVagw+}}R&BDphDn<`sTlwi#f7^g55g|NsG~42z|Gb`5{6e25B5D7O zJ4;dq1gzE`2?_sB+=ln%pT>yRLRv_T#3sEW{d^1}ECaeSY)5F$y^f5|&F4A#UAMSM8?#}>cVqJeh$<61@q%-AjYzkcvCGG8)eVUsNaUPZsmi0z_(4=m_ zpX=eB$U0>3)-0M(e+yz%*bE}0dF>ymf-q$HRb{5JV=0U6SXKQ{fiBVzi?+|HF-U$;gds=qC--drppa;lpJ? zBUIOZJ0S~~C!V)8)w_@huyF@)QviL8l@z&)gnwdAB4MP5=K7XqKSowS(x^gl&8gzN ztiqTD%C(}?D7|uY(L=&QY8@4YVXxF=lNyXY=Bm~f7l&Q&Gz{oE?^e{uEf`lWbZg+z zZ9eYj3%&m`SgDowa%7 zAwu1}i{T2u!(j5L9B+?m%Te4uG{3zC$_g>a;{B5|Xat!-06)BGqZx)Ee)<1QO_`aW zHu~2Z&@cf`{ip|DY)cNL!+w<*AN^*rBf8b|{X3kyPwOpH>mVd&1g)&8=~Tz9uH(N> z=%>X<<1f_0s&}`b4%L{*X1B}Xc$vNmkDWQX4WG^`h}~#rzu)`UrB~STgj4bCEGIKt z2E#n&_sm%qYcDGLs7IUBBggi*&npg26+(N(}(DiQR`}O8rWAOF# zLBv+hXO%vQqdroFc?MCWiyHfS&gBos(M*9ST(@^WGrVIiJb4P9(>w~%%oPzrQ><)D zmrYCe7GbFJZ^R+%yhZ0fq%rQqai2&VOIk|Jr0ufYR;w2cSuht)r&-0 zQ^{&1mn;<=%Ka&uk-`B2;wd-7;))EeW{}URK>pc(AB$$cloqze#27cvbC~u6EJNdYkh+JL~(PCLd{Hqemnc> zP|4$98KoGRGQIk5ZDN4%uHa=#woC$1i(B9MS-6t8+p!KTE;|y9)Jht~G2lI^B!=7U zJgI;Mb)(Ec>YS2Kd4x>!qAFmO?NsdY?dQTHB@gi1g8;N=>N;RPaZ)H7=5bUgqK^dC zjm^uo@L^E93Y9Afsidt;xk#3eGH-3&M%`gjm^?}?jWLJ1?~X(9T^RO=q*HM;5cBIm zD@h5*z0|CMVNVOeoDL~TJjLJTpFNbo(U62%DqTA6cgl@{zvDBibrfQrz0k5hN~HY4a)^}bMX zMKR$Nkq?>3?_$K5t9w18%;r&o+xI_nb)bIp@RYdkeM(cx2njn(O3#r@zg5i!SSNx5+>sMO%P3uF~SUwn&lcR!K4n5 zu~?JDzyWYDdw%;n$#HE%9={DI{ooO1%iMfh;HiFeUa-L8?sJl!YRGK$$Fpia0| zDf*~<%K}Vu3K6`>tGR619>%9#zkMyW4&jngQ_{ zyc4S6@DDs1n;{pITSK#ICE+1W6=F){vPHXLv4lzAe7^(E%CrJORWcn-@+K0i`eILa zuPPGV2r=T>(st1GVlRVGLf{_+g<6G0VAP6z01=Ni6!V)UsQD+a+KhOScDPLc!=z*w z(AiD1pGP>`RV5ffKVq}) zgkY`Q@lIU?-8P)6<^WGMG&E?S)d4f*ZR-{oL>1q5rx$?*7HVsn0*Xgw!Eq1qnrx@~ z;W#Unn_fCP3!vT=eN|4w%CnH=cc4BwW=k_K_v83c9NMgwnZ9AH%pLUR; z{pj)Dk`y`Dkbd+;fr|a*q{lwz+45-?HQr`9~wl)6a zElM#P8P=`>i`|@ljQZRziHGHci(f3P{byz4WKT-UVdiFo#n;?ZdWEO+pzDGv+8KWI zyxNpE&J%O#agM7^z}ogU2&^mt3^TW)Fa7?7Acn-|UAPTLM|{Nr3oI&=b#^0#YX$;; z64f94ifYES$Zxl?_>5>PA89K``@^r(`0f6SXx2FCTtzcaH<=^JjlN$)3|P$RaIjZNuba%=)UBVab3~ z*6eV9teIWgCMfWIpw#Qf4dX4?UJK$H`f_yB8}iuFB!C!TNWl6$MuTd9#kdFE2ZE{- zyN8h71O#lNYpVS3AZD4y#S1Zxzp7km7Am}aZHGN`6Q9wK>3) z>sNAOHLF#y)EJo3EM_+#1S>ghIh4&Wve(<{?v%*|x=rR{PR|0!{$R12;rH)>xmrGh z1P!-s_b5o~e|*h!`!WF+2RH=x_LUQ_Rd2jCIOmAao?^_jS!#56P#l6fLY=-8w8B^= z?WbiejgGUvHV2VDo$hm4ULfMVyS_A(j%Ob)SBb}19fn|02(QJ{Ae)k4wqVlYjPBYF z9n;nt=vS77NRU3??8rbFA?g-MJy*Q==i@uIIOegHl+ha*5A8k{S(Fjl($;==zGHGH zjaYx2W7k+(<;QJ6+b%^*-8#eY!m`ry(ff_nZYTHrKLIw}Gd}CHMpDy7+Bwj(8NIto z>0H)ccIK15sMprBqH5@ooVJ0w(odH(&o4ws@sIxY13 zUBz6DaksX_W1D$N-yL9N+lF4YFw0EO43m;FniDN?G*lXJy!GTV_R(RvvApqcJploE z9$PRU?MV7l&2nY5HXd71$oA*C&D;HOs-fGz&i&-L_iO=XI+M3P^vUq|Re;(T(x!5C zXU2h|D~QXMDAPf7gA45IMx~&wb6%rv%}24p!WJ4fh~it85`9(bXtdW3MK)#X%7Wl$ z$_!V72t%{UJ|_@>Z9H6Wk_3i*G_d&DBLCBMCLOH3UK}JX>K662S}yp;N7gCZqVAKl zK-}Ilux-b=&&sy>^2;5dChBX0`P?4kUK* z28v4ee2ucB4e!f_DPK#K_{Y~DE}$rqr3R*;DqGFZJGaWX^|Ol%db?W@ghG9QNX_mq z=98qxV;fI97lXeEaK{Q?(uS`brs=P>m0X;nGE*}UqS~B#6|vd^(opfOB>w~sl(l^^5dhzCZI{!);&K8$={0AP@yS!t3eA`Id!w-t zev05%!m4>^Xy~Dw_1=EfZVb5r$n8Sw9_ z9OWE!tTa*XIekIkp(09B|5`jW+N(%Up11muu+(oE)f?=^n_0YcK5TAg`v7r zAr;M8l#DD`NL0aKdnTTN%X3SKfEd65S3q`Fx-I zsUweYlGQ22eppuhLC7$h?+s{4xVyV+W+!Kn*uER6y6kHgCcNZ`mQ=bPOd_zFg%0Ld z3&!d-NuURkM=Sovq3c>{XUj3c6~iF>{hDUeTY;6tn!dun+sA^IUqaueP;<-N(n(i- z6KTs$89@pwvJi)%jSfIn^tFqi0U-gQ!lWvPQf%*%6n}Ldb(>Uv+t{^_xb>5YBGlR+ z#Oc#8(vNNH6NX{>sDfBs05t63>$zyG3?Q;WP3N`i4-rk0uZ>}%gs=5(-(a^Df5WnC zr-2d7&<`#RQhGgNG<GaSF&; zG3c+~qwjd=wV-V>KOmbIMd?^x8N*TBh6kxih!<*gXv?@y#u8Wh{!Y1YH0%Z8zxi^S3c4#q0BjiLVNA# zML z2jZ;8A7==zczs&&Q(Jy3ev#Xh^(Lfcc744o@^4$VsbT9bA{7^T{RMe-=QaNl7?nB zC~&t8uOG;qb~-kgv8}z{V%gTUY61cfwncT0N^DG}%~R)=pD7gwt>|=6>8j!r?AJK~ zb}%?$GUI1^t2{dv!`Xp&>o7vbQiUPW^3*n*eDErv;k`wNL%{v4Re1SPNn5;C}&GE9QOX!^bg zIvT2_p7^BA1wB2q)>y<77Bpu(?{iNL>*DhGPelIRGUeBd&Gi&LE*CCQ_Bkg-TuC2- zIs}QQX}f~ddpk!xp+ZjL5Yx}TX;z$>-}2JP+l5W47sSDDsfH>~!O4hLpkJ=oxfI_| z-eKgWU#_qfrOeGNRxE~%Aw5uW_gLlA8szK_Q!_+G*6rAAmi(GND;aOjZmxo>>XpCT zNx~*GvZ))ERf%Ms7I`ykN6o|Jyb&K~@o^pxc9%HSz3o$#>?{+xZ(hZRfWPk6YfS@) zW5q7ux`j^C3j~Koz37AZ&7r3!2<{C!-FMt?w5BdIva1$Zs{5LV1>SK_8MhJEnk>}i zChz%hmohZ9^P!w({ShY{K%MTa zU>%Up!-eda2>MqQTyeQG4_g1&xvSQbXEU~^aw1ykutw3CrsQosd^8o9<@z_{A}~v% zos!g)BwTF~Y6q`huy%1umC9u`m2&t#TQSV`(Z%Dt1G&J{iNkn_C@;IjF>6`uV;bIU zO32W_kSQ{eT;~JfnBOm;U}w`x@hdv~&;0HdJ`#p^yFR!ds*w(X`n0t^yqw$IOn&=D z2ILi&rge`4eaW+Gu1@6wuE_O=!jL`{hJr1_fXRC?|8N!T1BaaPzw q0IXPWu9HUZ8W`jM+``??{rkikv-pSXV6OvzBzYMX>1s)np#K3yo~CF3 literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-hdpi/ic_launcher_round.png b/android/gold/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..0bab70e86de578859f196dfab1cae88bd3efdb53 GIT binary patch literal 6568 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 FRJ6`l~phyw1q~L(uY<6KR3IqPVJg@ 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 literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/gold/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..1b164184ef69a0a0d4786fb0af049bbe53241eeb GIT binary patch literal 12189 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 literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-xhdpi/ic_launcher_round.png b/android/gold/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..545f37de120c3cf60ef16b49ef00861009f23e41 GIT binary patch literal 9704 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 literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/gold/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..9aad451c46c24f8266c6b1ef3edb786c5854112c GIT binary patch literal 21422 zcmd?QWm8;T6D|xPNN|FL;1=99I0SchcX!tzxD#9^KyY_=cLsNNx51rv?&qBIE8eQv zU#51g>fL(v)x9DV;Ut+;K9@i8F{}}OeEx;< zS@LqkeAU6Q!yDN^9h1Mgg}!2pa0(Z^`|g|(M7X_ z(l$P5Ziz##E={993-ftU=Lr-%y`|C-Yxq}w3!&98hka%@fwlXPz$J&gUMV{HItQm2 zP-e(Ii1_i2?K5x+C|8?e<$RvTYhHpo#RVC`v58HJ{g7AQ)6?$=*iU(!>DOu0d+h{ zxJ4uz4AyZ~_$Ic#Jb?7n$Kl6IvIIbXZJ5YKq^=Z&k#0pW=w3E7>GVyBbLx9P;1CvD^aivk1*X_52_`9w%EhrzWyUF3g3BjI6O?l}tvPpQ{YZh}&wS_*SIV zfuLE%y+U8~w!F_27e3g^u?uif5-RXFvx)O{-$m{Gm2NbPb!3*!{pHNAT5T7lA)>~I zVNe!x3i+IlwK|s&h>GenGYzJf08+u$afPB9L_^v!?JShVQQ^T zu;0}JjUj1$Y$e;0#=ZNtK!=L`)Ov~9&?8K!`hW%(g-IS1zduBu!qU9OEUROEy;l!T zB6qmHZDQf-PQh~-i)7B7^H-2cVd2-}_dg%_ZnsMw&KI?gyiQq{dP#4x8B%VH|7)=p zAHx|eVn?72Mqr$FAV~Y=F5G@8blz2zR}6wBvA3X+Trq%+9y+mJc&}9%G;w3!G&p+X z<4o&9{gK{IA@rX{;Cp~X4)5O{Ce2ZL7i&C?(BpxK(#rT@+ALui0W79yX(DkVXEmr9 z01aB_T>z=MjZygK+gDuFy#JIiyCoOL1<0XP(`-@X za@S!Ek9i{P@nELVeRzRv}iu*y9Gk=2dG&_etlj{LkgXx*-z#uN5fWFR(VkfJmKHNF{$h zFyIDp361J;N&b965w&9~Vu}CxP-z&;gJ$U2pV!}kUf1!t|B{yc?lnD@YYQ%k-v+Q; z63oBPvG{w(0nW(8r>6DQ&C#enRubLot5G;EcE{cgCXf-C%vpy+*f!r%-(R{}2&-b5YwvdUw3w&lCkPJm=`j|^o zkWX6f$eDHPN9wB4`aj2zEuh!@QM~U{KdX?iR|e#)Q{+C(@5GbDy(e6_>>{NOfG`p+ zpwckyvUfv0-O2}jo%21hPRoT~CY;>^rvJeQ4%da#vWbfp=;~^!*&}XP=Y{jnAj%qL zak8}!<@Nrw50!!vCnC(igi7$rKl;E9P=K$1-WS>?vbf{OC2FhrqrJaOCrflIgtGEE zeyAHrxH#$vLSCGp&HTuGE8s-bWsAN!gIx$FSw>C_dK%KS51)oouY2WY9}UNZ>Y;=F zRP^Z)1?uO#mWepG@Xsq@pO~3{VS7KwwRkDHEN6Kj;m#6FYOID`R<_TjU~C|IbS4?G z_DGgSY`aT|`=e-dP!dXpRU?vs!8kvBFkH!$OrgkxX%x;2fYKeq4OP@;6Mek-RlZBf zAp6hZ$C5|%0>*#3FK16Zoe$*LiBISY&KQiPd`hkF(i(crw>GCs{8cI$~C zM;8pqc6P$?8Vx&f4+T!aC?$OnQ4vv0_F!k2y$`Bh!Y$G`ic1EV<|n}bn?xu^l*3~e zsu-3xA8Xi}RXuj|aPR7jr^SkHT2|{R%5c62>hdij{k5@|(PS~(JkwB}D3O_DZs(hZ zVoH-zTTgn4phxZ~;n+_sKkm=RW2#^R6m$qNN42Eabfio|sfh^jLtTv;a5*e7MYBX( zV#5c55r+)^X+AZK{0Y18atduf4ln6XQUtP$W;tXJO`Hu$be%J& zuJ?dD9kZN*5#E!!GWS@jsRa+&`(ZMH*wcxL;ar;G^Vc>R}KU zYDsr8$Z!;W+bm_NsK$1tWle&ArM???F%Km^QrkhkD!5j-ZCnkIEj7}#*iW_jsDgKl z-Ef2b^0%)!)67(*g;R_1@0NVBCLqA2gQGBU7P~_XkfCrT?Viwu&cyP66eALJUvD*= z5uEjSo4X+tRxHOf8tU8%)D`M6mOlH@a;Z4v>Rh|yVO528w-m$wSWE5`RFKs#@xQdM z$Z5IDV_cvjSVKG~PHNSMWGJw#$%$P~HUvM6u~SgR0r~u7-y@FmJExE;3re1dIFf5d zV?vBP(&)(1s>fKra!y3jzU@Ub74B6ek{J=k($CS0xbpJfvL<(Ir~1+jmMO&liwg^k z)9{%+pa6qb-&DhM*zm5ba9hoq9!1f_qJ=dwRngeVa<5g;eMNySK7era|61Icu*P+O zwfs2~`z(5eTG10B$?y7Zpa+T+2wf>RjVo`jcov(GaVo;^Y~q20ZM^?IvtI&|rS^Hq zDl5Qi^3<`pzVQCx+#|3C#CBY@}M!Tdz)mo`4^~@bUIqig8P)B^EOw|H_IJ{U^+Q@nJ=Q__yhjb!-M-J$Y7R+=q~K$G?5JO zemHgMEm;`%kv*7+5&WrrBnf3D*^>ecIXL(XWu--T#OiN;#B_UAGQLR9d` zf$yPUVgO#;GAnclmxfU->KfhXB8v*GD?J1lU9RhonunDe!9&avc5<1z-V5FA#49a5 z=)k8P_EBDH`5rgb(6uZ$?nD@m98Y4qg~EteKc-3zvc8g(dVq^v)zUWM_t3ik9w|bZfdGNxZlE5PdiDO^{6D}F>786~`0HafTo@cp>;@WP4T67wLAnT8adOJ@D*u^20ziNo5FS-cT0P{#x=CmB*h?Uff~ag z4cF}Hn-6P8cg(pUdR+xB#YF{0gP>FxAVTUuo`M+ouZxb#mN4paHgMi_@_`vCaQLe+ z;k3X}&mq-8X=j8Yu2Y%<``nr@x0?CGAYaC4Q44Bvxx|6wOIlgoT(MMIFmvCl*=RLc z58YCng2y@9U0^*MLY|XuZnv9GnZ`mP%JvcG`K}D><=;_nwiZ(2MT`;jFTJ6X@GNc# zaQyVdBLb0*tir2~#f1lhW9ildas^2TPi1Zv+--^l^krjJZC_<#P+1soPJ|he zPJ76EDDD;oOB^j3)Vnb6+mS>2IDTMGRyx^C#L5Xhz4aWh3>o1habgCe)Wn9{SeU`P znae={95Y0dz4#h_yZfRed7XbXw3Q&qcZRrcspvJMY|E`~j)TJ}^f3eLxti4H39Rid z_I9U*QTYMsb)X|&^r3gBR}8tAKWC`}iolwLpoece4xix>zfEBG(If1n?^eeiDF>)^ zH2uv~-xQ_R9UsaPxC5mo2EQdt#1g8VoH^LSc5UG4dY)uC^8$-WzPUOX{rL2)j+p$f z=(yFFRNTEC2`wuIOeDhNiZ`>O8Hh)K@o>uV%!RGkgqIX6|BIiekDhm>P0?RzJ4UzQ zdNLrD3LT^uNjTsx!>-L(KYhlr8Lh(hurp-&Qg+shJB92-SaXz8Qf~LigH!bGU7=rH z&?QD{8SON%ZTFr4^saWNs*P1y^E`DXz?puFbk~v zkP^Uq_3LzLq2fQSxG;K!n{}vUf(S}kyvnkUc(JB)l4w1wyGJ(-2KeR-s?^tFm1j!) zapKG~4sRUjDmqpL1Z$PfmLV}4t{VaYLAoFA-p9-w0}(3=1XHm=CBC;Qff0&PHqTpPA4m%wcS+U?K1}_|x=1hG&eicKzS; zTU_IN5;nI!UuWk+zvbhDwaTl0oO=ii3xyYTjR5=@)?d}MtS577|Bw}ox;)o$5mlLa z%tMT2kCz7Y{g-j@grxTr^){%CUk|oW2$e+V6kVZj1RDW1Y&vvm8&f|_eKHAEGEy8* z39?MC>y>5de8_3kGynz-ul}ipM!WBN(=ODsWn^lMn&r53UOwM-^4_%@oJE)lm1hif zK|EydZ?Mf>&#(?D-YX;!)+YFqSyK1_wrqjpbcZ*%xBNZwa%p%g`K)n;gq2LzYTqkz zIaNGwq_DH&|JJ}te+T-)96H2LMRg|Vgf3~1lglHC=0~9IC6qEyMG~N^zOKGp_4anV16Uf$8 z?eq-piLou0t}h2K<1&Z*^q$6+UWRbv-vxKlJuP54UCpaLRBz_V8-9d* zs&;ZNJK5MHDR5ZssYQQ})=)(_d`)+_)~Pp2FMZ8l6lFy;OT-QW9p-=a3DtEs{E%gF zT1Sb((9Ee|yL92)x>p_%V(lnEDa%?SexMNhwg#IJf9}QgZbbEX zkCq6Q-ncAZwl~2yqX3E7ZnDoC>`Rr(A*V5LRkh|+y35&d>zdIkd^6ZMdhSU{3sCc1 z4&uS_83!zCz1(3c0>+o%L+x}cA5^hYUDrd^g?Nc}@JW>h(&DfAN%AIyID?p#6Jr&p z@D=sm!URVLyNFDBH)ckNKTe`dAS>GW-#b10NBxum>J%=kjJpK2L7ZN%-5ZT>z!?Ii zM-N?}z6MIOdQG3#uyU@reqZuhbcP*moY;;@*=g9ttGT#5Du0Hqm8`tktiHj9B^lDP z^tfl6`Cg7GfSbWJCgLJSUQ_A;t=WsF_(E(gdTYU1jC~B!Rzf)LEriYazf^2EB?+P1 zQ(tO1nY<6GcCWag<^X4KrI`oW9$Db}u;anzy4l$fEKL6KbT4iQP2>=!O;j_bM*68+ z>aVkk_1UHJFqnCRnDejX-;4wfA%}JHm z_Oo{T!w`DMAx8;rJP>UuVQ(IB=f1rcrJ6wW(l_GNEIeK{>!T$QyqNO?xP5Bmqi0DN zKMc;tev7yh@VR}El2QMJ#>?}9DvFdQLuP zpgpm~K!M9+lofOGLyf{|fUmdEt9l(kHETE`LyLCYXbZo=oi`}L`PiU|>NLt`YeA=& z(83A9@+ob1Mz+B#r5ChT*kK51D=~e|U zUSfx`K>EMop8xU98jSl}(x;b5$n!dOOReaXunIbsFKufoc&Il@_q2eRIN zFsxlhG*K0g(k$<`#8~CB#+ev8srnA;JXEr*o-iq-qfaq})zWkAi8uMaoOSp?wHiGc zMB|N$&uN=>Ih7+~94?%bE2dQfNdy0$ZIq^ctOK?Wl$rUL5W!SDhr=|ST1unfCK7W6 zGpQP%Qb)CrrH*22M;pClGg*HZNPE}c75o2q?wu#1|LEgR!5VpCndQAdYPKFrJUG1$ z<|3jv3*Z?{z*%@e*YXh)ujF(JPYlj9S*751EWA&Y{3(~F4Uw6B_sHDIkgP#047sBZ zQQ`c`$6@iG`7{46_i~g(kQPBhx*!iveHIP3zrCfU#~JPV(gnmzUOmYSi9GW%H@T@KUpsxL;oHjmh}6cr6K|KK68VI0bBc2fYP zIbxQl<@OO$ehF!Un}+PiqkveI^99@)v_Lbj=1?!9tjU!mMuv6viCnSh;i;caD7E69 zzU3QL1~p8Vm4=ICwT25nor#CesZ0$MP*U9{**W8nZwV+VDB4ZreVYfc0GF0~eccA+ z?pu&Qxc=?zAM=4n zehp+)0Odk~|J2MTWEXI9G@0`VR?|^`-utw`E1 zUv?^_o^F*V){eT4lX-%zsS*ckt8}z-yQ))5OT>^(uMs$JUcw)C|7-MUIuB{EzaN=p zV6($80<6HgvH9hTMQ32KT|vw7L27VGEf|auum^7#fdpkU^@&hrWL=tP25JX&p{9hf zpST()GSayXJFYq? zoWucJA^`K8R)OtzavhT#dRh?Amg^E+Dq=WYav*V=hE-7u3%z)K(#mw|&?2^-{xW%R z#OZpD-ima4JX<6?*MVsRinpNuP>Lf~qFeEqXLm8ICZvP~b2n2Pcjsw|tDxl~rMR(@9id$oxc0oDjM+ ziWqhj!Y~7=YPhQ2L2&R@rcqwcKAgUUQL39;%XClWn~!??`Ns>*j24>$hx5`a90~Dy z#5|CA9B8ckPA6vOE%ptA!T9cL-oU7Cm4;sg#|Bp-2(Xv(4yEqLUD!gMo&8bwhx?Md z|4{kyZJ}KGF?N&-!psKz5Rl{)=rds+(%&C!P6k|1e&`n8dWE+kJC-I6Dmu4~6EUfatXuc84^( z9pUul1!m$(z-!?%_it93bQ3?uhg+yLrR2K%(m73ewEH=qF9Gz9)RLo$?=NGg4cS&H{4-)uS=QxTLw!( zAkh%qoX0>umdX@9-LB~~uxSb0!qmH9T zpzSK%R^7BVSnGtQ{$Wtf7a@jAoRO6WUJmXflx5Qme2P|pxuhM!rw3W9ky zyarlD?HSV1J5W5VlLDJf?7FeMQh)~K_2vkJk|VgJKLP=as3ciM<7k{vy4kRfMo<9` z8c^AdJXKm3Dz&^^1G^QZ;LoKoa(1NC9fYrJ$8P0QDnXp_W)y6D-toY#hwW3Xz*sHQ zY|qc%IvT>~{zaEmK8g0p+WCxymuG?Uk62}m0}Y9o@_vr z0n}fAjhoheoC42(PYtPVwJ;hIk_mHP7%T0b_#s(I6bEBEr(WFcz~a7Ug(ORs$&vg| z6fvY}OU6sAvvE}yH|5!YGH%44_0pdRrm6gU5L)q~a5WI}1V`uINptLBy!`2(O&2nVCyaRV|Er_8oi@}BG{hxsTff7DI-fHrPZHKuC}G|x*&a;cTC3# zs6AeZh~D*>RG?8rSNC1*nVy{G_$xT^rho+4SX6!eJ%4XK=5D+7vyAVN`V9s8NRp^T< zxMmiG8|{4@t&Ua48=r3p?X6PM_a}^FFZ|*B({Iu@a06fzaqgqvB&@;AqV3aBi+;&! zU$hwRkgdn%6)Xc-R;wSClxY38;^Vb+UVNTe+qja#qOBJm9PJd!FKK4i=9YahfKj6B zx>}~%+3LzlV%$;^gbY06x__s;BsY2O3nsx>i+CL{@L%&$e>At>;I z=$D-hw*T>T$|!t4XG3t}WdOK`v6^xtUd2R(PxDE_1`$V}!K%o|m0-9`c4|z~$KWQ$Sf!K1DVfrvG!L08a7M;cr1IZ3zn2 z=pa&OHDuj!&axN<1Rb3n_ml)OMtc9@AvZ*rJ+75xB`ALw=Zl?=x!fB#(Hr&!r~kgK zApJnQk2Cd__f03_;)jg%bQpDOxO9E3*pPtO;r>kdbPlYUZeNocLTc#Ov&zqWJ2F|^ z|13RLKc>&Q_ncem%SW5|_#68#0EAyBk>O_ZVAhZwq>igNwi(m%CS;~_k7sbX@secY z@y&jrbM@%2oC0D^Z;#P~bKNIQ>3v(D9e z7cernUd$4Ica(PI-&-Qk0lEAX1ok8ix!rl0&WLugsVHDyL6DoE0_#hAAL!DA`LFoh z{s|S${x}tS`$wN(`mU5Ogz)(;j-|%j>Sd)5SQxMmKdb<1yY;X=*xwpb(R>|Dx;%CuF(F)%C6+9gqLSIjUkq5Ep}74 z=rKVfSS*p)n?}2vk;kfr6O!}`JF-@pbk*7}oL3VcfXS^@>O#Pu%#bu6h0gI~IxY24E0nfEdNa1+R5!sC8bZ(H?w|3#_ z&q|LL>>_4r%Ns67FCH%~lEvl7SMp;0ptKH-+zWeOJNu6bvFhTT@}t1Pa4zb~d1Ln24~4Xxjz6q- zH`4RDsO@fYR=(h7F;J&mMG5_?JW7y{Ocv{EOEuJlp&Z;8W8-P*N;HU5?YEQ zdS2nT?4T8cCOsBfB%cSKe8kJUn#|3mZu>@qTJ4ab|fYmnRQzVm}IXB~pGlLkg0lV;Qv z;3t&5wmR7g{X``mc=GNH>cR4kmI(0Z`RejzJnkMw7f1mly|4YTk>a!M_;#`|nPIT9 zMtw74{>QVp5p-K$_fS1WT6GzLq3TwEp_;ZcNLZRm(Au_v*HofrT|1Y_XdI&`iJS9B zRqJB8U3d8kMoz(Tw=O?JpDvTZ`kIqt-yUVHBz|WZy4>RS*nkI^OQ=paAdnpjhRFr z1zn;F9YJ$*^sS?ZhSjp@;}t#?fEsqDjYlJzT9ykYHWJ4t&3%pi6o`a>3@R2Bw$y~- z!EY|F7^c}7)Jw*MK<@zmDCf=>dcK4*&QFwE^6_720yUR!31Spl-qHg16azn++#OuFax(<*l9 znnC8K0Xu_)9TQ6EzaNGJ6~>|H%eXZIFmxF+^~tyak5D?hRTE71j41D44&+h-p`l%U++_Iti9^T0ccsR26b!_huqx7*i^K(jLTFvD~~|bwe;J+&iz%E+{R&iuL{507i1_GkwpIMZ(A6@!=uHTL=;Nj!y?pY`D70X!}%NT zW$fRqS+>v-sDnj#!UdX}GU%s17ZnV@@qy9CC78Ci_R=+`q}Xa{ug|;x!cNR056imT z<%2LVB-+-buFuTn)(h{m>gD7(1=mVQ-EEfKZT~(iCj1^do5glMpM;JQvqD((W$+K` z{>nU3IAYksIZ#;QXf>&^xumZE8E&(Nuu8|{)uT<&yk?5bUN3w_zkI{c{AxcY^4T#V zlAR9<9%;)pnPSy78NKBkMn@=6!!hVD>K2zGkzm1l$fQ|9B;$qj?5xhFjGT)IT0OX& za`F%pwAhP2{}qF$^L=OB^2JEw96!nGys2_MQnczJF?n^)bar;LBF9#n^Z7pE`F?Kk zrb=pPEr~L|Gt;_5PQ(EREt(CBz>ADt3%w*)uoO>8mZZTK0X0fyypQ54 z;Mdt@^l^ME7j_{%9xacWr%UQz|K<9XINnNhC6vn~z0vJv(Z9Xr40NQIOaku3WtMmu zvk4Jjg;M@o8W?KHF#-cSg(cSWsSl`duAv;l zY0Abtd~<5@mP^Y=g{5cF*mKpC)f6^KqAa5r zn}*QO6WLH2;-kD2jJ|M=m0aD&7f?k!higV?=~%Iu()X%(#5f$HMt$mYSKes7aqex( zrwu!v6qMo~kJ_}r>H_ogmzOp`hHt5dak)g58t||^#+(YTHF+=`pm7;fIiXetXd2bC zKR<35a=dp*WERLX^}V)7*?nTNMH$Pr`i`H{@)|15nte(|tW;{^SR%eS+A=qo{QVgB zZ{Bo+Yh|LgmQyhTmk^5}O80=v1f=^~kGjx7c)M94z>Aif&MM6LhR;7!eC1v&2a{S}T& zpltoou?dcgzr;$*TG!oHyYb;dj{q)Z_OeLa(|UI_+I3tG9|ZXd%tRMjA`IHFOO9g+aVju|mXP*Zm43%_)bHQF&y67y8Mc89m`rQ`7b8 z^|WBq-yO+q?mtWak2_tOluRxV)j5{c-|eJ*3I%g7UTC(i4u!Aqqf|H~Im zCO;TQyV`aS{h`-etV_X{pZ_z@HK4(Iew6t8lc(dav%GcEhf7AepAUA%uhWGY>v&%- zUiI+uBuc)qhzgX63`s%=hmO@>qa|p6Rb5n&@TZCV>^n9)eO)Le9GmZ{Lb<}JtI`ff zJvO(k>=WwP7acF6io=Fp6iyZ!L&L4-rgQD5L&_%Ra$>v%1-SRHxCD_d7XHX7;1Y8( z#KmW%fHVe2TO;3mmfD5}1Rc0vSh%`4zq7SavG92KrGxV<;H$3|SG=?+SSwLd;Gtgo+Ahv1 zvNjeSwajCF%{S~?+Gc*QAK8&hr{RKPA;9MF)&g=&@%AR#2(Sz!Yo%K&@*6<>QUsT^ zptq@#-y+^+l+s_<*FI@~w7SqZD<(TFtb%p=XY_adJzE}K$Jxx$@bw1U*NHf9YW!^Z zS=P9NJD-PU#<3XA36vmmae8l{?P3uB)3u07$~Kf9S@xIYPRKMt*gHG--YgoFFQ zK)4j41Rw~rI&+X#Z*Cp$buhWs&#!UzravBPv_a^#ZY&cfTYl%jA|46PI&Lz_`#jRCD)Dze3x&8^=y~m z99ZqL8K=;Y*0Q>@hZ$rewpr0ks(WBwk@?AgG+iywu)@ZzrcU&QM7Hdxc9{@A{}ClF z{y&GPJRcGHve&?$$^I~k%dAV_!eBVLl?CZ4b)e>_b6bxBr)dP@@O0fi(r5i7$6LNY zi`h;V|Y`Zo9 zEsQugP=v<8nvbjXs8iQEIY8^pBwHb4!T%2BVCgx($uEJ#6{C&v>KnX6wR7ULhApN~ zvsHN?XT$C_XG1<_#U2L{0kV%p&VsIUsjIf^t+w2F=lZO@Nxa3SmVEgUOL9S07L|L! z5)!G~X$l>_-^uBD@8ekr%D&vS8mSAi26o*f?} z3R<|C$V^5D_ENRZkj={NsAy<56J`8V>_Lmm^;s#kr;i$a0yy(Hcb>u`bbw2}XJ_B+ zroZ9c2VObf*W_7)3MaEf`oiufC#Uy1`!yZ`qtl%EAd6_?mBxovH@b$=)VTS+Q}gR< z*iO{kJ1H!+Ve|;(pf38ys30!AW8(q+aw4bd0XG(($xbm)qZ~?;yp#)i5RPTcp_cT} z+O4d-#z`dYXjuor7utn~+nKegL<3LN63tI^eJ5EWKBW8CvF~qksS^0JoSnA|4|@xDqCtiO}=x$#64U(N>d-55w#C3dqey4YRmv%lpuJ=I8dPn_C z$K_VStv#t&r(_whZBg{}e2L#-yFTeB;s0*bXCHDcCDES?y>4588;pU=6Vuh7hHqUCD`* zckG=0nkJ36nmY~0=KHYX5q7vIx>#WLcALS|5{KX<2()nZK2EBjG$$tDi-b#S?JP<> z(0*%t_y`%n__7gxqS|6uV>}=o>J|4K1k6&4y$=Q#;BY{qi)ye)d(%bM~UoNatd=NwXPT3_8+6T6|}IjsgR{xUZ(t+;~%w z(;m+)Kmx^j74(hFImb~)Xp3UtCk=CF=r1w)Rso)wkCXupUmv~0xe#CdDA_1#qx=4a z!ESbJ{1~~>t8>5K@cFazW*;gi&)KRzQNUR_E;+PC5K~#;LPH1H?&^uQF^42Ev1}r@ z8mY`w7QH^we29OQ{BgDv`?x;{D3OvcYvJ6jbDV8>M2Sa1M?z~o_0cA;8L>u4J9M(1 zt;V6h`$uP1Pp#~+o;$|6xM47;|JO_G&?&n#p=!eKb=c!%q>fjDUiV_fW{J1L+I4I4 zkil18x1qV(m}$nqH)eXA1yzmu=}_smDb|C!;u%{@xUcyl?zvbmHgTK z(|B9?@xofgB=V^clPOhLoS|*|OCu-;O zwIH?QD%R&&8NmE>c5!2r4b}mbD5az+{$o^dm+50v7!_E}-?jQh$)fII{MhbAT878` zfgMF5q0XPDiqUY}9O6)1T1rc4*0b!*PLIH3v75so1UQgH9e>=|e&x`k)7m5b3HxGA z#wlV--CK`qyI5(prjxx;3SIr$-0LUQXs;%3w;~1}$RtNMtc?Ho)SX!1KGXY?iss#} zx$0V)+!~Y#`GmZnkJrZ$_No8VUR%yvMyE!lF3Vs23P%4ed_?gwvbTZ5AajO=59Vi; z!Y;^wK8^T030M`fPgsJo0^EGdZdW09YYI*4vba9Z;-`F|5HB)u{%%i@k`em!@$j)? zU`X43u8c|GR<2{5EhIH%*L3(wQ=Pt6}AD8UVT2 z1R;{0uD;#vqabMm5}XfI$~MmUcaH_MO~z0YU5s77v$nY6hY^}>FOsBZJNqecxXwBI z$&bc%34Wg-XgZ`(+5d%7+NDZ40l3F$a9VPE`Sxc*;ULc9{_MmuSVE0wunJW4P18%Y z)ax(uu&>|yxla}*T)pj6r1N1kvse;!>z3P3bP;K%x}?{tMX2=1aY9JMD5;%uIqLE-H6Y4K zpF5!VVj(X67s|6frf49DVwR0ZtxlED0VxGZ#C8%Ava=}>5To)-{H zh&!dtEa+c6Z+D|-kF+sed~b2wMq`Ay0~*_giC~d z3;R8riO2c93gq)D6$e+5PH?w%`kSk{xddzyUt-WuHAr48bhkLVqh$1G6i}>U*wKX= z&G(!*ejzz%#IeYs3itSGJpEfYd^_e7pGhGn~FZW zDtlLbBr(~WT-9TaMZo9yJPa$gcV&~ktI^E2>~cp=*E#xgFS~7B>zmPHR$FK5JQv+W z7s@&hG;X{(77S8)R?l)`o`?eb$wWjP7~tm9EzQTHrQ)|;nbm@QqYnx_i) zxzMiS>4~rCl1<7zP;2BO6o#dtt~4F~py+pHrR3Mf#Kh(RM^26^IMzl!+x%F63IcA! z1_YlPq6mH&OkDqqpB0o*c=9JNdT8Zl_+CenuGEe4ozEn9V)E}x*6z5NS$#3Pc=Y|$ zt?0IhD8T!;s_rNb`Hv@Kw}JJmSt?#VfMC7WWOU$i#|@a$B4xg@=Nc_XP(y1{I@KY=-!kn8QzW$X>RM|FVnAVWZqWJWkg(5~bZf0tF##$`7gupu#_hc5S5d zlZ_S3nRZ#Z3%97dxW`%$bS;r5fo6Y_$T7)FzO(2~v$a)hUm%k@m|exAjWrl92x!+g z@}0;PWEI?Lfd{mJQ;Ep~S>0$;z4@mdZW-2dKI;}Hp3ic&*>dtV^l&psAC=Fiuko4} zFHSm44il%f+f&A3Vh@sHlQZhKFEReOpWv2k?m@Yv6#6Tu5Vr`k_MH8Sn?_3oSpf?E z%^`pwn`&VLl2fqsEG@AYjFDS0}V6@(oR$)E8> zJqGUW+>UmVc(+$eHhcCKB45S@E^XxK$w#ZF3+$Y~Yq(TDn#5% zG$=6Sg=8`{hs>rnX{O;n`3WXdd*Y@$p?b!IpW9gy09p8CL^JzuT7xn2%9vX4Ga92c z@`f$!;x2^W-qRLu78`QoK=guC8d@j|@S`HA!kA5vWtq{YpHmciger8XZV+mJ}3_xrBut|{vEw0UAB5Z_E&s| zXjqy6aN&1{lxf{DEZXwf;9_-?Xw&G0J;mxlIO#!4#7Aspc>q!<=H*RsWqNFll^mm& z!9lWfF1}`EzJb)Yoe~$zAh_f!IidUstRIja$C_Ab4$HP?tYSPLqtLKt@vp32?z6a= z3v;)(kTUzn&QIPUX5#4Gz7->p!}7P)O?I|#k8;ytiHceD-^j46^k>XsAJofN#-_!8 zq}tKWt+uhLvldybGQE>db@h~RK^zB&n!gkRpEhuq^`D@XKRUAJ}vM~akzQ(`T#)F|G~ZpLfB?&K&;1=bCQ&T2=lW|(;ocQ#)T z;yovnmiC~BmH%4641}fXN(MG6U?MZMD%Gk2GC5(IoZB#HHVvUZ<*{{%%Ao)LyYV6 zc9g~<8yihyM~Q&li$0B9&C>LmlWc%|z!fXzN1jvdUB*&-n`D(|LnhO45Xv(bSQK#? zFmhSO3^8NS;V2(;ca)(!zZX*Q=-He(MV15BQ2 zt-AVk`u?0fH-PSqlU@arJay`-4K@PPTnt-Tza^k~K+E)V`()V4AsmE0b}r1#B*ey> zX|~}N(B)kUfldQ<9Ne7%vd6J(#8wc|T+u_Yr~kc4hfn6;LF5|VTbD2~wX*J_cXOL} zEXGy9}~$ zyS*VEd4T_NPEu40a^M3Vf@F4y?a|3!nK>f#k7SyjS-dK{Zk@;%$p3fY3Z zc(~NFjuPZy?h+9c{<3`@M*^?EgIp;!lIP(;c^H!XVTT?ukAI5hY3{24&DbP6xZOb< zBxrtmBn2m-yX)t0DXx3`)uIN;Wus19B+D*;7WN48IclP%?cBdB?Q|~4lb=ZlsJxs0 zck@;razm}F-f{t6k3qN+?k*;{_L^GC#M6D5w%GEI1n>3j1G)XbzMjYqXRaCh2rp%= zAl(?JZx*l{|M3*tY6h~|yoD;+CsjB@N)MKyOFl)ZwBLxPini%!77q-ZecOp`rQiM@ zpDEf~JJ2Cle!&e|2;evt&@}$ky~QtUVtOoPXPiD08+u%f5odV^FG8W8b>6qvNNy%b zCXCJrxqfBF!&#<1gwFi%|CMv*|4?@SAJ-;p2xYnLZc6rj%}tu@Ygxull$j(#8OsP+ zvJ8=B>`NomASokp+q1>kw~U=h%uEqR!{_LJeE*8?<1vr<={k>duIv52&hh|}K5z#W-n=#`5C0n%$dxgs!4e#@fEh8HMJ;S!AX*uGARht)-Rd z@`T;+j_xTQ?aFLkw3?|`Ea0ugUC7w)idshz-q=OI6iol;DR-1*5wHXhtnW=*!wA_D z4D}&{b8g$~J*61A)&Q@jH<$M+c#F6P4-Fd?*ABz0jm~PTojX{FqmX`)W*fajXRNaB zM)tO+NGXL(E1B1{igI9jjFk+G+WF5(3(Y<+ANLU&OsM#gP|#@QyjYOw*7)(1^g^?n zx{fXU0gRaK09o!Q52r5}$ZhV-X3SY8#o4iLwJxhMIjI)4F@XdB0KS}?Gky}+Ep16K z95i12cR#^u&3n&T_XmxdZ$fYWJJ_v`jfuNA4qrIue#1u~D1oEeUWtp-MSQ7S=hN(M zR7J}NDCQ?YzYW_3eOTA?Aebpz=r6kVoCH2G6B7p&jgRk(=ZtL<4yHAdNBsnZ;^0*t zy=>gJ4EiVLSOAd*8=BjjkqjSI!;i3|hOD1szl5-V(;8d)p5k}(JJfbiM27#?eMe0d zTIV|3;K9FK4NU2~!b|3y{*xTGCOhY}+Td1v#i{RE(I0z$eQiOTrXOl%!fCOLkttqNQW~GXnm!wB1hbJ5Ra(S?7kDaDg)Tl%E&w4bQSHbQd~61N9nq}6n&{c^L}i!{U7+X_ zFy$WT?-;{Zb~(CR5)H5G`7!fu*Z&(^Gj8aZ=Q_rBq6N1?Or0tpifO#q?+TNSIIT-A z2-_RYtVU7^G1ybnKei`2U#6;W*g5?EY)Y*HBt0w=rX2e?fL2pnQ~>kj+|stnwMQU4 z()(iYjGa>T4plL@l)!?AN1%_tW`fkxTvZ{&%{Gg&B#cm5>RXz%HtV~6_fUt8sEL0ePGs++l{dKMhoQu zS+&uIO-rex22pCAwuw#TldPXc;aDH3}pa-ljg8-l{eU$ik`S>w79?C+aP^Hw! z1>I31DV{YsW+jj!sDSAVAPi z_TOrp6v0O(QtcF)8+{S-@a}ycBlq6Kv_g5^Aj-Asoxde{iUd6z=&CnYbjw>NxRdp| zrG@u9Za}Y%*hrXtXCxzH(&F|RIiOvwvq^-wIm z8!l?3vwnhyq`RSRBCvftg%0T%JZs~@@5St|WNfQd%|8T1HSkJcx|z@{zZ3&#-ps!A z$IoWhT~##8C9;fO<_ThPS2MuMBp!OJ&-27_1{&}&L~~-w??m7zT^t-Wp9nvwwf-%y zlJ%{J!V2!c9|G^nTUdaFN8rY2<;G30F9EM6VYJuXyIl)|y+@18*m*_Oatj69*cJGm z|MDd{tFAx1cf~sQ3={KtTr0U`6uR+hQotAFJlEsE*~gG*K?c!5(Qyv{udin%zkXBZ zqGiH(o9I{UfdXElrhL*Q@=$>lf6@ECcR=eOI|Q~UHEoE#b+oG8i;ljBvQ^0^y_(g{ z;V?vR5#Fo3$0)$2Dg}}@+}-G=9k-?mug0^>tIg+Qs_neN$qL~g;-bEpd_y>wka?Xc zGhePt@OkO@sbTSr*j;f4I5~!>aW~o4Xsgf%Yth&xY}el8@BCn%9xDd=1pW>g z0FG~kUUiH`S@SjLw>KA(T`Rm8vO^ugke8|!&#~s(lQ#QOfhT4=#n!)76%UOl{x9w|J?&caqoVjCv;VUg@Kh*X zd~vFD4MhBsw+Zu`T8;Fs^@98bVpV3@18f6LM|nab=WyW6DwyoU{{3^0>GK1!;~WZ7 zh!9XDASyw_h556Z^t*oOzof?21MBsx*3D#E5uOFBRLc*ulKmdXX%ce5D>`^;e4uiC zp~CYWNKJZ@T;1UEuySL6E*NBZMC&53hSiq7@==I8?wahpY zg96PkiAy1xP8RTch~aD}2^Nx(sb9!6lj9+#jEmr>JR#}4w6l+5;+BfJ7Ez&>EBr$k zD2zTs?QhbTj%@kQFs(5{eD9WcKCqZt9#+tF4`_s9s$;H&D^J`>Un#_q)b9M3HGrm# zs2R8VAlIVrIi$cG|8;C7C)=rEdUAAF0oQ*Ck@!=OEsHIQx97j0#|Ie@$y6ioY+Ip> zU~>Fh@aQJ|-j^~3jhAzyXeU)Z7X*{*SGw0v>QpA;n6$KfRe&N5UWAf+L$c0AbXDKJ zi(g&B;elYIWGZU|b>UB1y8*|tJ(Z-WV4VfoSpHniR&swRVkM1~F#vjSzz!_qZ_)C6 z0&;E+C!9cUq+=G=h-H&ZL>8(L6r)6=@k0@QURU!ihOHF7-j>H zCmfv+4@I6??W4w-5{XX+mtC{}JH=@rsEmgv#=G88ah^Zb6Du5;}i7p@W{|jlzHfg%wsTb1}qYH4=w%V^Qe5%cI76~@Ug)wA8)flQv(85E|TQYVb}in=6DQU z+kb-$AGh%3(y#qU7|XT|z8rR4ApQaTw1U>he-!Xf_a+6&+J|m z4`n@(eiS2JP4lvijSN|EFE2;9P9A(+tZ&&qXe5LN&HRKT^O@PO-6c%eis1t9sL#Sbr zw7lUAo3!!2?8MyAml568UUo*196?AnpCJ0l?^5_ypAKSk$yHYpp3mGRo~ zjd~xOy1RVV=oMF!+yye&>aZg%e0WAXgZ0~g5+mNWJx2#9T zJi0q{=CKVD^}Ts8_vs*73C_P=NDte#9HQh)Eo*NqJBk$CF^j|JUxn-hCFS^E2Y zlr?+QOH2z7?Uq*n)iG_uOQQOW2U8M#ypQ~aB>9sDr#cM5-C;SIIK{=p8T9qJY`;rV zo)+Z1H}SQ$u+bJZYhCO}>_70~-iZCC7=bqW`Z_-LylG?Kt{Z z$J)S))f@D{$_@?k34~c&Dz`%Q&G++I8ZS`Oy7vZ}!f5N0tXdb@vdIIIW`I$v3uBhJ zsB5qTYFkSPlGg~?LkA4)&V$*MDBjG?jA&sqXS(8$MwxDUWl5+Iyz?l*myOQRoBhxGgf6^8|AlVl6+Y34%CXeivL6jzvW)h^tgO6>*OsD znm3|yz+48NTE#d*c=dB+&~;81(HTpirU?F^%zX9zgtYj$rw4Al!$z+z>rQ;S{MS&cb(}nx*Ugi)Xe{Z$;H~<{+*UCDk87Ds-Xd&P@yD2t}uLlw{t z^4QEO%)t(#l6DJ&h`$mj{JU~O>b#DwQW;mKlwF$x6NMbikUhT{qCRtgXPh)`-0ZwN zCgmCT-UqslMI#K;)EvNO^HR#h+OP>@MyCV|4jxZ1{;Hf47+@) u6lP)|W-E248&33chZ2#a^ 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 _$~&>N^MeF>a7+jBe-n|kYz^M1ceF1(GCq_} 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 N002ovPDHLkV1jEdB8UJ0 literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-xxxhdpi/ic_launcher.png b/android/gold/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..61c0d3398f83a28e608daf87cd084840c7a8af9a GIT binary patch literal 14644 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 literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/gold/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..c11c07b0952b3ac646c5fc607e9f0f01875b142f GIT binary patch literal 32536 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 WEX!4_00D!6Aup{WRViWe<^KS&FFnBk literal 0 HcmV?d00001 diff --git a/android/gold/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/gold/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..45b824286890d8df7d41552657f0fc512add8cc5 GIT binary patch literal 23603 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 + + #53482D + \ No newline at end of file From f55782558cb7a273c4e0dc9a8cc6959e6bc1856b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Mar 2023 13:59:07 +0100 Subject: [PATCH 209/424] Debugger: Copy Address will now copy addresses for the whole selection --- Windows/Debugger/CtrlDisAsmView.cpp | 26 ++++++++++---------------- Windows/Debugger/CtrlDisAsmView.h | 8 +++++++- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index 3f54114fc5..8b28551ac7 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -906,10 +906,8 @@ void CtrlDisAsmView::onMouseDown(WPARAM wParam, LPARAM lParam, int button) redraw(); } -void CtrlDisAsmView::copyInstructions(u32 startAddr, u32 endAddr, bool withDisasm) -{ - if (withDisasm == false) - { +void CtrlDisAsmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode) { + if (mode != CopyInstructionsMode::DISASM) { int instructionSize = debugger->getInstructionSize(0); int count = (endAddr - startAddr) / instructionSize; int space = count * 32; @@ -918,7 +916,8 @@ void CtrlDisAsmView::copyInstructions(u32 startAddr, u32 endAddr, bool withDisas char *p = temp, *end = temp + space; for (u32 pos = startAddr; pos < endAddr && p < end; pos += instructionSize) { - p += snprintf(p, end - p, "%08X", debugger->readMemory(pos)); + u32 data = mode == CopyInstructionsMode::OPCODES ? debugger->readMemory(pos) : pos; + p += snprintf(p, end - p, "%08X", data); // Don't leave a trailing newline. if (pos + instructionSize < endAddr && p < end) @@ -926,8 +925,7 @@ void CtrlDisAsmView::copyInstructions(u32 startAddr, u32 endAddr, bool withDisas } W32Util::CopyTextToClipboard(wnd, temp); delete [] temp; - } else - { + } else { std::string disassembly = disassembleRange(startAddr,endAddr-startAddr); W32Util::CopyTextToClipboard(wnd, disassembly.c_str()); } @@ -956,14 +954,13 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) assembleOpcode(curAddress,""); break; case ID_DISASM_COPYINSTRUCTIONDISASM: - copyInstructions(selectRangeStart, selectRangeEnd, true); + CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::DISASM); break; case ID_DISASM_COPYADDRESS: - { - char temp[16]; - sprintf(temp,"%08X",curAddress); - W32Util::CopyTextToClipboard(wnd, temp); - } + CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::ADDRESSES); + break; + case ID_DISASM_COPYINSTRUCTIONHEX: + CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::OPCODES); break; case ID_DISASM_SETPCTOHERE: debugger->setPC(curAddress); @@ -972,9 +969,6 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) case ID_DISASM_FOLLOWBRANCH: followBranch(); break; - case ID_DISASM_COPYINSTRUCTIONHEX: - copyInstructions(selectRangeStart, selectRangeEnd, false); - break; case ID_DISASM_RUNTOHERE: { SendMessage(GetParent(wnd), WM_COMMAND, ID_DEBUG_RUNTOLINE, 0); diff --git a/Windows/Debugger/CtrlDisAsmView.h b/Windows/Debugger/CtrlDisAsmView.h index 2930e41544..ebddca20de 100644 --- a/Windows/Debugger/CtrlDisAsmView.h +++ b/Windows/Debugger/CtrlDisAsmView.h @@ -64,6 +64,12 @@ class CtrlDisAsmView bool dontRedraw; bool keyTaken; + enum class CopyInstructionsMode { + OPCODES, + DISASM, + ADDRESSES, + }; + void assembleOpcode(u32 address, std::string defaultText); std::string disassembleRange(u32 start, u32 size); void disassembleToFile(); @@ -73,7 +79,7 @@ class CtrlDisAsmView bool getDisasmAddressText(u32 address, char* dest, bool abbreviateLabels, bool showData); void updateStatusBarText(); void drawBranchLine(HDC hdc, std::map &addressPositions, const BranchLine &line); - void copyInstructions(u32 startAddr, u32 endAddr, bool withDisasm); + void CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode); std::set getSelectedLineArguments(); void drawArguments(HDC hdc, const DisassemblyLineInfo &line, int x, int y, int textColor, const std::set ¤tArguments); From 82097b4a3b8423638f3e42d309a3f4e69e03343e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Mar 2023 14:28:51 +0100 Subject: [PATCH 210/424] Implement NopInstruction feature in debugger See #16975 --- Windows/Debugger/CtrlDisAsmView.cpp | 21 +++++++++++++++++---- Windows/Debugger/CtrlDisAsmView.h | 1 + Windows/ppsspp.rc | 1 + Windows/resource.h | 1 + 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Windows/Debugger/CtrlDisAsmView.cpp b/Windows/Debugger/CtrlDisAsmView.cpp index 8b28551ac7..7b46ae2402 100644 --- a/Windows/Debugger/CtrlDisAsmView.cpp +++ b/Windows/Debugger/CtrlDisAsmView.cpp @@ -206,7 +206,7 @@ CtrlDisAsmView::~CtrlDisAsmView() manager.clear(); } -COLORREF scaleColor(COLORREF color, float factor) +static COLORREF scaleColor(COLORREF color, float factor) { unsigned char r = color & 0xFF; unsigned char g = (color >> 8) & 0xFF; @@ -315,7 +315,7 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) // try to assemble the input if it failed } - result = MIPSAsm::MipsAssembleOpcode(op.c_str(),debugger,address); + result = MIPSAsm::MipsAssembleOpcode(op.c_str(), debugger, address); Reporting::NotifyDebugger(); if (result == true) { @@ -331,7 +331,6 @@ void CtrlDisAsmView::assembleOpcode(u32 address, std::string defaultText) } } - void CtrlDisAsmView::drawBranchLine(HDC hdc, std::map &addressPositions, const BranchLine &line) { HPEN pen; u32 windowEnd = manager.getNthNextAddress(windowStart,visibleRows); @@ -725,7 +724,7 @@ void CtrlDisAsmView::onKeyDown(WPARAM wParam, LPARAM lParam) break; case 'c': case VK_INSERT: - copyInstructions(selectRangeStart, selectRangeEnd, true); + CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::DISASM); break; case 'x': disassembleToFile(); @@ -931,6 +930,16 @@ void CtrlDisAsmView::CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructio } } +void CtrlDisAsmView::NopInstructions(u32 selectRangeStart, u32 selectRangeEnd) { + for (u32 addr = selectRangeStart; addr < selectRangeEnd; addr += 4) { + Memory::Write_U32(0, addr); + } + + if (currentMIPS) { + currentMIPS->InvalidateICache(selectRangeStart, selectRangeEnd - selectRangeStart); + } +} + void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) { if (button == 1) @@ -962,6 +971,10 @@ void CtrlDisAsmView::onMouseUp(WPARAM wParam, LPARAM lParam, int button) case ID_DISASM_COPYINSTRUCTIONHEX: CopyInstructions(selectRangeStart, selectRangeEnd, CopyInstructionsMode::OPCODES); break; + case ID_DISASM_NOPINSTRUCTION: + NopInstructions(selectRangeStart, selectRangeEnd); + redraw(); + break; case ID_DISASM_SETPCTOHERE: debugger->setPC(curAddress); redraw(); diff --git a/Windows/Debugger/CtrlDisAsmView.h b/Windows/Debugger/CtrlDisAsmView.h index ebddca20de..c67306a76c 100644 --- a/Windows/Debugger/CtrlDisAsmView.h +++ b/Windows/Debugger/CtrlDisAsmView.h @@ -80,6 +80,7 @@ class CtrlDisAsmView void updateStatusBarText(); void drawBranchLine(HDC hdc, std::map &addressPositions, const BranchLine &line); void CopyInstructions(u32 startAddr, u32 endAddr, CopyInstructionsMode mode); + void NopInstructions(u32 startAddr, u32 endAddr); std::set getSelectedLineArguments(); void drawArguments(HDC hdc, const DisassemblyLineInfo &line, int x, int y, int textColor, const std::set ¤tArguments); diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index d5109b9cd0..d2a2c921d9 100644 --- a/Windows/ppsspp.rc +++ b/Windows/ppsspp.rc @@ -721,6 +721,7 @@ BEGIN MENUITEM "Rename Function...", ID_DISASM_RENAMEFUNCTION MENUITEM "Remove Function", ID_DISASM_REMOVEFUNCTION MENUITEM "Add Function Here", ID_DISASM_ADDFUNCTION + MENUITEM "NOP instruction(s)", ID_DISASM_NOPINSTRUCTION END POPUP "reglist" BEGIN diff --git a/Windows/resource.h b/Windows/resource.h index fc421b7e60..ffe653d58a 100644 --- a/Windows/resource.h +++ b/Windows/resource.h @@ -334,6 +334,7 @@ #define ID_GEDBG_COPY_IMAGE_ALPHA 40225 #define ID_GEDBG_TRACK_PIXEL 40226 #define ID_GEDBG_TRACK_PIXEL_STOP 40227 +#define ID_DISASM_NOPINSTRUCTION 40228 // Dummy option to let the buffered rendering hotkey cycle through all the options. From eab06caba9cf10e249cac06be1f833560aab6c67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Moraz=C3=A1n?= <35014183+GABO1423@users.noreply.github.com> Date: Thu, 2 Mar 2023 22:44:07 -0400 Subject: [PATCH 211/424] (UWP) More Cleanups --- UWP/UWP.vcxproj | 128 ++++++------------------------------------------ 1 file changed, 15 insertions(+), 113 deletions(-) diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 561080d0eb..0d06192ecb 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -64,121 +64,23 @@ 10.0 - + Application true - - Application - true - - - Application - true - - - Application - true - - - Application - false - true - true - - - Application - false - true - true - - + Application false false true - - Application - false - false - true - - - Application - false - false - true - - - Application - false - false - true - - - Application - false - true - true - - - Application - false - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -215,7 +117,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -240,7 +142,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -265,7 +167,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -290,7 +192,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -315,7 +217,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -340,7 +242,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -365,7 +267,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -390,7 +292,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -415,7 +317,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -440,7 +342,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -465,7 +367,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + @@ -490,7 +392,7 @@ robocopy "..\Assets\." "Content\." /xd "mime" /E /R:0 /W:0 ../Windows/git-version-gen.cmd EXIT 0 - + From 63f370916b883708abe83a6cdf7e45bc1319b4b7 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 3 Mar 2023 03:37:58 +0000 Subject: [PATCH 212/424] riscv: Enable Zba/Zbb by soc compatible. Instead of u74, because apparently some older u74 don't support it. --- Common/RiscVCPUDetect.cpp | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/Common/RiscVCPUDetect.cpp b/Common/RiscVCPUDetect.cpp index f05203488a..b4f8b608d8 100644 --- a/Common/RiscVCPUDetect.cpp +++ b/Common/RiscVCPUDetect.cpp @@ -40,6 +40,7 @@ const char procfile[] = "/proc/cpuinfo"; // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu const char syscpupresentfile[] = "/sys/devices/system/cpu/present"; +const char firmwarefile[] = "/sys/firmware/devicetree/base/compatible"; class RiscVCPUInfoParser { public: @@ -49,9 +50,12 @@ public: int TotalLogicalCount(); std::string ISAString(); + bool FirmwareMatchesCompatible(const std::string &str); private: std::vector> cores_; + std::vector firmware_; + bool firmwareLoaded_ = false; }; RiscVCPUInfoParser::RiscVCPUInfoParser() { @@ -126,6 +130,25 @@ std::string RiscVCPUInfoParser::ISAString() { return "Unknown"; } + +bool RiscVCPUInfoParser::FirmwareMatchesCompatible(const std::string &str) { + if (!firmwareLoaded_) { + firmwareLoaded_ = true; + + std::string data; + if (!File::ReadFileToString(true, Path(firmwarefile), data)) + return false; + + SplitString(data, '\0', firmware_); + } + + for (auto compatible : firmware_) { + if (compatible == str) + return true; + } + + return false; +} #endif static bool ExtensionSupported(unsigned long v, char c) { @@ -170,6 +193,12 @@ void CPUInfo::Detect() logical_cpu_count = 1; truncate_cpy(cpu_string, parser.ISAString().c_str()); + + // A number of CPUs support a limited set of B. It's not all U74, so we use SOC for now... + if (parser.FirmwareMatchesCompatible("starfive,jh7110")) { + RiscV_Zba = true; + RiscV_Zbb = true; + } #endif unsigned long hwcap = getauxval(AT_HWCAP); @@ -183,12 +212,6 @@ void CPUInfo::Detect() // Let's assume for now... RiscV_Zicsr = RiscV_M && RiscV_A && RiscV_F && RiscV_D; - // A number of CPUs support a limited set of B. - if (!strcmp(brand_string, "sifive,u74-mc")) { - RiscV_Zba = true; - RiscV_Zbb = true; - } - #ifdef USE_CPU_FEATURES cpu_features::RiscvInfo info = cpu_features::GetRiscvInfo(); CPU64bit = info.features.RV64I; From 2d5086112bf28ecc88b06f6ecb34cc2b1d065e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gabriel=20Moraz=C3=A1n?= <35014183+GABO1423@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:59:10 -0400 Subject: [PATCH 213/424] (UWP) Remove All Redundant Conditionals --- UWP/Armips_UWP/Armips_UWP.vcxproj | 98 +- UWP/CommonUWP/CommonUWP.vcxproj | 122 +- UWP/CoreUWP/CoreUWP.vcxproj | 4626 +---------------- UWP/GPU_UWP/GPU_UWP.vcxproj | 135 +- UWP/PPSSPP_UWP.sln | 10 +- UWP/PPSSPP_UWP_TemporaryKey.pfx | Bin 2520 -> 2520 bytes UWP/Package.appxmanifest | 1 + UWP/PackageGold.appxmanifest | 1 + UWP/PackageNormal.appxmanifest | 1 + UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj | 135 +- UWP/UI_UWP/UI_UWP.vcxproj | 135 +- UWP/UWP.vcxproj | 3 +- UWP/cpu_features_UWP/cpu_features_UWP.vcxproj | 135 +- UWP/glslang_UWP/glslang_UWP.vcxproj | 134 +- UWP/libkirk_UWP/libkirk_UWP.vcxproj | 122 +- UWP/libzstd_UWP/libzstd_UWP.vcxproj | 96 +- UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj | 135 +- UWP/zlib_UWP/zlib_UWP.vcxproj | 122 +- 18 files changed, 319 insertions(+), 5692 deletions(-) diff --git a/UWP/Armips_UWP/Armips_UWP.vcxproj b/UWP/Armips_UWP/Armips_UWP.vcxproj index f10d16ddfa..330b730cd1 100644 --- a/UWP/Armips_UWP/Armips_UWP.vcxproj +++ b/UWP/Armips_UWP/Armips_UWP.vcxproj @@ -47,38 +47,11 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false true @@ -88,61 +61,11 @@ - - - - - - - - - - - - - - - - - - - - - - + - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; - - + false $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips;$(ProjectDir)..\..\ext\armips\ext\filesystem\include;$(ProjectDir)..\..\ext\armips\ext\tinyformat; @@ -373,17 +296,8 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - + Create + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 4a10010455..a0747fc3e9 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 886dc9f29e..65b384657b 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -204,7 +90,7 @@ false false pch.h - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -220,7 +106,7 @@ false false pch.h - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -236,7 +122,7 @@ false false pch.h - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -252,7 +138,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -268,7 +154,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -284,7 +170,8 @@ false false pch.h - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -300,7 +187,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -316,7 +203,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -332,7 +219,7 @@ false false pch.h - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;ARMIPS_USE_STD_FILESYSTEM;%(ClCompile.PreprocessorDefinitions) stdcpp17 @@ -348,7 +235,7 @@ false false pch.h - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -364,7 +251,7 @@ false false pch.h - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -380,7 +267,7 @@ false false pch.h - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) USE_FFMPEG;WITH_UPNP;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;ARMIPS_USE_STD_FILESYSTEM;%(PreprocessorDefinitions) stdcpp17 @@ -642,20 +529,7 @@ - - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - + @@ -836,20 +710,7 @@ - - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x86/include;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/ARM64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - ../../ffmpeg/Windows10/x64/include;../../ffmpeg/WindowsInclude;../..;../../ext/native;../../ext/snappy;../../ext/libpng17;../../Common;../../ext/zlib;../../ext/zstd/lib;../../ext;../../ext/armips/;../../ext/armips/ext/filesystem/include/;../../ext/armips/ext/tinyformat/;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) - + @@ -896,4467 +757,492 @@ - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - - - - - - - - - - - - - - - - - - - - - - - - + NotUsing + - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing - NotUsing + NotUsing - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 03ce6c90bb..0448b3e1bd 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -503,18 +389,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/PPSSPP_UWP.sln b/UWP/PPSSPP_UWP.sln index 8fe54683af..e54559c70a 100644 --- a/UWP/PPSSPP_UWP.sln +++ b/UWP/PPSSPP_UWP.sln @@ -2,6 +2,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.28803.202 MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPP_UWP", "UWP.vcxproj", "{01D7D581-09A3-4A26-94BD-A7C529B29329}" + ProjectSection(ProjectDependencies) = postProject + {D31FD4F0-53EB-477C-9DC7-149796F628E2} = {D31FD4F0-53EB-477C-9DC7-149796F628E2} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CommonUWP", "CommonUWP\CommonUWP.vcxproj", "{ACB316CA-3ECB-48E5-BE0A-91E72D5B0F12}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CoreUWP", "CoreUWP\CoreUWP.vcxproj", "{40B76674-02DE-40EF-889B-FAD1489685E7}" @@ -17,11 +22,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libkirk_UWP", "libkirk_UWP\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib_UWP", "zlib_UWP\zlib_UWP.vcxproj", "{DDF90203-0AAE-4F38-B589-2E9637658CE6}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PPSSPP_UWP", "UWP.vcxproj", "{01D7D581-09A3-4A26-94BD-A7C529B29329}" - ProjectSection(ProjectDependencies) = postProject - {D31FD4F0-53EB-477C-9DC7-149796F628E2} = {D31FD4F0-53EB-477C-9DC7-149796F628E2} - EndProjectSection -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "glslang_UWP", "glslang_UWP\glslang_UWP.vcxproj", "{D326891E-ECE4-4B94-B5E7-8AA0A8E8ECBC}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SPIRVCross_UWP", "SPIRVCross_UWP\SPIRVCross_UWP.vcxproj", "{2B2D16BD-1D37-46AF-A3F8-552900951B26}" diff --git a/UWP/PPSSPP_UWP_TemporaryKey.pfx b/UWP/PPSSPP_UWP_TemporaryKey.pfx index 0d737acfe6d5fa2f9da43235e39ff9b2310ff61e..bbae735015bd5cf27a20835222f98c94826e4452 100644 GIT binary patch delta 2265 zcmV;~2qyQ~6W9}wXn!*2eVl2hdRYPj2haq91lTJ zY*yIzSoa|k{C{W0oF?L2!Ea5VaVG4*)?wAgt0eKXX$Y6dr8*=8NcR)aE}TU645JfHjSJUtjB?Mt&NF5q@YOJlcMt z-C!HTtd{9-V;;7&A)oTZtvx0T;yq0D!-Wkr>vv3-)_>yMMMj7FOAF(Ik-}lQ%7rXD zKAY;!e*q2da?0#ghoqtV7`}~ezNnAxl9Z+$tbMx?5ZkD+NRz4rn+%rOo#Cyz{%p9O zwOiogK{umq$Fv7GYtZo#1kywy(wND02#NB*d2b65Bm{xA8YYWhrL2}+-E)qw)zjV1 zKYopKe1DLN=!F5-D9H?y+R4Pmfwzy}l(F!g{!l>X{mYV|kaFWY=uZmNO@7urRiJX$oid8e39mgQ9-NniToK=6z^E(+7wrednV=nEFfN4DMySB7e$j{z&ly$`a}xK!a%TOHEiX_6YEX zzOLOO!ujbzP-*Bpqs3O(M3y}0Qad2pYqon?_?1Y6uXvbxaiJtl#js`5UT{B$6^c;6Fl>{g^GFF8>GNQD#`PP0XV@U=tK(P-+05`RDVf_;VkF{qaP#*YHFAFT;me8#BgE<+6y4aE9cfQwbnTaUNkf_(?Jir?&-n8Bx09$A5hN zgKIak&8v>3PZ@+Axym%~>9nVCe%F_LUu<^Q(v6!f-;SCo^3Y!~{H$a^HUi z6I*ii3$gy_j3$LvqZKknes{{~n@y>I`6~BB8v&{OWPeLVH9U!QReJH*u+K^0WJNKk z=Go-1B{vdsYc=h#QV_L*+PO{*4xL%>?#ixgThfz2=z1_>&LNQUf|x*;;n9W1Oh#3f9m7X-SsrQJ43^S^@?Rb7TlNfXs(Og%u0ah z^=t!PUdwA;-Xepf7NG~R_;vW5j(%B9c%a1cdk+*j)T^z?B;qRu(xWba1P2F_P?2^P zEcmOnymci8Yr0@sKOasBUn4N}J=mZ<1ycOCbDX zhY@eh+WowsTj>0$DTnNrol~JKlL(F2Pi#oiQgs$zVj&B3rQCMUmOpP~qX;ow?Q1C3l z(|ZEEhvPOww7AW9ypsp*k-MR0IX5Ar>YS}8F^gWgWq=v+K72h|8aLK1LMgd&=uZaf zH`RkT6ARz$Q3fV|1JHAA>^-V(b~y`^g3L&IqKghT3w1A%{L^jR5c>_ zwwGQ}Yxqo43V>a`vt9qJE%3&3Y87k4bpc#onq6+^qdiy^&(xg%CDY@}KiQ`X{I=Ss@H?M@F%P?>=l=!wBges_u4L zxNqG9=v|Jnx^(g{8(c{zuTdK;0#BULDqt`>Fdr}n1_dh)0|FWZ6eNDWf|Y^ufaduZ nvPfalRcgNd`verVW@vUWxNqod>?Y#kfH)<^4eSO40s;rnZOBUS delta 2265 zcmV;~2qyQ~6W9}wXn%KkgX5rn(VYSU2haq91lW}gE9wXuU>LW7!&{GSU3?$`N^5GU zsn57nuN83N#A)-ei1N}lN_CUQgmCB~B1P+#(&NZ^} zZ}T+FB*1BlpHSDa)c_C;Eor-0R3JbC>txlw$RNB1G%5+VPO#gzYNbx3l zZ`JCobaz4F3ptlPk>@z7TeL36D2{LBhx>AfZ14bHtvU(ov;rTlY%7;#B|oc)|phwLEQlTZ48dFAyh)svi)@tyx`!iWJHmx#{P!70D;fFUq-R)~bRR^==1gjudIyLIcnVPh)MF0@03s4aq zy)uTm;d{wP1jwnyIwS_#)v6%pt2`zE)VIBPe{xS5STSu*dCf;ixtLKEfSGer4f1Wj z<-{3lnSY%9UH3xr@GIbbuHJV|3BL&@^on-u`cyAyjhVWr(@OVhq{W`i^qqk$A`nJN z)JV(7dNpcqwkC)b?mv+xBvQOKxFvbHVY+)yKTWB-0hfBgJ~W< z@ylZ)=ocRoiQ)aR4riO+=eUsa#mxJn*nhnQSy?eEvP5$Lv9t%ZI`{Nt^CDNDr-!hp z+JB0{ON$#f^G=(yhn3;1kPFnw1h1smF1h0A!`rB`xJHs9`7BUuuf5O;ACa?Zc5vnO zSj=dU@SVo<1{-pPp6tv28pcur*Dxq7WmmbAGKQ5wEF!$o7DJMj$AxSzTZ~m9n!ZwH z1B4EEw#;upUy8rxjLXmnofvUv%HuUUihtEG{;TfE%~=|VF7wO!iFH)$lgOW2Lr}5O ze$sAfl^WjU9;hh2H%H;Qb&V*l@~G(UJ|rlvQ2(qEdqG&LU?7jzQVdY3moIv9d<>bL zDwQi8cN{QUMJ4jR}8ZHdhF49*Ah*=f&M>cdqmp3H3gv=MBOyq=BltrK=%19-W7q8+uxr4CiH!&BqPAm z1_gi+xzNT5ZXleTwNHoM>M9stD?+~nV6{|e^}r8Cy8_LBB9ci0I%UsFH=dn`9tTYE z|575BBw~ZhrR3&`8E>f7njc>VI)Ct&*dg3Lv>I{eU0EGZ!wRp-W|3l3?9Tcj)%_#( z|Aex4n1PoSo*Ct>MtCq|(RA1({stj(iC-deV=&LNQUQF#u)&VgM}wWdJe&HUKaHEdVqCV*oM$HUKREVgO?RH~=>QEdXNxGXOFG zVE|+RV*oV(GXP@%H~?jnzXhCs1|7&tflqq~0s;rnfPw=s?V*b{{{1qTulk2o^ufyF@xZ|K_W0|Bx^6g~Sv zp#QORV+^5fNztV!;?|rl!(R2t4kD~&<+Ym1SXg(<*57L*8cwvOqkb7!or$NPv~93G3SG%Xu+jS#U4V<^Dg6a`&!&;%O%T4kPZ z#}svfCrnM~_shO1P8-F4ihd(K#3|M{q}v9f0lwUY=~LiAKu$Xfr^)8+EHjmGp-cNy*F+MrFFJFdU@k95YQT_dhFzw*&Bh4ZUJ~*JOcFi7}#1 zUH_YuuH~_zhqzC2>|b+%WN}K&!Ml*34R;&hK)QD;MgYSywzyQLZ~xJL2~0m&$ue|> zO1c=3oR#)MGrqgHcjUT0q|=4Xe~sS55(4T7MDy}@mG3$h8Mp-o4GdjPng{`*nc2K* zvhWs8k|;(vWDi__QP%K2WZr2P`|Ho%T2oM> z@P{BXR;^@Syph{QATPxkmTWRx@OmNvBZCGc)4hPLRibox!I@E{)zTLee}{2l(t`SS z#l!jI`Rnqyx#8gj}b%hkQ8~=Ow(d~xzrv!5=#Jo|8wy#OeeN4gVQ!*bCSkI zYZlY$hL_h34*L_ci2xJpEl_%W4CHKvSAD58M#`3lLgfi8p@bF^ELIWAABEuhtlErtGwlQwUE=3XZ%1 z$U-`uiF#+^BfsJ4pkKN~$A6;4`}FP^v>`A%Fdr}n1_dh)0|FWZ6sT>S2@~xPlb~0s;rnk(Vp! diff --git a/UWP/Package.appxmanifest b/UWP/Package.appxmanifest index b1e9b4db73..967c48e26c 100644 --- a/UWP/Package.appxmanifest +++ b/UWP/Package.appxmanifest @@ -31,5 +31,6 @@ + diff --git a/UWP/PackageGold.appxmanifest b/UWP/PackageGold.appxmanifest index 216c2dfb5e..384fa2d9d7 100644 --- a/UWP/PackageGold.appxmanifest +++ b/UWP/PackageGold.appxmanifest @@ -35,5 +35,6 @@ + diff --git a/UWP/PackageNormal.appxmanifest b/UWP/PackageNormal.appxmanifest index c564357242..cc6f628a24 100644 --- a/UWP/PackageNormal.appxmanifest +++ b/UWP/PackageNormal.appxmanifest @@ -31,5 +31,6 @@ + diff --git a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj index f57655dc95..4b0eeb4236 100644 --- a/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj +++ b/UWP/SPIRVCross_UWP/SPIRVCross_UWP.vcxproj @@ -63,58 +63,11 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - + StaticLibrary false true @@ -124,78 +77,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -392,18 +278,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/UI_UWP/UI_UWP.vcxproj b/UWP/UI_UWP/UI_UWP.vcxproj index ad66ad74dc..9e892566ca 100644 --- a/UWP/UI_UWP/UI_UWP.vcxproj +++ b/UWP/UI_UWP/UI_UWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -446,18 +332,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/UWP.vcxproj b/UWP/UWP.vcxproj index 0d06192ecb..7a89e3c9f4 100644 --- a/UWP/UWP.vcxproj +++ b/UWP/UWP.vcxproj @@ -89,11 +89,12 @@ True False Never - 169879A9D7A20F22B0DD435921035E3E6D5996A4 + C8DEB388B9BC89D1DC61324E4E9D9FE6A796B7AA False 1 OnApplicationRun True + PPSSPP_UWP_TemporaryKey.pfx diff --git a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj index 722e0e8b16..6dcea065c8 100644 --- a/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj +++ b/UWP/cpu_features_UWP/cpu_features_UWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -422,18 +308,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/glslang_UWP/glslang_UWP.vcxproj b/UWP/glslang_UWP/glslang_UWP.vcxproj index 656b796b7d..1be05c7670 100644 --- a/UWP/glslang_UWP/glslang_UWP.vcxproj +++ b/UWP/glslang_UWP/glslang_UWP.vcxproj @@ -63,139 +63,26 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -491,18 +378,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/libkirk_UWP/libkirk_UWP.vcxproj b/UWP/libkirk_UWP/libkirk_UWP.vcxproj index 5664ad0d4a..045f0b48f2 100644 --- a/UWP/libkirk_UWP/libkirk_UWP.vcxproj +++ b/UWP/libkirk_UWP/libkirk_UWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false diff --git a/UWP/libzstd_UWP/libzstd_UWP.vcxproj b/UWP/libzstd_UWP/libzstd_UWP.vcxproj index 3f063dfb71..09cbd21e9b 100644 --- a/UWP/libzstd_UWP/libzstd_UWP.vcxproj +++ b/UWP/libzstd_UWP/libzstd_UWP.vcxproj @@ -47,38 +47,11 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false true @@ -88,61 +61,11 @@ - - - - - - - - - - - - - - - - - - - - - - + - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - - false - $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; - - + false $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)..\..\ext\armips; @@ -299,16 +222,7 @@ - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj b/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj index e89bebd5f5..cc9ce92352 100644 --- a/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj +++ b/UWP/miniupnpc_UWP/miniupnpc_UWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false @@ -469,18 +355,7 @@ cd ..\..\..\..\UWP\miniupnpc_UWP - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create - Create + Create diff --git a/UWP/zlib_UWP/zlib_UWP.vcxproj b/UWP/zlib_UWP/zlib_UWP.vcxproj index ea314b2c44..f60d2aa01a 100644 --- a/UWP/zlib_UWP/zlib_UWP.vcxproj +++ b/UWP/zlib_UWP/zlib_UWP.vcxproj @@ -63,139 +63,25 @@ 10.0 - + StaticLibrary true - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - true - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - + StaticLibrary false false - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - false - - - StaticLibrary - false - true - - - StaticLibrary - false - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - - false - - + false From d47e46dbb4cfd97748d312c9bb47ed8f5b137fcc Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 4 Mar 2023 21:57:04 -0800 Subject: [PATCH 214/424] iOS: Allow jit to be re-enabled. --- Core/Config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index 8b4cbe05ab..99575c3e33 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1558,8 +1558,8 @@ bool Config::Save(const char *saveReason) { void Config::PostLoadCleanup(bool gameSpecific) { // Override ppsspp.ini JIT value to prevent crashing - if (DefaultCpuCore() != (int)CPUCore::JIT && g_Config.iCpuCore == (int)CPUCore::JIT) { - jitForcedOff = true; + jitForcedOff = DefaultCpuCore() != (int)CPUCore::JIT && g_Config.iCpuCore == (int)CPUCore::JIT; + if (jitForcedOff) { g_Config.iCpuCore = (int)CPUCore::IR_JIT; } From cc9c01b1d06f6de86ef90ba2cdf4325e0499fe0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 4 Mar 2023 09:54:27 +0100 Subject: [PATCH 215/424] Vulkan texture uploads: Take optimalBufferCopyRowPitchAlignment into account Might marginally increase texture upload performance on some GPUs, but mainly just the right thing to do. For example, on Intel, this is 64. --- Common/GPU/Vulkan/VulkanContext.h | 3 ++- Common/Math/math_util.h | 4 ++++ GPU/Vulkan/TextureCacheVulkan.cpp | 20 +++++++++++--------- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index 4cc097b758..21dbaad08e 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -222,7 +222,8 @@ public: // Simple workaround for the casting warning. template void SetDebugName(T handle, VkObjectType type, const char *name) { - if (extensionsLookup_.EXT_debug_utils) { + if (extensionsLookup_.EXT_debug_utils && handle != VK_NULL_HANDLE) { + _dbg_assert_(handle != VK_NULL_HANDLE); SetDebugNameImpl((uint64_t)handle, type, name); } } diff --git a/Common/Math/math_util.h b/Common/Math/math_util.h index fd47662b54..b76e1f3937 100644 --- a/Common/Math/math_util.h +++ b/Common/Math/math_util.h @@ -40,6 +40,10 @@ inline uint32_t RoundUpToPowerOf2(uint32_t v) { return v; } +inline uint32_t RoundUpToPowerOf2(uint32_t v, uint32_t power) { + return (v + power - 1) & ~(power - 1); +} + inline uint32_t log2i(uint32_t val) { unsigned int ret = -1; while (val != 0) { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 1444c6abca..108356cadc 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -541,8 +541,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { plan.GetMipSize(i, &mipWidth, &mipHeight); int bpp = VkFormatBytesPerPixel(actualFmt); - int stride = (mipWidth * bpp + 15) & ~15; // output stride - int uploadSize = stride * mipHeight; + int optimalStrideAlignment = std::max(4, (int)vulkan->GetPhysicalDeviceProperties().properties.limits.optimalBufferCopyRowPitchAlignment); + int byteStride = RoundUpToPowerOf2(mipWidth * bpp, optimalStrideAlignment); // output stride + int pixelStride = byteStride / bpp; + int uploadSize = byteStride * mipHeight; uint32_t bufferOffset; VkBuffer texBuf; @@ -568,17 +570,17 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // Directly load the replaced image. data = drawEngine_->GetPushBufferForTextureData()->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); double replaceStart = time_now_d(); - plan.replaced->Load(plan.baseLevelSrc + i, data, stride); // if it fails, it'll just be garbage data... OK for now. + plan.replaced->Load(plan.baseLevelSrc + i, data, byteStride); // if it fails, it'll just be garbage data... OK for now. replacementTimeThisFrame_ += time_now_d() - replaceStart; VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, "Copy Upload (replaced): %dx%d", mipWidth, mipHeight); - entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, stride / bpp); + entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, pixelStride); VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); } else { if (plan.depth != 1) { // 3D texturing. - loadLevel(uploadSize, i, stride, plan.scaleFactor); - entry->vkTex->UploadMip(cmdInit, 0, mipWidth, mipHeight, i, texBuf, bufferOffset, stride / bpp); + loadLevel(uploadSize, i, byteStride, plan.scaleFactor); + entry->vkTex->UploadMip(cmdInit, 0, mipWidth, mipHeight, i, texBuf, bufferOffset, pixelStride); } else if (computeUpload) { int srcBpp = VkFormatBytesPerPixel(dstFmt); int srcStride = mipUnscaledWidth * srcBpp; @@ -599,10 +601,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT); vulkan->Delete().QueueDeleteImageView(view); } else { - loadLevel(uploadSize, i == 0 ? plan.baseLevelSrc : i, stride, plan.scaleFactor); + loadLevel(uploadSize, i == 0 ? plan.baseLevelSrc : i, byteStride, plan.scaleFactor); VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, "Copy Upload: %dx%d", mipWidth, mipHeight); - entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, stride / bpp); + entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, pixelStride); VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); } // Format might be wrong in lowMemoryMode_, so don't save. @@ -620,7 +622,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { replacedInfo.scaleFactor = plan.scaleFactor; replacedInfo.fmt = FromVulkanFormat(actualFmt); - replacer_.NotifyTextureDecoded(replacedInfo, data, stride, plan.baseLevelSrc + i, w, h); + replacer_.NotifyTextureDecoded(replacedInfo, data, byteStride, plan.baseLevelSrc + i, w, h); } } } From 9fcc1509e45ac72e684327a3041376f6127cff1b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 5 Mar 2023 08:41:44 -0800 Subject: [PATCH 216/424] GPU: Correct depth clip/cull for zero scale. --- GPU/Common/ShaderUniforms.cpp | 3 ++- GPU/Common/VertexShaderGenerator.cpp | 3 ++- GPU/Directx9/ShaderManagerDX9.cpp | 2 +- GPU/GLES/ShaderManagerGLES.cpp | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/GPU/Common/ShaderUniforms.cpp b/GPU/Common/ShaderUniforms.cpp index 207778cf56..173574fadd 100644 --- a/GPU/Common/ShaderUniforms.cpp +++ b/GPU/Common/ShaderUniforms.cpp @@ -252,6 +252,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView // These are just the reverse of the formulas in GPUStateUtils. float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; + float inverseDepthScale = gstate_c.vpDepthScale != 0.0f ? 1.0f / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; float viewZCenter = minz; @@ -259,7 +260,7 @@ void BaseUpdateUniforms(UB_VS_FS_Base *ub, uint64_t dirtyUniforms, bool flipView ub->depthRange[0] = viewZScale; ub->depthRange[1] = viewZCenter; ub->depthRange[2] = gstate_c.vpZOffset * 0.5f + 0.5f; - ub->depthRange[3] = 2.0f * (1.0f / gstate_c.vpDepthScale); + ub->depthRange[3] = 2.0f * inverseDepthScale; } if (dirtyUniforms & DIRTY_CULLRANGE) { diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 7da56ed7a0..4404ec254b 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -1350,7 +1350,8 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } if (gstate_c.Use(GPU_USE_CULL_DISTANCE)) { // Cull any triangle fully outside in the same direction when depth clamp enabled. - WRITE(p, " if (u_cullRangeMin.w > 0.0) {\n"); + // We check u_depthRange in case depthScale was zero - in that case we can't work out the cull distance. + WRITE(p, " if (u_cullRangeMin.w > 0.0 && u_depthRange.w != 0.0f) {\n"); WRITE(p, " %sgl_CullDistance%s = projPos.z - u_cullRangeMin.z;\n", compat.vsOutPrefix, cull0); WRITE(p, " %sgl_CullDistance%s = u_cullRangeMax.z - projPos.z;\n", compat.vsOutPrefix, cull1); WRITE(p, " } else {\n"); diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp index dee68027b1..374d66fb24 100644 --- a/GPU/Directx9/ShaderManagerDX9.cpp +++ b/GPU/Directx9/ShaderManagerDX9.cpp @@ -466,7 +466,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) { float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange * 2.0f; float viewZCenter = minz; - float reverseScale = 2.0f * (1.0f / gstate_c.vpDepthScale); + float reverseScale = gstate_c.vpDepthScale != 0.0f ? 2.0f * (1.0f / gstate_c.vpDepthScale) : 0.0f; float reverseTranslate = gstate_c.vpZOffset * 0.5f + 0.5f; float data[4] = { viewZScale, viewZCenter, reverseTranslate, reverseScale }; diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index e050b9381a..8007b31f46 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -589,6 +589,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin // These are just the reverse of the formulas in GPUStateUtils. float halfActualZRange = gstate_c.vpDepthScale != 0.0f ? vpZScale / gstate_c.vpDepthScale : 0.0f; + float inverseDepthScale = gstate_c.vpDepthScale != 0.0f ? 1.0f / gstate_c.vpDepthScale : 0.0f; float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange; float viewZScale = halfActualZRange; float viewZCenter = minz + halfActualZRange; @@ -598,7 +599,7 @@ void LinkedShader::UpdateUniforms(const ShaderID &vsid, bool useBufferedRenderin viewZCenter = vpZCenter; } - float data[4] = { viewZScale, viewZCenter, gstate_c.vpZOffset, 1.0f / gstate_c.vpDepthScale }; + float data[4] = { viewZScale, viewZCenter, gstate_c.vpZOffset, inverseDepthScale }; SetFloatUniform4(render_, &u_depthRange, data); } if (dirty & DIRTY_CULLRANGE) { From 3b39e9e068e344d24f403a178183297cf614d67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 14:23:56 +0100 Subject: [PATCH 217/424] Turn the VFS into a class, to be able to reuse it for other purposes. --- Common/Data/Format/IniFile.cpp | 2 +- Common/Data/Format/JSONReader.cpp | 2 +- Common/Data/Format/ZIMLoad.cpp | 2 +- Common/Data/Text/I18n.cpp | 2 +- Common/File/AndroidStorage.cpp | 2 + Common/File/VFS/VFS.cpp | 56 +++++++++++------------- Common/File/VFS/VFS.h | 30 +++++++++---- Common/GPU/OpenGL/GLSLProgram.cpp | 4 +- Common/Render/ManagedTexture.cpp | 2 +- Core/FileSystems/DirectoryFileSystem.cpp | 4 +- Core/Reporting.cpp | 2 +- Core/Util/PPGeDraw.cpp | 2 +- Core/WebServer.cpp | 2 +- GPU/Common/PostShader.cpp | 2 +- GPU/Common/PresentationCommon.cpp | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- SDL/SDLJoystick.cpp | 4 +- UI/BackgroundAudio.cpp | 2 +- UI/GameInfoCache.cpp | 2 +- UI/MiscScreens.cpp | 2 +- UI/NativeApp.cpp | 24 +++++----- UI/Theme.cpp | 6 +-- UWP/PPSSPP_UWPMain.cpp | 5 ++- Windows/main.cpp | 6 +-- android/jni/app-android.cpp | 4 +- headless/Headless.cpp | 8 ++-- headless/SDLHeadlessHost.cpp | 6 +-- headless/WindowsHeadlessHost.cpp | 10 ++--- libretro/libretro.cpp | 4 +- 29 files changed, 106 insertions(+), 95 deletions(-) diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index 72aeee6f89..27f38e3c16 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -569,7 +569,7 @@ bool IniFile::Load(const Path &path) bool IniFile::LoadFromVFS(const std::string &filename) { size_t size; - uint8_t *data = VFSReadFile(filename.c_str(), &size); + uint8_t *data = g_VFS.ReadFile(filename.c_str(), &size); if (!data) return false; std::string str((const char*)data, size); diff --git a/Common/Data/Format/JSONReader.cpp b/Common/Data/Format/JSONReader.cpp index 9c2128e6ef..b65381d986 100644 --- a/Common/Data/Format/JSONReader.cpp +++ b/Common/Data/Format/JSONReader.cpp @@ -8,7 +8,7 @@ namespace json { JsonReader::JsonReader(const std::string &filename) { size_t buf_size; - buffer_ = (char *)VFSReadFile(filename.c_str(), &buf_size); + buffer_ = (char *)g_VFS.ReadFile(filename.c_str(), &buf_size); if (buffer_) { parse(); } else { diff --git a/Common/Data/Format/ZIMLoad.cpp b/Common/Data/Format/ZIMLoad.cpp index 3fd759e92c..9a145afbe1 100644 --- a/Common/Data/Format/ZIMLoad.cpp +++ b/Common/Data/Format/ZIMLoad.cpp @@ -126,7 +126,7 @@ int LoadZIMPtr(const uint8_t *zim, size_t datasize, int *width, int *height, int int LoadZIM(const char *filename, int *width, int *height, int *format, uint8_t **image) { size_t size; - uint8_t *buffer = VFSReadFile(filename, &size); + uint8_t *buffer = g_VFS.ReadFile(filename, &size); if (!buffer) { ERROR_LOG(IO, "Couldn't read data for '%s'", filename); return 0; diff --git a/Common/Data/Text/I18n.cpp b/Common/Data/Text/I18n.cpp index 9c222da8b8..ebcb95a90e 100644 --- a/Common/Data/Text/I18n.cpp +++ b/Common/Data/Text/I18n.cpp @@ -73,7 +73,7 @@ Path I18NRepo::GetIniPath(const std::string &languageID) const { bool I18NRepo::IniExists(const std::string &languageID) const { File::FileInfo info; - if (!VFSGetFileInfo(GetIniPath(languageID).ToString().c_str(), &info)) + if (!g_VFS.GetFileInfo(GetIniPath(languageID).ToString().c_str(), &info)) return false; if (!info.exists) return false; diff --git a/Common/File/AndroidStorage.cpp b/Common/File/AndroidStorage.cpp index ec8248947b..c4ddcc73c1 100644 --- a/Common/File/AndroidStorage.cpp +++ b/Common/File/AndroidStorage.cpp @@ -1,3 +1,5 @@ +#include + #include "Common/File/AndroidStorage.h" #include "Common/StringUtils.h" #include "Common/Log.h" diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index cf347dcf44..3dc9c66a1f 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -3,26 +3,20 @@ #include "Common/File/VFS/AssetReader.h" #include "Common/File/AndroidStorage.h" -struct VFSEntry { - const char *prefix; - AssetReader *reader; -}; +VFS g_VFS; -static VFSEntry entries[16]; -static int num_entries = 0; - -void VFSRegister(const char *prefix, AssetReader *reader) { - entries[num_entries].prefix = prefix; - entries[num_entries].reader = reader; +void VFS::Register(const char *prefix, AssetReader *reader) { + entries_[numEntries_].prefix = prefix; + entries_[numEntries_].reader = reader; DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); - num_entries++; + numEntries_++; } -void VFSShutdown() { - for (int i = 0; i < num_entries; i++) { - delete entries[i].reader; +void VFS::Clear() { + for (int i = 0; i < numEntries_; i++) { + delete entries_[i].reader; } - num_entries = 0; + numEntries_ = 0; } // TODO: Use Path more. @@ -38,7 +32,7 @@ static bool IsLocalAbsolutePath(const char *path) { } // The returned data should be free'd with delete[]. -uint8_t *VFSReadFile(const char *filename, size_t *size) { +uint8_t *VFS::ReadFile(const char *filename, size_t *size) { if (IsLocalAbsolutePath(filename)) { // Local path, not VFS. // INFO_LOG(IO, "Not a VFS path: %s . Reading local file.", filename); @@ -47,13 +41,13 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { int fn_len = (int)strlen(filename); bool fileSystemFound = false; - for (int i = 0; i < num_entries; i++) { - int prefix_len = (int)strlen(entries[i].prefix); + for (int i = 0; i < numEntries_; i++) { + int prefix_len = (int)strlen(entries_[i].prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(filename, entries[i].prefix, prefix_len)) { + if (0 == memcmp(filename, entries_[i].prefix, prefix_len)) { fileSystemFound = true; // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entries[i].reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entries_[i].reader->ReadAsset(filename + prefix_len, size); if (data) return data; else @@ -67,7 +61,7 @@ uint8_t *VFSReadFile(const char *filename, size_t *size) { return 0; } -bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter) { +bool VFS::GetFileListing(const char *path, std::vector *listing, const char *filter) { if (IsLocalAbsolutePath(path)) { // Local path, not VFS. // INFO_LOG(IO, "Not a VFS path: %s . Reading local directory.", path); @@ -77,12 +71,12 @@ bool VFSGetFileListing(const char *path, std::vector *listing, c int fn_len = (int)strlen(path); bool fileSystemFound = false; - for (int i = 0; i < num_entries; i++) { - int prefix_len = (int)strlen(entries[i].prefix); + for (int i = 0; i < numEntries_; i++) { + int prefix_len = (int)strlen(entries_[i].prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { fileSystemFound = true; - if (entries[i].reader->GetFileListing(path + prefix_len, listing, filter)) { + if (entries_[i].reader->GetFileListing(path + prefix_len, listing, filter)) { return true; } } @@ -94,7 +88,7 @@ bool VFSGetFileListing(const char *path, std::vector *listing, c return false; } -bool VFSGetFileInfo(const char *path, File::FileInfo *info) { +bool VFS::GetFileInfo(const char *path, File::FileInfo *info) { if (IsLocalAbsolutePath(path)) { // Local path, not VFS. // INFO_LOG(IO, "Not a VFS path: %s . Getting local file info.", path); @@ -103,19 +97,19 @@ bool VFSGetFileInfo(const char *path, File::FileInfo *info) { bool fileSystemFound = false; int fn_len = (int)strlen(path); - for (int i = 0; i < num_entries; i++) { - int prefix_len = (int)strlen(entries[i].prefix); + for (int i = 0; i < numEntries_; i++) { + int prefix_len = (int)strlen(entries_[i].prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries[i].prefix, prefix_len)) { + if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { fileSystemFound = true; - if (entries[i].reader->GetFileInfo(path + prefix_len, info)) + if (entries_[i].reader->GetFileInfo(path + prefix_len, info)) return true; else continue; } } if (!fileSystemFound) { - ERROR_LOG(IO, "Missing filesystem for %s", path); + ERROR_LOG(IO, "Missing filesystem for '%s'", path); } // Otherwise, the file was just missing. No need to log. return false; } diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 0f7e03c3fa..baaeebf068 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -10,12 +10,26 @@ class AssetReader; -void VFSRegister(const char *prefix, AssetReader *reader); -void VFSShutdown(); +class VFS { +public: + void Register(const char *prefix, AssetReader *reader); + void Clear(); -// Use delete [] to release the returned memory. -// Always allocates an extra zero byte at the end, so that it -// can be used for text like shader sources. -uint8_t *VFSReadFile(const char *filename, size_t *size); -bool VFSGetFileListing(const char *path, std::vector *listing, const char *filter = 0); -bool VFSGetFileInfo(const char *filename, File::FileInfo *fileInfo); + // Use delete [] to release the returned memory. + // Always allocates an extra zero byte at the end, so that it + // can be used for text like shader sources. + uint8_t *ReadFile(const char *filename, size_t *size); + bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0); + bool GetFileInfo(const char *filename, File::FileInfo *fileInfo); + +private: + struct VFSEntry { + const char *prefix; + AssetReader *reader; + }; + + VFSEntry entries_[16]; + int numEntries_ = 0; +}; + +extern VFS g_VFS; diff --git a/Common/GPU/OpenGL/GLSLProgram.cpp b/Common/GPU/OpenGL/GLSLProgram.cpp index 45b098d714..fc5698085e 100644 --- a/Common/GPU/OpenGL/GLSLProgram.cpp +++ b/Common/GPU/OpenGL/GLSLProgram.cpp @@ -102,7 +102,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { if (!program->vshader_source && !vsh_src) { size_t sz; - vsh_src.reset((char *)VFSReadFile(program->vshader_filename, &sz)); + vsh_src.reset((char *)g_VFS.ReadFile(program->vshader_filename, &sz)); } if (!program->vshader_source && !vsh_src) { ERROR_LOG(G3D, "File missing: %s", program->vshader_filename); @@ -113,7 +113,7 @@ bool glsl_recompile(GLSLProgram *program, std::string *error_message) { } if (!program->fshader_source && !fsh_src) { size_t sz; - fsh_src.reset((char *)VFSReadFile(program->fshader_filename, &sz)); + fsh_src.reset((char *)g_VFS.ReadFile(program->fshader_filename, &sz)); } if (!program->fshader_source && !fsh_src) { ERROR_LOG(G3D, "File missing: %s", program->fshader_filename); diff --git a/Common/Render/ManagedTexture.cpp b/Common/Render/ManagedTexture.cpp index 771d4f8a92..dce43253c2 100644 --- a/Common/Render/ManagedTexture.cpp +++ b/Common/Render/ManagedTexture.cpp @@ -148,7 +148,7 @@ bool ManagedTexture::LoadFromFileData(const uint8_t *data, size_t dataSize, Imag bool ManagedTexture::LoadFromFile(const std::string &filename, ImageFileType type, bool generateMips) { generateMips_ = generateMips; size_t fileSize; - uint8_t *buffer = VFSReadFile(filename.c_str(), &fileSize); + uint8_t *buffer = g_VFS.ReadFile(filename.c_str(), &fileSize); if (!buffer) { filename_.clear(); ERROR_LOG(IO, "Failed to read file '%s'", filename.c_str()); diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index 27abc90564..b4fc833452 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -980,7 +980,7 @@ int VFSFileSystem::OpenFile(std::string filename, FileAccess access, const char VERBOSE_LOG(FILESYS, "VFSFileSystem actually opening %s (%s)", fullNameC, filename.c_str()); size_t size; - u8 *data = VFSReadFile(fullNameC, &size); + u8 *data = g_VFS.ReadFile(fullNameC, &size); if (!data) { ERROR_LOG(FILESYS, "VFSFileSystem failed to open %s", filename.c_str()); return SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; @@ -1001,7 +1001,7 @@ PSPFileInfo VFSFileSystem::GetFileInfo(std::string filename) { std::string fullName = GetLocalPath(filename); File::FileInfo fo; - if (VFSGetFileInfo(fullName.c_str(), &fo)) { + if (g_VFS.GetFileInfo(fullName.c_str(), &fo)) { x.exists = fo.exists; if (x.exists) { x.size = fo.size; diff --git a/Core/Reporting.cpp b/Core/Reporting.cpp index d85533d670..946285dfea 100644 --- a/Core/Reporting.cpp +++ b/Core/Reporting.cpp @@ -569,7 +569,7 @@ namespace Reporting return false; #else File::FileInfo fo; - if (!VFSGetFileInfo("flash0/font/jpn0.pgf", &fo)) + if (!g_VFS.GetFileInfo("flash0/font/jpn0.pgf", &fo)) return false; #endif diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 525937a512..12dc1e86a9 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -252,7 +252,7 @@ void __PPGeInit() { if (loadedZIM) { size_t atlas_data_size; if (!g_ppge_atlas.IsMetadataLoaded()) { - uint8_t *atlas_data = VFSReadFile("ppge_atlas.meta", &atlas_data_size); + uint8_t *atlas_data = g_VFS.ReadFile("ppge_atlas.meta", &atlas_data_size); if (atlas_data) g_ppge_atlas.Load(atlas_data, atlas_data_size); delete[] atlas_data; diff --git a/Core/WebServer.cpp b/Core/WebServer.cpp index 3de0fabc7b..5784827021 100644 --- a/Core/WebServer.cpp +++ b/Core/WebServer.cpp @@ -237,7 +237,7 @@ static bool ServeDebuggerFile(const http::Request &request) { return false; size_t size; - uint8_t *data = VFSReadFile(filename, &size); + uint8_t *data = g_VFS.ReadFile(filename, &size); if (!data) return false; diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index 831bc1bf85..ae03877d98 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -70,7 +70,7 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector &direct for (size_t d = 0; d < directories.size(); d++) { std::vector fileInfo; - VFSGetFileListing(directories[d].c_str(), &fileInfo, "ini:"); + g_VFS.GetFileListing(directories[d].c_str(), &fileInfo, "ini:"); if (fileInfo.empty()) { File::GetFilesInDir(directories[d], &fileInfo, "ini:"); diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp index 3305e03b73..3da9c795f9 100644 --- a/GPU/Common/PresentationCommon.cpp +++ b/GPU/Common/PresentationCommon.cpp @@ -212,7 +212,7 @@ void PresentationCommon::CalculatePostShaderUniforms(int bufferWidth, int buffer static std::string ReadShaderSrc(const Path &filename) { size_t sz = 0; - char *data = (char *)VFSReadFile(filename.c_str(), &sz); + char *data = (char *)g_VFS.ReadFile(filename.c_str(), &sz); if (!data) { return ""; } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 108356cadc..21cf131393 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -260,7 +260,7 @@ void TextureCacheVulkan::NotifyConfigChanged() { static std::string ReadShaderSrc(const Path &filename) { size_t sz = 0; - char *data = (char *)VFSReadFile(filename.c_str(), &sz); + char *data = (char *)g_VFS.ReadFile(filename.c_str(), &sz); if (!data) return std::string(); diff --git a/SDL/SDLJoystick.cpp b/SDL/SDLJoystick.cpp index 0a53ef80b7..59906f4a3e 100644 --- a/SDL/SDLJoystick.cpp +++ b/SDL/SDLJoystick.cpp @@ -29,7 +29,7 @@ SDLJoystick::SDLJoystick(bool init_SDL ) : registeredAsEventHandler(false) { cout << "loading control pad mappings from " << dbPath << ": "; size_t size; - u8 *mappingData = VFSReadFile(dbPath, &size); + u8 *mappingData = g_VFS.ReadFile(dbPath, &size); if (mappingData) { SDL_RWops *rw = SDL_RWFromConstMem(mappingData, size); // 1 to free the rw after use @@ -191,7 +191,7 @@ void SDLJoystick::ProcessInput(SDL_Event &event){ NativeAxis(axis); break; case SDL_CONTROLLERDEVICEREMOVED: - // for removal events, "which" is the instance ID for SDL_CONTROLLERDEVICEREMOVED + // for removal events, "which" is the instance ID for SDL_CONTROLLERDEVICEREMOVED for (auto it = controllers.begin(); it != controllers.end(); ++it) { if (SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(*it)) == event.cdevice.which) { SDL_GameControllerClose(*it); diff --git a/UI/BackgroundAudio.cpp b/UI/BackgroundAudio.cpp index ff83abcfc5..e9f13a4837 100644 --- a/UI/BackgroundAudio.cpp +++ b/UI/BackgroundAudio.cpp @@ -257,7 +257,7 @@ BackgroundAudio::~BackgroundAudio() { BackgroundAudio::Sample *BackgroundAudio::LoadSample(const std::string &path) { size_t bytes; - uint8_t *data = VFSReadFile(path.c_str(), &bytes); + uint8_t *data = g_VFS.ReadFile(path.c_str(), &bytes); if (!data) { return nullptr; } diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index c71e5e6fc4..ceef80cedd 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -314,7 +314,7 @@ static bool ReadFileToString(IFileSystem *fs, const char *filename, std::string static bool ReadVFSToString(const char *filename, std::string *contents, std::mutex *mtx) { size_t sz; - uint8_t *data = VFSReadFile(filename, &sz); + uint8_t *data = g_VFS.ReadFile(filename, &sz); if (data) { if (mtx) { std::lock_guard lock(*mtx); diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 6887d5ecd2..b9e93d7ab0 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -590,7 +590,7 @@ NewLanguageScreen::NewLanguageScreen(const std::string &title) : ListPopupScreen auto &langValuesMapping = g_Config.GetLangValuesMapping(); std::vector tempLangs; - VFSGetFileListing("lang", &tempLangs, "ini"); + g_VFS.GetFileListing("lang", &tempLangs, "ini"); std::vector listing; int selected = -1; int counter = 0; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index c89c7ec122..833f8fdd75 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -467,27 +467,27 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // We want this to be FIRST. #if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC) // Packed assets are included in app - VFSRegister("", new DirectoryAssetReader(Path(external_dir))); + g_VFS.Register("", new DirectoryAssetReader(Path(external_dir))); #endif #if defined(ASSETS_DIR) - VFSRegister("", new DirectoryAssetReader(Path(ASSETS_DIR))); + g_VFS.Register("", new DirectoryAssetReader(Path(ASSETS_DIR))); #endif #if !defined(MOBILE_DEVICE) && !defined(_WIN32) && !PPSSPP_PLATFORM(SWITCH) - VFSRegister("", new DirectoryAssetReader(File::GetExeDirectory() / "assets")); - VFSRegister("", new DirectoryAssetReader(File::GetExeDirectory())); - VFSRegister("", new DirectoryAssetReader(Path("/usr/local/share/ppsspp/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("/usr/local/share/games/ppsspp/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("/usr/share/ppsspp/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("/usr/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory() / "assets")); + g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory())); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/games/ppsspp/assets"))); #endif #if PPSSPP_PLATFORM(SWITCH) Path assetPath = Path(user_data_path) / "assets"; - VFSRegister("", new DirectoryAssetReader(assetPath)); + g_VFS.Register("", new DirectoryAssetReader(assetPath)); #else - VFSRegister("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); #endif - VFSRegister("", new DirectoryAssetReader(Path(savegame_dir))); + g_VFS.Register("", new DirectoryAssetReader(Path(savegame_dir))); #if (defined(MOBILE_DEVICE) || !defined(USING_QT_UI)) && !PPSSPP_PLATFORM(UWP) if (host == nullptr) { @@ -777,7 +777,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } #elif defined(USING_QT_UI) size_t fontSize = 0; - uint8_t *fontData = VFSReadFile("Roboto-Condensed.ttf", &fontSize); + uint8_t *fontData = g_VFS.ReadFile("Roboto-Condensed.ttf", &fontSize); if (fontData) { int fontID = QFontDatabase::addApplicationFontFromData(QByteArray((const char *)fontData, fontSize)); delete [] fontData; diff --git a/UI/Theme.cpp b/UI/Theme.cpp index 59be83522a..f733c37c75 100644 --- a/UI/Theme.cpp +++ b/UI/Theme.cpp @@ -84,7 +84,7 @@ static void LoadThemeInfo(const std::vector &directories) { for (size_t d = 0; d < directories.size(); d++) { std::vector fileInfo; - VFSGetFileListing(directories[d].c_str(), &fileInfo, "ini:"); + g_VFS.GetFileListing(directories[d].c_str(), &fileInfo, "ini:"); if (fileInfo.empty()) { File::GetFilesInDir(directories[d], &fileInfo, "ini:"); @@ -138,7 +138,7 @@ static void LoadThemeInfo(const std::vector &directories) { tmpPath = (path / tmpPath).ToString(); File::FileInfo tmpInfo; - if (VFSGetFileInfo((tmpPath+".meta").c_str(), &tmpInfo) && VFSGetFileInfo((tmpPath+".zim").c_str(), &tmpInfo)) { + if (g_VFS.GetFileInfo((tmpPath + ".meta").c_str(), &tmpInfo) && g_VFS.GetFileInfo((tmpPath + ".zim").c_str(), &tmpInfo)) { info.sUIAtlas = tmpPath; } } @@ -158,7 +158,7 @@ static UI::Style MakeStyle(uint32_t fg, uint32_t bg) { static void LoadAtlasMetadata(Atlas &metadata, const char *filename, bool required) { size_t atlas_data_size = 0; - const uint8_t *atlas_data = VFSReadFile(filename, &atlas_data_size); + const uint8_t *atlas_data = g_VFS.ReadFile(filename, &atlas_data_size); bool load_success = atlas_data != nullptr && metadata.Load(atlas_data, atlas_data_size); if (!load_success) { if (required) diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 23d1801cf2..c2995c8711 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -76,8 +76,8 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptrGetDrawContext()->HandleEvent(Draw::Event::LOST_BACKBUFFER, 0, 0, nullptr); NativeShutdownGraphics(); NativeShutdown(); + g_VFS.Clear(); // Deregister device notification m_deviceResources->RegisterDeviceNotify(nullptr); diff --git a/Windows/main.cpp b/Windows/main.cpp index d14b654f9e..0c313e72ad 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -583,8 +583,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin #endif const Path &exePath = File::GetExeDirectory(); - VFSRegister("", new DirectoryAssetReader(exePath / "assets")); - VFSRegister("", new DirectoryAssetReader(exePath)); + g_VFS.Register("", new DirectoryAssetReader(exePath / "assets")); + g_VFS.Register("", new DirectoryAssetReader(exePath)); langRegion = GetDefaultLangRegion(); osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture(); @@ -796,7 +796,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } } - VFSShutdown(); + g_VFS.Clear(); MainWindow::DestroyDebugWindows(); DialogManager::DestroyAll(); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 42d46cae43..e09288ee8d 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -695,7 +695,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init deviceType = jdeviceType; std::string apkPath = GetJavaString(env, japkpath); - VFSRegister("", new ZipAssetReader(apkPath.c_str(), "assets/")); + g_VFS.Register("", new ZipAssetReader(apkPath.c_str(), "assets/")); systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); @@ -907,7 +907,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { std::lock_guard guard(renderLock); inputBoxCallbacks.clear(); NativeShutdown(); - VFSShutdown(); + g_VFS.Clear(); } { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index fa63a489e1..1f3c54ed90 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -482,13 +482,13 @@ int main(int argc, const char* argv[]) #if PPSSPP_PLATFORM(ANDROID) // For some reason the debugger installs it with this name? if (File::Exists(Path("/data/app/org.ppsspp.ppsspp-2.apk"))) { - VFSRegister("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp-2.apk", "assets/")); + g_VFS.Register("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp-2.apk", "assets/")); } if (File::Exists(Path("/data/app/org.ppsspp.ppsspp.apk"))) { - VFSRegister("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp.apk", "assets/")); + g_VFS.Register("", new ZipAssetReader("/data/app/org.ppsspp.ppsspp.apk", "assets/")); } #elif !PPSSPP_PLATFORM(WINDOWS) - VFSRegister("", new DirectoryAssetReader(g_Config.flash0Directory / "..")); + g_VFS.Register("", new DirectoryAssetReader(g_Config.flash0Directory / "..")); #endif UpdateUIState(UISTATE_INGAME); @@ -557,7 +557,7 @@ int main(int argc, const char* argv[]) host = nullptr; headlessHost = nullptr; - VFSShutdown(); + g_VFS.Clear(); LogManager::Shutdown(); delete printfLogger; diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index 9960b01364..0a25cbdb8f 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -100,9 +100,9 @@ private: }; void SDLHeadlessHost::LoadNativeAssets() { - VFSRegister("", new DirectoryAssetReader(Path("assets"))); - VFSRegister("", new DirectoryAssetReader(Path(""))); - VFSRegister("", new DirectoryAssetReader(Path(".."))); + g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path(""))); + g_VFS.Register("", new DirectoryAssetReader(Path(".."))); } bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) { diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 32624f000d..7a9e744bb6 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -68,11 +68,11 @@ HWND CreateHiddenWindow() { void WindowsHeadlessHost::LoadNativeAssets() { - VFSRegister("", new DirectoryAssetReader(Path("assets"))); - VFSRegister("", new DirectoryAssetReader(Path(""))); - VFSRegister("", new DirectoryAssetReader(Path(".."))); - VFSRegister("", new DirectoryAssetReader(Path("../Windows/assets"))); - VFSRegister("", new DirectoryAssetReader(Path("../Windows"))); + g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path(""))); + g_VFS.Register("", new DirectoryAssetReader(Path(".."))); + g_VFS.Register("", new DirectoryAssetReader(Path("../Windows/assets"))); + g_VFS.Register("", new DirectoryAssetReader(Path("../Windows"))); } void WindowsHeadlessHost::SendDebugOutput(const std::string &output) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index a5909da4ae..26a33e59f6 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1284,7 +1284,7 @@ void retro_init(void) g_Config.bEnableNetworkChat = false; g_Config.bDiscordPresence = false; - VFSRegister("", new DirectoryAssetReader(retro_base_dir)); + g_VFS.Register("", new DirectoryAssetReader(retro_base_dir)); host = new LibretroHost(); } @@ -1486,7 +1486,7 @@ void retro_unload_game(void) Libretro::EmuThreadStop(); PSP_Shutdown(); - VFSShutdown(); + g_VFS.Clear(); delete ctx; ctx = nullptr; From 76497941644ba4c04947de9f674dea603f6af6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 14:29:47 +0100 Subject: [PATCH 218/424] Remove some ifdefs --- Common/File/VFS/AssetReader.cpp | 16 +++++----------- Common/File/VFS/AssetReader.h | 21 ++++----------------- Common/File/VFS/VFS.h | 11 ++++++++++- 3 files changed, 19 insertions(+), 29 deletions(-) diff --git a/Common/File/VFS/AssetReader.cpp b/Common/File/VFS/AssetReader.cpp index 306cd0c5e0..64116703b9 100644 --- a/Common/File/VFS/AssetReader.cpp +++ b/Common/File/VFS/AssetReader.cpp @@ -3,15 +3,16 @@ #include #include -#ifdef __ANDROID__ +#ifdef SHARED_LIBZIP #include +#else +#include "ext/libzip/zip.h" #endif #include "Common/Common.h" #include "Common/Log.h" #include "Common/File/VFS/AssetReader.h" -#ifdef __ANDROID__ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; @@ -31,10 +32,6 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -#endif - -#ifdef __ANDROID__ - ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); @@ -155,9 +152,8 @@ void ZipAssetReader::GetZipListings(const char *path, std::set &fil bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; - strcpy(temp_path, in_zip_path_); - strcat(temp_path, path); - if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED, &zstat)) { + snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); + if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) { // ZIP files do not have real directories, so we'll end up here if we // try to stat one. For now that's fine. info->exists = false; @@ -173,8 +169,6 @@ bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { return true; } -#endif - DirectoryAssetReader::DirectoryAssetReader(const Path &path) { path_ = path; } diff --git a/Common/File/VFS/AssetReader.h b/Common/File/VFS/AssetReader.h index 8352f8eea8..b1ec629725 100644 --- a/Common/File/VFS/AssetReader.h +++ b/Common/File/VFS/AssetReader.h @@ -1,8 +1,9 @@ -// TODO: Move much of this code to vfs.cpp #pragma once -#ifdef __ANDROID__ +#ifdef SHARED_LIBZIP #include +#else +#include "ext/libzip/zip.h" #endif #include @@ -14,24 +15,11 @@ #include "Common/File/FileUtil.h" #include "Common/File/Path.h" -class AssetReader { -public: - virtual ~AssetReader() {} - // use delete[] - virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; - // Filter support is optional but nice to have - virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; - virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; - virtual std::string toString() const = 0; -}; - -#ifdef __ANDROID__ -uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size); class ZipAssetReader : public AssetReader { public: ZipAssetReader(const char *zip_file, const char *in_zip_path); ~ZipAssetReader(); - // use delete[] + // use delete[] on the returned value. uint8_t *ReadAsset(const char *path, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; @@ -46,7 +34,6 @@ private: std::mutex lock_; char in_zip_path_[256]; }; -#endif class DirectoryAssetReader : public AssetReader { public: diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index baaeebf068..c6a2479e80 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -8,7 +8,16 @@ // read them manually out of the APK zipfile, while being able to run on other // platforms as well with the appropriate directory set-up. -class AssetReader; +class AssetReader { +public: + virtual ~AssetReader() {} + // use delete[] + virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + // Filter support is optional but nice to have + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; + virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; + virtual std::string toString() const = 0; +}; class VFS { public: From 54af2400135e8fef2639ecbc09a2cf1d2ea401b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 14:37:11 +0100 Subject: [PATCH 219/424] Use a vector internally in VFS. --- Common/File/DirListing.h | 4 +--- Common/File/VFS/VFS.cpp | 34 ++++++++++++++++------------------ Common/File/VFS/VFS.h | 16 +++++++++++----- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Common/File/DirListing.h b/Common/File/DirListing.h index c53d420588..4ad9ce0c3e 100644 --- a/Common/File/DirListing.h +++ b/Common/File/DirListing.h @@ -2,10 +2,8 @@ #include #include - #include - -#include +#include #include "Common/File/Path.h" diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index 3dc9c66a1f..e765c9ca78 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -6,17 +6,15 @@ VFS g_VFS; void VFS::Register(const char *prefix, AssetReader *reader) { - entries_[numEntries_].prefix = prefix; - entries_[numEntries_].reader = reader; + entries_.push_back(VFSEntry{ prefix, reader }); DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); - numEntries_++; } void VFS::Clear() { - for (int i = 0; i < numEntries_; i++) { - delete entries_[i].reader; + for (auto &entry : entries_) { + delete entry.reader; } - numEntries_ = 0; + entries_.clear(); } // TODO: Use Path more. @@ -41,13 +39,13 @@ uint8_t *VFS::ReadFile(const char *filename, size_t *size) { int fn_len = (int)strlen(filename); bool fileSystemFound = false; - for (int i = 0; i < numEntries_; i++) { - int prefix_len = (int)strlen(entries_[i].prefix); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(filename, entries_[i].prefix, prefix_len)) { + if (0 == memcmp(filename, entry.prefix, prefix_len)) { fileSystemFound = true; // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entries_[i].reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entry.reader->ReadAsset(filename + prefix_len, size); if (data) return data; else @@ -71,12 +69,12 @@ bool VFS::GetFileListing(const char *path, std::vector *listing, int fn_len = (int)strlen(path); bool fileSystemFound = false; - for (int i = 0; i < numEntries_; i++) { - int prefix_len = (int)strlen(entries_[i].prefix); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { + if (0 == memcmp(path, entry.prefix, prefix_len)) { fileSystemFound = true; - if (entries_[i].reader->GetFileListing(path + prefix_len, listing, filter)) { + if (entry.reader->GetFileListing(path + prefix_len, listing, filter)) { return true; } } @@ -97,12 +95,12 @@ bool VFS::GetFileInfo(const char *path, File::FileInfo *info) { bool fileSystemFound = false; int fn_len = (int)strlen(path); - for (int i = 0; i < numEntries_; i++) { - int prefix_len = (int)strlen(entries_[i].prefix); + for (const auto &entry : entries_) { + int prefix_len = (int)strlen(entry.prefix); if (prefix_len >= fn_len) continue; - if (0 == memcmp(path, entries_[i].prefix, prefix_len)) { + if (0 == memcmp(path, entry.prefix, prefix_len)) { fileSystemFound = true; - if (entries_[i].reader->GetFileInfo(path + prefix_len, info)) + if (entry.reader->GetFileInfo(path + prefix_len, info)) return true; else continue; diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index c6a2479e80..41ac6ae3f9 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -1,18 +1,25 @@ #pragma once #include +#include #include "Common/File/DirListing.h" -// Basic virtual file system. Used to manage assets on Android, where we have to +// Basic read-only virtual file system. Used to manage assets on Android, where we have to // read them manually out of the APK zipfile, while being able to run on other // platforms as well with the appropriate directory set-up. +// Note that this is kinda similar in concept to Core/MetaFileSystem.h, but that one +// is specifically for operations done by the emulated PSP, while this is for operations +// on the system level, like loading assets, and maybe texture packs. Also, as mentioned, +// this one is read-only, so a bit smaller and simpler. + class AssetReader { public: virtual ~AssetReader() {} - // use delete[] + // use delete[] to release the returned memory. virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; @@ -21,6 +28,7 @@ public: class VFS { public: + ~VFS() { Clear(); } void Register(const char *prefix, AssetReader *reader); void Clear(); @@ -36,9 +44,7 @@ private: const char *prefix; AssetReader *reader; }; - - VFSEntry entries_[16]; - int numEntries_ = 0; + std::vector entries_; }; extern VFS g_VFS; From 53172eff6376481ab03f58b42b6dda57c294bdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 15:30:39 +0100 Subject: [PATCH 220/424] Renaming and file splitting --- CMakeLists.txt | 8 ++- Common/Common.vcxproj | 6 +- Common/Common.vcxproj.filters | 18 ++++-- Common/File/VFS/DirectoryReader.cpp | 31 ++++++++++ Common/File/VFS/DirectoryReader.h | 21 +++++++ Common/File/VFS/VFS.cpp | 8 ++- Common/File/VFS/VFS.h | 10 ++-- .../{AssetReader.cpp => ZipFileReader.cpp} | 57 +++++-------------- .../VFS/{AssetReader.h => ZipFileReader.h} | 25 ++------ Qt/QtMain.h | 3 +- UI/NativeApp.cpp | 25 ++++---- UWP/CommonUWP/CommonUWP.vcxproj | 6 +- UWP/CommonUWP/CommonUWP.vcxproj.filters | 10 +++- UWP/PPSSPP_UWPMain.cpp | 6 +- Windows/main.cpp | 6 +- android/jni/Android.mk | 3 +- android/jni/app-android.cpp | 5 +- headless/Headless.cpp | 11 ++-- headless/SDLHeadlessHost.cpp | 8 +-- headless/WindowsHeadlessHost.cpp | 12 ++-- ios/PPSSPPUIApplication.mm | 12 ++-- libretro/Makefile.common | 5 +- libretro/libretro.cpp | 12 ++-- 23 files changed, 169 insertions(+), 139 deletions(-) create mode 100644 Common/File/VFS/DirectoryReader.cpp create mode 100644 Common/File/VFS/DirectoryReader.h rename Common/File/VFS/{AssetReader.cpp => ZipFileReader.cpp} (70%) rename Common/File/VFS/{AssetReader.h => ZipFileReader.h} (51%) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebd1b151c0..91f08e233b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -588,8 +588,10 @@ add_library(Common STATIC Common/Data/Random/Rng.h Common/File/VFS/VFS.h Common/File/VFS/VFS.cpp - Common/File/VFS/AssetReader.cpp - Common/File/VFS/AssetReader.h + Common/File/VFS/ZipFileReader.cpp + Common/File/VFS/ZipFileReader.h + Common/File/VFS/DirectoryReader.cpp + Common/File/VFS/DirectoryReader.h Common/File/AndroidStorage.h Common/File/AndroidStorage.cpp Common/File/DiskFree.h @@ -1150,7 +1152,7 @@ elseif(IOS AND NOT LIBRETRO) UI/DarwinFileSystemServices.h Common/Battery/AppleBatteryClient.m ) - + set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreVideo -framework CoreMedia -framework CoreServices" ) if(EXISTS "${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks/GameController.framework") set(nativeExtraLibs ${nativeExtraLibs} "-weak_framework GameController") diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 451e8dd426..8557f133d3 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -425,8 +425,9 @@ + - + @@ -861,8 +862,9 @@ + - + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 3c0a310aff..0f40093153 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -176,9 +176,6 @@ File\VFS - - File\VFS - Data\Format @@ -467,6 +464,12 @@ GPU\OpenGL + + File\VFS + + + File\VFS + @@ -628,9 +631,6 @@ File\VFS - - File\VFS - Data\Format @@ -884,6 +884,12 @@ GPU\OpenGL + + File\VFS + + + File\VFS + diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp new file mode 100644 index 0000000000..d979dd4d7c --- /dev/null +++ b/Common/File/VFS/DirectoryReader.cpp @@ -0,0 +1,31 @@ +#include "Common/Common.h" +#include "Common/Log.h" +#include "Common/File/VFS/DirectoryReader.h" + +DirectoryReader::DirectoryReader(const Path &path) { + path_ = path; +} + +uint8_t *DirectoryReader::ReadFile(const char *path, size_t *size) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + return File::ReadLocalFile(new_path, size); +} + +bool DirectoryReader::GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + + File::FileInfo info; + if (!File::GetFileInfo(new_path, &info)) + return false; + + if (info.isDirectory) { + File::GetFilesInDir(new_path, listing, filter); + return true; + } + return false; +} + +bool DirectoryReader::GetFileInfo(const char *path, File::FileInfo *info) { + Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; + return File::GetFileInfo(new_path, info); +} diff --git a/Common/File/VFS/DirectoryReader.h b/Common/File/VFS/DirectoryReader.h new file mode 100644 index 0000000000..facd3efe72 --- /dev/null +++ b/Common/File/VFS/DirectoryReader.h @@ -0,0 +1,21 @@ +#pragma once + +#include "Common/File/VFS/VFS.h" +#include "Common/File/FileUtil.h" +#include "Common/File/Path.h" + +class DirectoryReader : public VFSBackend { +public: + explicit DirectoryReader(const Path &path); + // use delete[] on the returned value. + uint8_t *ReadFile(const char *path, size_t *size) override; + bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; + bool GetFileInfo(const char *path, File::FileInfo *info) override; + std::string toString() const override { + return path_.ToString(); + } + +private: + Path path_; +}; + diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index e765c9ca78..634f53baa1 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -1,11 +1,13 @@ +#include + #include "Common/Log.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/FileUtil.h" #include "Common/File/AndroidStorage.h" VFS g_VFS; -void VFS::Register(const char *prefix, AssetReader *reader) { +void VFS::Register(const char *prefix, VFSBackend *reader) { entries_.push_back(VFSEntry{ prefix, reader }); DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); } @@ -45,7 +47,7 @@ uint8_t *VFS::ReadFile(const char *filename, size_t *size) { if (0 == memcmp(filename, entry.prefix, prefix_len)) { fileSystemFound = true; // INFO_LOG(IO, "Prefix match: %s (%s) -> %s", entries[i].prefix, filename, filename + prefix_len); - uint8_t *data = entry.reader->ReadAsset(filename + prefix_len, size); + uint8_t *data = entry.reader->ReadFile(filename + prefix_len, size); if (data) return data; else diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 41ac6ae3f9..bd6cc6f3fb 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -14,11 +14,11 @@ // on the system level, like loading assets, and maybe texture packs. Also, as mentioned, // this one is read-only, so a bit smaller and simpler. -class AssetReader { +class VFSBackend { public: - virtual ~AssetReader() {} + virtual ~VFSBackend() {} // use delete[] to release the returned memory. - virtual uint8_t *ReadAsset(const char *path, size_t *size) = 0; + virtual uint8_t *ReadFile(const char *path, size_t *size) = 0; // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; @@ -29,7 +29,7 @@ public: class VFS { public: ~VFS() { Clear(); } - void Register(const char *prefix, AssetReader *reader); + void Register(const char *prefix, VFSBackend *reader); void Clear(); // Use delete [] to release the returned memory. @@ -42,7 +42,7 @@ public: private: struct VFSEntry { const char *prefix; - AssetReader *reader; + VFSBackend *reader; }; std::vector entries_; }; diff --git a/Common/File/VFS/AssetReader.cpp b/Common/File/VFS/ZipFileReader.cpp similarity index 70% rename from Common/File/VFS/AssetReader.cpp rename to Common/File/VFS/ZipFileReader.cpp index 64116703b9..f058deb486 100644 --- a/Common/File/VFS/AssetReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include #ifdef SHARED_LIBZIP #include @@ -11,9 +12,9 @@ #include "Common/Common.h" #include "Common/Log.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/ZipFileReader.h" -uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { +static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. struct zip_stat zstat; zip_file *file = zip_fopen(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED); @@ -32,7 +33,7 @@ uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { +ZipFileReader::ZipFileReader(const char *zip_file, const char *in_zip_path) { zip_file_ = zip_open(zip_file, 0, NULL); strcpy(in_zip_path_, in_zip_path); if (!zip_file_) { @@ -50,24 +51,22 @@ ZipAssetReader::ZipAssetReader(const char *zip_file, const char *in_zip_path) { } } -ZipAssetReader::~ZipAssetReader() { +ZipFileReader::~ZipFileReader() { std::lock_guard guard(lock_); zip_close(zip_file_); } -uint8_t *ZipAssetReader::ReadAsset(const char *path, size_t *size) { - char temp_path[1024]; - strcpy(temp_path, in_zip_path_); - strcat(temp_path, path); +uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { + char temp_path[2048]; + snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); std::lock_guard guard(lock_); return ReadFromZip(zip_file_, temp_path, size); } -bool ZipAssetReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { - char path[1024]; - strcpy(path, in_zip_path_); - strcat(path, orig_path); +bool ZipFileReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { + char path[2048]; + snprintf(path, sizeof(path), "%s%s", in_zip_path_, orig_path); std::set filters; std::string tmp; @@ -123,7 +122,7 @@ bool ZipAssetReader::GetFileListing(const char *orig_path, std::vector &files, std::set &directories) { +void ZipFileReader::GetZipListings(const char *path, std::set &files, std::set &directories) { size_t pathlen = strlen(path); if (path[pathlen - 1] == '/') pathlen--; @@ -149,7 +148,7 @@ void ZipAssetReader::GetZipListings(const char *path, std::set &fil } } -bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { +bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); @@ -168,31 +167,3 @@ bool ZipAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { info->size = zstat.size; return true; } - -DirectoryAssetReader::DirectoryAssetReader(const Path &path) { - path_ = path; -} - -uint8_t *DirectoryAssetReader::ReadAsset(const char *path, size_t *size) { - Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; - return File::ReadLocalFile(new_path, size); -} - -bool DirectoryAssetReader::GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) { - Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; - - File::FileInfo info; - if (!File::GetFileInfo(new_path, &info)) - return false; - - if (info.isDirectory) { - File::GetFilesInDir(new_path, listing, filter); - return true; - } - return false; -} - -bool DirectoryAssetReader::GetFileInfo(const char *path, File::FileInfo *info) { - Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; - return File::GetFileInfo(new_path, info); -} diff --git a/Common/File/VFS/AssetReader.h b/Common/File/VFS/ZipFileReader.h similarity index 51% rename from Common/File/VFS/AssetReader.h rename to Common/File/VFS/ZipFileReader.h index b1ec629725..0480d9673d 100644 --- a/Common/File/VFS/AssetReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -8,19 +8,18 @@ #include #include -#include #include #include "Common/File/VFS/VFS.h" #include "Common/File/FileUtil.h" #include "Common/File/Path.h" -class ZipAssetReader : public AssetReader { +class ZipFileReader : public VFSBackend { public: - ZipAssetReader(const char *zip_file, const char *in_zip_path); - ~ZipAssetReader(); + ZipFileReader(const char *zip_file, const char *in_zip_path); + ~ZipFileReader(); // use delete[] on the returned value. - uint8_t *ReadAsset(const char *path, size_t *size) override; + uint8_t *ReadFile(const char *path, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { @@ -34,19 +33,3 @@ private: std::mutex lock_; char in_zip_path_[256]; }; - -class DirectoryAssetReader : public AssetReader { -public: - explicit DirectoryAssetReader(const Path &path); - // use delete[] - uint8_t *ReadAsset(const char *path, size_t *size) override; - bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; - bool GetFileInfo(const char *path, File::FileInfo *info) override; - std::string toString() const override { - return path_.ToString(); - } - -private: - Path path_; -}; - diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 0177ca9292..639806bcf5 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -25,7 +25,7 @@ QTM_USE_NAMESPACE #include "Common/System/Display.h" #include "Common/TimeUtil.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/GPU/OpenGL/GLCommon.h" #include "Common/GPU/OpenGL/GLFeatures.h" #include "Common/Input/InputState.h" @@ -191,4 +191,3 @@ private: #endif //SDL #endif - diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 833f8fdd75..e482eca117 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -67,7 +67,8 @@ #include "Common/Profiler/Profiler.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/ZipFileReader.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/CPUDetect.h" #include "Common/File/FileUtil.h" #include "Common/TimeUtil.h" @@ -467,27 +468,27 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch // We want this to be FIRST. #if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC) // Packed assets are included in app - g_VFS.Register("", new DirectoryAssetReader(Path(external_dir))); + g_VFS.Register("", new DirectoryReader(Path(external_dir))); #endif #if defined(ASSETS_DIR) - g_VFS.Register("", new DirectoryAssetReader(Path(ASSETS_DIR))); + g_VFS.Register("", new DirectoryReader(Path(ASSETS_DIR))); #endif #if !defined(MOBILE_DEVICE) && !defined(_WIN32) && !PPSSPP_PLATFORM(SWITCH) - g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory() / "assets")); - g_VFS.Register("", new DirectoryAssetReader(File::GetExeDirectory())); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/ppsspp/assets"))); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/local/share/games/ppsspp/assets"))); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/ppsspp/assets"))); - g_VFS.Register("", new DirectoryAssetReader(Path("/usr/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(File::GetExeDirectory() / "assets")); + g_VFS.Register("", new DirectoryReader(File::GetExeDirectory())); + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/games/ppsspp/assets"))); #endif #if PPSSPP_PLATFORM(SWITCH) Path assetPath = Path(user_data_path) / "assets"; - g_VFS.Register("", new DirectoryAssetReader(assetPath)); + g_VFS.Register("", new DirectoryReader(assetPath)); #else - g_VFS.Register("", new DirectoryAssetReader(Path("assets"))); + g_VFS.Register("", new DirectoryReader(Path("assets"))); #endif - g_VFS.Register("", new DirectoryAssetReader(Path(savegame_dir))); + g_VFS.Register("", new DirectoryReader(Path(savegame_dir))); #if (defined(MOBILE_DEVICE) || !defined(USING_QT_UI)) && !PPSSPP_PLATFORM(UWP) if (host == nullptr) { diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index a0747fc3e9..6160d923d6 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -306,7 +306,8 @@ - + + @@ -443,7 +444,8 @@ - + + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index f8e8679432..40b8f80da4 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -252,7 +252,10 @@ Data\Format - + + File\VFS + + File\VFS @@ -589,7 +592,10 @@ Data\Format - + + File\VFS + + File\VFS diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index c2995c8711..5fabe3a4e1 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -11,7 +11,7 @@ #include "Common/Common.h" #include "Common/Input/InputState.h" #include "Common/File/VFS/VFS.h" -#include "Common/File/VFS/AssetReader.h" +#include "Common/File/VFS/DirectoryReader.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/DirectXHelper.h" @@ -76,8 +76,8 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr Date: Mon, 6 Mar 2023 16:34:52 +0100 Subject: [PATCH 221/424] VFS: Add support for opening zip files through a Content URI --- Common/File/VFS/ZipFileReader.cpp | 35 ++++++++++++++----------------- Common/File/VFS/ZipFileReader.h | 6 +++--- android/jni/app-android.cpp | 4 ++-- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index f058deb486..aea50985bb 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -13,6 +13,7 @@ #include "Common/Common.h" #include "Common/Log.h" #include "Common/File/VFS/ZipFileReader.h" +#include "Common/StringUtils.h" static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { // Figure out the file size first. @@ -33,21 +34,17 @@ static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -ZipFileReader::ZipFileReader(const char *zip_file, const char *in_zip_path) { - zip_file_ = zip_open(zip_file, 0, NULL); - strcpy(in_zip_path_, in_zip_path); - if (!zip_file_) { - ERROR_LOG(IO, "Failed to open %s as a zip file", zip_file); +ZipFileReader::ZipFileReader(const Path &zipFile, const char *inZipPath) { + int error = 0; + if (zipFile.Type() == PathType::CONTENT_URI) { + int fd = File::OpenFD(zipFile, File::OPEN_READ); + zip_file_ = zip_fdopen(fd, 0, &error); + } else { + zip_file_ = zip_open(zipFile.c_str(), 0, &error); } - - std::vector info; - GetFileListing("assets", &info, 0); - for (size_t i = 0; i < info.size(); i++) { - if (info[i].isDirectory) { - DEBUG_LOG(IO, "Directory: %s", info[i].name.c_str()); - } else { - DEBUG_LOG(IO, "File: %s", info[i].name.c_str()); - } + truncate_cpy(inZipPath_, inZipPath); + if (!zip_file_) { + ERROR_LOG(IO, "Failed to open %s as a zip file", zipFile.c_str()); } } @@ -58,7 +55,7 @@ ZipFileReader::~ZipFileReader() { uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { char temp_path[2048]; - snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); + snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path); std::lock_guard guard(lock_); return ReadFromZip(zip_file_, temp_path, size); @@ -66,7 +63,7 @@ uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { bool ZipFileReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { char path[2048]; - snprintf(path, sizeof(path), "%s%s", in_zip_path_, orig_path); + snprintf(path, sizeof(path), "%s%s", inZipPath_, orig_path); std::set filters; std::string tmp; @@ -94,7 +91,7 @@ bool ZipFileReader::GetFileListing(const char *orig_path, std::vector &file bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { struct zip_stat zstat; char temp_path[1024]; - snprintf(temp_path, sizeof(temp_path), "%s%s", in_zip_path_, path); + snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path); if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) { // ZIP files do not have real directories, so we'll end up here if we // try to stat one. For now that's fine. diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index 0480d9673d..9930ea1bad 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -16,14 +16,14 @@ class ZipFileReader : public VFSBackend { public: - ZipFileReader(const char *zip_file, const char *in_zip_path); + ZipFileReader(const Path &zipFile, const char *inZipPath); ~ZipFileReader(); // use delete[] on the returned value. uint8_t *ReadFile(const char *path, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { - return in_zip_path_; + return inZipPath_; } private: @@ -31,5 +31,5 @@ private: zip *zip_file_; std::mutex lock_; - char in_zip_path_[256]; + char inZipPath_[256]; }; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 5fc9b2cba0..a85fba04f2 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -695,8 +695,8 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init androidVersion = jAndroidVersion; deviceType = jdeviceType; - std::string apkPath = GetJavaString(env, japkpath); - g_VFS.Register("", new ZipFileReader(apkPath.c_str(), "assets/")); + Path apkPath(GetJavaString(env, japkpath)); + g_VFS.Register("", new ZipFileReader(apkPath, "assets/")); systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); From a8bdf11fdcfdf469e203d81aeb740f71ec7d0077 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 16:56:16 +0100 Subject: [PATCH 222/424] Headless buildfix --- headless/Headless.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 5e034ede20..c61e248d0a 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -483,10 +483,10 @@ int main(int argc, const char* argv[]) #if PPSSPP_PLATFORM(ANDROID) // For some reason the debugger installs it with this name? if (File::Exists(Path("/data/app/org.ppsspp.ppsspp-2.apk"))) { - g_VFS.Register("", new ZipFileReader("/data/app/org.ppsspp.ppsspp-2.apk", "assets/")); + g_VFS.Register("", new ZipFileReader(Path("/data/app/org.ppsspp.ppsspp-2.apk"), "assets/")); } if (File::Exists(Path("/data/app/org.ppsspp.ppsspp.apk"))) { - g_VFS.Register("", new ZipFileReader("/data/app/org.ppsspp.ppsspp.apk", "assets/")); + g_VFS.Register("", new ZipFileReader(Path("/data/app/org.ppsspp.ppsspp.apk"), "assets/")); } #elif !PPSSPP_PLATFORM(WINDOWS) g_VFS.Register("", new DirectoryReader(g_Config.flash0Directory / "..")); From 3d5526a1757e7ee929c4c17821f51f75991304cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2023 10:02:59 +0100 Subject: [PATCH 223/424] Allow specifying the VFS when loading INI files. Will be useful in the tex replacer. --- Common/Data/Format/IniFile.cpp | 4 ++-- Common/Data/Format/IniFile.h | 4 +++- Common/Data/Text/I18n.cpp | 4 ++-- Common/File/VFS/VFS.h | 17 ++++++++++++----- Core/Compatibility.cpp | 5 +++-- Core/Config.cpp | 9 +++++---- Core/TextureReplacer.cpp | 9 +++++---- GPU/Common/PostShader.cpp | 2 +- UI/Theme.cpp | 2 +- 9 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index 27f38e3c16..02bd00d2ef 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -567,9 +567,9 @@ bool IniFile::Load(const Path &path) return success; } -bool IniFile::LoadFromVFS(const std::string &filename) { +bool IniFile::LoadFromVFS(VFSInterface &vfs, const std::string &filename) { size_t size; - uint8_t *data = g_VFS.ReadFile(filename.c_str(), &size); + uint8_t *data = vfs.ReadFile(filename.c_str(), &size); if (!data) return false; std::string str((const char*)data, size); diff --git a/Common/Data/Format/IniFile.h b/Common/Data/Format/IniFile.h index 707f0ab3eb..1008fff5df 100644 --- a/Common/Data/Format/IniFile.h +++ b/Common/Data/Format/IniFile.h @@ -11,6 +11,8 @@ #include "Common/File/Path.h" +class VFSInterface; + class Section { friend class IniFile; @@ -86,7 +88,7 @@ public: bool Load(const Path &path); bool Load(const std::string &filename) { return Load(Path(filename)); } bool Load(std::istream &istream); - bool LoadFromVFS(const std::string &filename); + bool LoadFromVFS(VFSInterface &vfs, const std::string &filename); bool Save(const Path &path); bool Save(const std::string &filename) { return Save(Path(filename)); } diff --git a/Common/Data/Text/I18n.cpp b/Common/Data/Text/I18n.cpp index ebcb95a90e..ab5509dcbd 100644 --- a/Common/Data/Text/I18n.cpp +++ b/Common/Data/Text/I18n.cpp @@ -91,7 +91,7 @@ bool I18NRepo::LoadIni(const std::string &languageID, const Path &overridePath) iniPath = GetIniPath(languageID); } - if (!ini.LoadFromVFS(iniPath.ToString())) + if (!ini.LoadFromVFS(g_VFS, iniPath.ToString())) return false; Clear(); @@ -127,7 +127,7 @@ I18NCategory *I18NRepo::LoadSection(const Section *section, const char *name) { return cat; } -// This is a very light touched save variant - it won't overwrite +// This is a very light touched save variant - it won't overwrite // anything, only create new entries. void I18NRepo::SaveIni(const std::string &languageID) { IniFile ini; diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index bd6cc6f3fb..544ad969b7 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -14,11 +14,18 @@ // on the system level, like loading assets, and maybe texture packs. Also, as mentioned, // this one is read-only, so a bit smaller and simpler. -class VFSBackend { +// Common inteface parts between VFSBackend and VFS. +// Sometimes you don't need the VFS multiplexing and only have a VFSBackend *, sometimes you do need it, +// and it would be cool to be able to use the same interface, like when loading INI files. +class VFSInterface { public: - virtual ~VFSBackend() {} - // use delete[] to release the returned memory. + virtual ~VFSInterface() {} virtual uint8_t *ReadFile(const char *path, size_t *size) = 0; +}; + +class VFSBackend : public VFSInterface { +public: + // use delete[] to release the returned memory. // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; @@ -26,7 +33,7 @@ public: virtual std::string toString() const = 0; }; -class VFS { +class VFS : public VFSInterface { public: ~VFS() { Clear(); } void Register(const char *prefix, VFSBackend *reader); @@ -35,7 +42,7 @@ public: // Use delete [] to release the returned memory. // Always allocates an extra zero byte at the end, so that it // can be used for text like shader sources. - uint8_t *ReadFile(const char *filename, size_t *size); + uint8_t *ReadFile(const char *filename, size_t *size) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0); bool GetFileInfo(const char *filename, File::FileInfo *fileInfo); diff --git a/Core/Compatibility.cpp b/Core/Compatibility.cpp index a40a62bf4d..bf4d1a564d 100644 --- a/Core/Compatibility.cpp +++ b/Core/Compatibility.cpp @@ -19,6 +19,7 @@ #include "Common/Log.h" #include "Common/Data/Format/IniFile.h" +#include "Common/File/VFS/VFS.h" #include "Common/StringUtils.h" #include "Core/Compatibility.h" #include "Core/Config.h" @@ -38,7 +39,7 @@ void Compatibility::Load(const std::string &gameID) { { IniFile compat; // This loads from assets. - if (compat.LoadFromVFS("compat.ini")) { + if (compat.LoadFromVFS(g_VFS, "compat.ini")) { CheckSettings(compat, gameID); } } @@ -55,7 +56,7 @@ void Compatibility::Load(const std::string &gameID) { { IniFile compat; // This loads from assets. - if (compat.LoadFromVFS("compatvr.ini")) { + if (compat.LoadFromVFS(g_VFS, "compatvr.ini")) { CheckVRSettings(compat, gameID); } } diff --git a/Core/Config.cpp b/Core/Config.cpp index 99575c3e33..ca8e44e023 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -39,6 +39,7 @@ #include "Common/Data/Text/Parsers.h" #include "Common/CPUDetect.h" #include "Common/File/FileUtil.h" +#include "Common/File/VFS/VFS.h" #include "Common/LogManager.h" #include "Common/OSVersion.h" #include "Common/System/Display.h" @@ -436,7 +437,7 @@ const char *DefaultLangRegion() { } else if (langRegion.length() >= 3) { // Don't give up. Let's try a fuzzy match - so nl_BE can match nl_NL. IniFile mapping; - mapping.LoadFromVFS("langregion.ini"); + mapping.LoadFromVFS(g_VFS, "langregion.ini"); std::vector keys; mapping.GetKeys("LangRegionNames", keys); @@ -1222,7 +1223,7 @@ Config::~Config() { void Config::LoadLangValuesMapping() { IniFile mapping; - mapping.LoadFromVFS("langregion.ini"); + mapping.LoadFromVFS(g_VFS, "langregion.ini"); std::vector keys; mapping.GetKeys("LangRegionNames", keys); @@ -1932,8 +1933,8 @@ bool Config::loadGameConfig(const std::string &pGameId, const std::string &title }); KeyMap::LoadFromIni(iniFile); - - if (!appendedConfigFileName_.ToString().empty() && + + if (!appendedConfigFileName_.ToString().empty() && std::find(appendedConfigUpdatedGames_.begin(), appendedConfigUpdatedGames_.end(), pGameId) == appendedConfigUpdatedGames_.end()) { LoadAppendedConfig(); diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index ef6f20e27c..0bfee36647 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -35,6 +35,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" #include "Common/File/FileUtil.h" +#include "Common/File/VFS/VFS.h" #include "Common/LogReporting.h" #include "Common/StringUtils.h" #include "Common/Thread/ParallelLoop.h" @@ -179,7 +180,7 @@ bool TextureReplacer::LoadIni() { } if (!iniLoaded) { - iniLoaded = ini.LoadFromVFS((basePath_ / INI_FILENAME).ToString()); + iniLoaded = ini.LoadFromVFS(g_VFS, (basePath_ / INI_FILENAME).ToString()); } if (iniLoaded) { @@ -196,7 +197,7 @@ bool TextureReplacer::LoadIni() { std::lock_guard guard(zip_.lock); iniLoaded = LoadIniZip(overrideIni, zip_.z, overrideFilename); } else { - iniLoaded = overrideIni.LoadFromVFS((basePath_ / overrideFilename).ToString()); + iniLoaded = overrideIni.LoadFromVFS(g_VFS, (basePath_ / overrideFilename).ToString()); } if (!iniLoaded) { ERROR_LOG(G3D, "Failed to load extra texture ini: %s", overrideFilename.c_str()); @@ -298,7 +299,7 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { if (ini.HasSection("reducehashranges")) { auto reducehashranges = ini.GetOrCreateSection("reducehashranges")->ToMap(); - // Format: w,h = reducehashvalues + // Format: w,h = reducehashvalues for (const auto& item : reducehashranges) { ParseReduceHashRange(item.first, item.second); } @@ -390,7 +391,7 @@ void TextureReplacer::ParseReduceHashRange(const std::string& key, const std::st const u64 reducerangeKey = ((u64)forW << 16) | forH; reducehashranges_[reducerangeKey] = rhashvalue; -} +} u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV) { _dbg_assert_msg_(enabled_, "Replacement not enabled"); diff --git a/GPU/Common/PostShader.cpp b/GPU/Common/PostShader.cpp index ae03877d98..51864c903c 100644 --- a/GPU/Common/PostShader.cpp +++ b/GPU/Common/PostShader.cpp @@ -90,7 +90,7 @@ void LoadPostShaderInfo(Draw::DrawContext *draw, const std::vector &direct if (path.ToString().substr(0, 7) == "assets/") path = Path(path.ToString().substr(7)); - if (ini.LoadFromVFS(name.ToString()) || ini.Load(fileInfo[f].fullName)) { + if (ini.LoadFromVFS(g_VFS, name.ToString()) || ini.Load(fileInfo[f].fullName)) { success = true; // vsh load. meh. } diff --git a/UI/Theme.cpp b/UI/Theme.cpp index f733c37c75..9119259e7c 100644 --- a/UI/Theme.cpp +++ b/UI/Theme.cpp @@ -104,7 +104,7 @@ static void LoadThemeInfo(const std::vector &directories) { if (path.ToString().substr(0, 7) == "assets/") path = Path(path.ToString().substr(7)); - if (ini.LoadFromVFS(name.ToString()) || ini.Load(fileInfo[f].fullName)) { + if (ini.LoadFromVFS(g_VFS, name.ToString()) || ini.Load(fileInfo[f].fullName)) { success = true; } From 9fe7eabadee3264622384f29ead5d9746348dc97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 23:25:49 +0100 Subject: [PATCH 224/424] IniFile: Allow specifying which VFS to load from --- Common/Data/Format/IniFile.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Common/Data/Format/IniFile.cpp b/Common/Data/Format/IniFile.cpp index 02bd00d2ef..91c042d5b4 100644 --- a/Common/Data/Format/IniFile.cpp +++ b/Common/Data/Format/IniFile.cpp @@ -582,10 +582,10 @@ bool IniFile::LoadFromVFS(VFSInterface &vfs, const std::string &filename) { bool IniFile::Load(std::istream &in) { // Maximum number of letters in a line static const int MAX_BYTES = 1024*32; + char *templine = new char[MAX_BYTES]; // avoid using up massive stack space while (!(in.eof() || in.fail())) { - char templine[MAX_BYTES]; in.getline(templine, MAX_BYTES); std::string line = templine; @@ -624,6 +624,7 @@ bool IniFile::Load(std::istream &in) { } } + delete[] templine; return true; } From 23b310f59a054739e8ac1245ecbf0027fa304111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 17:30:13 +0100 Subject: [PATCH 225/424] VFS: Add boilerplate --- Common/File/VFS/DirectoryReader.cpp | 36 +++++++++++++++++++++++++++++ Common/File/VFS/DirectoryReader.h | 10 +++++++- Common/File/VFS/VFS.h | 24 +++++++++++++++++++ Common/File/VFS/ZipFileReader.cpp | 34 +++++++++++++++++++++++++++ Common/File/VFS/ZipFileReader.h | 9 ++++++++ 5 files changed, 112 insertions(+), 1 deletion(-) diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp index d979dd4d7c..332bb0bb48 100644 --- a/Common/File/VFS/DirectoryReader.cpp +++ b/Common/File/VFS/DirectoryReader.cpp @@ -29,3 +29,39 @@ bool DirectoryReader::GetFileInfo(const char *path, File::FileInfo *info) { Path new_path = Path(path).StartsWith(path_) ? Path(path) : path_ / path; return File::GetFileInfo(new_path, info); } + +class DirectoryReaderFileReference : public VFSFileReference { +public: + Path path; +}; + +class DirectoryReaderOpenFile : public VFSOpenFile { +public: + FILE *file; +}; + +VFSFileReference *DirectoryReader::GetFile(const char *path) { + return nullptr; +} + +void DirectoryReader::ReleaseFile(VFSFileReference *reference) { + DirectoryReaderFileReference *file = (DirectoryReaderFileReference *)reference; +} + +VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *reference) { + DirectoryReaderFileReference *file = (DirectoryReaderFileReference *)reference; + return nullptr; +} + +void DirectoryReader::Rewind(VFSOpenFile *openFile) { + DirectoryReaderOpenFile *file = (DirectoryReaderOpenFile *)openFile; +} + +size_t DirectoryReader::Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) { + DirectoryReaderOpenFile *file = (DirectoryReaderOpenFile *)openFile; + return 0; +} + +void DirectoryReader::CloseFile(VFSOpenFile *openFile) { + DirectoryReaderOpenFile *file = (DirectoryReaderOpenFile *)openFile; +} diff --git a/Common/File/VFS/DirectoryReader.h b/Common/File/VFS/DirectoryReader.h index facd3efe72..00cb8f7878 100644 --- a/Common/File/VFS/DirectoryReader.h +++ b/Common/File/VFS/DirectoryReader.h @@ -9,6 +9,15 @@ public: explicit DirectoryReader(const Path &path); // use delete[] on the returned value. uint8_t *ReadFile(const char *path, size_t *size) override; + + virtual VFSFileReference *GetFile(const char *path) override; + virtual void ReleaseFile(VFSFileReference *reference) override; + + virtual VFSOpenFile *OpenFileForRead(VFSFileReference *reference) override; + virtual void Rewind(VFSOpenFile *openFile) override; + virtual size_t Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) override; + virtual void CloseFile(VFSOpenFile *openFile) override; + bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { @@ -18,4 +27,3 @@ public: private: Path path_; }; - diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 544ad969b7..6c94bfbecb 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -14,6 +14,22 @@ // on the system level, like loading assets, and maybe texture packs. Also, as mentioned, // this one is read-only, so a bit smaller and simpler. +// VFSBackend instances can be used on their own, without the VFS, to serve as an abstraction of +// a single directory or ZIP file. + +// The VFSFileReference level of abstraction is there to hold things like zip file indices, +// for fast re-open etc. + +class VFSFileReference { +public: + virtual ~VFSFileReference() {} +}; + +class VFSOpenFile { +public: + virtual ~VFSOpenFile() {} +}; + // Common inteface parts between VFSBackend and VFS. // Sometimes you don't need the VFS multiplexing and only have a VFSBackend *, sometimes you do need it, // and it would be cool to be able to use the same interface, like when loading INI files. @@ -27,6 +43,14 @@ class VFSBackend : public VFSInterface { public: // use delete[] to release the returned memory. + virtual VFSFileReference *GetFile(const char *path) = 0; + virtual void ReleaseFile(VFSFileReference *file) = 0; + + virtual VFSOpenFile *OpenFileForRead(VFSFileReference *reference) = 0; + virtual void Rewind(VFSOpenFile *file) = 0; + virtual size_t Read(VFSOpenFile *file, uint8_t *buffer, size_t length) = 0; + virtual void CloseFile(VFSOpenFile *file) = 0; + // Filter support is optional but nice to have virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index aea50985bb..2c63a9c4db 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -164,3 +164,37 @@ bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { info->size = zstat.size; return true; } + +class ZipFileReaderFileReference : public VFSFileReference { +public: +}; + +class ZipFileReaderOpenFile : public VFSOpenFile { +public: +}; + +VFSFileReference *ZipFileReader::GetFile(const char *path) { + return nullptr; +} + +void ZipFileReader::ReleaseFile(VFSFileReference *reference) { + ZipFileReaderFileReference *file = (ZipFileReaderFileReference *)reference; +} + +VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *reference) { + ZipFileReaderFileReference *file = (ZipFileReaderFileReference *)reference; + return nullptr; +} + +void ZipFileReader::Rewind(VFSOpenFile *openFile) { + ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile; +} + +size_t ZipFileReader::Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) { + ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile; + return 0; +} + +void ZipFileReader::CloseFile(VFSOpenFile *openFile) { + ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile; +} diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index 9930ea1bad..841491fb44 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -20,6 +20,15 @@ public: ~ZipFileReader(); // use delete[] on the returned value. uint8_t *ReadFile(const char *path, size_t *size) override; + + VFSFileReference *GetFile(const char *path) override; + void ReleaseFile(VFSFileReference *reference) override; + + VFSOpenFile *OpenFileForRead(VFSFileReference *reference) override; + void Rewind(VFSOpenFile *openFile) override; + size_t Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) override; + void CloseFile(VFSOpenFile *openFile) override; + bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; std::string toString() const override { From 433be0a098d7789cdd59ed61a13a1dd9ce798e94 Mon Sep 17 00:00:00 2001 From: Felipe Date: Tue, 7 Mar 2023 13:26:23 -0300 Subject: [PATCH 226/424] Updated brazilian portuguese Updated all strings based on the several changes that were made. --- assets/lang/pt_BR.ini | 62 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 61a97a6d42..f7963e1dff 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -114,11 +114,11 @@ Swipe = Deslizar Swipe sensitivity = Sensibilidade do deslizar Swipe smoothing = Suavidade do deslizar Thin borders = Bordas finas -Tilt control setup = Personalizar inclinação... +Tilt control setup = Configuração do controle da inclinação Tilt Input Type = Controle da entrada da inclinação Tilt Sensitivity along X axis = Sensibilidade da inclinação junto ao eixo X Tilt Sensitivity along Y axis = Sensibilidade da inclinação junto ao eixo Y -To Calibrate = Segure o dispositivo em seu ângulo preferido e pressione "Calibrar". +To Calibrate = Mantenha o dispositivo no seu ângulo preferido e pressione "Calibrar". Toggle mode = Alternar modo Repeat mode = Modo de repetição Touch Control Visibility = Visibilidade do controle de toque @@ -243,7 +243,7 @@ Backspace = Backspace Block address = Bloquear endereço By Address = Pelo endereço Copy savestates to memstick root = Copiar os save states pra raiz do cartão de memória -Create/Open textures.ini file for current game = Criar/abrir o arquivo textures.ini pro jogo atual +Create/Open textures.ini file for current game = Criar/Abrir o arquivo textures.ini pro jogo atual Current = Atual Dev Tools = Ferramentas de desenvolvimento DevMenu = Menu do DEV @@ -262,7 +262,7 @@ GPU Profile = Perfil da GPU GPU log profiler = Criador do perfil do registro da GPU Jit Compare = Comparar JIT JIT debug tools = Ferramentas de debug do JIT -Log Dropped Frame Statistics = Pôr no registro as estátisticas da queda dos frames +Log Dropped Frame Statistics = Registrar as estátisticas da queda dos frames Log Level = Nível do registro Log View = Visualização do registro Logging Channels = Canais do registro @@ -273,7 +273,7 @@ Random = Aleatório Replace textures = Substituir texturas Reset = Resetar Reset limited logging = Resetar o registro limitado -RestoreDefaultSettings = Você tem certeza que você quer restaurar todas as configurações de volta aos padrões delas?\n\nVocê não pode desfazer isto.\nPor favor reinicie o PPSSPP para as mudanças terem efeito. +RestoreDefaultSettings = Restaurar estas configurações aos padrões delas?\nVocê não pode desfazer isto.\nPor favor reinicie o PPSSPP após restaurar as configurações. RestoreGameDefaultSettings = Você tem certeza que você quer restaurar as configurações específicas do jogo\nde volta para os padrões do PPSSPP? Resume = Resumo Run CPU Tests = Executar testes da CPU @@ -372,11 +372,11 @@ Zoom = Zoom A PSP game couldn't be found on the disc. = Um jogo de PSP não pôde ser achado no disco. Cannot boot ELF located outside mountRoot. = Não pôde dar boot no ELF localizado fora do mountRoot. Could not save screenshot file = Não pôde salvar o arquivo da screenshot. -D3D9or11 = Direct3D 9? (ou "não" pro Direct3D 11) +D3D9or11 = Direct3D 9? (Ou "não" pro Direct3D 11) D3D11CompilerMissing = O D3DCompiler_47.dll não foi achado. Por favor instale-o. Ou pressione Sim pra tentar de novo usando o Direct3D 9 ao invés disto. D3D11InitializationError = Erro de inicialização do Direct3D 11 -D3D11Missing = Sua versão do sistema operacional não inclui o D3D11. Por favor execute o Windows Update.\n\nPressione Sim pra tentar de novo usando o Direct3D 9 ao invés disto. -D3D11NotSupported = Sua GPU não aparenta suportar o Direct3D 11.\n\nVocê gostaria de tentar de novo usando o Direct3D 9 ao invés disto? +D3D11Missing = Sua versão do sistema operacional não inclui o D3D11. Por favor execute o Windows Update.\n\nPressione Sim pra tentar de novo usando o Direct3D 9 ao invés deste. +D3D11NotSupported = Sua GPU não aparenta suportar o Direct3D 11.\n\nVocê gostaria de tentar de novo usando o Direct3D 9 ao invés deste? Disk full while writing data = O disco ficou cheio enquanto gravava os dados. ELF file truncated - can't load = Arquivo ELF truncado - não pôde carregar Error loading file = Não pôde carregar o arquivo. @@ -405,7 +405,7 @@ OpenGLDriverError = Erro do driver do OpenGL PPSSPP doesn't support UMD Music. = O PPSSPP não suporta a música do UMD. PPSSPP doesn't support UMD Video. = O PPSSPP não suporta o vídeo do UMD. PPSSPP plays PSP games, not PlayStation 1 or 2 games. = O PPSSPP roda jogos de PSP, não jogos de PlayStation 1 ou 2. -PPSSPPDoesNotSupportInternet = O PPSSPP atualmente não suporta conexão com a Internet pra DLC, PSN ou atualizações de jogos. +PPSSPPDoesNotSupportInternet = O PPSSPP atualmente não suporta conexão com a Internet pro DLC, PSN ou atualizações de jogos. PS1 EBOOTs are not supported by PPSSPP. = OS EBOOTS do PS1 não são suportados pelo PPSSPP. PSX game image detected. = O arquivo é uma imagem do MODE2. O PPSSPP não suporta jogos de PS1. RAR file detected (Require UnRAR) = O arquivo está comprimido (RAR).\nPor favor descomprima-o primeiro (tente o UnRAR). @@ -482,7 +482,7 @@ Aspect Ratio = Proporção do Aspecto Auto = Auto Auto (1:1) = Auto (1:1) Auto (same as Rendering) = Auto (a mesma que a da resolução de renderização) -Auto FrameSkip = Auto-pulo dos frames +Auto FrameSkip = Auto frameskip Auto Max Quality = Auto-maximizar a qualidade Auto Scaling = Auto-redimensionamento Backend = Backend @@ -517,7 +517,7 @@ Frame Skipping = Pulo dos frames Frame Skipping Type = Tipo de pulo dos frames FullScreen = Tela cheia Geometry shader culling = Abate do shader da geometria -Hack Settings = Configurações dos hacks (pode causar erros gráficos) +Hack Settings = Configurações dos hacks (pode causar erros gráficos) Hardware Tessellation = Tesselação por hardware Hardware Transform = Transformação por hardware hardware transform error - falling back to software = Erro de transformação pelo hardware, retrocedendo pro software. @@ -541,8 +541,8 @@ Must Restart = Você deve reiniciar o PPSSPP pra esta mudança ter efeito. Native device resolution = Resolução nativa do dispositivo Nearest = Mais próximo No buffer = Sem buffer -Show Battery % = Show Battery % -Show Speed = Show Speed +Show Battery % = Mostrar Bateria % +Show Speed = Mostrar Velocidade Skip Buffer Effects = Ignorar efeitos do buffer None = Nenhum Number of Frames = Número de frames @@ -564,7 +564,7 @@ Safe = Seguro Screen Scaling Filter = Filtro do dimensionamento da tela Show Debug Statistics = Mostrar estatísticas do debug Show FPS Counter = Mostrar contador de FPS -Skip GPU Readbacks = Ignorar Leituras da GPU +Skip GPU Readbacks = Ignorar leituras da GPU Software Rendering = Renderização por software (lento) Software Skinning = Skinning via software SoftwareSkinning Tip = Combina os desenhos dos modelos de skinning na CPU, mais rápido na maioria dos jogos @@ -599,7 +599,7 @@ Install game from ZIP file? = Instalar o jogo do arquivo ZIP? Install textures from ZIP file? = Instalar as texturas do arquivo ZIP? Installed! = Instalado! Texture pack doesn't support install = O pacote das texturas não suporta a instalação -Zip archive corrupt = Arquivo ZIP compactado corrompido +Zip archive corrupt = Arquivo ZIP corrompido Zip file does not contain PSP software = O arquivo ZIP não contém software do PSP [KeyMapping] @@ -696,15 +696,15 @@ R = R RapidFire = Fogo rápido Record = Gravar Remote hold = Segurar remoto -Rewind = Rebobinar +Rewind = Retroceder Right = Direcional Direito Right Analog Stick = Direcional Análogico Direito RightAn.Down = Analógico Direito pra Baixo RightAn.Left = Analógico Direito a Esquerda RightAn.Right = Analógico Direito a Direita RightAn.Up = Analógico Direito pra Cima -Rotate Analog (CCW) = Rotação do analógico (Anti-horário) -Rotate Analog (CW) = Rotação do analógico (sentido horário) +Rotate Analog (CCW) = Rotação do analógico (Sentido anti-horário) +Rotate Analog (CW) = Rotação do analógico (Sentido horário) Save State = Salvar state Screen = Tela Screenshot = Screenshot @@ -807,7 +807,7 @@ Delete Game Config = Apagar configuração do jogo Exit to menu = Sair pro menu Game Settings = Configurações do jogo Load State = Carregar state -Rewind = Rebobinar +Rewind = Retroceder Save State = Salvar state Settings = Configurações Switch UMD = Trocar UMD @@ -886,10 +886,10 @@ tools = Ferramentas grátis usadas: # Leave extra lines blank. 4 contributors per line seems to look best. translators1 = Papel, gabrielmop, Efraim Lopes, AkiraJkr translators2 = Felipe -translators3 = -translators4 = -translators5 = -translators6 = +translators3 = +translators4 = +translators5 = +translators6 = Twitter @PPSSPP_emu = Twitter @PPSSPP_emu website = Verifique o site da web: written = Escrito em C++ pela velocidade e portabilidade @@ -932,7 +932,7 @@ Remote Port = Porta remota Remote Server = Servidor remoto Remote Subdirectory = Sub-diretório remoto RemoteISODesc = Os jogos na sua lista de "Recentes" serão compartilhados -RemoteISOLoading = Conectado, carregando a lista de jogos... +RemoteISOLoading = Conectado, carregando a lista dos jogos... RemoteISOScanning = Escaneando... Cliqme em "compartilhar jogos" no dispositivo do seu servidor RemoteISOScanningTimeout = Escaneando... Verifique suas configurações do firewall na área de trabalho RemoteISOWifi = Nota: Conecte os dois dispositivos na mesma rede Wi-Fi @@ -1062,7 +1062,7 @@ Debugger Present = Debugger presente Depth buffer format = Formato do buffer de profundidade Device Info = Informação do dispositivo Directories = Diretórios -Display Information = Informação da tela +Display Information = Exibir informação DPI = DPI Driver bugs = Bugs do driver Driver Version = Versão do driver @@ -1143,13 +1143,13 @@ Fast (lag on slow storage) = Rápido (atraso na armazenagem lenta) Fast Memory = Memória rápida (instável) Floating symbols = Símbolos flutuantes Force real clock sync (slower, less lag) = Forçar sincronização com o relógio real (mais lento, menos atrasos) -seconds, 0:off = seconds, 0 = Desligado +seconds, 0:off = segundos, 0 = Desligado Game crashed = O jogo teve um crash Games list settings = Configurações da lista de jogos General = Geral Grid icon size = Tamanho do ícone da grade Help the PPSSPP team = Ajude o time do PPSSPP -Host (bugs, less lag) = Hospedeiro (bugs, menos atrasos) +Host (bugs, less lag) = Hospedeiro (tem bugs, menos atrasos) Ignore bad memory accesses = Ignorar acessos ruins da memória Increase size = Aumentar tamanho Interpreter = Interpretador @@ -1177,13 +1177,13 @@ Record Audio = Gravar áudio Record Display = Gravar tela Reset Recording on Save/Load State = Resetar a gravação ao salvar/carregar o state Restore Default Settings = Restaurar as configurações do PPSSPP para os padrões -Rewind Snapshot Frequency = Retroceder a frequência dos snapshots (consome memória) +Rewind Snapshot Frequency = Retroceder a frequência dos snapshots (consome muita memória) Save path in installed.txt = Caminho do save em installed.txt Save path in My Documents = Caminho do save em Meus Documentos Savestate Slot = Slot do state salvo Savestate slot backups = Backups dos slots dos states salvos Screenshots as PNG = Salvar as screenshots no formato PNG -Set Memory Stick folder = Set Memory Stick folder +Set Memory Stick folder = Definir a pasta do cartão de memória Set UI background... = Definir o cenário de fundo da interface do usuário... Show ID = Mostrar ID Show region flag = Mostrar a bandeira da região @@ -1255,9 +1255,9 @@ Screen representation = Representação da tela % of native FoV = % do campo de visão nativo 6DoF movement = Movimentação do 6DoF Distance to 2D menus and scenes = Distância até os menus e cenas 2D -Field of view scale = Campo da escala de visualização +Field of view scale = Escala do campo de visualização Force 72Hz update = Forçar atualização em 72 Hz -Heads-up display scale = Aviso da escala de exibição +Heads-up display scale = Escala do aviso antecipado da exibição Map controller movements to keys = Mapear os movimentos do controle nas teclas Motion needed to generate action = Movimento necessário pra gerar ação Stereoscopic vision (Experimental) = Visão estereoscópica (Experimental) From 97cf5f8d81ec8221e2c074d2dee553efe4e48e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Mar 2023 22:46:05 +0100 Subject: [PATCH 227/424] More renaming, initial implementation of manual file access for both VFS backends --- Common/File/VFS/DirectoryReader.cpp | 44 +++++++---- Common/File/VFS/DirectoryReader.h | 13 ++-- Common/File/VFS/VFS.h | 17 +++-- Common/File/VFS/ZipFileReader.cpp | 114 ++++++++++++++++++++++------ Common/File/VFS/ZipFileReader.h | 18 +++-- 5 files changed, 148 insertions(+), 58 deletions(-) diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp index 332bb0bb48..e4da6a712d 100644 --- a/Common/File/VFS/DirectoryReader.cpp +++ b/Common/File/VFS/DirectoryReader.cpp @@ -41,27 +41,45 @@ public: }; VFSFileReference *DirectoryReader::GetFile(const char *path) { - return nullptr; + DirectoryReaderFileReference *reference = new DirectoryReaderFileReference(); + reference->path = path_ / path; + return reference; } -void DirectoryReader::ReleaseFile(VFSFileReference *reference) { - DirectoryReaderFileReference *file = (DirectoryReaderFileReference *)reference; +bool DirectoryReader::GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) { + DirectoryReaderFileReference *reference = (DirectoryReaderFileReference *)vfsReference; + return File::GetFileInfo(reference->path, fileInfo); } -VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *reference) { - DirectoryReaderFileReference *file = (DirectoryReaderFileReference *)reference; - return nullptr; +void DirectoryReader::ReleaseFile(VFSFileReference *vfsReference) { + DirectoryReaderFileReference *reference = (DirectoryReaderFileReference *)vfsReference; + delete reference; } -void DirectoryReader::Rewind(VFSOpenFile *openFile) { - DirectoryReaderOpenFile *file = (DirectoryReaderOpenFile *)openFile; +VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *vfsReference) { + DirectoryReaderFileReference *reference = (DirectoryReaderFileReference *)vfsReference; + FILE *file = File::OpenCFile(reference->path, "rb"); + if (!file) { + return nullptr; + } + + DirectoryReaderOpenFile *openFile = new DirectoryReaderOpenFile(); + openFile->file = file; + return openFile; } -size_t DirectoryReader::Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) { - DirectoryReaderOpenFile *file = (DirectoryReaderOpenFile *)openFile; - return 0; +void DirectoryReader::Rewind(VFSOpenFile *vfsOpenFile) { + DirectoryReaderOpenFile *openFile = (DirectoryReaderOpenFile *)vfsOpenFile; + fseek(openFile->file, 0, SEEK_SET); } -void DirectoryReader::CloseFile(VFSOpenFile *openFile) { - DirectoryReaderOpenFile *file = (DirectoryReaderOpenFile *)openFile; +size_t DirectoryReader::Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) { + DirectoryReaderOpenFile *openFile = (DirectoryReaderOpenFile *)vfsOpenFile; + return fread(buffer, 1, length, openFile->file); +} + +void DirectoryReader::CloseFile(VFSOpenFile *vfsOpenFile) { + DirectoryReaderOpenFile *openFile = (DirectoryReaderOpenFile *)vfsOpenFile; + fclose(openFile->file); + delete openFile; } diff --git a/Common/File/VFS/DirectoryReader.h b/Common/File/VFS/DirectoryReader.h index 00cb8f7878..cc6d971371 100644 --- a/Common/File/VFS/DirectoryReader.h +++ b/Common/File/VFS/DirectoryReader.h @@ -10,13 +10,14 @@ public: // use delete[] on the returned value. uint8_t *ReadFile(const char *path, size_t *size) override; - virtual VFSFileReference *GetFile(const char *path) override; - virtual void ReleaseFile(VFSFileReference *reference) override; + VFSFileReference *GetFile(const char *path) override; + bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) override; + void ReleaseFile(VFSFileReference *vfsReference) override; - virtual VFSOpenFile *OpenFileForRead(VFSFileReference *reference) override; - virtual void Rewind(VFSOpenFile *openFile) override; - virtual size_t Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) override; - virtual void CloseFile(VFSOpenFile *openFile) override; + VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) override; + void Rewind(VFSOpenFile *vfsOpenFile) override; + size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) override; + void CloseFile(VFSOpenFile *vfsOpenFile) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 6c94bfbecb..22a242c903 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -30,13 +30,14 @@ public: virtual ~VFSOpenFile() {} }; -// Common inteface parts between VFSBackend and VFS. +// Common interface parts between VFSBackend and VFS. // Sometimes you don't need the VFS multiplexing and only have a VFSBackend *, sometimes you do need it, // and it would be cool to be able to use the same interface, like when loading INI files. class VFSInterface { public: virtual ~VFSInterface() {} virtual uint8_t *ReadFile(const char *path, size_t *size) = 0; + virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) = 0; }; class VFSBackend : public VFSInterface { @@ -44,15 +45,15 @@ public: // use delete[] to release the returned memory. virtual VFSFileReference *GetFile(const char *path) = 0; - virtual void ReleaseFile(VFSFileReference *file) = 0; + virtual bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) = 0; + virtual void ReleaseFile(VFSFileReference *vfsReference) = 0; - virtual VFSOpenFile *OpenFileForRead(VFSFileReference *reference) = 0; - virtual void Rewind(VFSOpenFile *file) = 0; - virtual size_t Read(VFSOpenFile *file, uint8_t *buffer, size_t length) = 0; - virtual void CloseFile(VFSOpenFile *file) = 0; + virtual VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) = 0; + virtual void Rewind(VFSOpenFile *vfsOpenFile) = 0; + virtual size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) = 0; + virtual void CloseFile(VFSOpenFile *vfsOpenFile) = 0; // Filter support is optional but nice to have - virtual bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0) = 0; virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0; virtual std::string toString() const = 0; }; @@ -67,8 +68,8 @@ public: // Always allocates an extra zero byte at the end, so that it // can be used for text like shader sources. uint8_t *ReadFile(const char *filename, size_t *size) override; - bool GetFileListing(const char *path, std::vector *listing, const char *filter = 0); bool GetFileInfo(const char *filename, File::FileInfo *fileInfo); + bool GetFileListing(const char *path, std::vector *listing, const char *filter = nullptr) override; private: struct VFSEntry { diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index 2c63a9c4db..1ba7e5bf9f 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -34,18 +34,29 @@ static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { return contents; } -ZipFileReader::ZipFileReader(const Path &zipFile, const char *inZipPath) { +ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath) { int error = 0; + zip *zip_file; if (zipFile.Type() == PathType::CONTENT_URI) { int fd = File::OpenFD(zipFile, File::OPEN_READ); - zip_file_ = zip_fdopen(fd, 0, &error); + if (!fd) { + ERROR_LOG(IO, "Failed to open FD for %s as zip file", zipFile.c_str()); + return nullptr; + } + zip_file = zip_fdopen(fd, 0, &error); } else { - zip_file_ = zip_open(zipFile.c_str(), 0, &error); + zip_file = zip_open(zipFile.c_str(), 0, &error); } - truncate_cpy(inZipPath_, inZipPath); - if (!zip_file_) { + + if (!zip_file) { ERROR_LOG(IO, "Failed to open %s as a zip file", zipFile.c_str()); + return nullptr; } + + ZipFileReader *reader = new ZipFileReader(); + reader->zip_file_ = zip_file; + truncate_cpy(reader->inZipPath_, inZipPath); + return reader; } ZipFileReader::~ZipFileReader() { @@ -78,6 +89,7 @@ bool ZipFileReader::GetFileListing(const char *orig_path, std::vectorexists = false; - info->size = 0; - return false; + + { + std::lock_guard guard(lock_); + if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) { + // ZIP files do not have real directories, so we'll end up here if we + // try to stat one. For now that's fine. + info->exists = false; + info->size = 0; + return false; + } } info->fullName = Path(path); @@ -167,34 +183,84 @@ bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { class ZipFileReaderFileReference : public VFSFileReference { public: + int zi; }; class ZipFileReaderOpenFile : public VFSOpenFile { public: + ZipFileReaderFileReference *reference; + zip_file_t *zf; }; +static constexpr zip_uint64_t INVALID_ZIP_SIZE = 0xFFFFFFFFFFFFFFFFULL; + VFSFileReference *ZipFileReader::GetFile(const char *path) { - return nullptr; + std::lock_guard guard(lock_); + int zi = zip_name_locate(zip_file_, path, ZIP_FL_NOCASE); + if (zi < 0) { + // Not found. + return nullptr; + } + ZipFileReaderFileReference *ref = new ZipFileReaderFileReference(); + ref->zi = zi; + return ref; } -void ZipFileReader::ReleaseFile(VFSFileReference *reference) { - ZipFileReaderFileReference *file = (ZipFileReaderFileReference *)reference; +bool ZipFileReader::GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) { + ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference; + // If you crash here, you called this while having the lock held by having the file open. + // Don't do that, check the info before you open the file. + std::lock_guard guard(lock_); + zip_stat_t zstat; + if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0) + return false; + *fileInfo = File::FileInfo{}; + fileInfo->size = 0; + if (zstat.valid & ZIP_STAT_SIZE) + fileInfo->size = zstat.size; + return zstat.size; } -VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *reference) { - ZipFileReaderFileReference *file = (ZipFileReaderFileReference *)reference; - return nullptr; +void ZipFileReader::ReleaseFile(VFSFileReference *vfsReference) { + ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference; + // Don't do anything other than deleting it. + delete reference; } -void ZipFileReader::Rewind(VFSOpenFile *openFile) { - ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile; +VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference) { + ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference; + ZipFileReaderOpenFile *openFile = new ZipFileReaderOpenFile(); + openFile->reference = reference; + // We only allow one file to be open for read concurrently. It's possible that this can be improved, + // especially if we only access by index like this. + lock_.lock(); + openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0); + + if (!openFile->zf) { + WARN_LOG(G3D, "File with index %d not found in zip", reference->zi); + lock_.unlock(); + return nullptr; + } + + return openFile; } -size_t ZipFileReader::Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) { - ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile; - return 0; +void ZipFileReader::Rewind(VFSOpenFile *vfsOpenFile) { + ZipFileReaderOpenFile *openFile = (ZipFileReaderOpenFile *)vfsOpenFile; + // Close and re-open. + zip_fclose(openFile->zf); + openFile->zf = zip_fopen_index(zip_file_, openFile->reference->zi, 0); } -void ZipFileReader::CloseFile(VFSOpenFile *openFile) { - ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)openFile; +size_t ZipFileReader::Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) { + ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile; + return zip_fread(file->zf, buffer, length); +} + +void ZipFileReader::CloseFile(VFSOpenFile *vfsOpenFile) { + ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile; + _dbg_assert_(file->zf != nullptr); + zip_fclose(file->zf); + lock_.unlock(); + delete file; } diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index 841491fb44..e3c50b38bf 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -16,18 +16,22 @@ class ZipFileReader : public VFSBackend { public: - ZipFileReader(const Path &zipFile, const char *inZipPath); + static ZipFileReader *Create(const Path &zipFile, const char *inZipPath); ~ZipFileReader(); + + bool IsValid() const { return zip_file_ != nullptr; } + // use delete[] on the returned value. uint8_t *ReadFile(const char *path, size_t *size) override; VFSFileReference *GetFile(const char *path) override; - void ReleaseFile(VFSFileReference *reference) override; + bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) override; + void ReleaseFile(VFSFileReference *vfsReference) override; - VFSOpenFile *OpenFileForRead(VFSFileReference *reference) override; - void Rewind(VFSOpenFile *openFile) override; - size_t Read(VFSOpenFile *openFile, uint8_t *buffer, size_t length) override; - void CloseFile(VFSOpenFile *openFile) override; + VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) override; + void Rewind(VFSOpenFile *vfsOpenFile) override; + size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) override; + void CloseFile(VFSOpenFile *vfsOpenFile) override; bool GetFileListing(const char *path, std::vector *listing, const char *filter) override; bool GetFileInfo(const char *path, File::FileInfo *info) override; @@ -38,7 +42,7 @@ public: private: void GetZipListings(const char *path, std::set &files, std::set &directories); - zip *zip_file_; + zip *zip_file_ = nullptr; std::mutex lock_; char inZipPath_[256]; }; From a43b62537a0f606a61d7d4f5884291ae643c458d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2023 20:22:28 +0100 Subject: [PATCH 228/424] Buildfixes --- Common/File/VFS/VFS.cpp | 8 ++++++-- android/jni/app-android.cpp | 2 +- headless/Headless.cpp | 4 ++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Common/File/VFS/VFS.cpp b/Common/File/VFS/VFS.cpp index 634f53baa1..260a6b007a 100644 --- a/Common/File/VFS/VFS.cpp +++ b/Common/File/VFS/VFS.cpp @@ -8,8 +8,12 @@ VFS g_VFS; void VFS::Register(const char *prefix, VFSBackend *reader) { - entries_.push_back(VFSEntry{ prefix, reader }); - DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); + if (reader) { + entries_.push_back(VFSEntry{ prefix, reader }); + DEBUG_LOG(IO, "Registered VFS for prefix %s: %s", prefix, reader->toString().c_str()); + } else { + ERROR_LOG(IO, "Trying to register null VFS backend for prefix %s", prefix); + } } void VFS::Clear() { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index a85fba04f2..d7ac20ec4b 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -696,7 +696,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init deviceType = jdeviceType; Path apkPath(GetJavaString(env, japkpath)); - g_VFS.Register("", new ZipFileReader(apkPath, "assets/")); + g_VFS.Register("", ZipFileReader::Create(apkPath, "assets/")); systemName = GetJavaString(env, jmodel); langRegion = GetJavaString(env, jlangRegion); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index c61e248d0a..9f9da25825 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -483,10 +483,10 @@ int main(int argc, const char* argv[]) #if PPSSPP_PLATFORM(ANDROID) // For some reason the debugger installs it with this name? if (File::Exists(Path("/data/app/org.ppsspp.ppsspp-2.apk"))) { - g_VFS.Register("", new ZipFileReader(Path("/data/app/org.ppsspp.ppsspp-2.apk"), "assets/")); + g_VFS.Register("", ZipFileReader::Create(Path("/data/app/org.ppsspp.ppsspp-2.apk"), "assets/")); } if (File::Exists(Path("/data/app/org.ppsspp.ppsspp.apk"))) { - g_VFS.Register("", new ZipFileReader(Path("/data/app/org.ppsspp.ppsspp.apk"), "assets/")); + g_VFS.Register("", ZipFileReader::Create(Path("/data/app/org.ppsspp.ppsspp.apk"), "assets/")); } #elif !PPSSPP_PLATFORM(WINDOWS) g_VFS.Register("", new DirectoryReader(g_Config.flash0Directory / "..")); From 76c6058abe052120e47d59997c2a8c705f94ac6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2023 22:20:56 +0100 Subject: [PATCH 229/424] Texture replacer: Faster way to get width/height from a png --- Common/Data/Format/PNGLoad.cpp | 11 +++++++++++ Common/Data/Format/PNGLoad.h | 25 ++++++++++++++++++++++--- Core/TextureReplacer.cpp | 25 +++++++------------------ 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/Common/Data/Format/PNGLoad.cpp b/Common/Data/Format/PNGLoad.cpp index 0174b156fe..b2ed18f99b 100644 --- a/Common/Data/Format/PNGLoad.cpp +++ b/Common/Data/Format/PNGLoad.cpp @@ -59,3 +59,14 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, in png_image_finish_read(&png, NULL, *image_data_ptr, stride, NULL); return 1; } + +bool PNGHeaderPeek::IsValidPNGHeader() const { + if (magic != 0x474e5089 || ihdrTag != 0x52444849) { + return false; + } + // Reject crazy sized images, too. + if (Width() > 32768 && Height() > 32768) { + return false; + } + return true; +} diff --git a/Common/Data/Format/PNGLoad.h b/Common/Data/Format/PNGLoad.h index 48eaf6a1db..282fed9d44 100644 --- a/Common/Data/Format/PNGLoad.h +++ b/Common/Data/Format/PNGLoad.h @@ -1,5 +1,8 @@ -#ifndef _PNG_LOAD_H -#define _PNG_LOAD_H +#pragma once + +#include + +#include "Common/BitSet.h" // *image_data_ptr should be deleted with free() // return value of 1 == success. @@ -9,4 +12,20 @@ int pngLoad(const char *file, int *pwidth, int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, int *pheight, unsigned char **image_data_ptr); -#endif // _PNG_LOAD_H +// PNG peeker - just read the start of a PNG straight into this struct, in order to +// look at basic parameters like width and height. Note that while PNG is a chunk-based +// format, the IHDR chunk is REQUIRED to be the first one, so this will work. +struct PNGHeaderPeek { + uint32_t magic; + uint32_t ignore0; + uint32_t ignore1; + uint32_t ihdrTag; + uint32_t be_width; // big endian + uint32_t be_height; + uint8_t bitDepth; // bits per channel, can be 1, 2, 4, 8, 16 + uint8_t colorType; // really, pixel format. 0 = grayscale, 2 = rgb, 3 = palette index, 4 = gray+alpha, 6 = rgba + + bool IsValidPNGHeader() const; + int Width() const { return swap32(be_width); } + int Height() const { return swap32(be_height); } +}; diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 0bfee36647..d30da0beed 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -32,6 +32,7 @@ #include "Common/Data/Convert/ColorConv.h" #include "Common/Data/Format/IniFile.h" #include "Common/Data/Format/ZIMLoad.h" +#include "Common/Data/Format/PNGLoad.h" #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" #include "Common/File/FileUtil.h" @@ -645,27 +646,15 @@ bool TextureReplacer::PopulateLevelFromZip(ReplacedTextureLevel &level, bool ign good = (flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; } } else if (imageType == ReplacedImageType::PNG) { - png_image png = {}; - png.version = PNG_IMAGE_VERSION; - - // TODO: Use some way to stream data into libpng. Better than the IO lookups on Android... - zip_uint64_t zsize = ZipFileSize(level.zinfo->z, level.zi); - std::string pngdata; - if (zsize != INVALID_ZIP_SIZE) - pngdata.resize(zsize); - if (!pngdata.empty()) { - pngdata.resize(zip_fread(zf, &pngdata[0], pngdata.size())); - } - - if (png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { - // We pad files that have been hashrange'd so they are the same texture size. - level.w = png.width; - level.h = png.height; + PNGHeaderPeek headerPeek; + good = zip_fread(zf, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); + if (headerPeek.IsValidPNGHeader()) { + level.w = headerPeek.Width(); + level.h = headerPeek.Height(); good = true; } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", level.file.ToVisualString().c_str(), png.message); + ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); } - png_image_free(&png); } else { ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format (zip)", level.file.ToVisualString().c_str()); } From 84b7df62ab575cac29872b9be583bda94aaf7d24 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 7 Mar 2023 21:36:33 -0800 Subject: [PATCH 230/424] Common: Cleanup zip file stat flag checks. --- Common/File/VFS/ZipFileReader.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index 1ba7e5bf9f..2e7e87863c 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -162,22 +162,31 @@ bool ZipFileReader::GetFileInfo(const char *path, File::FileInfo *info) { char temp_path[1024]; snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path); + // Clear some things to start. + info->isDirectory = false; + info->isWritable = false; + info->size = 0; + { std::lock_guard guard(lock_); if (0 != zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat)) { // ZIP files do not have real directories, so we'll end up here if we // try to stat one. For now that's fine. info->exists = false; - info->size = 0; return false; } } + // Zips usually don't contain directory entries, but they may. + if ((zstat.valid & ZIP_STAT_NAME) != 0 && zstat.name) { + info->isDirectory = zstat.name[strlen(zstat.name) - 1] == '/'; + } + if ((zstat.valid & ZIP_STAT_SIZE) != 0) { + info->size = zstat.size; + } + info->fullName = Path(path); - info->exists = true; // TODO - info->isWritable = false; - info->isDirectory = false; // TODO - info->size = zstat.size; + info->exists = true; return true; } From 2fce2df7f6d278bbcd62b975e0c2b2ed348370aa Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 7 Mar 2023 21:37:04 -0800 Subject: [PATCH 231/424] Common: Ensure VFS references not directly deleted. --- Common/File/VFS/DirectoryReader.cpp | 7 ++++++- Common/File/VFS/VFS.h | 2 -- Common/File/VFS/ZipFileReader.cpp | 7 ++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp index e4da6a712d..999807ed0a 100644 --- a/Common/File/VFS/DirectoryReader.cpp +++ b/Common/File/VFS/DirectoryReader.cpp @@ -37,7 +37,10 @@ public: class DirectoryReaderOpenFile : public VFSOpenFile { public: - FILE *file; + ~DirectoryReaderOpenFile() { + _dbg_assert_(file == nullptr); + } + FILE *file = nullptr; }; VFSFileReference *DirectoryReader::GetFile(const char *path) { @@ -80,6 +83,8 @@ size_t DirectoryReader::Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t leng void DirectoryReader::CloseFile(VFSOpenFile *vfsOpenFile) { DirectoryReaderOpenFile *openFile = (DirectoryReaderOpenFile *)vfsOpenFile; + _dbg_assert_(openFile->file != nullptr); fclose(openFile->file); + openFile->file = nullptr; delete openFile; } diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 22a242c903..67d737d5f7 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -42,8 +42,6 @@ public: class VFSBackend : public VFSInterface { public: - // use delete[] to release the returned memory. - virtual VFSFileReference *GetFile(const char *path) = 0; virtual bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) = 0; virtual void ReleaseFile(VFSFileReference *vfsReference) = 0; diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index 2e7e87863c..92b78f5355 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -197,8 +197,12 @@ public: class ZipFileReaderOpenFile : public VFSOpenFile { public: + ~ZipFileReaderOpenFile() { + // Needs to be closed properly and unlocked. + _dbg_assert_(zf == nullptr); + } ZipFileReaderFileReference *reference; - zip_file_t *zf; + zip_file_t *zf = nullptr; }; static constexpr zip_uint64_t INVALID_ZIP_SIZE = 0xFFFFFFFFFFFFFFFFULL; @@ -270,6 +274,7 @@ void ZipFileReader::CloseFile(VFSOpenFile *vfsOpenFile) { ZipFileReaderOpenFile *file = (ZipFileReaderOpenFile *)vfsOpenFile; _dbg_assert_(file->zf != nullptr); zip_fclose(file->zf); + file->zf = nullptr; lock_.unlock(); delete file; } From bfb7a5b093d5143ee75bc3979ef75c228c749a47 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 7 Mar 2023 22:00:30 -0800 Subject: [PATCH 232/424] Common: Cleanup an unused constant. --- Common/File/VFS/ZipFileReader.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index 92b78f5355..694ef95864 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -205,8 +205,6 @@ public: zip_file_t *zf = nullptr; }; -static constexpr zip_uint64_t INVALID_ZIP_SIZE = 0xFFFFFFFFFFFFFFFFULL; - VFSFileReference *ZipFileReader::GetFile(const char *path) { std::lock_guard guard(lock_); int zi = zip_name_locate(zip_file_, path, ZIP_FL_NOCASE); From c4652d30e282918efcdbf4234e5cc808801a38e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 08:29:23 +0100 Subject: [PATCH 233/424] Address feedback --- Common/Data/Format/PNGLoad.h | 2 ++ Core/TextureReplacer.cpp | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Common/Data/Format/PNGLoad.h b/Common/Data/Format/PNGLoad.h index 282fed9d44..76ab04ee9e 100644 --- a/Common/Data/Format/PNGLoad.h +++ b/Common/Data/Format/PNGLoad.h @@ -15,6 +15,8 @@ int pngLoadPtr(const unsigned char *input_ptr, size_t input_len, int *pwidth, // PNG peeker - just read the start of a PNG straight into this struct, in order to // look at basic parameters like width and height. Note that while PNG is a chunk-based // format, the IHDR chunk is REQUIRED to be the first one, so this will work. +// Does not handle Apple's weirdo extension CgBI. http://iphonedevwiki.net/index.php/CgBI_file_format +// That should not be an issue. struct PNGHeaderPeek { uint32_t magic; uint32_t ignore0; diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index d30da0beed..875ded80fe 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -648,12 +648,13 @@ bool TextureReplacer::PopulateLevelFromZip(ReplacedTextureLevel &level, bool ign } else if (imageType == ReplacedImageType::PNG) { PNGHeaderPeek headerPeek; good = zip_fread(zf, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); - if (headerPeek.IsValidPNGHeader()) { + if (good && headerPeek.IsValidPNGHeader()) { level.w = headerPeek.Width(); level.h = headerPeek.Height(); good = true; } else { ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); + good = false; } } else { ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format (zip)", level.file.ToVisualString().c_str()); From 10ecc4afbd345696e966a94088ccc59aee0720c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2023 20:53:50 +0100 Subject: [PATCH 234/424] Use the VFS in the replacer to remove duplicated code --- Core/TextureReplacer.cpp | 330 +++++++++++---------------------------- Core/TextureReplacer.h | 30 ++-- 2 files changed, 104 insertions(+), 256 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 875ded80fe..43e6fbf83b 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -21,11 +21,6 @@ #include #include #include -#ifdef SHARED_LIBZIP -#include -#else -#include "ext/libzip/zip.h" -#endif #include "ext/xxhash.h" @@ -35,6 +30,8 @@ #include "Common/Data/Format/PNGLoad.h" #include "Common/Data/Text/I18n.h" #include "Common/Data/Text/Parsers.h" +#include "Common/File/VFS/DirectoryReader.h" +#include "Common/File/VFS/ZipFileReader.h" #include "Common/File/FileUtil.h" #include "Common/File/VFS/VFS.h" #include "Common/LogReporting.h" @@ -63,17 +60,8 @@ TextureReplacer::TextureReplacer() { none_.prepareDone_ = true; } -void ReplacerZipInfo::Close() { - if (!z) - return; - - std::lock_guard guard(lock); - zip_close(z); - z = nullptr; -} - TextureReplacer::~TextureReplacer() { - zip_.Close(); + delete vfs_; } void TextureReplacer::Init() { @@ -98,7 +86,8 @@ void TextureReplacer::NotifyConfigChanged() { enabled_ = File::IsDirectory(basePath_); } else if (wasEnabled) { - zip_.Close(); + delete vfs_; + vfs_ = nullptr; Decimate(ReplacerDecimateMode::ALL); } @@ -107,46 +96,7 @@ void TextureReplacer::NotifyConfigChanged() { } } -static struct zip *ZipOpenPath(Path fileName) { - int error = 0; - if (fileName.Type() == PathType::CONTENT_URI) { - int fd = File::OpenFD(fileName, File::OPEN_READ); - return zip_fdopen(fd, 0, &error); - } - return zip_open(fileName.c_str(), 0, &error); -} - -static constexpr zip_uint64_t INVALID_ZIP_SIZE = 0xFFFFFFFFFFFFFFFFULL; -static zip_uint64_t ZipFileSize(zip *z, zip_int64_t i) { - zip_stat_t zstat; - if (zip_stat_index(z, i, 0, &zstat) != 0) - return INVALID_ZIP_SIZE; - if ((zstat.valid & ZIP_STAT_SIZE) == 0) - return INVALID_ZIP_SIZE; - return zstat.size; -} - -static bool LoadIniZip(IniFile &ini, zip *z, const std::string &filename) { - zip_int64_t i = zip_name_locate(z, filename.c_str(), ZIP_FL_NOCASE); - if (i < 0) - return false; - - std::string inistr; - zip_uint64_t sz = ZipFileSize(z, i); - if (sz == INVALID_ZIP_SIZE) - return false; - inistr.resize(sz); - - zip_file_t *zf = zip_fopen_index(z, i, 0); - inistr.resize(zip_fread(zf, &inistr[0], inistr.size())); - zip_fclose(zf); - - std::stringstream sstream(inistr); - return ini.Load(sstream); -} - bool TextureReplacer::LoadIni() { - // TODO: Use crc32c? hash_ = ReplacedTextureHash::QUICK; aliases_.clear(); hashranges_.clear(); @@ -160,32 +110,21 @@ bool TextureReplacer::LoadIni() { // Prevents dumping the mipmaps. ignoreMipmap_ = false; - zip_.Close(); - - IniFile ini; - bool iniLoaded = false; + delete vfs_; + vfs_ = nullptr; // First, check for textures.zip, which is used to reduce IO. - zip *z = ZipOpenPath(basePath_ / ZIP_FILENAME); - if (z) { - iniLoaded = LoadIniZip(ini, z, INI_FILENAME); - // Require the zip have textures.ini to use it. - if (iniLoaded) { - iniLoaded = true; - std::lock_guard guard(zip_.lock); - zip_.z = z; - } else { - zip_close(z); - z = nullptr; - } + VFSBackend *dir = ZipFileReader::Create(basePath_ / ZIP_FILENAME, ""); + if (!dir) { + dir = new DirectoryReader(basePath_); } - if (!iniLoaded) { - iniLoaded = ini.LoadFromVFS(g_VFS, (basePath_ / INI_FILENAME).ToString()); - } + IniFile ini; + bool iniLoaded = ini.LoadFromVFS(g_VFS, (basePath_ / INI_FILENAME).ToString()); if (iniLoaded) { if (!LoadIniValues(ini)) { + delete dir; return false; } @@ -194,26 +133,26 @@ bool TextureReplacer::LoadIni() { if (ini.GetOrCreateSection("games")->Get(gameID_.c_str(), &overrideFilename, "")) { if (!overrideFilename.empty() && overrideFilename != INI_FILENAME) { IniFile overrideIni; - if (zip_.z) { - std::lock_guard guard(zip_.lock); - iniLoaded = LoadIniZip(overrideIni, zip_.z, overrideFilename); - } else { - iniLoaded = overrideIni.LoadFromVFS(g_VFS, (basePath_ / overrideFilename).ToString()); - } + iniLoaded = overrideIni.LoadFromVFS(*dir, overrideFilename); if (!iniLoaded) { ERROR_LOG(G3D, "Failed to load extra texture ini: %s", overrideFilename.c_str()); + // TODO: Should we just move on instead? + delete dir; return false; } INFO_LOG(G3D, "Loading extra texture ini: %s", overrideFilename.c_str()); if (!LoadIniValues(overrideIni, true)) { + delete dir; return false; } } } } - // The ini doesn't have to exist for it to be valid. + vfs_ = dir; + + // The ini doesn't have to exist for the texture directory or zip to be valid. return true; } @@ -481,6 +420,7 @@ ReplacedTexture &TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, // Okay, let's construct the result. ReplacedTexture &result = cache_[replacementKey]; + result.vfs_ = this->vfs_; if (!g_Config.bReplaceTexturesAllowLate || budget > 0.0) { PopulateReplacement(&result, cachekey, hash, w, h); } @@ -498,27 +438,24 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, for (int i = 0; i < MAX_MIP_LEVELS; ++i) { const std::string hashfile = LookupHashFile(cachekey, hash, i); - const Path filename = basePath_ / hashfile; if (hashfile.empty()) { // Out of valid mip levels. Bail out. break; } + const Path filename = basePath_ / hashfile; + ReplacedTextureLevel level; level.fmt = Draw::DataFormat::R8G8B8A8_UNORM; level.file = filename; bool good; bool logError = hashfile != HashName(cachekey, hash, i) + ".png"; - if (zip_.z) { - level.zinfo = &zip_; - std::lock_guard guard(zip_.lock); - level.zi = zip_name_locate(zip_.z, hashfile.c_str(), ZIP_FL_NOCASE); - good = PopulateLevelFromZip(level, !logError); - } else { - good = PopulateLevelFromPath(level, !logError); - } + VFSFileReference *fileRef = vfs_->GetFile(hashfile.c_str()); + + level.fileRef = fileRef; + good = PopulateLevel(level, !logError); // We pad files that have been hashrange'd so they are the same texture size. level.w = (level.w * w) / newW; @@ -554,7 +491,7 @@ enum class ReplacedImageType { INVALID, }; -static ReplacedImageType Identify(const uint8_t magic[4]) { +static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { if (strncmp((const char *)magic, "ZIMG", 4) == 0) return ReplacedImageType::ZIM; if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) @@ -562,92 +499,57 @@ static ReplacedImageType Identify(const uint8_t magic[4]) { return ReplacedImageType::INVALID; } -static ReplacedImageType Identify(FILE *fp) { +static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { uint8_t magic[4]; - if (fread(magic, 1, 4, fp) != 4) + if (vfs->Read(openFile, magic, 4) != 4) { + *outMagic = "FAIL"; return ReplacedImageType::INVALID; - rewind(fp); - - return Identify(magic); -} - -static ReplacedImageType Identify(zip_file_t *zf) { - uint8_t magic[4]; - if (zip_fread(zf, magic, 4) != 4) - return ReplacedImageType::INVALID; - - return Identify(magic); -} - -bool TextureReplacer::PopulateLevelFromPath(ReplacedTextureLevel &level, bool ignoreError) { - bool good = false; - - FILE *fp = File::OpenCFile(level.file, "rb"); - if (!fp) { - if (!ignoreError) - ERROR_LOG(G3D, "Error opening replacement texture file '%s'", level.file.c_str()); - return false; } - - auto imageType = Identify(fp); - if (imageType == ReplacedImageType::ZIM) { - fseek(fp, 4, SEEK_SET); - good = fread(&level.w, 4, 1, fp) == 1; - good = good && fread(&level.h, 4, 1, fp) == 1; - int flags; - if (good && fread(&flags, 4, 1, fp) == 1) { - good = (flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; + // Turn the signature into a readable string that we can display in an error message. + *outMagic = std::string((const char *)magic, 4); + for (int i = 0; i < outMagic->size(); i++) { + if ((s8)(*outMagic)[i] < 32) { + (*outMagic)[i] = '_'; } - } else if (imageType == ReplacedImageType::PNG) { - png_image png = {}; - png.version = PNG_IMAGE_VERSION; - if (png_image_begin_read_from_stdio(&png, fp)) { - // We pad files that have been hashrange'd so they are the same texture size. - level.w = png.width; - level.h = png.height; - good = true; - } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s", level.file.ToVisualString().c_str(), png.message); - } - png_image_free(&png); - } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format", level.file.ToVisualString().c_str()); } - fclose(fp); - - return good; + vfs->Rewind(openFile); + return IdentifyMagic(magic); } -bool TextureReplacer::PopulateLevelFromZip(ReplacedTextureLevel &level, bool ignoreError) { +bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { bool good = false; // Everything in here is within a lock, so we don't need to relock. - if (!level.zinfo || !level.zinfo->z || level.zi < 0) { + if (!level.fileRef) { if (!ignoreError) ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); return false; } + File::FileInfo info; + vfs_->GetFileInfo(level.fileRef, &info); + size_t zsize = info.size; - zip_file_t *zf = zip_fopen_index(level.zinfo->z, level.zi, 0); - if (!zf) + VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef); + if (!file) { return false; + } - auto imageType = Identify(zf); - zip_fclose(zf); + std::string magic; + auto imageType = Identify(vfs_, file, &magic); - zf = zip_fopen_index(level.zinfo->z, level.zi, 0); if (imageType == ReplacedImageType::ZIM) { uint32_t ignore = 0; - good = zip_fread(zf, &ignore, 4) == 4; - good = good && zip_fread(zf, &level.w, 4) == 4; - good = good && zip_fread(zf, &level.h, 4) == 4; - int flags; - if (good && zip_fread(zf, &flags, 4) == 4) { - good = (flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; - } + struct ZimHeader { + uint32_t magic; + uint32_t w; + uint32_t h; + uint32_t flags; + } header; + good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); + good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; } else if (imageType == ReplacedImageType::PNG) { PNGHeaderPeek headerPeek; - good = zip_fread(zf, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); + good = vfs_->Read(file, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); if (good && headerPeek.IsValidPNGHeader()) { level.w = headerPeek.Width(); level.h = headerPeek.Height(); @@ -657,9 +559,9 @@ bool TextureReplacer::PopulateLevelFromZip(ReplacedTextureLevel &level, bool ign good = false; } } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format (zip)", level.file.ToVisualString().c_str()); + ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); } - zip_fclose(zf); + vfs_->CloseFile(file); return good; } @@ -986,7 +888,7 @@ float TextureReplacer::LookupReduceHashRange(int& w, int& h) { class ReplacedTextureTask : public Task { public: - ReplacedTextureTask(ReplacedTexture &tex, LimitedWaitable *w) : tex_(tex), waitable_(w) {} + ReplacedTextureTask(VFSBackend *vfs, ReplacedTexture &tex, LimitedWaitable *w) : vfs_(vfs), tex_(tex), waitable_(w) {} TaskType Type() const override { return TaskType::IO_BLOCKING; @@ -997,16 +899,18 @@ public: } void Run() override { - tex_.Prepare(); + tex_.Prepare(vfs_); waitable_->Notify(); } private: ReplacedTexture &tex_; LimitedWaitable *waitable_; + VFSBackend *vfs_; }; bool ReplacedTexture::IsReady(double budget) { + _assert_(vfs_ != nullptr); lastUsed_ = time_now_d(); if (threadWaitable_ && !threadWaitable_->WaitFor(budget)) { return false; @@ -1028,14 +932,14 @@ bool ReplacedTexture::IsReady(double budget) { if (threadWaitable_) delete threadWaitable_; threadWaitable_ = new LimitedWaitable(); - g_threadManager.EnqueueTask(new ReplacedTextureTask(*this, threadWaitable_)); + g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); if (threadWaitable_->WaitFor(budget)) { // If we finished all the levels, we're done. return initDone_ && !levelData_.empty(); } } else { - Prepare(); + Prepare(vfs_); _assert_(initDone_); return true; } @@ -1044,8 +948,9 @@ bool ReplacedTexture::IsReady(double budget) { return false; } -void ReplacedTexture::Prepare() { +void ReplacedTexture::Prepare(VFSBackend *vfs) { std::unique_lock lock(mutex_); + this->vfs_ = vfs; if (cancelPrepare_) { initDone_ = true; return; @@ -1069,83 +974,47 @@ void ReplacedTexture::PrepareData(int level) { // We must lock around access to levelData_ in case two textures try to load it at once. std::lock_guard guard(levelData_[level]->lock); - const ReplacedTextureLevel &info = levels_[level]; + ReplacedTextureLevel &info = levels_[level]; std::vector &out = levelData_[level]->data; // Already populated from cache. if (!out.empty()) return; - FILE *fp = nullptr; - zip_file_t *zf = nullptr; ReplacedImageType imageType; - std::unique_lock zguard; - if (info.zinfo && info.zinfo->z) { - zguard = std::unique_lock(info.zinfo->lock); - zf = zip_fopen_index(info.zinfo->z, info.zi, 0); - if (!zf) - return; - imageType = Identify(zf); - // Can't assume we can seek. Reopen. - zip_fclose(zf); - zf = zip_fopen_index(info.zinfo->z, info.zi, 0); - } else { - fp = File::OpenCFile(info.file, "rb"); - if (!fp) { - // Leaving the data sized at zero means failure. - return; - } - - imageType = Identify(fp); + File::FileInfo fileInfo; + if (!vfs_->GetFileInfo(info.fileRef, &fileInfo)) { + ERROR_LOG(G3D, "Failed to get file info for level"); + return; } + size_t fileSize = fileInfo.size; + + VFSOpenFile *openFile = vfs_->OpenFileForRead(info.fileRef); + std::string magic; + imageType = Identify(vfs_, openFile, &magic); auto cleanup = [&] { - if (zf) - zip_fclose(zf); - if (fp) - fclose(fp); + vfs_->CloseFile(openFile); }; if (imageType == ReplacedImageType::ZIM) { - size_t zimSize = 0; - if (fp) { - zimSize = File::GetFileSize(fp); - } else if (zf) { - zip_uint64_t zsize = ZipFileSize(info.zinfo->z, info.zi); - zimSize = zsize == INVALID_ZIP_SIZE ? 0 : (size_t)zsize; - } else { - _assert_(false); - } - std::unique_ptr zim(new uint8_t[zimSize]); + std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); cleanup(); return; } - if (fp) { - if (fread(&zim[0], 1, zimSize, fp) != zimSize) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); - cleanup(); - return; - } - } else if (zf) { - if (zip_fread(zf, &zim[0], zimSize) != zimSize) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM (zip)", info.file.c_str()); - cleanup(); - return; - } - // Try to unlock early to prevent blocking threads. - zguard.unlock(); - } else { - _assert_(false); + if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { + ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); + cleanup(); + return; } int w, h, f; uint8_t *image; - - if (LoadZIMPtr(&zim[0], zimSize, &w, &h, &f, &image)) { + if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > info.w || h > info.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); cleanup(); @@ -1171,31 +1040,13 @@ void ReplacedTexture::PrepareData(int level) { png_image png = {}; png.version = PNG_IMAGE_VERSION; - // Needs to survive for a little while, used for zip only. std::string pngdata; - if (fp) { - if (!png_image_begin_read_from_stdio(&png, fp)) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s", info.file.c_str(), png.message); - cleanup(); - return; - } - } else if (zf) { - zip_uint64_t zsize = ZipFileSize(info.zinfo->z, info.zi); - if (zsize != INVALID_ZIP_SIZE) - pngdata.resize(zsize); - if (!pngdata.empty()) { - pngdata.resize(zip_fread(zf, &pngdata[0], pngdata.size())); - } - // Try to unlock early to prevent blocking threads. - zguard.unlock(); - - if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); - cleanup(); - return; - } - } else { - _assert_(false); + pngdata.resize(fileSize); + vfs_->Read(openFile, &pngdata[0], fileSize); + if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { + ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); + cleanup(); + return; } if (png.width > (uint32_t)info.w || png.height > (uint32_t)info.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); @@ -1280,6 +1131,7 @@ bool ReplacedTexture::Load(int level, void *out, int rowPitch) { if (data.empty()) return false; + if (rowPitch < info.w * 4) { ERROR_LOG_REPORT(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); return false; diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index cc9e4abed1..849186bc5f 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -27,6 +27,7 @@ #include "Common/CommonTypes.h" #include "Common/MemoryUtil.h" #include "Common/File/Path.h" +#include "Common/File/VFS/VFS.h" #include "Common/GPU/DataFormat.h" #include "GPU/Common/TextureDecoder.h" @@ -37,7 +38,7 @@ class TextureCacheCommon; class TextureReplacer; class ReplacedTextureTask; class LimitedWaitable; -struct zip; +class VFSBackend; // These must match the constants in TextureCacheCommon. enum class ReplacedTextureAlpha { @@ -52,13 +53,6 @@ enum class ReplacedTextureHash { XXH64, }; -struct ReplacerZipInfo { - zip *z = nullptr; - std::mutex lock; - - void Close(); -}; - struct ReplacedTextureLevel { int w; int h; @@ -66,9 +60,7 @@ struct ReplacedTextureLevel { Path file; // Can be ignored for hashing/equal, since file has all uniqueness. // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. - ReplacerZipInfo *zinfo = nullptr; - int64_t zi = -1; - + VFSFileReference *fileRef; bool operator ==(const ReplacedTextureLevel &other) const { if (w != other.w || h != other.h || fmt != other.fmt) return false; @@ -206,7 +198,7 @@ struct ReplacedTexture { bool Load(int level, void *out, int rowPitch); protected: - void Prepare(); + void Prepare(VFSBackend *vfs); void PrepareData(int level); void PurgeIfOlder(double t); @@ -216,10 +208,13 @@ protected: double lastUsed_ = 0.0; LimitedWaitable *threadWaitable_ = nullptr; std::mutex mutex_; + bool cancelPrepare_ = false; bool initDone_ = false; bool prepareDone_ = false; + VFSBackend *vfs_ = nullptr; + friend TextureReplacer; friend ReplacedTextureTask; }; @@ -282,21 +277,22 @@ protected: std::string LookupHashFile(u64 cachekey, u32 hash, int level); std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); - bool PopulateLevelFromPath(ReplacedTextureLevel &level, bool ignoreError); - bool PopulateLevelFromZip(ReplacedTextureLevel &level, bool ignoreError); + bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); bool enabled_ = false; bool allowVideo_ = false; bool ignoreAddress_ = false; bool reduceHash_ = false; - float reduceHashSize = 1.0; // default value with reduceHash to false - float reduceHashGlobalValue = 0.5; // Global value for textures dump pngs of all sizes, 0.5 by default but can be set in textures.ini + float reduceHashSize = 1.0f; // default value with reduceHash to false + float reduceHashGlobalValue = 0.5f; // Global value for textures dump pngs of all sizes, 0.5 by default but can be set in textures.ini + double lastTextureCacheSizeGB_ = 0.0; bool ignoreMipmap_ = false; std::string gameID_; Path basePath_; ReplacedTextureHash hash_ = ReplacedTextureHash::QUICK; - ReplacerZipInfo zip_; + + VFSBackend *vfs_ = nullptr; typedef std::pair WidthHeightPair; std::unordered_map hashranges_; From 16b0e1103a00991fda4a2ccd2816a451ab3ab983 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2023 20:59:34 +0100 Subject: [PATCH 235/424] Check file existence early. Although, not sure if this is the right thing on Android... --- Common/File/VFS/DirectoryReader.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp index 999807ed0a..af05120450 100644 --- a/Common/File/VFS/DirectoryReader.cpp +++ b/Common/File/VFS/DirectoryReader.cpp @@ -44,8 +44,13 @@ public: }; VFSFileReference *DirectoryReader::GetFile(const char *path) { + Path filePath = path_ / path; + if (!File::Exists(filePath)) { + return nullptr; + } + DirectoryReaderFileReference *reference = new DirectoryReaderFileReference(); - reference->path = path_ / path; + reference->path = filePath; return reference; } From 41fcb7a79f958dc053dd29099ef92cb71f18b9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 7 Mar 2023 22:02:44 +0100 Subject: [PATCH 236/424] Add necessary check --- Core/TextureReplacer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 43e6fbf83b..98e20a480e 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -453,6 +453,10 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, bool logError = hashfile != HashName(cachekey, hash, i) + ".png"; VFSFileReference *fileRef = vfs_->GetFile(hashfile.c_str()); + if (!fileRef) { + // If the file doesn't exist, let's just bail immediately here. + break; + } level.fileRef = fileRef; good = PopulateLevel(level, !logError); @@ -525,8 +529,11 @@ bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreErro ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); return false; } + File::FileInfo info; - vfs_->GetFileInfo(level.fileRef, &info); + if (!vfs_->GetFileInfo(level.fileRef, &info)) { + return false; + } size_t zsize = info.size; VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef); From ce9000e7e04e7d258bda00fb30cda9058f0e3d69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 08:23:13 +0100 Subject: [PATCH 237/424] Address most of the feedback --- Core/TextureReplacer.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 98e20a480e..6d2cab9f60 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -136,7 +136,8 @@ bool TextureReplacer::LoadIni() { iniLoaded = overrideIni.LoadFromVFS(*dir, overrideFilename); if (!iniLoaded) { ERROR_LOG(G3D, "Failed to load extra texture ini: %s", overrideFilename.c_str()); - // TODO: Should we just move on instead? + // Since this error is most likely to occure for texture pack creators, let's just bail here + // so that the creator is more likely to look in the logs for what happened. delete dir; return false; } @@ -523,7 +524,6 @@ static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::s bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { bool good = false; - // Everything in here is within a lock, so we don't need to relock. if (!level.fileRef) { if (!ignoreError) ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); @@ -553,6 +553,8 @@ bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreErro uint32_t flags; } header; good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); + level.w = header.w; + level.h = header.h; good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; } else if (imageType == ReplacedImageType::PNG) { PNGHeaderPeek headerPeek; @@ -911,9 +913,9 @@ public: } private: + VFSBackend *vfs_; ReplacedTexture &tex_; LimitedWaitable *waitable_; - VFSBackend *vfs_; }; bool ReplacedTexture::IsReady(double budget) { @@ -981,7 +983,7 @@ void ReplacedTexture::PrepareData(int level) { // We must lock around access to levelData_ in case two textures try to load it at once. std::lock_guard guard(levelData_[level]->lock); - ReplacedTextureLevel &info = levels_[level]; + const ReplacedTextureLevel &info = levels_[level]; std::vector &out = levelData_[level]->data; // Already populated from cache. From e277db63c0586904db20bfa612585098ca22998b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 09:11:25 +0100 Subject: [PATCH 238/424] Optimize away those extra GetFileInfo, since both backends can get the size during Open efficiently. --- Common/File/VFS/DirectoryReader.cpp | 8 ++++++-- Common/File/VFS/DirectoryReader.h | 2 +- Common/File/VFS/VFS.h | 4 +++- Common/File/VFS/ZipFileReader.cpp | 12 ++++++++++-- Common/File/VFS/ZipFileReader.h | 2 +- Core/TextureReplacer.cpp | 20 +++++--------------- 6 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Common/File/VFS/DirectoryReader.cpp b/Common/File/VFS/DirectoryReader.cpp index af05120450..981dff905b 100644 --- a/Common/File/VFS/DirectoryReader.cpp +++ b/Common/File/VFS/DirectoryReader.cpp @@ -1,3 +1,5 @@ +#include + #include "Common/Common.h" #include "Common/Log.h" #include "Common/File/VFS/DirectoryReader.h" @@ -64,13 +66,15 @@ void DirectoryReader::ReleaseFile(VFSFileReference *vfsReference) { delete reference; } -VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *vfsReference) { +VFSOpenFile *DirectoryReader::OpenFileForRead(VFSFileReference *vfsReference, size_t *size) { DirectoryReaderFileReference *reference = (DirectoryReaderFileReference *)vfsReference; FILE *file = File::OpenCFile(reference->path, "rb"); if (!file) { return nullptr; } - + fseek(file, 0, SEEK_END); + *size = ftell(file); + fseek(file, 0, SEEK_SET); DirectoryReaderOpenFile *openFile = new DirectoryReaderOpenFile(); openFile->file = file; return openFile; diff --git a/Common/File/VFS/DirectoryReader.h b/Common/File/VFS/DirectoryReader.h index cc6d971371..f742c6b3da 100644 --- a/Common/File/VFS/DirectoryReader.h +++ b/Common/File/VFS/DirectoryReader.h @@ -14,7 +14,7 @@ public: bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) override; void ReleaseFile(VFSFileReference *vfsReference) override; - VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) override; + VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference, size_t *size) override; void Rewind(VFSOpenFile *vfsOpenFile) override; size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) override; void CloseFile(VFSOpenFile *vfsOpenFile) override; diff --git a/Common/File/VFS/VFS.h b/Common/File/VFS/VFS.h index 67d737d5f7..5d585e309e 100644 --- a/Common/File/VFS/VFS.h +++ b/Common/File/VFS/VFS.h @@ -46,7 +46,9 @@ public: virtual bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) = 0; virtual void ReleaseFile(VFSFileReference *vfsReference) = 0; - virtual VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) = 0; + // Must write the size of the file to *size. Both backends can do this efficiently here, + // avoiding a call to GetFileInfo. + virtual VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference, size_t *size) = 0; virtual void Rewind(VFSOpenFile *vfsOpenFile) = 0; virtual size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) = 0; virtual void CloseFile(VFSOpenFile *vfsOpenFile) = 0; diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index 694ef95864..a03307ed72 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -238,21 +238,29 @@ void ZipFileReader::ReleaseFile(VFSFileReference *vfsReference) { delete reference; } -VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference) { +VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference, size_t *size) { ZipFileReaderFileReference *reference = (ZipFileReaderFileReference *)vfsReference; ZipFileReaderOpenFile *openFile = new ZipFileReaderOpenFile(); openFile->reference = reference; + *size = 0; // We only allow one file to be open for read concurrently. It's possible that this can be improved, // especially if we only access by index like this. lock_.lock(); - openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0); + zip_stat_t zstat; + if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0) { + lock_.unlock(); + return false; + } + openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0); if (!openFile->zf) { WARN_LOG(G3D, "File with index %d not found in zip", reference->zi); lock_.unlock(); return nullptr; } + *size = zstat.size; + // Intentionally leaving the mutex locked, will be closed in CloseFile. return openFile; } diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index e3c50b38bf..f39058beed 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -28,7 +28,7 @@ public: bool GetFileInfo(VFSFileReference *vfsReference, File::FileInfo *fileInfo) override; void ReleaseFile(VFSFileReference *vfsReference) override; - VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference) override; + VFSOpenFile *OpenFileForRead(VFSFileReference *vfsReference, size_t *size) override; void Rewind(VFSOpenFile *vfsOpenFile) override; size_t Read(VFSOpenFile *vfsOpenFile, void *buffer, size_t length) override; void CloseFile(VFSOpenFile *vfsOpenFile) override; diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 6d2cab9f60..bc81d0e032 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -530,13 +530,8 @@ bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreErro return false; } - File::FileInfo info; - if (!vfs_->GetFileInfo(level.fileRef, &info)) { - return false; - } - size_t zsize = info.size; - - VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef); + size_t fileSize; + VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef, &fileSize); if (!file) { return false; } @@ -992,14 +987,9 @@ void ReplacedTexture::PrepareData(int level) { ReplacedImageType imageType; - File::FileInfo fileInfo; - if (!vfs_->GetFileInfo(info.fileRef, &fileInfo)) { - ERROR_LOG(G3D, "Failed to get file info for level"); - return; - } - size_t fileSize = fileInfo.size; + size_t fileSize; + VFSOpenFile *openFile = vfs_->OpenFileForRead(info.fileRef, &fileSize); - VFSOpenFile *openFile = vfs_->OpenFileForRead(info.fileRef); std::string magic; imageType = Identify(vfs_, openFile, &magic); @@ -1051,7 +1041,7 @@ void ReplacedTexture::PrepareData(int level) { std::string pngdata; pngdata.resize(fileSize); - vfs_->Read(openFile, &pngdata[0], fileSize); + pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); cleanup(); From 74cad6b5211a2f821e4ceae379e67cbaf6395cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 09:17:26 +0100 Subject: [PATCH 239/424] Quick buildfix --- Common/File/VFS/ZipFileReader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index a03307ed72..35a8aa4afa 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -249,7 +249,7 @@ VFSOpenFile *ZipFileReader::OpenFileForRead(VFSFileReference *vfsReference, size zip_stat_t zstat; if (zip_stat_index(zip_file_, reference->zi, 0, &zstat) != 0) { lock_.unlock(); - return false; + return nullptr; } openFile->zf = zip_fopen_index(zip_file_, reference->zi, 0); From 306fdde9d0dd606fad5732de917709573b52e393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 09:29:19 +0100 Subject: [PATCH 240/424] Correct error handling for missing ini (only accept it in directories, not zip) --- Common/File/VFS/ZipFileReader.cpp | 35 +++++++++++++------------------ Core/TextureReplacer.cpp | 13 ++++++++++++ Core/TextureReplacer.h | 1 + 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index 35a8aa4afa..d4e4f69e66 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -15,25 +15,6 @@ #include "Common/File/VFS/ZipFileReader.h" #include "Common/StringUtils.h" -static uint8_t *ReadFromZip(zip *archive, const char* filename, size_t *size) { - // Figure out the file size first. - struct zip_stat zstat; - zip_file *file = zip_fopen(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED); - if (!file) { - ERROR_LOG(IO, "Error opening %s from ZIP", filename); - return 0; - } - zip_stat(archive, filename, ZIP_FL_NOCASE|ZIP_FL_UNCHANGED, &zstat); - - uint8_t *contents = new uint8_t[zstat.size + 1]; - zip_fread(file, contents, zstat.size); - zip_fclose(file); - contents[zstat.size] = 0; - - *size = zstat.size; - return contents; -} - ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath) { int error = 0; zip *zip_file; @@ -69,7 +50,21 @@ uint8_t *ZipFileReader::ReadFile(const char *path, size_t *size) { snprintf(temp_path, sizeof(temp_path), "%s%s", inZipPath_, path); std::lock_guard guard(lock_); - return ReadFromZip(zip_file_, temp_path, size); + // Figure out the file size first. + struct zip_stat zstat; + zip_stat(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat); + zip_file *file = zip_fopen(zip_file_, temp_path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED); + if (!file) { + ERROR_LOG(IO, "Error opening %s from ZIP", temp_path); + return 0; + } + uint8_t *contents = new uint8_t[zstat.size + 1]; + zip_fread(file, contents, zstat.size); + zip_fclose(file); + contents[zstat.size] = 0; + + *size = zstat.size; + return contents; } bool ZipFileReader::GetFileListing(const char *orig_path, std::vector *listing, const char *filter = 0) { diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index bc81d0e032..89b71963d2 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -116,7 +116,10 @@ bool TextureReplacer::LoadIni() { // First, check for textures.zip, which is used to reduce IO. VFSBackend *dir = ZipFileReader::Create(basePath_ / ZIP_FILENAME, ""); if (!dir) { + vfsIsZip_ = false; dir = new DirectoryReader(basePath_); + } else { + vfsIsZip_ = true; } IniFile ini; @@ -149,9 +152,19 @@ bool TextureReplacer::LoadIni() { } } } + } else { + if (vfsIsZip_) { + // We don't accept zip files without inis. + ERROR_LOG(G3D, "Texture pack lacking ini file: %s", basePath_.c_str()); + delete dir; + return false; + } else { + WARN_LOG(G3D, "Texture pack lacking ini file: %s", basePath_.c_str()); + } } vfs_ = dir; + INFO_LOG(G3D, "Texture pack activated from '%s'", basePath_.c_str()); // The ini doesn't have to exist for the texture directory or zip to be valid. return true; diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 849186bc5f..9281edf3ef 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -293,6 +293,7 @@ protected: ReplacedTextureHash hash_ = ReplacedTextureHash::QUICK; VFSBackend *vfs_ = nullptr; + bool vfsIsZip_ = false; typedef std::pair WidthHeightPair; std::unordered_map hashranges_; From bfddd04c118455ec8d084f035719af21d414c88c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 10:57:26 +0100 Subject: [PATCH 241/424] Simplify GenerateIni using raw strings --- Core/TextureReplacer.cpp | 46 +++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 89b71963d2..e82bcc744f 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -1188,31 +1188,33 @@ bool TextureReplacer::GenerateIni(const std::string &gameID, Path &generatedFile FILE *f = File::OpenCFile(generatedFilename, "wb"); if (f) { + // Unicode byte order mark fwrite("\xEF\xBB\xBF", 1, 3, f); // Let's also write some defaults. - fprintf(f, "# This file is optional and describes your textures.\n"); - fprintf(f, "# Some information on syntax available here:\n"); - fprintf(f, "# https://github.com/hrydgard/ppsspp/wiki/Texture-replacement-ini-syntax \n"); - fprintf(f, "[options]\n"); - fprintf(f, "version = 1\n"); - fprintf(f, "hash = quick\n"); - fprintf(f, "ignoreMipmap = false\n"); - fprintf(f, "\n"); - fprintf(f, "[games]\n"); - fprintf(f, "# Used to make it easier to install, and override settings for other regions.\n"); - fprintf(f, "# Files still have to be copied to each TEXTURES folder."); - fprintf(f, "%s = %s\n", gameID.c_str(), INI_FILENAME.c_str()); - fprintf(f, "\n"); - fprintf(f, "[hashes]\n"); - fprintf(f, "# Use / for folders not \\, avoid special characters, and stick to lowercase.\n"); - fprintf(f, "# See wiki for more info.\n"); - fprintf(f, "\n"); - fprintf(f, "[hashranges]\n"); - fprintf(f, "\n"); - fprintf(f, "[filtering]\n"); - fprintf(f, "\n"); - fprintf(f, "[reducehashranges]\n"); + fprintf(f, R"(# This file is optional and describes your textures. +# Some information on syntax available here: +# https://github.com/hrydgard/ppsspp/wiki/Texture-replacement-ini-syntax +[options] +version = 1 +hash = quick +ignoreMipmap = false + +[games] +# Used to make it easier to install, and override settings for other regions. +# Files still have to be copied to each TEXTURES folder. +%s = %s + +[hashes] +# Use / for folders not \\, avoid special characters, and stick to lowercase. +# See wiki for more info. + +[hashranges] + +[filtering] + +[reducehashranges] +)", gameID.c_str(), INI_FILENAME.c_str()); fclose(f); } return File::Exists(generatedFilename); From 81351056f4306d10736fcf197929ce9a9a4feca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 11:06:29 +0100 Subject: [PATCH 242/424] Move file identification to the top of the file --- Core/TextureReplacer.cpp | 63 ++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index e82bcc744f..e2cc217feb 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "ppsspp_config.h" + #include #include #include @@ -55,6 +56,37 @@ static const int VERSION = 1; static const int MAX_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP. static const double MAX_CACHE_SIZE = 4.0; +enum class ReplacedImageType { + PNG, + ZIM, + INVALID, +}; + +static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { + if (strncmp((const char *)magic, "ZIMG", 4) == 0) + return ReplacedImageType::ZIM; + if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) + return ReplacedImageType::PNG; + return ReplacedImageType::INVALID; +} + +static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { + uint8_t magic[4]; + if (vfs->Read(openFile, magic, 4) != 4) { + *outMagic = "FAIL"; + return ReplacedImageType::INVALID; + } + // Turn the signature into a readable string that we can display in an error message. + *outMagic = std::string((const char *)magic, 4); + for (int i = 0; i < outMagic->size(); i++) { + if ((s8)(*outMagic)[i] < 32) { + (*outMagic)[i] = '_'; + } + } + vfs->Rewind(openFile); + return IdentifyMagic(magic); +} + TextureReplacer::TextureReplacer() { none_.initDone_ = true; none_.prepareDone_ = true; @@ -503,37 +535,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, result->prepareDone_ = true; } -enum class ReplacedImageType { - PNG, - ZIM, - INVALID, -}; - -static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { - if (strncmp((const char *)magic, "ZIMG", 4) == 0) - return ReplacedImageType::ZIM; - if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) - return ReplacedImageType::PNG; - return ReplacedImageType::INVALID; -} - -static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { - uint8_t magic[4]; - if (vfs->Read(openFile, magic, 4) != 4) { - *outMagic = "FAIL"; - return ReplacedImageType::INVALID; - } - // Turn the signature into a readable string that we can display in an error message. - *outMagic = std::string((const char *)magic, 4); - for (int i = 0; i < outMagic->size(); i++) { - if ((s8)(*outMagic)[i] < 32) { - (*outMagic)[i] = '_'; - } - } - vfs->Rewind(openFile); - return IdentifyMagic(magic); -} - bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { bool good = false; From 226197f30f6a919f4b1952ba955ea65809e3a2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 8 Mar 2023 11:31:32 +0100 Subject: [PATCH 243/424] Replace "none_" with nullptr. --- Core/TextureReplacer.cpp | 31 +++++++++++++++++-------------- Core/TextureReplacer.h | 18 ++++++++---------- GPU/Common/TextureCacheCommon.cpp | 27 ++++++++++++++++----------- GPU/Common/TextureCacheCommon.h | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- 5 files changed, 43 insertions(+), 37 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index e2cc217feb..42c58460d5 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -87,12 +87,13 @@ static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::s return IdentifyMagic(magic); } -TextureReplacer::TextureReplacer() { - none_.initDone_ = true; - none_.prepareDone_ = true; -} +TextureReplacer::TextureReplacer() {} TextureReplacer::~TextureReplacer() { + for (auto &iter : cache_) { + delete iter.second; + } + delete vfs_; } @@ -206,7 +207,6 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { auto options = ini.GetOrCreateSection("options"); std::string hash; options->Get("hash", &hash, ""); - // TODO: crc32c. if (strcasecmp(hash.c_str(), "quick") == 0) { hash_ = ReplacedTextureHash::QUICK; } else if (strcasecmp(hash.c_str(), "xxh32") == 0) { @@ -448,27 +448,29 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm } } -ReplacedTexture &TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, int h, double budget) { +ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, int h, double budget) { // Only actually replace if we're replacing. We might just be saving. if (!Enabled() || !g_Config.bReplaceTextures) { - return none_; + return nullptr; } ReplacementCacheKey replacementKey(cachekey, hash); auto it = cache_.find(replacementKey); if (it != cache_.end()) { - if (!it->second.prepareDone_ && budget > 0.0) { + if (!it->second->prepareDone_ && budget > 0.0) { // We don't do this on a thread, but we only do it while within budget. - PopulateReplacement(&it->second, cachekey, hash, w, h); + PopulateReplacement(it->second, cachekey, hash, w, h); } return it->second; } // Okay, let's construct the result. - ReplacedTexture &result = cache_[replacementKey]; - result.vfs_ = this->vfs_; + + ReplacedTexture *result = new ReplacedTexture(); + cache_[replacementKey] = result; + result->vfs_ = this->vfs_; if (!g_Config.bReplaceTexturesAllowLate || budget > 0.0) { - PopulateReplacement(&result, cachekey, hash, w, h); + PopulateReplacement(result, cachekey, hash, w, h); } return result; } @@ -531,7 +533,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, for (size_t i = 0; i < result->levels_.size(); ++i) { result->levelData_[i] = &levelCache_[result->levels_[i]]; } - + result->prepareDone_ = true; } @@ -776,7 +778,8 @@ void TextureReplacer::Decimate(ReplacerDecimateMode mode) { const double threshold = time_now_d() - age; for (auto &item : cache_) { - item.second.PurgeIfOlder(threshold); + item.second->PurgeIfOlder(threshold); + // don't actually delete the items here, just clean out the data. } size_t totalSize = 0; diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 9281edf3ef..0b4633e05f 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -54,13 +54,14 @@ enum class ReplacedTextureHash { }; struct ReplacedTextureLevel { - int w; - int h; - Draw::DataFormat fmt; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. + ReplacedTextureLevel() {} + int w = 0; + int h = 0; + Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. Path file; // Can be ignored for hashing/equal, since file has all uniqueness. // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. - VFSFileReference *fileRef; + VFSFileReference *fileRef = nullptr; bool operator ==(const ReplacedTextureLevel &other) const { if (w != other.w || h != other.h || fmt != other.fmt) return false; @@ -249,11 +250,9 @@ public: u32 ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV); - ReplacedTexture &FindReplacement(u64 cachekey, u32 hash, int w, int h, double budget); + // Returns nullptr if not found. + ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h, double budget); bool FindFiltering(u64 cachekey, u32 hash, TextureFiltering *forceFiltering); - ReplacedTexture &FindNone() { - return none_; - } // Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.) bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo); @@ -301,8 +300,7 @@ protected: std::unordered_map aliases_; std::unordered_map filtering_; - ReplacedTexture none_; - std::unordered_map cache_; + std::unordered_map cache_; std::unordered_map> savedCache_; std::unordered_map levelCache_; }; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index c7985e82fa..7a35252f36 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -528,8 +528,8 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { int w0 = gstate.getTextureWidth(0); int h0 = gstate.getTextureHeight(0); int d0 = 1; - ReplacedTexture &replaced = FindReplacement(entry, w0, h0, d0); - if (replaced.IsInvalid()) { + ReplacedTexture *replaced = FindReplacement(entry, w0, h0, d0); + if (replaced && replaced->IsInvalid()) { entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; if (g_Config.bSaveNewTextures) { // Load once more to actually save. @@ -1482,17 +1482,17 @@ u32 TextureCacheCommon::EstimateTexMemoryUsage(const TexCacheEntry *entry) { return pixelSize << (dimW + dimH); } -ReplacedTexture &TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d) { +ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d) { if (d != 1) { // We don't yet support replacing 3D textures. - return replacer_.FindNone(); + return nullptr; } // Short circuit the non-enabled case. // Otherwise, due to bReplaceTexturesAllowLate, we'll still spawn tasks looking for replacements // that then won't be used. if (!replacer_.Enabled()) { - return replacer_.FindNone(); + return nullptr; } // Allow some delay to reduce pop-in. @@ -1501,16 +1501,21 @@ ReplacedTexture &TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & double replaceStart = time_now_d(); double budget = std::min(MAX_BUDGET_PER_TEX, replacementFrameBudget_ - replacementTimeThisFrame_); u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; - ReplacedTexture &replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h, budget); - if (replaced.IsReady(budget)) { - if (replaced.GetSize(0, w, h)) { + ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h, budget); + if (!replaced) { + replacementTimeThisFrame_ += time_now_d() - replaceStart; + return nullptr; + } + + if (replaced->IsReady(budget)) { + if (replaced->GetSize(0, w, h)) { // Consider it already "scaled." entry->status |= TexCacheEntry::STATUS_IS_SCALED; } // Remove the flag, even if it was invalid. entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; - } else if (!replaced.IsInvalid()) { + } else if (!replaced->IsInvalid()) { entry->status |= TexCacheEntry::STATUS_TO_REPLACE; } replacementTimeThisFrame_ += time_now_d() - replaceStart; @@ -2778,10 +2783,10 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt } if (canReplace) { - plan.replaced = &FindReplacement(entry, plan.w, plan.h, plan.depth); + plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); plan.replaceValid = plan.replaced->Valid(); } else { - plan.replaced = &replacer_.FindNone(); + plan.replaced = nullptr; plan.replaceValid = false; } diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index ec45251fa8..da42b07de4 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -378,7 +378,7 @@ protected: CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags); void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel); CheckAlphaResult ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool reverseColors, bool expandTo32Bit); - ReplacedTexture &FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d); + ReplacedTexture *FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d); // Return value is mapData normally, but could be another buffer allocated with AllocateAlignedMemory. void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, int mapRowPitch, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 21cf131393..6c898b5579 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -501,7 +501,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { } // Turn off texture replacement for this texture. - plan.replaced = &replacer_.FindNone(); + plan.replaced = nullptr; plan.createW /= plan.scaleFactor; plan.createH /= plan.scaleFactor; From 0fe5bd79c471e7a7151546ab4f5adcba242a0e92 Mon Sep 17 00:00:00 2001 From: Lubos Date: Wed, 8 Mar 2023 22:13:55 +0100 Subject: [PATCH 244/424] OpenXR - Manifest merge fail fixed --- android/VRManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/VRManifest.xml b/android/VRManifest.xml index e607741e3b..4dfda7647a 100644 --- a/android/VRManifest.xml +++ b/android/VRManifest.xml @@ -6,7 +6,7 @@ Date: Wed, 8 Mar 2023 22:23:54 +0100 Subject: [PATCH 245/424] OpenXR - Only horizontal HMD rotations to keys --- Core/Config.cpp | 2 +- Core/Config.h | 2 +- UI/GameSettingsScreen.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index ca8e44e023..3b23a7791f 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1154,7 +1154,7 @@ static const ConfigSetting vrSettings[] = { ConfigSetting("VRMotionLength", &g_Config.fMotionLength, 0.5f), ConfigSetting("VRHeadRotationScale", &g_Config.fHeadRotationScale, 5.0f), ConfigSetting("VRHeadRotationSmoothing", &g_Config.bHeadRotationSmoothing, false), - ConfigSetting("VRHeadRotation", &g_Config.iHeadRotation, 0), + ConfigSetting("VRHeadRotation", &g_Config.iHeadRotation, false), }; struct ConfigSectionSettings { diff --git a/Core/Config.h b/Core/Config.h index 17f198f920..aa57a2d3c7 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -472,7 +472,7 @@ public: float fMotionLength; float fHeadRotationScale; bool bHeadRotationSmoothing; - int iHeadRotation; + bool iHeadRotation; // Debugger int iDisasmWindowX; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 6c8f8469f3..0e902ad9a2 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1143,8 +1143,7 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new ItemHeader(vr->T("Experts only"))); vrSettings->Add(new CheckBox(&g_Config.bManualForceVR, vr->T("Manual switching between flat screen and VR using SCREEN key"))); - static const char *vrHeadRotations[] = { vr->T("Disabled"), vr->T("Horizontal only"), vr->T("Horizontal and vertical") }; - vrSettings->Add(new PopupMultiChoice(&g_Config.iHeadRotation, vr->T("Map HMD rotations on keys instead of VR camera"), vrHeadRotations, 0, ARRAY_SIZE(vrHeadRotations), vr->GetName(), screenManager())); + vrSettings->Add(new CheckBox(&g_Config.iHeadRotation, vr->T("Map HMD rotations on keys instead of VR camera"))); PopupSliderChoiceFloat *vrHeadRotationScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadRotationScale, 0.1f, 10.0f, vr->T("Game camera rotation step per frame"), 0.1f, screenManager(), "°")); vrHeadRotationScale->SetEnabledFunc([&] { return g_Config.iHeadRotation > 0; }); CheckBox *vrHeadRotationSmoothing = vrSettings->Add(new CheckBox(&g_Config.bHeadRotationSmoothing, vr->T("Game camera uses rotation smoothing"))); From 4ba200147962f37d379de283671881e6d663d2a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 00:01:38 +0100 Subject: [PATCH 246/424] Replacer: Make the cache data model texture-centric instead of level-centric --- Core/TextureReplacer.cpp | 155 +++++++++++++++++++----------- Core/TextureReplacer.h | 67 +++---------- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 14 ++- 4 files changed, 121 insertions(+), 117 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 42c58460d5..2c2022a0ce 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -243,10 +243,14 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); // Format: hashname = filename.png bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames; + + std::map> filenameMap; + for (const auto &item : hashes) { - ReplacementAliasKey key(0, 0, 0); - if (sscanf(item.first.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &key.level) >= 1) { - aliases_[key] = item.second; + ReplacementCacheKey key(0, 0); + int level = 0; // sscanf might fail to pluck the level, but that's ok, we default to 0. + if (sscanf(item.first.c_str(), "%16llx%8x_%d", &key.cachekey, &key.hash, &level) >= 1) { + filenameMap[key][level] = item.second; if (checkFilenames) { #if PPSSPP_PLATFORM(WINDOWS) // Uppercase probably means the filenames don't match. @@ -260,11 +264,30 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { ERROR_LOG(G3D, "Unsupported syntax under [hashes]: %s", item.first.c_str()); } } + + // Now, translate the filenameMap to the final aliasMap. + for (auto &pair : filenameMap) { + std::string alias; + int mipIndex = 0; + for (auto &level : pair.second) { + if (level.first == mipIndex) { + alias += level.second + "|"; + mipIndex++; + } else { + WARN_LOG(G3D, "Non-sequential mip index %d, breaking", level.first); + break; + } + } + if (alias == "|") { + alias = ""; // marker for no replacement + } + aliases_[pair.first] = alias; + } } if (filenameWarning) { auto err = GetI18NCategory("Error"); - host->NotifyUserMessage(err->T("textures.ini filenames may not be cross-platform"), 6.0f); + host->NotifyUserMessage(err->T("textures.ini filenames may not be cross-platform (banned characters)"), 6.0f); } if (ini.HasSection("hashranges")) { @@ -475,7 +498,7 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, return result; } -void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h) { +void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey, u32 hash, int w, int h) { int newW = w; int newH = h; LookupHashRange(cachekey >> 32, newW, newH); @@ -484,30 +507,43 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, cachekey = cachekey & 0xFFFFFFFFULL; } - for (int i = 0; i < MAX_MIP_LEVELS; ++i) { - const std::string hashfile = LookupHashFile(cachekey, hash, i); - if (hashfile.empty()) { + bool foundReplacement = false; + const std::string hashfiles = LookupHashFile(cachekey, hash, &foundReplacement); + + if (!foundReplacement) { + // nothing to do? + return; + } + + INFO_LOG(G3D, "Found: %s", hashfiles.c_str()); + + std::vector filenames; + SplitString(hashfiles, '|', filenames); + + for (int i = 0; i < std::min(MAX_MIP_LEVELS, (int)filenames.size()); ++i) { + if (filenames[i].empty()) { // Out of valid mip levels. Bail out. break; } - const Path filename = basePath_ / hashfile; + const Path filename = basePath_ / filenames[i]; + // TODO: Here, if we find a file with multiple built-in mipmap levels, + // we'll have to change a bit how things work... ReplacedTextureLevel level; level.fmt = Draw::DataFormat::R8G8B8A8_UNORM; level.file = filename; bool good; - bool logError = hashfile != HashName(cachekey, hash, i) + ".png"; - VFSFileReference *fileRef = vfs_->GetFile(hashfile.c_str()); + VFSFileReference *fileRef = vfs_->GetFile(filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. break; } level.fileRef = fileRef; - good = PopulateLevel(level, !logError); + good = PopulateLevel(level, false); // We pad files that have been hashrange'd so they are the same texture size. level.w = (level.w * w) / newW; @@ -515,26 +551,22 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *result, u64 cachekey, if (good && i != 0) { // Check that the mipmap size is correct. Can't load mips of the wrong size. - if (level.w != (result->levels_[0].w >> i) || level.h != (result->levels_[0].h >> i)) { - WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, result->levels_[0].w >> i, result->levels_[0].h >> i, i, filename.c_str()); + if (level.w != (texture->levels_[0].w >> i) || level.h != (texture->levels_[0].h >> i)) { + WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, texture->levels_[0].w >> i, texture->levels_[0].h >> i, i, filename.c_str()); good = false; } } if (good) - result->levels_.push_back(level); + texture->levels_.push_back(level); // Otherwise, we're done loading mips (bad PNG or bad size, either way.) else break; } - // Populate the level data pointers for each level. - result->levelData_.resize(result->levels_.size()); - for (size_t i = 0; i < result->levels_.size(); ++i) { - result->levelData_[i] = &levelCache_[result->levels_[i]]; - } - - result->prepareDone_ = true; + // Populate the data pointer. + texture->levelData_ = &levelCache_[hashfiles]; + texture->prepareDone_ = true; } bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { @@ -607,7 +639,7 @@ static bool WriteTextureToPNG(png_imagep image, const Path &filename, int conver class TextureSaveTask : public Task { public: // Could probably just use a vector. - SimpleBuf data; + std::vector rgbaData; int w = 0; int h = 0; @@ -619,7 +651,7 @@ public: bool skipIfExists = false; - TextureSaveTask(SimpleBuf _data) : data(std::move(_data)) {} + TextureSaveTask(std::vector _rgbaData) : rgbaData(std::move(_rgbaData)) {} // This must be IO blocking because of Android storage, despite being CPU heavy. TaskType Type() const override { return TaskType::IO_BLOCKING; } @@ -661,7 +693,7 @@ public: png.format = PNG_FORMAT_RGBA; png.width = w; png.height = h; - bool success = WriteTextureToPNG(&png, saveFilename, 0, data.data(), pitch, nullptr); + bool success = WriteTextureToPNG(&png, saveFilename, 0, rgbaData.data(), pitch, nullptr); png_image_free(&png); if (png.warning_or_error >= 2) { ERROR_LOG(COMMON, "Saving screenshot to PNG produced errors."); @@ -699,7 +731,9 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl cachekey = cachekey & 0xFFFFFFFFULL; } - std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, level); + /* + bool found = false; + std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &found); const Path filename = basePath_ / hashfile; // If it's empty, it's an ignored hash, we intentionally don't save. @@ -732,11 +766,11 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl h = lookupH * replacedInfo.scaleFactor; } - SimpleBuf saveBuf; + std::vector saveBuf; // Copy data to a buffer so we can send it to the thread. Might as well compact-away the pitch // while we're at it. - saveBuf.resize(w * h); + saveBuf.resize(w * h * 4); for (int y = 0; y < h; y++) { memcpy((u8 *)saveBuf.data() + y * w * 4, (const u8 *)data + y * pitch, w * sizeof(u32)); } @@ -761,6 +795,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl saved.w = w; saved.h = h; savedCache_[replacementKey] = std::make_pair(saved, now); + */ } void TextureReplacer::Decimate(ReplacerDecimateMode mode) { @@ -860,15 +895,16 @@ bool TextureReplacer::FindFiltering(u64 cachekey, u32 hash, TextureFiltering *fo return false; } -std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, int level) { - ReplacementAliasKey key(cachekey, hash, level); +std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement) { + ReplacementCacheKey key(cachekey, hash); auto alias = LookupWildcard(aliases_, key, cachekey, hash, ignoreAddress_); if (alias != aliases_.end()) { // Note: this will be blank if explicitly ignored. + *foundReplacement = alias->second.size() > 0; return alias->second; } - - return HashName(cachekey, hash, level) + ".png"; + *foundReplacement = false; + return ""; } std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) { @@ -938,11 +974,12 @@ bool ReplacedTexture::IsReady(double budget) { } // Loaded already, or not yet on a thread? - if (initDone_ && !levelData_.empty()) { - for (auto &l : levelData_) - l->lastUsed = lastUsed_; + if (initDone_ && levelData_ && !levelData_->data.empty()) { + // TODO: lock? + levelData_->lastUsed = lastUsed_; return true; } + // Let's not even start a new texture if we're already behind. if (budget < 0.0) return false; @@ -957,7 +994,7 @@ bool ReplacedTexture::IsReady(double budget) { if (threadWaitable_->WaitFor(budget)) { // If we finished all the levels, we're done. - return initDone_ && !levelData_.empty(); + return initDone_ && levelData_ != nullptr && !levelData_->data.empty(); } } else { Prepare(vfs_); @@ -990,13 +1027,18 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { void ReplacedTexture::PrepareData(int level) { _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); - _assert_msg_(levelData_[level] != nullptr, "Level cache not set for miplevel"); + _assert_msg_(levelData_ != nullptr, "Level cache not set"); // We must lock around access to levelData_ in case two textures try to load it at once. - std::lock_guard guard(levelData_[level]->lock); + std::lock_guard guard(levelData_->lock); const ReplacedTextureLevel &info = levels_[level]; - std::vector &out = levelData_[level]->data; + + if (levelData_->data.size() <= level) { + levelData_->data.resize(level + 1); + } + + std::vector &out = levelData_->data[level]; // Already populated from cache. if (!out.empty()) @@ -1107,14 +1149,12 @@ void ReplacedTexture::PurgeIfOlder(double t) { if (lastUsed_ >= t) return; - for (auto &l : levelData_) { - if (l->lastUsed < t) { - // We have to lock since multiple textures might reference this same data. - std::lock_guard guard(l->lock); - l->data.clear(); - // This means we have to reload. If we never purge any, there's no need. - initDone_ = false; - } + if (levelData_->lastUsed < t) { + // We have to lock since multiple textures might reference this same data. + std::lock_guard guard(levelData_->lock); + levelData_->data.clear(); + // This means we have to reload. If we never purge any, there's no need. + initDone_ = false; } } @@ -1128,28 +1168,28 @@ ReplacedTexture::~ReplacedTexture() { } } -bool ReplacedTexture::Load(int level, void *out, int rowPitch) { +bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); - if (!initDone_) + if (!initDone_) { + WARN_LOG(G3D, "Init not done yet"); return false; - if (levelData_.empty()) - return false; - - _assert_msg_(levelData_[level] != nullptr, "Level cache not set for miplevel"); + } // We probably could avoid this lock, but better to play it safe. - std::lock_guard guard(levelData_[level]->lock); + std::lock_guard guard(levelData_->lock); const ReplacedTextureLevel &info = levels_[level]; - const std::vector &data = levelData_[level]->data; + const std::vector &data = levelData_->data[level]; - if (data.empty()) + if (data.empty()) { + WARN_LOG(G3D, "Level %d is empty", level); return false; + } if (rowPitch < info.w * 4) { - ERROR_LOG_REPORT(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); + ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); return false; } _assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size"); @@ -1165,6 +1205,7 @@ bool ReplacedTexture::Load(int level, void *out, int rowPitch) { }, 0, info.h, MIN_LINES_PER_THREAD); } + INFO_LOG(G3D, "Successfully copied texture level"); return true; } diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 0b4633e05f..880b3d1d7e 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -46,13 +46,14 @@ enum class ReplacedTextureAlpha { FULL = 0x00, }; -// For forward comatibility, we specify the hash. +// For forward compatibility, we specify the hash. enum class ReplacedTextureHash { QUICK, XXH32, XXH64, }; +// Metadata about a given texture level. struct ReplacedTextureLevel { ReplacedTextureLevel() {} int w = 0; @@ -69,25 +70,9 @@ struct ReplacedTextureLevel { } }; -namespace std { - template <> - struct hash { - std::size_t operator()(const ReplacedTextureLevel &k) const { -#if PPSSPP_ARCH(64BIT) - uint64_t v = (uint64_t)k.w | ((uint64_t)k.h << 32); - v = __rotl64(v ^ (uint64_t)k.fmt, 13); -#else - uint32_t v = k.w ^ (uint32_t)k.fmt; - v = __rotl(__rotl(v, 13) ^ k.h, 13); -#endif - return v ^ hash()(k.file.ToString()); - } - }; -} - -struct ReplacedLevelCache { +struct ReplacedLevelsCache { std::mutex lock; - std::vector data; + std::vector> data; double lastUsed = 0.0; }; @@ -109,30 +94,6 @@ struct ReplacementCacheKey { } }; -struct ReplacementAliasKey { - u64 cachekey; - union { - u64 hashAndLevel; - struct { - u32 level; - u32 hash; - }; - }; - - ReplacementAliasKey(u64 c, u32 h, u32 l) : cachekey(c), level(l), hash(h) { } - - bool operator ==(const ReplacementAliasKey &k) const { - return k.cachekey == cachekey && k.hashAndLevel == hashAndLevel; - } - - bool operator <(const ReplacementAliasKey &k) const { - if (k.cachekey == cachekey) { - return k.hashAndLevel < hashAndLevel; - } - return k.cachekey < cachekey; - } -}; - namespace std { template <> struct hash { @@ -140,13 +101,6 @@ namespace std { return std::hash()(k.cachekey ^ ((u64)k.hash << 32)); } }; - - template <> - struct hash { - size_t operator()(const ReplacementAliasKey &k) const { - return std::hash()(k.cachekey ^ k.hashAndLevel); - } - }; } struct ReplacedTexture { @@ -196,7 +150,7 @@ struct ReplacedTexture { bool IsReady(double budget); - bool Load(int level, void *out, int rowPitch); + bool CopyLevelTo(int level, void *out, int rowPitch); protected: void Prepare(VFSBackend *vfs); @@ -204,7 +158,8 @@ protected: void PurgeIfOlder(double t); std::vector levels_; - std::vector levelData_; + ReplacedLevelsCache *levelData_; + ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; double lastUsed_ = 0.0; LimitedWaitable *threadWaitable_ = nullptr; @@ -273,7 +228,7 @@ protected: void ParseReduceHashRange(const std::string& key, const std::string& value); bool LookupHashRange(u32 addr, int &w, int &h); float LookupReduceHashRange(int& w, int& h); - std::string LookupHashFile(u64 cachekey, u32 hash, int level); + std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement); std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); @@ -297,10 +252,12 @@ protected: typedef std::pair WidthHeightPair; std::unordered_map hashranges_; std::unordered_map reducehashranges_; - std::unordered_map aliases_; + std::unordered_map aliases_; std::unordered_map filtering_; std::unordered_map cache_; std::unordered_map> savedCache_; - std::unordered_map levelCache_; + + // the key is from aliases_. It's a |-separated sequence of texture filenames of the levels of a texture. + std::unordered_map levelCache_; }; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 7a35252f36..9fe735487c 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2854,7 +2854,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i if (plan.replaceValid && plan.replaced->GetSize(srcLevel, w, h)) { double replaceStart = time_now_d(); - plan.replaced->Load(srcLevel, data, stride); + plan.replaced->CopyLevelTo(srcLevel, data, stride); replacementTimeThisFrame_ += time_now_d() - replaceStart; } else { GETextureFormat tfmt = (GETextureFormat)entry.format; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 6c898b5579..83bd9bc520 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -532,6 +532,8 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { levels = plan.levelsToLoad; } + VulkanPushBuffer *pushBuffer = drawEngine_->GetPushBufferForTextureData(); + for (int i = 0; i < levels; i++) { int mipUnscaledWidth = gstate.getTextureWidth(i); int mipUnscaledHeight = gstate.getTextureHeight(i); @@ -553,24 +555,28 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { void *data; std::vector saveData; + // Simple wrapper to avoid reading back from VRAM (very, very expensive). auto loadLevel = [&](int sz, int srcLevel, int lstride, int lfactor) { if (plan.saveTexture) { saveData.resize(sz); data = &saveData[0]; } else { - data = drawEngine_->GetPushBufferForTextureData()->PushAligned(sz, &bufferOffset, &texBuf, pushAlignment); + data = pushBuffer->PushAligned(sz, &bufferOffset, &texBuf, pushAlignment); } LoadVulkanTextureLevel(*entry, (uint8_t *)data, lstride, srcLevel, lfactor, actualFmt); if (plan.saveTexture) - bufferOffset = drawEngine_->GetPushBufferForTextureData()->PushAligned(&saveData[0], sz, pushAlignment, &texBuf); + bufferOffset = pushBuffer->PushAligned(&saveData[0], sz, pushAlignment, &texBuf); }; bool dataScaled = true; if (plan.replaceValid) { // Directly load the replaced image. - data = drawEngine_->GetPushBufferForTextureData()->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); + data = pushBuffer->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); double replaceStart = time_now_d(); - plan.replaced->Load(plan.baseLevelSrc + i, data, byteStride); // if it fails, it'll just be garbage data... OK for now. + if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, data, byteStride)) { // If plan.replaceValid, this shouldn't fail. + WARN_LOG(G3D, "Failed to copy replaced texture level"); + // TODO: Fill with some pattern? + } replacementTimeThisFrame_ += time_now_d() - replaceStart; VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, "Copy Upload (replaced): %dx%d", mipWidth, mipHeight); From bda09be1094b8e66abae956f9e6a50e0c5fc1849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 00:05:24 +0100 Subject: [PATCH 247/424] Texture color format doesn't belong as a per-level property, that's not supported. All levels of a texture must have the same format. --- Core/TextureReplacer.cpp | 11 ++++++++--- Core/TextureReplacer.h | 28 ++++++++++++---------------- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/D3D11/TextureCacheD3D11.cpp | 4 ++-- GPU/Directx9/TextureCacheDX9.cpp | 2 +- GPU/GLES/TextureCacheGLES.cpp | 4 ++-- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- 7 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 2c2022a0ce..e15df31edd 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -87,7 +87,9 @@ static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::s return IdentifyMagic(magic); } -TextureReplacer::TextureReplacer() {} +TextureReplacer::TextureReplacer(Draw::DrawContext *draw) { + // TODO: Check draw for supported texture formats. +} TextureReplacer::~TextureReplacer() { for (auto &iter : cache_) { @@ -274,7 +276,7 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { alias += level.second + "|"; mipIndex++; } else { - WARN_LOG(G3D, "Non-sequential mip index %d, breaking", level.first); + WARN_LOG(G3D, "Non-sequential mip index %d, breaking. filenames=%s", level.first, level.second.c_str()); break; } } @@ -531,9 +533,12 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey // TODO: Here, if we find a file with multiple built-in mipmap levels, // we'll have to change a bit how things work... ReplacedTextureLevel level; - level.fmt = Draw::DataFormat::R8G8B8A8_UNORM; level.file = filename; + if (i == 0) { + texture->fmt = Draw::DataFormat::R8G8B8A8_UNORM; + } + bool good; VFSFileReference *fileRef = vfs_->GetFile(filenames[i].c_str()); diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 880b3d1d7e..efcd4269ae 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -55,19 +55,13 @@ enum class ReplacedTextureHash { // Metadata about a given texture level. struct ReplacedTextureLevel { - ReplacedTextureLevel() {} int w = 0; int h = 0; - Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. Path file; - // Can be ignored for hashing/equal, since file has all uniqueness. + // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. + // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. VFSFileReference *fileRef = nullptr; - bool operator ==(const ReplacedTextureLevel &other) const { - if (w != other.w || h != other.h || fmt != other.fmt) - return false; - return file == other.file; - } }; struct ReplacedLevelsCache { @@ -135,13 +129,13 @@ struct ReplacedTexture { return (int)levels_.size(); } - Draw::DataFormat Format(int level) const { + Draw::DataFormat Format() const { if (initDone_) { - if ((size_t)level < levels_.size()) { - return levels_[level].fmt; - } + return fmt; + } else { + // Shouldn't get here. + return Draw::DataFormat::UNDEFINED; } - return Draw::DataFormat::R8G8B8A8_UNORM; } u8 AlphaStatus() const { @@ -164,6 +158,7 @@ protected: double lastUsed_ = 0.0; LimitedWaitable *threadWaitable_ = nullptr; std::mutex mutex_; + Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. bool cancelPrepare_ = false; bool initDone_ = false; @@ -171,8 +166,8 @@ protected: VFSBackend *vfs_ = nullptr; - friend TextureReplacer; - friend ReplacedTextureTask; + friend class TextureReplacer; + friend class ReplacedTextureTask; }; struct ReplacedTextureDecodeInfo { @@ -193,7 +188,8 @@ enum class ReplacerDecimateMode { class TextureReplacer { public: - TextureReplacer(); + // The draw context will be checked for supported texture formats. + TextureReplacer(Draw::DrawContext *draw); ~TextureReplacer(); void Init(); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 9fe735487c..745fd29a3e 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -107,7 +107,7 @@ inline int dimHeight(u16 dim) { } TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw, Draw2D *draw2D) - : draw_(draw), draw2D_(draw2D) { + : draw_(draw), draw2D_(draw2D), replacer_(draw) { decimationCounter_ = TEXCACHE_DECIMATION_INTERVAL; // It's only possible to have 1KB of palette entries, although we allow 2KB in a hack. diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 047a3504f9..b551e573df 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -263,7 +263,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaceValid) { - dstFmt = ToDXGIFormat(plan.replaced->Format(plan.baseLevelSrc)); + dstFmt = ToDXGIFormat(plan.replaced->Format()); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM; } else if (plan.decodeToClut8) { @@ -339,7 +339,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { // For UpdateSubresource, we can't decode directly into the texture so we allocate a buffer :( // NOTE: Could reuse it between levels or textures! if (plan.replaceValid) { - bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format(srcLevel)); + bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); } else { if (plan.scaleFactor > 1) { bpp = 4; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 4e349fbe73..dc1ed423d6 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -235,7 +235,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { D3DFORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaceValid) { - dstFmt = ToD3D9Format(plan.replaced->Format(plan.baseLevelSrc)); + dstFmt = ToD3D9Format(plan.replaced->Format()); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = D3DFMT_A8R8G8B8; } else if (plan.decodeToClut8) { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index aacba8e3d6..127b6d7699 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -247,7 +247,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { - dstFmt = plan.replaced->Format(plan.baseLevelSrc); + dstFmt = plan.replaced->Format(); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = Draw::DataFormat::R8G8B8A8_UNORM; } else if (plan.decodeToClut8) { @@ -294,7 +294,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { int bpp; if (plan.replaceValid) { - bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format(srcLevel)); + bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); } else { if (plan.scaleFactor > 1) { bpp = 4; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 83bd9bc520..16eeb41a98 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -443,7 +443,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // Any texture scaling is gonna move away from the original 16-bit format, if any. VkFormat actualFmt = plan.scaleFactor > 1 ? VULKAN_8888_FORMAT : dstFmt; if (plan.replaceValid) { - actualFmt = ToVulkanFormat(plan.replaced->Format(plan.baseLevelSrc)); + actualFmt = ToVulkanFormat(plan.replaced->Format()); } bool computeUpload = false; From 4752e20ad42dff8afd2015a7a74fca42da680943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 00:24:30 +0100 Subject: [PATCH 248/424] Don't reuse the ReplacedTexture struct in "saved cache". --- Core/TextureReplacer.cpp | 18 ++++++++---------- Core/TextureReplacer.h | 9 ++++++++- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index e15df31edd..22ce25ebb1 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -736,7 +736,6 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl cachekey = cachekey & 0xFFFFFFFFULL; } - /* bool found = false; std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &found); const Path filename = basePath_ / hashfile; @@ -753,9 +752,10 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl double now = time_now_d(); if (it != savedCache_.end()) { // We've already saved this texture. Let's only save if it's bigger (e.g. scaled now.) - if (it->second.first.w >= w && it->second.first.h >= h) { + // TODO: Isn't this check backwards? + if (it->second.levelW[level] >= w && it->second.levelH[level] >= h) { // If it's been more than 5 seconds, we'll check again. Maybe they deleted. - double age = now - it->second.second; + double age = now - it->second.lastTimeSaved; if (age < 5.0) return; @@ -794,13 +794,11 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl // Remember that we've saved this for next time. // Should be OK that the actual disk write may not be finished yet. - ReplacedTextureLevel saved; - saved.fmt = Draw::DataFormat::R8G8B8A8_UNORM; - saved.file = filename; - saved.w = w; - saved.h = h; - savedCache_[replacementKey] = std::make_pair(saved, now); - */ + SavedTextureCacheData &saveData = savedCache_[replacementKey]; + saveData.levelW[level] = w; + saveData.levelH[level] = h; + saveData.levelSaved[level] = true; + saveData.lastTimeSaved = now; } void TextureReplacer::Decimate(ReplacerDecimateMode mode) { diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index efcd4269ae..7d6eafefcb 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -64,6 +64,13 @@ struct ReplacedTextureLevel { VFSFileReference *fileRef = nullptr; }; +struct SavedTextureCacheData { + int levelW[8]{}; + int levelH[8]{}; + bool levelSaved[8]{}; + double lastTimeSaved; +}; + struct ReplacedLevelsCache { std::mutex lock; std::vector> data; @@ -252,7 +259,7 @@ protected: std::unordered_map filtering_; std::unordered_map cache_; - std::unordered_map> savedCache_; + std::unordered_map savedCache_; // the key is from aliases_. It's a |-separated sequence of texture filenames of the levels of a texture. std::unordered_map levelCache_; From ef14f28099756bf4bf34ca9d9f1d3cbd76e6ea64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 00:26:45 +0100 Subject: [PATCH 249/424] Fix logspam --- Core/TextureReplacer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 22ce25ebb1..31fd7edef0 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -517,7 +517,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey return; } - INFO_LOG(G3D, "Found: %s", hashfiles.c_str()); + // INFO_LOG(G3D, "Found: %s", hashfiles.c_str()); std::vector filenames; SplitString(hashfiles, '|', filenames); @@ -1208,7 +1208,6 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { }, 0, info.h, MIN_LINES_PER_THREAD); } - INFO_LOG(G3D, "Successfully copied texture level"); return true; } From 03df5b78311ddd0744d779dbd8a64968bbadbefd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 00:33:37 +0100 Subject: [PATCH 250/424] Fix fileref memory leak --- Core/TextureReplacer.cpp | 5 +++++ Core/TextureReplacer.h | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 31fd7edef0..c1d02a2792 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -1169,6 +1169,11 @@ ReplacedTexture::~ReplacedTexture() { threadWaitable_->WaitAndRelease(); threadWaitable_ = nullptr; } + + for (auto &level : levels_) { + vfs_->ReleaseFile(level.fileRef); + level.fileRef = nullptr; + } } bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index 7d6eafefcb..fec6a69a4c 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -150,7 +150,6 @@ struct ReplacedTexture { } bool IsReady(double budget); - bool CopyLevelTo(int level, void *out, int rowPitch); protected: From 092bbf5eaaa2ded689a7df490c1f18978d466bd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 10:51:15 +0100 Subject: [PATCH 251/424] Fix saving of textures --- Core/TextureReplacer.cpp | 52 ++++++++++++++++++------------- Core/TextureReplacer.h | 4 +-- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- 4 files changed, 34 insertions(+), 26 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index c1d02a2792..6fd0205f71 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -244,7 +244,7 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { if (ini.HasSection("hashes")) { auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); // Format: hashname = filename.png - bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames; + bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; std::map> filenameMap; @@ -257,7 +257,7 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { #if PPSSPP_PLATFORM(WINDOWS) // Uppercase probably means the filenames don't match. // Avoiding an actual check of the filenames to avoid performance impact. - filenameWarning = filenameWarning || item.second.find_first_of("\\ABCDEFGHIJKLMNOPQRSTUVWXYZ") != std::string::npos; + filenameWarning = filenameWarning || item.second.find_first_of("\\ABCDEFGHIJKLMNOPQRSTUVWXYZ:<>|?*") != std::string::npos; #else filenameWarning = filenameWarning || item.second.find_first_of("\\:<>|?*") != std::string::npos; #endif @@ -510,9 +510,10 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey } bool foundReplacement = false; - const std::string hashfiles = LookupHashFile(cachekey, hash, &foundReplacement); + bool ignored = false; + const std::string hashfiles = LookupHashFile(cachekey, hash, &foundReplacement, &ignored); - if (!foundReplacement) { + if (!foundReplacement || ignored) { // nothing to do? return; } @@ -641,9 +642,10 @@ static bool WriteTextureToPNG(png_imagep image, const Path &filename, int conver } } -class TextureSaveTask : public Task { +// We save textures on threadpool tasks since it's a fire-and-forget task, and both I/O and png compression +// can be pretty slow. +class SaveTextureTask : public Task { public: - // Could probably just use a vector. std::vector rgbaData; int w = 0; @@ -652,13 +654,13 @@ public: Path basePath; std::string hashfile; - u32 replacedInfoHash; + u32 replacedInfoHash = 0; bool skipIfExists = false; - TextureSaveTask(std::vector _rgbaData) : rgbaData(std::move(_rgbaData)) {} + SaveTextureTask(std::vector &&_rgbaData) : rgbaData(std::move(_rgbaData)) {} - // This must be IO blocking because of Android storage, despite being CPU heavy. + // This must be set to I/O blocking because of Android storage (so we attach the thread to JNI), while being CPU heavy too. TaskType Type() const override { return TaskType::IO_BLOCKING; } TaskPriority Priority() const override { @@ -670,9 +672,9 @@ public: const Path saveFilename = basePath / NEW_TEXTURE_DIR / hashfile; // Should we skip writing if the newly saved data already exists? - // We do this on the thread due to slow IO. - if (skipIfExists && File::Exists(saveFilename)) + if (skipIfExists && File::Exists(saveFilename)) { return; + } // And we always skip if the replace file already exists. if (File::Exists(filename)) @@ -701,9 +703,11 @@ public: bool success = WriteTextureToPNG(&png, saveFilename, 0, rgbaData.data(), pitch, nullptr); png_image_free(&png); if (png.warning_or_error >= 2) { - ERROR_LOG(COMMON, "Saving screenshot to PNG produced errors."); + ERROR_LOG(G3D, "Saving screenshot to PNG produced errors."); } else if (success) { NOTICE_LOG(G3D, "Saving texture for replacement: %08x / %dx%d in '%s'", replacedInfoHash, w, h, saveFilename.ToVisualString().c_str()); + } else { + ERROR_LOG(G3D, "Failed to write '%s'", saveFilename.c_str()); } } }; @@ -736,29 +740,32 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl cachekey = cachekey & 0xFFFFFFFFULL; } - bool found = false; - std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &found); - const Path filename = basePath_ / hashfile; + bool found = false, ignored = false; + std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &found, &ignored); // If it's empty, it's an ignored hash, we intentionally don't save. - if (hashfile.empty()) { + if (found) { // If it exists, must've been decoded and saved as a new texture already. return; } + // Generate a new filename. + hashfile = HashName(cachekey, replacedInfo.hash, level) + ".png"; + + const Path filename = basePath_ / hashfile; + ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash); auto it = savedCache_.find(replacementKey); bool skipIfExists = false; double now = time_now_d(); if (it != savedCache_.end()) { // We've already saved this texture. Let's only save if it's bigger (e.g. scaled now.) - // TODO: Isn't this check backwards? + // This check isn't backwards, it's just to check if we should *skip* saving, a bit confusing. if (it->second.levelW[level] >= w && it->second.levelH[level] >= h) { // If it's been more than 5 seconds, we'll check again. Maybe they deleted. double age = now - it->second.lastTimeSaved; if (age < 5.0) return; - skipIfExists = true; } } @@ -781,8 +788,7 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl } pitch = w * 4; - TextureSaveTask *task = new TextureSaveTask(std::move(saveBuf)); - // Should probably do a proper move constructor but this'll work. + SaveTextureTask *task = new SaveTextureTask(std::move(saveBuf)); task->w = w; task->h = h; task->pitch = pitch; @@ -898,15 +904,17 @@ bool TextureReplacer::FindFiltering(u64 cachekey, u32 hash, TextureFiltering *fo return false; } -std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement) { +std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement, bool *ignored) { ReplacementCacheKey key(cachekey, hash); auto alias = LookupWildcard(aliases_, key, cachekey, hash, ignoreAddress_); if (alias != aliases_.end()) { // Note: this will be blank if explicitly ignored. - *foundReplacement = alias->second.size() > 0; + *foundReplacement = true; + *ignored = alias->second.empty(); return alias->second; } *foundReplacement = false; + *ignored = false; return ""; } diff --git a/Core/TextureReplacer.h b/Core/TextureReplacer.h index fec6a69a4c..a2faa7a763 100644 --- a/Core/TextureReplacer.h +++ b/Core/TextureReplacer.h @@ -68,7 +68,7 @@ struct SavedTextureCacheData { int levelW[8]{}; int levelH[8]{}; bool levelSaved[8]{}; - double lastTimeSaved; + double lastTimeSaved = 0.0; }; struct ReplacedLevelsCache { @@ -230,7 +230,7 @@ protected: void ParseReduceHashRange(const std::string& key, const std::string& value); bool LookupHashRange(u32 addr, int &w, int &h); float LookupReduceHashRange(int& w, int& h); - std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement); + std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement, bool *ignored); std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 745fd29a3e..48a4a4e14c 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2901,7 +2901,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i } } - if (replacer_.Enabled() && plan.replaced->IsInvalid()) { + if (plan.saveTexture && !lowMemoryMode_) { ReplacedTextureDecodeInfo replacedInfo; replacedInfo.cachekey = entry.CacheKey(); replacedInfo.hash = entry.fullhash; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 16eeb41a98..2ec829f511 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -614,7 +614,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); } // Format might be wrong in lowMemoryMode_, so don't save. - if (replacer_.Enabled() && plan.replaced->IsInvalid() && !lowMemoryMode_) { + if (plan.saveTexture && !lowMemoryMode_) { // When hardware texture scaling is enabled, this saves the original. int w = dataScaled ? mipWidth : mipUnscaledWidth; int h = dataScaled ? mipHeight : mipUnscaledHeight; From b1f41c44fedfdfe6dfe01c39b663520d9a8521d0 Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 9 Mar 2023 11:22:54 +0100 Subject: [PATCH 252/424] OpenXR - Vertical HMD rotation to keys cleanup --- Common/VR/PPSSPPVR.cpp | 24 ++---------------------- Core/Config.cpp | 2 +- Core/Config.h | 2 +- UI/GameSettingsScreen.cpp | 6 +++--- 4 files changed, 7 insertions(+), 27 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 20a54ab678..e9d40b3cbc 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -315,7 +315,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { } // Head control - if (g_Config.iHeadRotation) { + if (g_Config.bHeadRotationEnabled) { float pitch = -VR_GetHMDAngles().x; float yaw = -VR_GetHMDAngles().y; bool disable = vrFlatForced || appMode == VR_MENU_MODE; @@ -342,25 +342,6 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { float limit = isVR ? g_Config.fHeadRotationScale : 20; keyInput.deviceId = DEVICE_ID_XR_HMD; - // vertical rotations - if (g_Config.iHeadRotation == 2) { - //up - activate = !disable && pitch > limit; - keyInput.flags = activate ? KEY_DOWN : KEY_UP; - keyInput.keyCode = NKCODE_EXT_ROTATION_UP; - if (hmdMotion[0] != activate) NativeKey(keyInput); - if (isVR && activate) hmdMotionDiff[0] -= limit; - hmdMotion[0] = activate; - - //down - activate = !disable && pitch < -limit; - keyInput.flags = activate ? KEY_DOWN : KEY_UP; - keyInput.keyCode = NKCODE_EXT_ROTATION_DOWN; - if (hmdMotion[1] != activate) NativeKey(keyInput); - if (isVR && activate) hmdMotionDiff[0] += limit; - hmdMotion[1] = activate; - } - //left activate = !disable && yaw < -limit; keyInput.flags = activate ? KEY_DOWN : KEY_UP; @@ -690,8 +671,7 @@ bool StartVRRender() { float mRoll = mz * ToRadians(rotation.z); // use in-game camera interpolated rotation - if (g_Config.iHeadRotation >= 2) mPitch = -mx * ToRadians(hmdMotionDiffLast[0]); // vertical - if (g_Config.iHeadRotation >= 1) mYaw = -my * ToRadians(hmdMotionDiffLast[1]); // horizontal + if (g_Config.bHeadRotationEnabled) mYaw = -my * ToRadians(hmdMotionDiffLast[1]); // horizontal // create updated quaternion XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mPitch); diff --git a/Core/Config.cpp b/Core/Config.cpp index 3b23a7791f..da0b1aa0d1 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1153,8 +1153,8 @@ static const ConfigSetting vrSettings[] = { ConfigSetting("VRHeadUpDisplayScale", &g_Config.fHeadUpDisplayScale, 0.3f), ConfigSetting("VRMotionLength", &g_Config.fMotionLength, 0.5f), ConfigSetting("VRHeadRotationScale", &g_Config.fHeadRotationScale, 5.0f), + ConfigSetting("VRHeadRotationEnabled", &g_Config.bHeadRotationEnabled, false), ConfigSetting("VRHeadRotationSmoothing", &g_Config.bHeadRotationSmoothing, false), - ConfigSetting("VRHeadRotation", &g_Config.iHeadRotation, false), }; struct ConfigSectionSettings { diff --git a/Core/Config.h b/Core/Config.h index aa57a2d3c7..f5f902c5f1 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -471,8 +471,8 @@ public: float fHeadUpDisplayScale; float fMotionLength; float fHeadRotationScale; + bool bHeadRotationEnabled; bool bHeadRotationSmoothing; - bool iHeadRotation; // Debugger int iDisasmWindowX; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 0e902ad9a2..abf2e2034f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1143,11 +1143,11 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new ItemHeader(vr->T("Experts only"))); vrSettings->Add(new CheckBox(&g_Config.bManualForceVR, vr->T("Manual switching between flat screen and VR using SCREEN key"))); - vrSettings->Add(new CheckBox(&g_Config.iHeadRotation, vr->T("Map HMD rotations on keys instead of VR camera"))); + vrSettings->Add(new CheckBox(&g_Config.bHeadRotationEnabled, vr->T("Map HMD rotations on keys instead of VR camera"))); PopupSliderChoiceFloat *vrHeadRotationScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadRotationScale, 0.1f, 10.0f, vr->T("Game camera rotation step per frame"), 0.1f, screenManager(), "°")); - vrHeadRotationScale->SetEnabledFunc([&] { return g_Config.iHeadRotation > 0; }); + vrHeadRotationScale->SetEnabledPtr(&g_Config.bHeadRotationEnabled); CheckBox *vrHeadRotationSmoothing = vrSettings->Add(new CheckBox(&g_Config.bHeadRotationSmoothing, vr->T("Game camera uses rotation smoothing"))); - vrHeadRotationSmoothing->SetEnabledFunc([&] { return g_Config.iHeadRotation > 0; }); + vrHeadRotationSmoothing->SetEnabledPtr(&g_Config.bHeadRotationEnabled); vrSettings->Add(new CheckBox(&g_Config.bEnableMotions, vr->T("Map controller movements to keys"))); PopupSliderChoiceFloat *vrMotions = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMotionLength, 0.3f, 1.0f, vr->T("Motion needed to generate action"), 0.1f, screenManager(), vr->T("m"))); vrMotions->SetEnabledPtr(&g_Config.bEnableMotions); From 44c4e637538376f1012409d2a5ce0f6cfabe3e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 14:43:59 +0100 Subject: [PATCH 253/424] Simplifies and speeds up D3D11 texture uploads. Also, fixes a bug with replacement off --- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/D3D11/TextureCacheD3D11.cpp | 104 ++++++++++++++++++------------ 2 files changed, 62 insertions(+), 44 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 48a4a4e14c..f89bf64898 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2784,7 +2784,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (canReplace) { plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); - plan.replaceValid = plan.replaced->Valid(); + plan.replaceValid = plan.replaced ? plan.replaced->Valid() : plan.replaced; } else { plan.replaced = nullptr; plan.replaceValid = false; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index b551e573df..90d1927898 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -284,45 +284,16 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (th > 16384) th = 16384; + // The PSP only supports 8 mip levels, but we support 12 in the texture replacer (4k textures down to 1). + D3D11_SUBRESOURCE_DATA subresData[12]{}; + if (plan.depth == 1) { // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. levels = std::min(plan.levelsToCreate, plan.levelsToLoad); - - ID3D11Texture2D *tex = nullptr; - D3D11_TEXTURE2D_DESC desc{}; - desc.CPUAccessFlags = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.ArraySize = 1; - desc.SampleDesc.Count = 1; - desc.Width = tw; - desc.Height = th; - desc.Format = dstFmt; - desc.MipLevels = levels; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - - ASSERT_SUCCESS(device_->CreateTexture2D(&desc, nullptr, &tex)); - texture = tex; } else { - ID3D11Texture3D *tex = nullptr; - D3D11_TEXTURE3D_DESC desc{}; - desc.CPUAccessFlags = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.Width = tw; - desc.Height = th; - desc.Depth = plan.depth; - desc.Format = dstFmt; - desc.MipLevels = 1; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - ASSERT_SUCCESS(device_->CreateTexture3D(&desc, nullptr, &tex)); - texture = tex; - levels = plan.depth; } - ASSERT_SUCCESS(device_->CreateShaderResourceView(texture, nullptr, &view)); - entry->texturePtr = texture; - entry->textureView = view; - Draw::DataFormat texFmt = FromD3D11Format(dstFmt); for (int i = 0; i < levels; i++) { @@ -349,7 +320,20 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { } stride = std::max(mipWidth * bpp, 16); - data = (u8 *)AllocateAlignedMemory(stride * mipHeight, 16); + + if (plan.depth == 1) { + data = (u8 *)AllocateAlignedMemory(stride * mipHeight, 16); + subresData[i].pSysMem = data; + subresData[i].SysMemPitch = stride; + subresData[i].SysMemSlicePitch = 0; + } else { + if (i == 0) { + subresData[0].pSysMem = AllocateAlignedMemory(stride * mipHeight * plan.depth, 16); + subresData[0].SysMemPitch = stride; + subresData[0].SysMemSlicePitch = stride * mipHeight; + } + data = (uint8_t *)subresData[0].pSysMem + stride * mipHeight * i; + } if (!data) { ERROR_LOG(G3D, "Ran out of RAM trying to allocate a temporary texture upload buffer (%dx%d)", mipWidth, mipHeight); @@ -357,17 +341,51 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { } LoadTextureLevel(*entry, data, stride, plan, srcLevel, texFmt, TexDecodeFlags{}); - if (plan.depth == 1) { - context_->UpdateSubresource(texture, i, nullptr, data, stride, 0); - } else { - D3D11_BOX box{}; - box.front = i; - box.back = i + 1; - box.right = mipWidth; - box.bottom = mipHeight; - context_->UpdateSubresource(texture, 0, &box, data, stride, 0); + } + + if (plan.depth == 1) { + // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. + levels = std::min(plan.levelsToCreate, plan.levelsToLoad); + + ID3D11Texture2D *tex = nullptr; + D3D11_TEXTURE2D_DESC desc{}; + desc.CPUAccessFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.ArraySize = 1; + desc.SampleDesc.Count = 1; + desc.Width = tw; + desc.Height = th; + desc.Format = dstFmt; + desc.MipLevels = levels; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + ASSERT_SUCCESS(device_->CreateTexture2D(&desc, subresData, &tex)); + texture = tex; + } else { + ID3D11Texture3D *tex = nullptr; + D3D11_TEXTURE3D_DESC desc{}; + desc.CPUAccessFlags = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.Width = tw; + desc.Height = th; + desc.Depth = plan.depth; + desc.Format = dstFmt; + desc.MipLevels = 1; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + ASSERT_SUCCESS(device_->CreateTexture3D(&desc, subresData, &tex)); + texture = tex; + + levels = plan.depth; + } + + ASSERT_SUCCESS(device_->CreateShaderResourceView(texture, nullptr, &view)); + entry->texturePtr = texture; + entry->textureView = view; + + for (int i = 0; i < 12; i++) { + if (subresData[i].pSysMem) { + FreeAlignedMemory((void *)subresData[i].pSysMem); } - FreeAlignedMemory(data); } // Signal that we support depth textures so use it as one. From b253225815b1aee417d919f41039810c55a60b54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 14:57:38 +0100 Subject: [PATCH 254/424] Fix another replacer lifecycle issue, causing unnecessary texture invalidation. --- Core/TextureReplacer.cpp | 1 + GPU/Common/TextureCacheCommon.cpp | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 6fd0205f71..98de573b2f 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -515,6 +515,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey if (!foundReplacement || ignored) { // nothing to do? + texture->prepareDone_ = true; return; } diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index f89bf64898..8751efbb6e 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -529,16 +529,18 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { int h0 = gstate.getTextureHeight(0); int d0 = 1; ReplacedTexture *replaced = FindReplacement(entry, w0, h0, d0); - if (replaced && replaced->IsInvalid()) { - entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; - if (g_Config.bSaveNewTextures) { - // Load once more to actually save. + if (replaced) { + if (replaced->IsInvalid()) { + entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; + if (g_Config.bSaveNewTextures) { + // Load once more to actually save. + match = false; + reason = "replacing"; + } + } else { match = false; reason = "replacing"; } - } else { - match = false; - reason = "replacing"; } } @@ -2784,7 +2786,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (canReplace) { plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); - plan.replaceValid = plan.replaced ? plan.replaced->Valid() : plan.replaced; + plan.replaceValid = plan.replaced ? plan.replaced->Valid() : false; } else { plan.replaced = nullptr; plan.replaceValid = false; From b75a51f05494cdf1dbd558978efb8fc423fe2fad Mon Sep 17 00:00:00 2001 From: xujibbs <79200793+xujibbs@users.noreply.github.com> Date: Thu, 9 Mar 2023 22:12:14 +0800 Subject: [PATCH 255/424] Update zh_CN.ini --- assets/lang/zh_CN.ini | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 9bb0c7a322..0c6796ad2d 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1089,6 +1089,7 @@ AVI Dump started. = AVI转储开始 AVI Dump stopped. = AVI转储停止 Cache ISO in RAM = 在内存中缓存完整ISO Change CPU Clock = 修改PSP的CPU频率(不稳定) +Rewind Snapshot Interval = 倒带快照间隔 Color Tint = 颜色色调 Color Saturation = 饱和度 Error: load undo state is from a different game = 错误:撤回的即时存档是来自不同游戏的 @@ -1146,17 +1147,17 @@ Not a PSP game = 这不是一个PSP游戏 Off = 关闭 Oldest Save = 最旧的即时存档 Path does not exist! = 路径不存在! -PSP Memory Stick = PSP储存 -PSP Model = PSP机型 -PSP Settings = PSP设置 +PSP Memory Stick = PSP 储存 +PSP Model = PSP 机型 +PSP Settings = PSP 设置 PSP-1000 = PSP-1000 PSP-2000/3000 = PSP-2000/3000 Recent games = 最近的游戏 Record Audio = 录制音频 Record Display = 录制视频 Reset Recording on Save/Load State = 保存/载入存档时重置录制 -Restore Default Settings = 恢复默认PPSSPP设置 -Rewind Snapshot Frequency = 倒带存档频率 +Restore Default Settings = 恢复默认 PPSSPP 设置 +Rewind Snapshot Frequency = 倒带快照频率 Save path in installed.txt = 记忆棒目录使用"installed.txt" Save path in My Documents = 记忆棒目录使用"我的文档" Savestate Slot = 即时存档插槽 From 8e02f14276018bc09332be12f2d30f100089c06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 15:39:46 +0100 Subject: [PATCH 256/424] Remove hidden option ReplaceTextureAllowLate Don't want to have to test little-used paths like this. --- Core/Config.cpp | 1 - Core/Config.h | 1 - Core/TextureReplacer.cpp | 23 ++++++++--------------- 3 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index da0b1aa0d1..cce0b9d7cb 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -877,7 +877,6 @@ static const ConfigSetting graphicsSettings[] = { ReportedConfigSetting("ReplaceTextures", &g_Config.bReplaceTextures, true, true, true), ReportedConfigSetting("SaveNewTextures", &g_Config.bSaveNewTextures, false, true, true), ConfigSetting("IgnoreTextureFilenames", &g_Config.bIgnoreTextureFilenames, false, true, true), - ConfigSetting("ReplaceTexturesAllowLate", &g_Config.bReplaceTexturesAllowLate, true, true, true), ReportedConfigSetting("TexScalingLevel", &g_Config.iTexScalingLevel, 1, true, true), ReportedConfigSetting("TexScalingType", &g_Config.iTexScalingType, 0, true, true), diff --git a/Core/Config.h b/Core/Config.h index f5f902c5f1..38f90902a0 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -213,7 +213,6 @@ public: bool bReplaceTextures; bool bSaveNewTextures; bool bIgnoreTextureFilenames; - bool bReplaceTexturesAllowLate; int iTexScalingLevel; // 0 = auto, 1 = off, 2 = 2x, ..., 5 = 5x int iTexScalingType; // 0 = xBRZ, 1 = Hybrid bool bTexDeposterize; diff --git a/Core/TextureReplacer.cpp b/Core/TextureReplacer.cpp index 98de573b2f..2ac2e23133 100644 --- a/Core/TextureReplacer.cpp +++ b/Core/TextureReplacer.cpp @@ -494,7 +494,7 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, ReplacedTexture *result = new ReplacedTexture(); cache_[replacementKey] = result; result->vfs_ = this->vfs_; - if (!g_Config.bReplaceTexturesAllowLate || budget > 0.0) { + if (budget > 0.0) { PopulateReplacement(result, cachekey, hash, w, h); } return result; @@ -998,20 +998,13 @@ bool ReplacedTexture::IsReady(double budget) { if (!prepareDone_) return false; - if (g_Config.bReplaceTexturesAllowLate) { - if (threadWaitable_) - delete threadWaitable_; - threadWaitable_ = new LimitedWaitable(); - g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); - - if (threadWaitable_->WaitFor(budget)) { - // If we finished all the levels, we're done. - return initDone_ && levelData_ != nullptr && !levelData_->data.empty(); - } - } else { - Prepare(vfs_); - _assert_(initDone_); - return true; + if (threadWaitable_) + delete threadWaitable_; + threadWaitable_ = new LimitedWaitable(); + g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); + if (threadWaitable_->WaitFor(budget)) { + // If we finished all the levels, we're done. + return initDone_ && levelData_ != nullptr && !levelData_->data.empty(); } // Still pending on thread. From 61b05130468b240bf54637e6d7620038848fd58a Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 9 Mar 2023 17:54:34 +0100 Subject: [PATCH 257/424] OpenXR - Platform flags for extensions refactored --- Common/VR/PPSSPPVR.cpp | 4 ++-- Common/VR/VRBase.cpp | 6 +++--- Common/VR/VRBase.h | 4 ++-- Common/VR/VRFramebuffer.cpp | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index e9d40b3cbc..657f3e1420 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -150,10 +150,10 @@ void InitVROnAndroid(void* vm, void* activity, const char* system, int version, //Set platform flags if (strcmp(vendor, "PICO") == 0) { VR_SetPlatformFLag(VR_PLATFORM_CONTROLLER_PICO, true); - VR_SetPlatformFLag(VR_PLATFORM_INSTANCE_EXT, true); + VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_INSTANCE, true); } else if ((strcmp(vendor, "META") == 0) || (strcmp(vendor, "OCULUS") == 0)) { VR_SetPlatformFLag(VR_PLATFORM_CONTROLLER_QUEST, true); - VR_SetPlatformFLag(VR_PLATFORM_PERFORMANCE_EXT, true); + VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_PERFORMANCE, true); } VR_SetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN, (GPUBackend)g_Config.iGPUBackend == GPUBackend::VULKAN); diff --git a/Common/VR/VRBase.cpp b/Common/VR/VRBase.cpp index 3ada93d754..6b795f4245 100644 --- a/Common/VR/VRBase.cpp +++ b/Common/VR/VRBase.cpp @@ -49,10 +49,10 @@ void VR_Init( void* system, const char* name, int version ) { } extensions.push_back(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME); #ifdef ANDROID - if (VR_GetPlatformFlag(VR_PLATFORM_INSTANCE_EXT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_INSTANCE)) { extensions.push_back(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME); } - if (VR_GetPlatformFlag(VR_PLATFORM_PERFORMANCE_EXT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PERFORMANCE)) { extensions.push_back(XR_EXT_PERFORMANCE_SETTINGS_EXTENSION_NAME); extensions.push_back(XR_KHR_ANDROID_THREAD_SETTINGS_EXTENSION_NAME); } @@ -80,7 +80,7 @@ void VR_Init( void* system, const char* name, int version ) { #ifdef ANDROID XrInstanceCreateInfoAndroidKHR instanceCreateInfoAndroid = {XR_TYPE_INSTANCE_CREATE_INFO_ANDROID_KHR}; - if (VR_GetPlatformFlag(VR_PLATFORM_INSTANCE_EXT)) { + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_INSTANCE)) { ovrJava* java = (ovrJava*)system; instanceCreateInfoAndroid.applicationVM = java->Vm; instanceCreateInfoAndroid.applicationActivity = java->ActivityObject; diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index 7ed105c846..157ae7c2b3 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -120,8 +120,8 @@ typedef struct { enum VRPlatformFlag { VR_PLATFORM_CONTROLLER_PICO, VR_PLATFORM_CONTROLLER_QUEST, - VR_PLATFORM_INSTANCE_EXT, - VR_PLATFORM_PERFORMANCE_EXT, + VR_PLATFORM_EXTENSION_INSTANCE, + VR_PLATFORM_EXTENSION_PERFORMANCE, VR_PLATFORM_RENDERER_VULKAN, VR_PLATFORM_TRACKING_FLOOR, VR_PLATFORM_MAX diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 6d8b94177a..0450712114 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -456,7 +456,7 @@ void ovrApp_HandleSessionStateChanges(ovrApp* app, XrSessionState state) { app->SessionActive = (result == XR_SUCCESS); #ifdef ANDROID - if (app->SessionActive && VR_GetPlatformFlag(VR_PLATFORM_PERFORMANCE_EXT)) { + if (app->SessionActive && VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_PERFORMANCE)) { XrPerfSettingsLevelEXT cpuPerfLevel = XR_PERF_SETTINGS_LEVEL_PERFORMANCE_MAX_EXT; XrPerfSettingsLevelEXT gpuPerfLevel = XR_PERF_SETTINGS_LEVEL_PERFORMANCE_MAX_EXT; From ecf113449418a0ec1d2a2a1980408a980ef6a1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 19:12:47 +0100 Subject: [PATCH 258/424] GL crashfix --- GPU/GLES/TextureCacheGLES.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 127b6d7699..307a43c1e0 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -246,7 +246,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { int th = plan.createH; Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - if (plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { + if (plan.replaced && plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { dstFmt = plan.replaced->Format(); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = Draw::DataFormat::R8G8B8A8_UNORM; From 4fcc69242ecabaa6bab4a070ff88b877a1bc7c6c Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 9 Mar 2023 20:42:49 +0100 Subject: [PATCH 259/424] OpenXR - Foveation implemented (Quest only) --- Common/VR/PPSSPPVR.cpp | 1 + Common/VR/VRBase.cpp | 9 ++++++ Common/VR/VRBase.h | 1 + Common/VR/VRFramebuffer.cpp | 59 +++++++++++++++++++++++++++++++++++++ Common/VR/VRFramebuffer.h | 3 ++ Common/VR/VRRenderer.cpp | 5 ++++ 6 files changed, 78 insertions(+) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index 657f3e1420..f39f1bcc1d 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -153,6 +153,7 @@ void InitVROnAndroid(void* vm, void* activity, const char* system, int version, VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_INSTANCE, true); } else if ((strcmp(vendor, "META") == 0) || (strcmp(vendor, "OCULUS") == 0)) { VR_SetPlatformFLag(VR_PLATFORM_CONTROLLER_QUEST, true); + VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_FOVEATION, true); VR_SetPlatformFLag(VR_PLATFORM_EXTENSION_PERFORMANCE, true); } VR_SetPlatformFLag(VR_PLATFORM_RENDERER_VULKAN, (GPUBackend)g_Config.iGPUBackend == GPUBackend::VULKAN); diff --git a/Common/VR/VRBase.cpp b/Common/VR/VRBase.cpp index 6b795f4245..715ea6644e 100644 --- a/Common/VR/VRBase.cpp +++ b/Common/VR/VRBase.cpp @@ -49,6 +49,15 @@ void VR_Init( void* system, const char* name, int version ) { } extensions.push_back(XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME); #ifdef ANDROID + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { + extensions.push_back(XR_FB_SWAPCHAIN_UPDATE_STATE_EXTENSION_NAME); + extensions.push_back(XR_FB_SWAPCHAIN_UPDATE_STATE_OPENGL_ES_EXTENSION_NAME); + extensions.push_back(XR_FB_FOVEATION_EXTENSION_NAME); + extensions.push_back(XR_FB_FOVEATION_CONFIGURATION_EXTENSION_NAME); + if (VR_GetPlatformFlag(VR_PLATFORM_RENDERER_VULKAN)) { + extensions.push_back(XR_FB_SWAPCHAIN_UPDATE_STATE_VULKAN_EXTENSION_NAME); + } + } if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_INSTANCE)) { extensions.push_back(XR_KHR_ANDROID_CREATE_INSTANCE_EXTENSION_NAME); } diff --git a/Common/VR/VRBase.h b/Common/VR/VRBase.h index 157ae7c2b3..2d3405f8a7 100644 --- a/Common/VR/VRBase.h +++ b/Common/VR/VRBase.h @@ -120,6 +120,7 @@ typedef struct { enum VRPlatformFlag { VR_PLATFORM_CONTROLLER_PICO, VR_PLATFORM_CONTROLLER_QUEST, + VR_PLATFORM_EXTENSION_FOVEATION, VR_PLATFORM_EXTENSION_INSTANCE, VR_PLATFORM_EXTENSION_PERFORMANCE, VR_PLATFORM_RENDERER_VULKAN, diff --git a/Common/VR/VRFramebuffer.cpp b/Common/VR/VRFramebuffer.cpp index 0450712114..4f53b9eb25 100644 --- a/Common/VR/VRFramebuffer.cpp +++ b/Common/VR/VRFramebuffer.cpp @@ -105,6 +105,15 @@ static bool ovrFramebuffer_CreateGLES(XrSession session, ovrFramebuffer* frameBu swapChainCreateInfo.mipCount = 1; swapChainCreateInfo.arraySize = multiview ? 2 : 1; +#ifdef ANDROID + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { + XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo; + memset(&swapChainFoveationCreateInfo, 0, sizeof(swapChainFoveationCreateInfo)); + swapChainFoveationCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB; + swapChainCreateInfo.next = &swapChainFoveationCreateInfo; + } +#endif + frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; @@ -198,6 +207,15 @@ static bool ovrFramebuffer_CreateVK(XrSession session, ovrFramebuffer* frameBuff swapChainCreateInfo.mipCount = 1; swapChainCreateInfo.arraySize = multiview ? 2 : 1; +#ifdef ANDROID + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { + XrSwapchainCreateInfoFoveationFB swapChainFoveationCreateInfo; + memset(&swapChainFoveationCreateInfo, 0, sizeof(swapChainFoveationCreateInfo)); + swapChainFoveationCreateInfo.type = XR_TYPE_SWAPCHAIN_CREATE_INFO_FOVEATION_FB; + swapChainCreateInfo.next = &swapChainFoveationCreateInfo; + } +#endif + frameBuffer->ColorSwapChain.Width = swapChainCreateInfo.width; frameBuffer->ColorSwapChain.Height = swapChainCreateInfo.height; @@ -407,6 +425,47 @@ void ovrRenderer_MouseCursor(ovrRenderer* renderer, int x, int y, int sx, int sy } } +#ifdef ANDROID +void ovrRenderer_SetFoveation(XrInstance* instance, XrSession* session, ovrRenderer* renderer, XrFoveationLevelFB level, float verticalOffset, XrFoveationDynamicFB dynamic) { + PFN_xrCreateFoveationProfileFB pfnCreateFoveationProfileFB; + OXR(xrGetInstanceProcAddr(*instance, "xrCreateFoveationProfileFB", (PFN_xrVoidFunction*)(&pfnCreateFoveationProfileFB))); + + PFN_xrDestroyFoveationProfileFB pfnDestroyFoveationProfileFB; + OXR(xrGetInstanceProcAddr(*instance, "xrDestroyFoveationProfileFB", (PFN_xrVoidFunction*)(&pfnDestroyFoveationProfileFB))); + + PFN_xrUpdateSwapchainFB pfnUpdateSwapchainFB; + OXR(xrGetInstanceProcAddr(*instance, "xrUpdateSwapchainFB", (PFN_xrVoidFunction*)(&pfnUpdateSwapchainFB))); + + int instances = renderer->Multiview ? 1 : ovrMaxNumEyes; + for (int eye = 0; eye < instances; eye++) { + XrFoveationLevelProfileCreateInfoFB levelProfileCreateInfo; + memset(&levelProfileCreateInfo, 0, sizeof(levelProfileCreateInfo)); + levelProfileCreateInfo.type = XR_TYPE_FOVEATION_LEVEL_PROFILE_CREATE_INFO_FB; + levelProfileCreateInfo.level = level; + levelProfileCreateInfo.verticalOffset = verticalOffset; + levelProfileCreateInfo.dynamic = dynamic; + + XrFoveationProfileCreateInfoFB profileCreateInfo; + memset(&profileCreateInfo, 0, sizeof(profileCreateInfo)); + profileCreateInfo.type = XR_TYPE_FOVEATION_PROFILE_CREATE_INFO_FB; + profileCreateInfo.next = &levelProfileCreateInfo; + + XrFoveationProfileFB foveationProfile; + + pfnCreateFoveationProfileFB(*session, &profileCreateInfo, &foveationProfile); + + XrSwapchainStateFoveationFB foveationUpdateState; + memset(&foveationUpdateState, 0, sizeof(foveationUpdateState)); + foveationUpdateState.type = XR_TYPE_SWAPCHAIN_STATE_FOVEATION_FB; + foveationUpdateState.profile = foveationProfile; + + pfnUpdateSwapchainFB(renderer->FrameBuffer[eye].ColorSwapChain.Handle, (XrSwapchainStateBaseHeaderFB*)(&foveationUpdateState)); + + pfnDestroyFoveationProfileFB(foveationProfile); + } +} +#endif + /* ================================================================================ diff --git a/Common/VR/VRFramebuffer.h b/Common/VR/VRFramebuffer.h index 07a5c19834..49f7484c99 100644 --- a/Common/VR/VRFramebuffer.h +++ b/Common/VR/VRFramebuffer.h @@ -13,3 +13,6 @@ void* ovrFramebuffer_SetCurrent(ovrFramebuffer* frameBuffer); void ovrRenderer_Create(XrSession session, ovrRenderer* renderer, int width, int height, bool multiview, void* vulkanContext); void ovrRenderer_Destroy(ovrRenderer* renderer); void ovrRenderer_MouseCursor(ovrRenderer* renderer, int x, int y, int sx, int sy); +#ifdef ANDROID +void ovrRenderer_SetFoveation(XrInstance* instance, XrSession* session, ovrRenderer* renderer, XrFoveationLevelFB level, float verticalOffset, XrFoveationDynamicFB dynamic); +#endif diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 8a3cc8ef90..8a4efd8657 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -216,6 +216,11 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { engine->appState.ViewConfigurationView[0].recommendedImageRectWidth, engine->appState.ViewConfigurationView[0].recommendedImageRectHeight, multiview, vulkanContext); +#ifdef ANDROID + if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { + ovrRenderer_SetFoveation(&engine->appState.Instance, &engine->appState.Session, &engine->appState.Renderer, XR_FOVEATION_LEVEL_HIGH_FB, 0, XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB); + } +#endif initialized = true; } From f24026d1636760eb1902984da004880b8efb5b9b Mon Sep 17 00:00:00 2001 From: Lubos Date: Thu, 9 Mar 2023 21:04:30 +0100 Subject: [PATCH 260/424] OpenXR - Increase foveation level --- Common/VR/VRRenderer.cpp | 2 +- ext/openxr/openxr.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Common/VR/VRRenderer.cpp b/Common/VR/VRRenderer.cpp index 8a4efd8657..5a9a208926 100644 --- a/Common/VR/VRRenderer.cpp +++ b/Common/VR/VRRenderer.cpp @@ -218,7 +218,7 @@ void VR_InitRenderer( engine_t* engine, bool multiview ) { multiview, vulkanContext); #ifdef ANDROID if (VR_GetPlatformFlag(VR_PLATFORM_EXTENSION_FOVEATION)) { - ovrRenderer_SetFoveation(&engine->appState.Instance, &engine->appState.Session, &engine->appState.Renderer, XR_FOVEATION_LEVEL_HIGH_FB, 0, XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB); + ovrRenderer_SetFoveation(&engine->appState.Instance, &engine->appState.Session, &engine->appState.Renderer, XR_FOVEATION_LEVEL_HIGH_TOP_FB, 0, XR_FOVEATION_DYNAMIC_LEVEL_ENABLED_FB); } #endif initialized = true; diff --git a/ext/openxr/openxr.h b/ext/openxr/openxr.h index 2e4dec9fe1..0e38fbc331 100644 --- a/ext/openxr/openxr.h +++ b/ext/openxr/openxr.h @@ -3476,6 +3476,7 @@ typedef enum XrFoveationLevelFB { XR_FOVEATION_LEVEL_LOW_FB = 1, XR_FOVEATION_LEVEL_MEDIUM_FB = 2, XR_FOVEATION_LEVEL_HIGH_FB = 3, + XR_FOVEATION_LEVEL_HIGH_TOP_FB = 4, XR_FOVEATION_LEVEL_MAX_ENUM_FB = 0x7FFFFFFF } XrFoveationLevelFB; From cb108625108732734af09742d53365e01ec5f129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 21:11:53 +0100 Subject: [PATCH 261/424] Move texture replacer to GPU/Common. Add new files ReplacedTexture.cpp/h too. --- CMakeLists.txt | 6 +- Core/Core.vcxproj | 2 - Core/Core.vcxproj.filters | 6 - GPU/Common/ReplacedTexture.cpp | 1 + GPU/Common/ReplacedTexture.h | 1 + GPU/Common/TextureCacheCommon.h | 2 +- {Core => GPU/Common}/TextureReplacer.cpp | 2 +- {Core => GPU/Common}/TextureReplacer.h | 0 GPU/GPU.vcxproj | 20 +- GPU/GPU.vcxproj.filters | 12 + UI/GameSettingsScreen.cpp | 2 +- UWP/CoreUWP/CoreUWP.vcxproj | 344 +++++++++++++++-------- UWP/CoreUWP/CoreUWP.vcxproj.filters | 2 - UWP/GPU_UWP/GPU_UWP.vcxproj | 28 +- UWP/GPU_UWP/GPU_UWP.vcxproj.filters | 4 + android/jni/Android.mk | 3 +- libretro/Makefile.common | 3 +- 17 files changed, 285 insertions(+), 153 deletions(-) create mode 100644 GPU/Common/ReplacedTexture.cpp create mode 100644 GPU/Common/ReplacedTexture.h rename {Core => GPU/Common}/TextureReplacer.cpp (99%) rename {Core => GPU/Common}/TextureReplacer.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 91f08e233b..25505d597c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1639,6 +1639,10 @@ set(GPU_SOURCES GPU/Common/TextureScalerCommon.h GPU/Common/PostShader.cpp GPU/Common/PostShader.h + GPU/Common/TextureReplacer.cpp + GPU/Common/TextureReplacer.h + GPU/Common/ReplacedTexture.cpp + GPU/Common/ReplacedTexture.h GPU/Debugger/Breakpoints.cpp GPU/Debugger/Breakpoints.h GPU/Debugger/Debugger.cpp @@ -2047,8 +2051,6 @@ add_library(${CoreLibName} ${CoreLinkType} Core/Screenshot.h Core/System.cpp Core/System.h - Core/TextureReplacer.cpp - Core/TextureReplacer.h Core/ThreadPools.cpp Core/ThreadPools.h Core/Util/AudioFormat.cpp diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 0ad2df793f..0fad6b30a7 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -591,7 +591,6 @@ - @@ -1157,7 +1156,6 @@ - diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 1fe06c2b6e..4b2b04de05 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -652,9 +652,6 @@ FileLoaders - - Core - MIPS\IR @@ -1737,9 +1734,6 @@ FileLoaders - - Core - MIPS\IR diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp new file mode 100644 index 0000000000..3bf7e731e0 --- /dev/null +++ b/GPU/Common/ReplacedTexture.cpp @@ -0,0 +1 @@ +#include "GPU/Common/ReplacedTexture.h" diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h new file mode 100644 index 0000000000..6f70f09bee --- /dev/null +++ b/GPU/Common/ReplacedTexture.h @@ -0,0 +1 @@ +#pragma once diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index da42b07de4..7db6507b13 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -23,13 +23,13 @@ #include "Common/CommonTypes.h" #include "Common/MemoryUtil.h" -#include "Core/TextureReplacer.h" #include "Core/System.h" #include "GPU/GPU.h" #include "GPU/Common/GPUDebugInterface.h" #include "GPU/Common/TextureDecoder.h" #include "GPU/Common/TextureScalerCommon.h" #include "GPU/Common/TextureShaderCommon.h" +#include "GPU/Common/TextureReplacer.h" class Draw2D; diff --git a/Core/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp similarity index 99% rename from Core/TextureReplacer.cpp rename to GPU/Common/TextureReplacer.cpp index 2ac2e23133..654a65d5e8 100644 --- a/Core/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -44,9 +44,9 @@ #include "Core/Config.h" #include "Core/Host.h" #include "Core/System.h" -#include "Core/TextureReplacer.h" #include "Core/ThreadPools.h" #include "Core/ELF/ParamSFO.h" +#include "GPU/Common/TextureReplacer.h" #include "GPU/Common/TextureDecoder.h" static const std::string INI_FILENAME = "textures.ini"; diff --git a/Core/TextureReplacer.h b/GPU/Common/TextureReplacer.h similarity index 100% rename from Core/TextureReplacer.h rename to GPU/Common/TextureReplacer.h diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 606e169859..3b6f07c66f 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -164,7 +164,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 _CRTDBG_MAP_ALLOC;USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_M_IX86=1;_DEBUG;_LIB;_UNICODE;UNICODE;%(PreprocessorDefinitions) StreamingSIMDExtensions2 Precise @@ -182,7 +182,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 NotSet Precise false @@ -202,7 +202,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 NotSet Precise false @@ -221,7 +221,7 @@ Level3 - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 NotSet Precise false @@ -244,7 +244,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 false StreamingSIMDExtensions2 Precise @@ -267,7 +267,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 false NotSet Precise @@ -292,7 +292,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 false NotSet Precise @@ -317,7 +317,7 @@ MaxSpeed true true - ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib + ..\dx9sdk\Include\DX11;../common;..;../ext;../ext/glew;../ext/snappy;../ext/glslang;../ext/zstd/lib;../ext/libpng17 false NotSet Precise @@ -338,6 +338,8 @@ + + @@ -456,6 +458,8 @@ + + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index b34942e06c..6b35f8f33a 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -267,6 +267,12 @@ Common + + Common + + + Common + @@ -530,6 +536,12 @@ Common + + Common + + + Common + diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index abf2e2034f..0ef3060135 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -66,10 +66,10 @@ #include "Core/Instance.h" #include "Core/System.h" #include "Core/Reporting.h" -#include "Core/TextureReplacer.h" #include "Core/WebServer.h" #include "Core/HLE/sceUsbCam.h" #include "Core/HLE/sceUsbMic.h" +#include "GPU/Common/TextureReplacer.h" #include "GPU/Common/PostShader.h" #include "android/jni/TestRunner.h" #include "GPU/GPUInterface.h" diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index 65b384657b..6fe4ea1320 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -476,7 +476,6 @@ - @@ -739,7 +738,6 @@ - @@ -758,459 +756,573 @@ NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing - + + NotUsing diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 119c2d0936..7fead01f06 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -108,7 +108,6 @@ - MIPS\ARM @@ -1150,7 +1149,6 @@ - diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 0448b3e1bd..0548c117a6 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -90,7 +90,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -105,7 +105,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -120,7 +120,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -135,7 +135,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -150,7 +150,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -165,7 +165,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -180,7 +180,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -195,7 +195,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -210,7 +210,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_ARM64_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1;%(ClCompile.PreprocessorDefinitions) @@ -225,7 +225,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -240,7 +240,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -255,7 +255,7 @@ false false pch.h - ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) + ../..;../../ext/snappy;../../ext/native;../../Common;../../ext;../../ext/glslang;../../ext/zstd/lib;../../ext/libpng17;$(ProjectDir);$(GeneratedFilesDir);$(IntDir);%(AdditionalIncludeDirectories) _CRT_SECURE_NO_WARNINGS;NOMINMAX;_UNICODE;UNICODE;%(PreprocessorDefinitions) @@ -265,6 +265,8 @@ + + @@ -329,6 +331,8 @@ + + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index dc746a6f6d..314574f863 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -62,6 +62,8 @@ + + @@ -125,5 +127,7 @@ + + \ No newline at end of file diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 3cc90b6dcf..57b695f3e5 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -389,6 +389,8 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/Common/ShaderUniforms.cpp \ $(SRC)/GPU/Common/VertexShaderGenerator.cpp \ $(SRC)/GPU/Common/GeometryShaderGenerator.cpp \ + $(SRC)/GPU/Common/TextureReplacer.cpp \ + $(SRC)/GPU/Common/ReplacedTexture.cpp \ $(SRC)/GPU/Debugger/Breakpoints.cpp \ $(SRC)/GPU/Debugger/Debugger.cpp \ $(SRC)/GPU/Debugger/GECommandTable.cpp \ @@ -456,7 +458,6 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/SaveState.cpp \ $(SRC)/Core/Screenshot.cpp \ $(SRC)/Core/System.cpp \ - $(SRC)/Core/TextureReplacer.cpp \ $(SRC)/Core/TiltEventProcessor.cpp \ $(SRC)/Core/ThreadPools.cpp \ $(SRC)/Core/WebServer.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 2b3bcfed99..67149d94d4 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -386,6 +386,8 @@ SOURCES_CXX += \ $(GPUCOMMONDIR)/IndexGenerator.cpp \ $(GPUCOMMONDIR)/TextureDecoder.cpp \ $(GPUCOMMONDIR)/PostShader.cpp \ + $(GPUCOMMONDIR)/TextureReplacer.cpp \ + $(GPUCOMMONDIR)/ReplacedTexture.cpp \ $(COMMONDIR)/Data/Convert/ColorConv.cpp \ $(GPUDIR)/Debugger/Breakpoints.cpp \ $(GPUDIR)/Debugger/Debugger.cpp \ @@ -495,7 +497,6 @@ SOURCES_CXX += \ $(COREDIR)/AVIDump.cpp \ $(COREDIR)/Config.cpp \ $(COREDIR)/ControlMapper.cpp \ - $(COREDIR)/TextureReplacer.cpp \ $(COREDIR)/Core.cpp \ $(COREDIR)/WaveFile.cpp \ $(COREDIR)/KeyMap.cpp \ From 654f4bff40913897148abb88b73a073e42db7598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 9 Mar 2023 21:19:20 +0100 Subject: [PATCH 262/424] Split out ReplacedTexture into its own file. --- GPU/Common/ReplacedTexture.cpp | 294 +++++++++++++++++++++++++++++++++ GPU/Common/ReplacedTexture.h | 131 +++++++++++++++ GPU/Common/TextureReplacer.cpp | 272 +----------------------------- GPU/Common/TextureReplacer.h | 97 +---------- 4 files changed, 427 insertions(+), 367 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 3bf7e731e0..40b81c8a9b 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -1 +1,295 @@ +// Copyright (c) 2016- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "ppsspp_config.h" + +#include + #include "GPU/Common/ReplacedTexture.h" +#include "GPU/Common/TextureReplacer.h" + +#include "Common/Data/Format/IniFile.h" +#include "Common/Data/Format/ZIMLoad.h" +#include "Common/Data/Format/PNGLoad.h" +#include "Common/Thread/ParallelLoop.h" +#include "Common/Thread/Waitable.h" +#include "Common/Thread/ThreadManager.h" +#include "Common/Log.h" +#include "Common/TimeUtil.h" + +class ReplacedTextureTask : public Task { +public: + ReplacedTextureTask(VFSBackend *vfs, ReplacedTexture &tex, LimitedWaitable *w) : vfs_(vfs), tex_(tex), waitable_(w) {} + + TaskType Type() const override { + return TaskType::IO_BLOCKING; + } + + TaskPriority Priority() const override { + return TaskPriority::NORMAL; + } + + void Run() override { + tex_.Prepare(vfs_); + waitable_->Notify(); + } + +private: + VFSBackend *vfs_; + ReplacedTexture &tex_; + LimitedWaitable *waitable_; +}; + +bool ReplacedTexture::IsReady(double budget) { + _assert_(vfs_ != nullptr); + lastUsed_ = time_now_d(); + if (threadWaitable_ && !threadWaitable_->WaitFor(budget)) { + return false; + } + + // Loaded already, or not yet on a thread? + if (initDone_ && levelData_ && !levelData_->data.empty()) { + // TODO: lock? + levelData_->lastUsed = lastUsed_; + return true; + } + + // Let's not even start a new texture if we're already behind. + if (budget < 0.0) + return false; + if (!prepareDone_) + return false; + + if (threadWaitable_) + delete threadWaitable_; + threadWaitable_ = new LimitedWaitable(); + g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); + if (threadWaitable_->WaitFor(budget)) { + // If we finished all the levels, we're done. + return initDone_ && levelData_ != nullptr && !levelData_->data.empty(); + } + + // Still pending on thread. + return false; +} + +void ReplacedTexture::Prepare(VFSBackend *vfs) { + std::unique_lock lock(mutex_); + this->vfs_ = vfs; + if (cancelPrepare_) { + initDone_ = true; + return; + } + + for (int i = 0; i < (int)levels_.size(); ++i) { + if (cancelPrepare_) + break; + PrepareData(i); + } + + initDone_ = true; + if (!cancelPrepare_ && threadWaitable_) + threadWaitable_->Notify(); +} + +void ReplacedTexture::PrepareData(int level) { + _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); + _assert_msg_(levelData_ != nullptr, "Level cache not set"); + + // We must lock around access to levelData_ in case two textures try to load it at once. + std::lock_guard guard(levelData_->lock); + + const ReplacedTextureLevel &info = levels_[level]; + + if (levelData_->data.size() <= level) { + levelData_->data.resize(level + 1); + } + + std::vector &out = levelData_->data[level]; + + // Already populated from cache. + if (!out.empty()) + return; + + ReplacedImageType imageType; + + size_t fileSize; + VFSOpenFile *openFile = vfs_->OpenFileForRead(info.fileRef, &fileSize); + + std::string magic; + imageType = Identify(vfs_, openFile, &magic); + + auto cleanup = [&] { + vfs_->CloseFile(openFile); + }; + + if (imageType == ReplacedImageType::ZIM) { + std::unique_ptr zim(new uint8_t[fileSize]); + if (!zim) { + ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); + cleanup(); + return; + } + + if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { + ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); + cleanup(); + return; + } + + int w, h, f; + uint8_t *image; + if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { + if (w > info.w || h > info.h) { + ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); + cleanup(); + return; + } + + out.resize(info.w * info.h * 4); + if (w == info.w) { + memcpy(&out[0], image, info.w * 4 * info.h); + } else { + for (int y = 0; y < h; ++y) { + memcpy(&out[info.w * 4 * y], image + w * 4 * y, w * 4); + } + } + free(image); + } + + CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], info.w, w, h, 0xFF000000); + if (res == CHECKALPHA_ANY || level == 0) { + alphaStatus_ = ReplacedTextureAlpha(res); + } + } else if (imageType == ReplacedImageType::PNG) { + png_image png = {}; + png.version = PNG_IMAGE_VERSION; + + std::string pngdata; + pngdata.resize(fileSize); + pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); + if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { + ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); + cleanup(); + return; + } + if (png.width > (uint32_t)info.w || png.height > (uint32_t)info.h) { + ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); + cleanup(); + return; + } + + bool checkedAlpha = false; + if ((png.format & PNG_FORMAT_FLAG_ALPHA) == 0) { + // Well, we know for sure it doesn't have alpha. + if (level == 0) { + alphaStatus_ = ReplacedTextureAlpha::FULL; + } + checkedAlpha = true; + } + png.format = PNG_FORMAT_RGBA; + + out.resize(info.w * info.h * 4); + if (!png_image_finish_read(&png, nullptr, &out[0], info.w * 4, nullptr)) { + ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", info.file.c_str(), png.message); + cleanup(); + out.resize(0); + return; + } + png_image_free(&png); + + if (!checkedAlpha) { + // This will only check the hashed bits. + CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], info.w, png.width, png.height, 0xFF000000); + if (res == CHECKALPHA_ANY || level == 0) { + alphaStatus_ = ReplacedTextureAlpha(res); + } + } + } + + cleanup(); +} + +void ReplacedTexture::PurgeIfOlder(double t) { + if (threadWaitable_ && !threadWaitable_->WaitFor(0.0)) + return; + if (lastUsed_ >= t) + return; + + if (levelData_->lastUsed < t) { + // We have to lock since multiple textures might reference this same data. + std::lock_guard guard(levelData_->lock); + levelData_->data.clear(); + // This means we have to reload. If we never purge any, there's no need. + initDone_ = false; + } +} + +ReplacedTexture::~ReplacedTexture() { + if (threadWaitable_) { + cancelPrepare_ = true; + + std::unique_lock lock(mutex_); + threadWaitable_->WaitAndRelease(); + threadWaitable_ = nullptr; + } + + for (auto &level : levels_) { + vfs_->ReleaseFile(level.fileRef); + level.fileRef = nullptr; + } +} + +bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { + _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); + _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); + + if (!initDone_) { + WARN_LOG(G3D, "Init not done yet"); + return false; + } + + // We probably could avoid this lock, but better to play it safe. + std::lock_guard guard(levelData_->lock); + + const ReplacedTextureLevel &info = levels_[level]; + const std::vector &data = levelData_->data[level]; + + if (data.empty()) { + WARN_LOG(G3D, "Level %d is empty", level); + return false; + } + + if (rowPitch < info.w * 4) { + ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); + return false; + } + _assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size"); + + if (rowPitch == info.w * 4) { + ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); + } else { + const int MIN_LINES_PER_THREAD = 4; + ParallelRangeLoop(&g_threadManager, [&](int l, int h) { + for (int y = l; y < h; ++y) { + memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); + } + }, 0, info.h, MIN_LINES_PER_THREAD); + } + + return true; +} diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 6f70f09bee..4e00d8df28 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -1 +1,132 @@ +// Copyright (c) 2016- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + #pragma once + +#include +#include + +#include "Common/File/VFS/VFS.h" +#include "Common/GPU/thin3d.h" + +struct ReplacedLevelsCache; +class TextureReplacer; +class LimitedWaitable; + +// These must match the constants in TextureCacheCommon. +enum class ReplacedTextureAlpha { + UNKNOWN = 0x04, + FULL = 0x00, +}; + +// For forward compatibility, we specify the hash. +enum class ReplacedTextureHash { + QUICK, + XXH32, + XXH64, +}; + +enum class ReplacedImageType { + PNG, + ZIM, + INVALID, +}; + +// Metadata about a given texture level. +struct ReplacedTextureLevel { + int w = 0; + int h = 0; + Path file; + + // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. + // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. + VFSFileReference *fileRef = nullptr; +}; + +ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic); + +struct ReplacedTexture { + ~ReplacedTexture(); + + inline bool Valid() const { + if (!initDone_) + return false; + return !levels_.empty(); + } + + inline bool IsInvalid() const { + if (!initDone_) + return false; + return levels_.empty(); + } + + bool GetSize(int level, int &w, int &h) const { + if (!initDone_) + return false; + if ((size_t)level < levels_.size()) { + w = levels_[level].w; + h = levels_[level].h; + return true; + } + return false; + } + + int NumLevels() const { + if (!initDone_) + return 0; + return (int)levels_.size(); + } + + Draw::DataFormat Format() const { + if (initDone_) { + return fmt; + } else { + // Shouldn't get here. + return Draw::DataFormat::UNDEFINED; + } + } + + u8 AlphaStatus() const { + return (u8)alphaStatus_; + } + + bool IsReady(double budget); + bool CopyLevelTo(int level, void *out, int rowPitch); + +protected: + void Prepare(VFSBackend *vfs); + void PrepareData(int level); + void PurgeIfOlder(double t); + + std::vector levels_; + ReplacedLevelsCache *levelData_; + + ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; + double lastUsed_ = 0.0; + LimitedWaitable *threadWaitable_ = nullptr; + std::mutex mutex_; + Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. + + bool cancelPrepare_ = false; + bool initDone_ = false; + bool prepareDone_ = false; + + VFSBackend *vfs_ = nullptr; + + friend class TextureReplacer; + friend class ReplacedTextureTask; +}; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 654a65d5e8..296acc0031 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -18,7 +18,6 @@ #include "ppsspp_config.h" #include -#include #include #include #include @@ -56,12 +55,6 @@ static const int VERSION = 1; static const int MAX_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP. static const double MAX_CACHE_SIZE = 4.0; -enum class ReplacedImageType { - PNG, - ZIM, - INVALID, -}; - static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { if (strncmp((const char *)magic, "ZIMG", 4) == 0) return ReplacedImageType::ZIM; @@ -70,7 +63,7 @@ static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { return ReplacedImageType::INVALID; } -static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { +ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { uint8_t magic[4]; if (vfs->Read(openFile, magic, 4) != 4) { *outMagic = "FAIL"; @@ -955,269 +948,6 @@ float TextureReplacer::LookupReduceHashRange(int& w, int& h) { } } -class ReplacedTextureTask : public Task { -public: - ReplacedTextureTask(VFSBackend *vfs, ReplacedTexture &tex, LimitedWaitable *w) : vfs_(vfs), tex_(tex), waitable_(w) {} - - TaskType Type() const override { - return TaskType::IO_BLOCKING; - } - - TaskPriority Priority() const override { - return TaskPriority::NORMAL; - } - - void Run() override { - tex_.Prepare(vfs_); - waitable_->Notify(); - } - -private: - VFSBackend *vfs_; - ReplacedTexture &tex_; - LimitedWaitable *waitable_; -}; - -bool ReplacedTexture::IsReady(double budget) { - _assert_(vfs_ != nullptr); - lastUsed_ = time_now_d(); - if (threadWaitable_ && !threadWaitable_->WaitFor(budget)) { - return false; - } - - // Loaded already, or not yet on a thread? - if (initDone_ && levelData_ && !levelData_->data.empty()) { - // TODO: lock? - levelData_->lastUsed = lastUsed_; - return true; - } - - // Let's not even start a new texture if we're already behind. - if (budget < 0.0) - return false; - if (!prepareDone_) - return false; - - if (threadWaitable_) - delete threadWaitable_; - threadWaitable_ = new LimitedWaitable(); - g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); - if (threadWaitable_->WaitFor(budget)) { - // If we finished all the levels, we're done. - return initDone_ && levelData_ != nullptr && !levelData_->data.empty(); - } - - // Still pending on thread. - return false; -} - -void ReplacedTexture::Prepare(VFSBackend *vfs) { - std::unique_lock lock(mutex_); - this->vfs_ = vfs; - if (cancelPrepare_) { - initDone_ = true; - return; - } - - for (int i = 0; i < (int)levels_.size(); ++i) { - if (cancelPrepare_) - break; - PrepareData(i); - } - - initDone_ = true; - if (!cancelPrepare_ && threadWaitable_) - threadWaitable_->Notify(); -} - -void ReplacedTexture::PrepareData(int level) { - _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); - _assert_msg_(levelData_ != nullptr, "Level cache not set"); - - // We must lock around access to levelData_ in case two textures try to load it at once. - std::lock_guard guard(levelData_->lock); - - const ReplacedTextureLevel &info = levels_[level]; - - if (levelData_->data.size() <= level) { - levelData_->data.resize(level + 1); - } - - std::vector &out = levelData_->data[level]; - - // Already populated from cache. - if (!out.empty()) - return; - - ReplacedImageType imageType; - - size_t fileSize; - VFSOpenFile *openFile = vfs_->OpenFileForRead(info.fileRef, &fileSize); - - std::string magic; - imageType = Identify(vfs_, openFile, &magic); - - auto cleanup = [&] { - vfs_->CloseFile(openFile); - }; - - if (imageType == ReplacedImageType::ZIM) { - std::unique_ptr zim(new uint8_t[fileSize]); - if (!zim) { - ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); - cleanup(); - return; - } - - if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); - cleanup(); - return; - } - - int w, h, f; - uint8_t *image; - if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { - if (w > info.w || h > info.h) { - ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); - cleanup(); - return; - } - - out.resize(info.w * info.h * 4); - if (w == info.w) { - memcpy(&out[0], image, info.w * 4 * info.h); - } else { - for (int y = 0; y < h; ++y) { - memcpy(&out[info.w * 4 * y], image + w * 4 * y, w * 4); - } - } - free(image); - } - - CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], info.w, w, h, 0xFF000000); - if (res == CHECKALPHA_ANY || level == 0) { - alphaStatus_ = ReplacedTextureAlpha(res); - } - } else if (imageType == ReplacedImageType::PNG) { - png_image png = {}; - png.version = PNG_IMAGE_VERSION; - - std::string pngdata; - pngdata.resize(fileSize); - pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); - if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); - cleanup(); - return; - } - if (png.width > (uint32_t)info.w || png.height > (uint32_t)info.h) { - ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); - cleanup(); - return; - } - - bool checkedAlpha = false; - if ((png.format & PNG_FORMAT_FLAG_ALPHA) == 0) { - // Well, we know for sure it doesn't have alpha. - if (level == 0) { - alphaStatus_ = ReplacedTextureAlpha::FULL; - } - checkedAlpha = true; - } - png.format = PNG_FORMAT_RGBA; - - out.resize(info.w * info.h * 4); - if (!png_image_finish_read(&png, nullptr, &out[0], info.w * 4, nullptr)) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", info.file.c_str(), png.message); - cleanup(); - out.resize(0); - return; - } - png_image_free(&png); - - if (!checkedAlpha) { - // This will only check the hashed bits. - CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], info.w, png.width, png.height, 0xFF000000); - if (res == CHECKALPHA_ANY || level == 0) { - alphaStatus_ = ReplacedTextureAlpha(res); - } - } - } - - cleanup(); -} - -void ReplacedTexture::PurgeIfOlder(double t) { - if (threadWaitable_ && !threadWaitable_->WaitFor(0.0)) - return; - if (lastUsed_ >= t) - return; - - if (levelData_->lastUsed < t) { - // We have to lock since multiple textures might reference this same data. - std::lock_guard guard(levelData_->lock); - levelData_->data.clear(); - // This means we have to reload. If we never purge any, there's no need. - initDone_ = false; - } -} - -ReplacedTexture::~ReplacedTexture() { - if (threadWaitable_) { - cancelPrepare_ = true; - - std::unique_lock lock(mutex_); - threadWaitable_->WaitAndRelease(); - threadWaitable_ = nullptr; - } - - for (auto &level : levels_) { - vfs_->ReleaseFile(level.fileRef); - level.fileRef = nullptr; - } -} - -bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { - _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); - _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); - - if (!initDone_) { - WARN_LOG(G3D, "Init not done yet"); - return false; - } - - // We probably could avoid this lock, but better to play it safe. - std::lock_guard guard(levelData_->lock); - - const ReplacedTextureLevel &info = levels_[level]; - const std::vector &data = levelData_->data[level]; - - if (data.empty()) { - WARN_LOG(G3D, "Level %d is empty", level); - return false; - } - - if (rowPitch < info.w * 4) { - ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); - return false; - } - _assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size"); - - if (rowPitch == info.w * 4) { - ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); - } else { - const int MIN_LINES_PER_THREAD = 4; - ParallelRangeLoop(&g_threadManager, [&](int l, int h) { - for (int y = l; y < h; ++y) { - memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); - } - }, 0, info.h, MIN_LINES_PER_THREAD); - } - - return true; -} - bool TextureReplacer::IniExists(const std::string &gameID) { if (gameID.empty()) return false; diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index a2faa7a763..1efc9d7a54 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -31,6 +31,7 @@ #include "Common/GPU/DataFormat.h" #include "GPU/Common/TextureDecoder.h" +#include "GPU/Common/ReplacedTexture.h" #include "GPU/ge_constants.h" class IniFile; @@ -40,30 +41,6 @@ class ReplacedTextureTask; class LimitedWaitable; class VFSBackend; -// These must match the constants in TextureCacheCommon. -enum class ReplacedTextureAlpha { - UNKNOWN = 0x04, - FULL = 0x00, -}; - -// For forward compatibility, we specify the hash. -enum class ReplacedTextureHash { - QUICK, - XXH32, - XXH64, -}; - -// Metadata about a given texture level. -struct ReplacedTextureLevel { - int w = 0; - int h = 0; - Path file; - - // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. - // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. - VFSFileReference *fileRef = nullptr; -}; - struct SavedTextureCacheData { int levelW[8]{}; int levelH[8]{}; @@ -104,78 +81,6 @@ namespace std { }; } -struct ReplacedTexture { - ~ReplacedTexture(); - - inline bool Valid() const { - if (!initDone_) - return false; - return !levels_.empty(); - } - - inline bool IsInvalid() const { - if (!initDone_) - return false; - return levels_.empty(); - } - - bool GetSize(int level, int &w, int &h) const { - if (!initDone_) - return false; - if ((size_t)level < levels_.size()) { - w = levels_[level].w; - h = levels_[level].h; - return true; - } - return false; - } - - int NumLevels() const { - if (!initDone_) - return 0; - return (int)levels_.size(); - } - - Draw::DataFormat Format() const { - if (initDone_) { - return fmt; - } else { - // Shouldn't get here. - return Draw::DataFormat::UNDEFINED; - } - } - - u8 AlphaStatus() const { - return (u8)alphaStatus_; - } - - bool IsReady(double budget); - bool CopyLevelTo(int level, void *out, int rowPitch); - -protected: - void Prepare(VFSBackend *vfs); - void PrepareData(int level); - void PurgeIfOlder(double t); - - std::vector levels_; - ReplacedLevelsCache *levelData_; - - ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; - double lastUsed_ = 0.0; - LimitedWaitable *threadWaitable_ = nullptr; - std::mutex mutex_; - Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. - - bool cancelPrepare_ = false; - bool initDone_ = false; - bool prepareDone_ = false; - - VFSBackend *vfs_ = nullptr; - - friend class TextureReplacer; - friend class ReplacedTextureTask; -}; - struct ReplacedTextureDecodeInfo { u64 cachekey; u32 hash; From 06b83115a5acf48ac22a58123ceb01ad1f466592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 12:20:55 +0100 Subject: [PATCH 263/424] Replacer: Avoid tracking video textures --- Common/GPU/Vulkan/VulkanDebug.cpp | 6 ++++++ GPU/Common/ReplacedTexture.h | 2 ++ GPU/Common/TextureCacheCommon.cpp | 11 ++++++++++- GPU/Common/TextureCacheCommon.h | 6 ++++-- GPU/Common/TextureReplacer.h | 3 +++ GPU/GPU.h | 4 ++++ GPU/GPUCommonHW.cpp | 3 +++ 7 files changed, 32 insertions(+), 3 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanDebug.cpp b/Common/GPU/Vulkan/VulkanDebug.cpp index 4daf41bdf7..29a71cf61e 100644 --- a/Common/GPU/Vulkan/VulkanDebug.cpp +++ b/Common/GPU/Vulkan/VulkanDebug.cpp @@ -62,6 +62,12 @@ VKAPI_ATTR VkBool32 VKAPI_CALL VulkanDebugUtilsCallback( // See https://github.com/hrydgard/ppsspp/pull/16354 return false; } + if (messageCode == -375211665) { + // VUID-vkAllocateMemory-pAllocateInfo-01713 + // Can happen when VMA aggressively tries to allocate aperture memory for upload. It gracefully + // falls back to regular video memory, so we just ignore this. I'd argue this is a VMA bug, actually. + return false; + } int count; { diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 4e00d8df28..735be70590 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -59,6 +59,8 @@ struct ReplacedTextureLevel { ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic); +// These aren't actually all replaced, they can also represent a placeholder for a not-found +// replacement. struct ReplacedTexture { ~ReplacedTexture(); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 8751efbb6e..5d914c061b 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -144,6 +144,11 @@ void TextureCacheCommon::StartFrame() { timesInvalidatedAllThisFrame_ = 0; replacementTimeThisFrame_ = 0.0; + if (g_Config.bShowDebugStats) { + gpuStats.numReplacerTrackedTex = replacer_.GetNumTrackedTextures(); + gpuStats.numCachedReplacedTextures = replacer_.GetNumCachedReplacedTextures(); + } + if (texelsScaledThisFrame_) { VERBOSE_LOG(G3D, "Scaled %d texels", texelsScaledThisFrame_); } @@ -1497,6 +1502,10 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & return nullptr; } + if (entry->status & TexCacheEntry::STATUS_VIDEO) { + return nullptr; + } + // Allow some delay to reduce pop-in. constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0; @@ -2039,7 +2048,7 @@ void TextureCacheCommon::ApplyTexture() { // Regardless of hash fails or otherwise, if this is a video, mark it frequently changing. // This prevents temporary scaling perf hits on the first second of video. if (IsVideo(entry->addr)) { - entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT; + entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT | TexCacheEntry::STATUS_VIDEO; } if (nextNeedsRehash_) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 7db6507b13..a51660d364 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -149,10 +149,12 @@ struct TexCacheEntry { STATUS_3D = 0x4000, STATUS_CLUT_GPU = 0x8000, + + STATUS_VIDEO = 0x10000, }; - // Status, but int so we can zero initialize. - int status; + // TexStatus enum flag combination. + u32 status; u32 addr; u32 minihash; diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 1efc9d7a54..27c6b1b83f 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -127,6 +127,9 @@ public: static bool GenerateIni(const std::string &gameID, Path &generatedFilename); static bool IniExists(const std::string &gameID); + int GetNumTrackedTextures() const { return (int)cache_.size(); } + int GetNumCachedReplacedTextures() const { return (int)levelCache_.size(); } + protected: bool LoadIni(); bool LoadIniValues(IniFile &ini, bool isOverride = false); diff --git a/GPU/GPU.h b/GPU/GPU.h index 12274e51fb..c44749cb63 100644 --- a/GPU/GPU.h +++ b/GPU/GPU.h @@ -100,6 +100,8 @@ struct GPUStatistics { numColorCopies = 0; numCopiesForShaderBlend = 0; numCopiesForSelfTex = 0; + numReplacerTrackedTex = 0; + numCachedReplacedTextures = 0; msProcessingDisplayLists = 0; vertexGPUCycles = 0; otherGPUCycles = 0; @@ -133,6 +135,8 @@ struct GPUStatistics { int numColorCopies; int numCopiesForShaderBlend; int numCopiesForSelfTex; + int numReplacerTrackedTex; + int numCachedReplacedTextures; double msProcessingDisplayLists; int vertexGPUCycles; int otherGPUCycles; diff --git a/GPU/GPUCommonHW.cpp b/GPU/GPUCommonHW.cpp index 01d6dd02c2..e5fd62a0ae 100644 --- a/GPU/GPUCommonHW.cpp +++ b/GPU/GPUCommonHW.cpp @@ -1636,6 +1636,7 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { "FBOs active: %d (evaluations: %d)\n" "Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n" "readbacks %d (%d non-block), uploads %d, depal %d\n" + "replacer: tracks %d textures, %d unique loaded\n" "Copies: depth %d, color %d, reint %d, blend %d, selftex %d\n" "GPU cycles executed: %d (%f per vertex)\n", gpuStats.msProcessingDisplayLists * 1000.0f, @@ -1659,6 +1660,8 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) { gpuStats.numReadbacks, gpuStats.numUploads, gpuStats.numDepal, + gpuStats.numReplacerTrackedTex, + gpuStats.numCachedReplacedTextures, gpuStats.numDepthCopies, gpuStats.numColorCopies, gpuStats.numReinterpretCopies, From 9f45271730938381be1daf2a8afa019d24bf0227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 13:43:48 +0100 Subject: [PATCH 264/424] Tex replacer state machine instead of flags --- GPU/Common/ReplacedTexture.cpp | 77 ++++++++++++++++++++++--------- GPU/Common/ReplacedTexture.h | 52 ++++++++++++--------- GPU/Common/TextureCacheCommon.cpp | 28 ++++++++--- GPU/Common/TextureReplacer.cpp | 20 ++++++-- 4 files changed, 120 insertions(+), 57 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 40b81c8a9b..f4b3c52b7c 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -56,33 +56,46 @@ private: bool ReplacedTexture::IsReady(double budget) { _assert_(vfs_ != nullptr); - lastUsed_ = time_now_d(); - if (threadWaitable_ && !threadWaitable_->WaitFor(budget)) { + + switch (State()) { + case ReplacementState::ACTIVE: + case ReplacementState::NOT_FOUND: + if (threadWaitable_) { + if (!threadWaitable_->WaitFor(budget)) { + return false; + } + // Successfully waited! Can get rid of it. + threadWaitable_->WaitAndRelease(); + threadWaitable_ = nullptr; + } + lastUsed_ = time_now_d(); + return true; + case ReplacementState::UNINITIALIZED: + // _dbg_assert_(false); return false; + case ReplacementState::CANCEL_INIT: + case ReplacementState::PENDING: + return false; + case ReplacementState::PREPARED: + // We're gonna need to spawn a task. + break; } - // Loaded already, or not yet on a thread? - if (initDone_ && levelData_ && !levelData_->data.empty()) { - // TODO: lock? - levelData_->lastUsed = lastUsed_; - return true; - } + lastUsed_ = time_now_d(); // Let's not even start a new texture if we're already behind. if (budget < 0.0) return false; - if (!prepareDone_) - return false; - if (threadWaitable_) - delete threadWaitable_; + _assert_(!threadWaitable_); threadWaitable_ = new LimitedWaitable(); g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); if (threadWaitable_->WaitFor(budget)) { - // If we finished all the levels, we're done. - return initDone_ && levelData_ != nullptr && !levelData_->data.empty(); + // If we successfully wait here, we're done. The thread will set state accordingly. + _assert_(State() == ReplacementState::ACTIVE || State() == ReplacementState::NOT_FOUND); + return true; } - + SetState(ReplacementState::PENDING); // Still pending on thread. return false; } @@ -90,19 +103,18 @@ bool ReplacedTexture::IsReady(double budget) { void ReplacedTexture::Prepare(VFSBackend *vfs) { std::unique_lock lock(mutex_); this->vfs_ = vfs; - if (cancelPrepare_) { - initDone_ = true; + + if (State() == ReplacementState::CANCEL_INIT) { return; } for (int i = 0; i < (int)levels_.size(); ++i) { - if (cancelPrepare_) + if (State() == ReplacementState::CANCEL_INIT) break; PrepareData(i); } - initDone_ = true; - if (!cancelPrepare_ && threadWaitable_) + if (threadWaitable_) threadWaitable_->Notify(); } @@ -141,12 +153,14 @@ void ReplacedTexture::PrepareData(int level) { std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); + SetState(ReplacementState::NOT_FOUND); cleanup(); return; } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); + SetState(ReplacementState::NOT_FOUND); cleanup(); return; } @@ -156,6 +170,7 @@ void ReplacedTexture::PrepareData(int level) { if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > info.w || h > info.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); + SetState(ReplacementState::NOT_FOUND); cleanup(); return; } @@ -184,11 +199,13 @@ void ReplacedTexture::PrepareData(int level) { pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); + SetState(ReplacementState::NOT_FOUND); cleanup(); return; } if (png.width > (uint32_t)info.w || png.height > (uint32_t)info.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); + SetState(ReplacementState::NOT_FOUND); cleanup(); return; } @@ -206,6 +223,7 @@ void ReplacedTexture::PrepareData(int level) { out.resize(info.w * info.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], info.w * 4, nullptr)) { ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", info.file.c_str(), png.message); + SetState(ReplacementState::NOT_FOUND); cleanup(); out.resize(0); return; @@ -221,6 +239,7 @@ void ReplacedTexture::PrepareData(int level) { } } + SetState(ReplacementState::ACTIVE); cleanup(); } @@ -235,13 +254,13 @@ void ReplacedTexture::PurgeIfOlder(double t) { std::lock_guard guard(levelData_->lock); levelData_->data.clear(); // This means we have to reload. If we never purge any, there's no need. - initDone_ = false; + SetState(ReplacementState::PREPARED); } } ReplacedTexture::~ReplacedTexture() { if (threadWaitable_) { - cancelPrepare_ = true; + SetState(ReplacementState::CANCEL_INIT); std::unique_lock lock(mutex_); threadWaitable_->WaitAndRelease(); @@ -258,7 +277,7 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); - if (!initDone_) { + if (State() != ReplacementState::ACTIVE) { WARN_LOG(G3D, "Init not done yet"); return false; } @@ -293,3 +312,15 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { return true; } + +const char *StateString(ReplacementState state) { + switch (state) { + case ReplacementState::UNINITIALIZED: return "UNINITIALIZED"; + case ReplacementState::PREPARED: return "PREPARED"; + case ReplacementState::PENDING: return "PENDING"; + case ReplacementState::NOT_FOUND: return "NOT_FOUND"; + case ReplacementState::ACTIVE: return "ACTIVE"; + case ReplacementState::CANCEL_INIT: return "CANCEL_INIT"; + default: return "N/A"; + } +} diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 735be70590..d36e53cc50 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -22,6 +22,7 @@ #include "Common/File/VFS/VFS.h" #include "Common/GPU/thin3d.h" +#include "Common/Log.h" struct ReplacedLevelsCache; class TextureReplacer; @@ -59,26 +60,36 @@ struct ReplacedTextureLevel { ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic); +enum class ReplacementState : uint32_t { + UNINITIALIZED, + PREPARED, // We located the texture files but have not started the thread. + PENDING, + NOT_FOUND, // Also used on error loading the images. + ACTIVE, + CANCEL_INIT, +}; + +const char *StateString(ReplacementState state); + // These aren't actually all replaced, they can also represent a placeholder for a not-found -// replacement. +// replacement (state_ == NOT_FOUND). struct ReplacedTexture { ~ReplacedTexture(); - inline bool Valid() const { - if (!initDone_) - return false; - return !levels_.empty(); + inline ReplacementState State() const { + return state_; } - inline bool IsInvalid() const { - if (!initDone_) - return false; - return levels_.empty(); + void SetState(ReplacementState state) { + _dbg_assert_(state != state_); +#ifdef _DEBUG + WARN_LOG(G3D, "Texture %s changed from %s to %s", logId_.c_str(), StateString(state_), StateString(state)); +#endif + state_ = state; } bool GetSize(int level, int &w, int &h) const { - if (!initDone_) - return false; + _dbg_assert_(State() == ReplacementState::ACTIVE); if ((size_t)level < levels_.size()) { w = levels_[level].w; h = levels_[level].h; @@ -88,18 +99,13 @@ struct ReplacedTexture { } int NumLevels() const { - if (!initDone_) - return 0; + _dbg_assert_(State() == ReplacementState::ACTIVE); return (int)levels_.size(); } Draw::DataFormat Format() const { - if (initDone_) { - return fmt; - } else { - // Shouldn't get here. - return Draw::DataFormat::UNDEFINED; - } + _dbg_assert_(State() == ReplacementState::ACTIVE); + return fmt; } u8 AlphaStatus() const { @@ -114,8 +120,10 @@ protected: void PrepareData(int level); void PurgeIfOlder(double t); + std::string logId_; + std::vector levels_; - ReplacedLevelsCache *levelData_; + ReplacedLevelsCache *levelData_ = nullptr; ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; double lastUsed_ = 0.0; @@ -123,9 +131,7 @@ protected: std::mutex mutex_; Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. - bool cancelPrepare_ = false; - bool initDone_ = false; - bool prepareDone_ = false; + ReplacementState state_ = ReplacementState::UNINITIALIZED; VFSBackend *vfs_ = nullptr; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 5d914c061b..c15876c538 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -535,16 +535,27 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { int d0 = 1; ReplacedTexture *replaced = FindReplacement(entry, w0, h0, d0); if (replaced) { - if (replaced->IsInvalid()) { + // This texture is pending a replacement load. + // So check the replacer if it's reached a conclusion. + switch (replaced->State()) { + case ReplacementState::NOT_FOUND: + // Didn't find a replacement, so stop looking. entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; if (g_Config.bSaveNewTextures) { - // Load once more to actually save. + // Load it once more to actually save it. Since we don't set STATUS_TO_REPLACE, we won't end up looping. match = false; reason = "replacing"; } - } else { + break; + case ReplacementState::ACTIVE: + // There is now replacement data available! + // Just reload the texture to process the replacement. match = false; reason = "replacing"; + break; + default: + // We'll just wait for a result. + break; } } } @@ -1514,19 +1525,22 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h, budget); if (!replaced) { + // TODO: Remove the flag here? + // entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; replacementTimeThisFrame_ += time_now_d() - replaceStart; return nullptr; } if (replaced->IsReady(budget)) { - if (replaced->GetSize(0, w, h)) { - // Consider it already "scaled." + if (replaced->State() == ReplacementState::ACTIVE && replaced->GetSize(0, w, h)) { + // Consider it already "scaled.". entry->status |= TexCacheEntry::STATUS_IS_SCALED; } // Remove the flag, even if it was invalid. entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; - } else if (!replaced->IsInvalid()) { + } else if (replaced->State() == ReplacementState::PREPARED) { + // Make sure we keep polling. entry->status |= TexCacheEntry::STATUS_TO_REPLACE; } replacementTimeThisFrame_ += time_now_d() - replaceStart; @@ -2795,7 +2809,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (canReplace) { plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); - plan.replaceValid = plan.replaced ? plan.replaced->Valid() : false; + plan.replaceValid = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false; } else { plan.replaced = nullptr; plan.replaceValid = false; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 296acc0031..e2c4418897 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -235,6 +235,8 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { bool filenameWarning = false; if (ini.HasSection("hashes")) { + aliases_.clear(); + auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); // Format: hashname = filename.png bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; @@ -475,7 +477,7 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, ReplacementCacheKey replacementKey(cachekey, hash); auto it = cache_.find(replacementKey); if (it != cache_.end()) { - if (!it->second->prepareDone_ && budget > 0.0) { + if (it->second->State() == ReplacementState::UNINITIALIZED && budget > 0.0) { // We don't do this on a thread, but we only do it while within budget. PopulateReplacement(it->second, cachekey, hash, w, h); } @@ -485,11 +487,12 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, // Okay, let's construct the result. ReplacedTexture *result = new ReplacedTexture(); - cache_[replacementKey] = result; result->vfs_ = this->vfs_; if (budget > 0.0) { + _dbg_assert_(result->State() == ReplacementState::UNINITIALIZED); PopulateReplacement(result, cachekey, hash, w, h); } + cache_[replacementKey] = result; return result; } @@ -507,11 +510,13 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey const std::string hashfiles = LookupHashFile(cachekey, hash, &foundReplacement, &ignored); if (!foundReplacement || ignored) { + WARN_LOG(G3D, "Not found/ignored: %s (%d, %d)", hashfiles.c_str(), (int)foundReplacement, (int)ignored); // nothing to do? - texture->prepareDone_ = true; + texture->SetState(ReplacementState::NOT_FOUND); return; } + texture->logId_ = hashfiles; // INFO_LOG(G3D, "Found: %s", hashfiles.c_str()); std::vector filenames; @@ -564,9 +569,16 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey break; } + if (texture->levels_.empty()) { + // Bad. + texture->SetState(ReplacementState::NOT_FOUND); + texture->levelData_ = nullptr; + return; + } + // Populate the data pointer. texture->levelData_ = &levelCache_[hashfiles]; - texture->prepareDone_ = true; + texture->SetState(ReplacementState::PREPARED); } bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { From 07fc551e4eca67cabc79f9d84807a4b002624a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 14:16:14 +0100 Subject: [PATCH 265/424] State fixes, disable logspam --- GPU/Common/ReplacedTexture.cpp | 1 + GPU/Common/ReplacedTexture.h | 13 +++++-------- GPU/Common/TextureCacheCommon.cpp | 18 +++++++++++++----- GPU/Common/TextureCacheCommon.h | 3 ++- GPU/Common/TextureReplacer.cpp | 4 +++- GPU/GLES/TextureCacheGLES.cpp | 3 ++- 6 files changed, 26 insertions(+), 16 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index f4b3c52b7c..60073457fe 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -54,6 +54,7 @@ private: LimitedWaitable *waitable_; }; +// This can only return true if ACTIVE or NOT_FOUND. bool ReplacedTexture::IsReady(double budget) { _assert_(vfs_ != nullptr); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index d36e53cc50..d7527e4bde 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -83,19 +83,16 @@ struct ReplacedTexture { void SetState(ReplacementState state) { _dbg_assert_(state != state_); #ifdef _DEBUG - WARN_LOG(G3D, "Texture %s changed from %s to %s", logId_.c_str(), StateString(state_), StateString(state)); + // WARN_LOG(G3D, "Texture %s changed state from %s to %s", logId_.c_str(), StateString(state_), StateString(state)); #endif state_ = state; } - bool GetSize(int level, int &w, int &h) const { + void GetSize(int level, int *w, int *h) const { _dbg_assert_(State() == ReplacementState::ACTIVE); - if ((size_t)level < levels_.size()) { - w = levels_[level].w; - h = levels_[level].h; - return true; - } - return false; + _dbg_assert_(level < levels_.size()); + *w = levels_[level].w; + *h = levels_[level].h; } int NumLevels() const { diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index c15876c538..fde5fff389 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -540,6 +540,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { switch (replaced->State()) { case ReplacementState::NOT_FOUND: // Didn't find a replacement, so stop looking. + WARN_LOG(G3D, "No replacement for texture %dx%d", w0, h0); entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; if (g_Config.bSaveNewTextures) { // Load it once more to actually save it. Since we don't set STATUS_TO_REPLACE, we won't end up looping. @@ -1532,16 +1533,23 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & } if (replaced->IsReady(budget)) { - if (replaced->State() == ReplacementState::ACTIVE && replaced->GetSize(0, w, h)) { + if (replaced->State() == ReplacementState::ACTIVE) { + replaced->GetSize(0, &w, &h); // Consider it already "scaled.". entry->status |= TexCacheEntry::STATUS_IS_SCALED; } // Remove the flag, even if it was invalid. entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; - } else if (replaced->State() == ReplacementState::PREPARED) { + } + + switch (replaced->State()) { + case ReplacementState::PREPARED: + case ReplacementState::PENDING: + case ReplacementState::UNINITIALIZED: // Make sure we keep polling. entry->status |= TexCacheEntry::STATUS_TO_REPLACE; + break; } replacementTimeThisFrame_ += time_now_d() - replaceStart; return replaced; @@ -2825,7 +2833,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt plan.levelsToCreate = std::min(plan.levelsToLoad, plan.levelsToCreate); plan.badMipSizes = false; // But, we still need to create the texture at a larger size. - plan.replaced->GetSize(0, plan.createW, plan.createH); + plan.replaced->GetSize(0, &plan.createW, &plan.createH); } else { if (replacer_.Enabled() && !plan.replaceValid && plan.depth == 1 && canReplace) { ReplacedTextureDecodeInfo replacedInfo; @@ -2833,7 +2841,6 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt replacedInfo.cachekey = entry->CacheKey(); replacedInfo.hash = entry->fullhash; replacedInfo.addr = entry->addr; - replacedInfo.isVideo = plan.isVideo; replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; replacedInfo.scaleFactor = plan.scaleFactor; replacedInfo.fmt = Draw::DataFormat::R8G8B8A8_UNORM; @@ -2877,7 +2884,8 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i PROFILE_THIS_SCOPE("decodetex"); - if (plan.replaceValid && plan.replaced->GetSize(srcLevel, w, h)) { + if (plan.replaceValid) { + plan.replaced->GetSize(srcLevel, &w, &h); double replaceStart = time_now_d(); plan.replaced->CopyLevelTo(srcLevel, data, stride); replacementTimeThisFrame_ += time_now_d() - replaceStart; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index a51660d364..ff44e35664 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -292,7 +292,8 @@ struct BuildTexturePlan { bool decodeToClut8; void GetMipSize(int level, int *w, int *h) const { - if (replaceValid && replaced->GetSize(level, *w, *h)) { + if (replaceValid) { + replaced->GetSize(level, w, h); return; } if (depth == 1) { diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index e2c4418897..095b83ae43 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -491,6 +491,8 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, if (budget > 0.0) { _dbg_assert_(result->State() == ReplacementState::UNINITIALIZED); PopulateReplacement(result, cachekey, hash, w, h); + } else { + // WARN_LOG(G3D, "Postponing preparing texture (%dx%d)", w, h); } cache_[replacementKey] = result; return result; @@ -510,7 +512,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey const std::string hashfiles = LookupHashFile(cachekey, hash, &foundReplacement, &ignored); if (!foundReplacement || ignored) { - WARN_LOG(G3D, "Not found/ignored: %s (%d, %d)", hashfiles.c_str(), (int)foundReplacement, (int)ignored); + // WARN_LOG(G3D, "Not found/ignored: %s (%d, %d)", hashfiles.c_str(), (int)foundReplacement, (int)ignored); // nothing to do? texture->SetState(ReplacementState::NOT_FOUND); return; diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 307a43c1e0..d44a883bcc 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -246,7 +246,8 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { int th = plan.createH; Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - if (plan.replaced && plan.replaced->GetSize(plan.baseLevelSrc, tw, th)) { + if (plan.replaceValid) { + plan.replaced->GetSize(plan.baseLevelSrc, &tw, &th); dstFmt = plan.replaced->Format(); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = Draw::DataFormat::R8G8B8A8_UNORM; From 53791b1816ae508e1448485ab54c16d390db22c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 14:18:42 +0100 Subject: [PATCH 266/424] Restore functionality of the allowVideo flag, while preserving the early-out. --- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Common/TextureReplacer.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index fde5fff389..7387534084 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1514,7 +1514,7 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & return nullptr; } - if (entry->status & TexCacheEntry::STATUS_VIDEO) { + if ((entry->status & TexCacheEntry::STATUS_VIDEO) && replacer_.AllowVideo()) { return nullptr; } diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 27c6b1b83f..cae53a67f1 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -106,9 +106,8 @@ public: void Init(); void NotifyConfigChanged(); - inline bool Enabled() { - return enabled_; - } + bool Enabled() const { return enabled_; } + bool AllowVideo() const { return allowVideo_; } u32 ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV); From f459a8f71a5a8a93fa519d7bf559d55a4d5b9425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 14:58:44 +0100 Subject: [PATCH 267/424] Fix ini-less texture replacement --- GPU/Common/ReplacedTexture.cpp | 6 ++-- GPU/Common/TextureCacheCommon.cpp | 1 + GPU/Common/TextureReplacer.cpp | 55 ++++++++++++++++++------------- GPU/Common/TextureReplacer.h | 1 + 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 60073457fe..76748f6b64 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -93,7 +93,7 @@ bool ReplacedTexture::IsReady(double budget) { g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); if (threadWaitable_->WaitFor(budget)) { // If we successfully wait here, we're done. The thread will set state accordingly. - _assert_(State() == ReplacementState::ACTIVE || State() == ReplacementState::NOT_FOUND); + _assert_(State() == ReplacementState::ACTIVE || State() == ReplacementState::NOT_FOUND || State() == ReplacementState::CANCEL_INIT); return true; } SetState(ReplacementState::PENDING); @@ -135,8 +135,10 @@ void ReplacedTexture::PrepareData(int level) { std::vector &out = levelData_->data[level]; // Already populated from cache. - if (!out.empty()) + if (!out.empty()) { + SetState(ReplacementState::ACTIVE); return; + } ReplacedImageType imageType; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 7387534084..fe016955b3 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2843,6 +2843,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt replacedInfo.addr = entry->addr; replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; replacedInfo.scaleFactor = plan.scaleFactor; + replacedInfo.isVideo = plan.isVideo; replacedInfo.fmt = Draw::DataFormat::R8G8B8A8_UNORM; plan.saveTexture = replacer_.WillSave(replacedInfo); } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 095b83ae43..3fd199ffc6 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -104,12 +104,12 @@ void TextureReplacer::NotifyConfigChanged() { if (enabled_) { basePath_ = GetSysDirectory(DIRECTORY_TEXTURES) / gameID_; - Path newTextureDir = basePath_ / NEW_TEXTURE_DIR; + newTextureDir_ = basePath_ / NEW_TEXTURE_DIR; // If we're saving, auto-create the directory. - if (g_Config.bSaveNewTextures && !File::Exists(newTextureDir)) { - File::CreateFullPath(newTextureDir); - File::CreateEmptyFile(newTextureDir / ".nomedia"); + if (g_Config.bSaveNewTextures && !File::Exists(newTextureDir_)) { + File::CreateFullPath(newTextureDir_); + File::CreateEmptyFile(newTextureDir_ / ".nomedia"); } enabled_ = File::IsDirectory(basePath_); @@ -507,22 +507,33 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey cachekey = cachekey & 0xFFFFFFFFULL; } - bool foundReplacement = false; + bool foundAlias = false; bool ignored = false; - const std::string hashfiles = LookupHashFile(cachekey, hash, &foundReplacement, &ignored); + std::string hashfiles = LookupHashFile(cachekey, hash, &foundAlias, &ignored); - if (!foundReplacement || ignored) { + if (ignored) { // WARN_LOG(G3D, "Not found/ignored: %s (%d, %d)", hashfiles.c_str(), (int)foundReplacement, (int)ignored); // nothing to do? texture->SetState(ReplacementState::NOT_FOUND); return; } - texture->logId_ = hashfiles; - // INFO_LOG(G3D, "Found: %s", hashfiles.c_str()); - std::vector filenames; - SplitString(hashfiles, '|', filenames); + + if (!foundAlias) { + // We'll just need to generate the names for each level. + // By default, we look for png since that's also what's dumped. + // For other file formats, use the ini to create aliases. + filenames.resize(MAX_MIP_LEVELS); + for (int level = 0; level < filenames.size(); level++) { + filenames[level] = HashName(cachekey, hash, level) + ".png"; + } + texture->logId_ = filenames[0]; + hashfiles = filenames[0]; // This is used as the key in the data cache. + } else { + texture->logId_ = hashfiles; + SplitString(hashfiles, '|', filenames); + } for (int i = 0; i < std::min(MAX_MIP_LEVELS, (int)filenames.size()); ++i) { if (filenames[i].empty()) { @@ -532,6 +543,12 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey const Path filename = basePath_ / filenames[i]; + VFSFileReference *fileRef = vfs_->GetFile(filenames[i].c_str()); + if (!fileRef) { + // If the file doesn't exist, let's just bail immediately here. + break; + } + // TODO: Here, if we find a file with multiple built-in mipmap levels, // we'll have to change a bit how things work... ReplacedTextureLevel level; @@ -543,12 +560,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey bool good; - VFSFileReference *fileRef = vfs_->GetFile(filenames[i].c_str()); - if (!fileRef) { - // If the file doesn't exist, let's just bail immediately here. - break; - } - level.fileRef = fileRef; good = PopulateLevel(level, false); @@ -748,19 +759,19 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl cachekey = cachekey & 0xFFFFFFFFULL; } - bool found = false, ignored = false; - std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &found, &ignored); + bool foundAlias = false, ignored = false; + std::string hashfile = LookupHashFile(cachekey, replacedInfo.hash, &foundAlias, &ignored); // If it's empty, it's an ignored hash, we intentionally don't save. - if (found) { + if (foundAlias || ignored) { // If it exists, must've been decoded and saved as a new texture already. return; } - // Generate a new filename. + // Generate a new PNG filename, complete with level. hashfile = HashName(cachekey, replacedInfo.hash, level) + ".png"; - const Path filename = basePath_ / hashfile; + const Path filename = newTextureDir_ / hashfile; ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash); auto it = savedCache_.find(replacementKey); diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index cae53a67f1..08cac604e3 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -153,6 +153,7 @@ protected: bool ignoreMipmap_ = false; std::string gameID_; Path basePath_; + Path newTextureDir_; ReplacedTextureHash hash_ = ReplacedTextureHash::QUICK; VFSBackend *vfs_ = nullptr; From 207e2259e723a1efdbf830b7c341abe2df5f912c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 15:39:45 +0100 Subject: [PATCH 268/424] Cleanup texture saving a bit --- GPU/Common/TextureReplacer.cpp | 54 ++++++++++++++++++---------------- GPU/Common/TextureReplacer.h | 2 +- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 3fd199ffc6..430b45f21c 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -671,8 +671,11 @@ public: int h = 0; int pitch = 0; // bytes - Path basePath; - std::string hashfile; + Path filename; + Path saveFilename; + bool createSaveDirectory; + Path saveDirectory; + u32 replacedInfoHash = 0; bool skipIfExists = false; @@ -687,9 +690,6 @@ public: } void Run() override { - const Path filename = basePath / hashfile; - const Path saveFilename = basePath / NEW_TEXTURE_DIR / hashfile; - // Should we skip writing if the newly saved data already exists? if (skipIfExists && File::Exists(saveFilename)) { return; @@ -699,19 +699,9 @@ public: if (File::Exists(filename)) return; - // Create subfolder as needed. -#ifdef _WIN32 - size_t slash = hashfile.find_last_of("/\\"); -#else - size_t slash = hashfile.find_last_of("/"); -#endif - if (slash != hashfile.npos) { - // Create any directory structure as needed. - const Path saveDirectory = basePath / NEW_TEXTURE_DIR / hashfile.substr(0, slash); - if (!File::Exists(saveDirectory)) { - File::CreateFullPath(saveDirectory); - File::CreateEmptyFile(saveDirectory / ".nomedia"); - } + if (createSaveDirectory && !File::Exists(saveDirectory)) { + File::CreateFullPath(saveDirectory); + File::CreateEmptyFile(saveDirectory / ".nomedia"); } png_image png{}; @@ -771,8 +761,6 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl // Generate a new PNG filename, complete with level. hashfile = HashName(cachekey, replacedInfo.hash, level) + ".png"; - const Path filename = newTextureDir_ / hashfile; - ReplacementCacheKey replacementKey(cachekey, replacedInfo.hash); auto it = savedCache_.find(replacementKey); bool skipIfExists = false; @@ -808,11 +796,27 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl pitch = w * 4; SaveTextureTask *task = new SaveTextureTask(std::move(saveBuf)); + + task->filename = basePath_ / hashfile; + task->saveFilename = newTextureDir_ / hashfile; + task->createSaveDirectory = false; + + // Create subfolder as needed. +#ifdef _WIN32 + size_t slash = hashfile.find_last_of("/\\"); +#else + size_t slash = hashfile.find_last_of("/"); +#endif + if (slash != hashfile.npos) { + // Does this ever happen? + // Create any directory structure as needed. + task->saveDirectory = newTextureDir_ / hashfile.substr(0, slash); + task->createSaveDirectory = true; + } + task->w = w; task->h = h; task->pitch = pitch; - task->basePath = basePath_; - task->hashfile = hashfile; task->replacedInfoHash = replacedInfo.hash; task->skipIfExists = skipIfExists; g_threadManager.EnqueueTask(task); // We don't care about waiting for the task. It'll be fine. @@ -923,16 +927,16 @@ bool TextureReplacer::FindFiltering(u64 cachekey, u32 hash, TextureFiltering *fo return false; } -std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement, bool *ignored) { +std::string TextureReplacer::LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored) { ReplacementCacheKey key(cachekey, hash); auto alias = LookupWildcard(aliases_, key, cachekey, hash, ignoreAddress_); if (alias != aliases_.end()) { // Note: this will be blank if explicitly ignored. - *foundReplacement = true; + *foundAlias = true; *ignored = alias->second.empty(); return alias->second; } - *foundReplacement = false; + *foundAlias = false; *ignored = false; return ""; } diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 08cac604e3..bb3c020a98 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -137,7 +137,7 @@ protected: void ParseReduceHashRange(const std::string& key, const std::string& value); bool LookupHashRange(u32 addr, int &w, int &h); float LookupReduceHashRange(int& w, int& h); - std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundReplacement, bool *ignored); + std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored); std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); From 36f78a46c1eb7f5ac59e59bce2d872ca5f59f322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 17:21:23 +0100 Subject: [PATCH 269/424] Rename PREPARED->POPULATED --- GPU/Common/ReplacedTexture.cpp | 6 +++--- GPU/Common/ReplacedTexture.h | 2 +- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Common/TextureReplacer.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 76748f6b64..356cfc1858 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -77,7 +77,7 @@ bool ReplacedTexture::IsReady(double budget) { case ReplacementState::CANCEL_INIT: case ReplacementState::PENDING: return false; - case ReplacementState::PREPARED: + case ReplacementState::POPULATED: // We're gonna need to spawn a task. break; } @@ -257,7 +257,7 @@ void ReplacedTexture::PurgeIfOlder(double t) { std::lock_guard guard(levelData_->lock); levelData_->data.clear(); // This means we have to reload. If we never purge any, there's no need. - SetState(ReplacementState::PREPARED); + SetState(ReplacementState::POPULATED); } } @@ -319,7 +319,7 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { const char *StateString(ReplacementState state) { switch (state) { case ReplacementState::UNINITIALIZED: return "UNINITIALIZED"; - case ReplacementState::PREPARED: return "PREPARED"; + case ReplacementState::POPULATED: return "PREPARED"; case ReplacementState::PENDING: return "PENDING"; case ReplacementState::NOT_FOUND: return "NOT_FOUND"; case ReplacementState::ACTIVE: return "ACTIVE"; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index d7527e4bde..b46261b46b 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -62,7 +62,7 @@ ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string * enum class ReplacementState : uint32_t { UNINITIALIZED, - PREPARED, // We located the texture files but have not started the thread. + POPULATED, // We located the texture files but have not started the thread. PENDING, NOT_FOUND, // Also used on error loading the images. ACTIVE, diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index fe016955b3..5c056eb87f 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1544,7 +1544,7 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & } switch (replaced->State()) { - case ReplacementState::PREPARED: + case ReplacementState::POPULATED: case ReplacementState::PENDING: case ReplacementState::UNINITIALIZED: // Make sure we keep polling. diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 430b45f21c..a026d31c7b 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -591,7 +591,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey // Populate the data pointer. texture->levelData_ = &levelCache_[hashfiles]; - texture->SetState(ReplacementState::PREPARED); + texture->SetState(ReplacementState::POPULATED); } bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { From 96111537e2709cb0307c77ba5314f225091901da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 17:26:41 +0100 Subject: [PATCH 270/424] Move PopulateLevel to the texture --- GPU/Common/ReplacedTexture.cpp | 49 ++++++++++++++++++++++++++++++++ GPU/Common/ReplacedTexture.h | 2 ++ GPU/Common/TextureReplacer.cpp | 51 +--------------------------------- GPU/Common/TextureReplacer.h | 1 - 4 files changed, 52 insertions(+), 51 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 356cfc1858..9ec0fae2bb 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -101,6 +101,55 @@ bool ReplacedTexture::IsReady(double budget) { return false; } +bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { + bool good = false; + + if (!level.fileRef) { + if (!ignoreError) + ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); + return false; + } + + size_t fileSize; + VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef, &fileSize); + if (!file) { + return false; + } + + std::string magic; + auto imageType = Identify(vfs_, file, &magic); + + if (imageType == ReplacedImageType::ZIM) { + uint32_t ignore = 0; + struct ZimHeader { + uint32_t magic; + uint32_t w; + uint32_t h; + uint32_t flags; + } header; + good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); + level.w = header.w; + level.h = header.h; + good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; + } else if (imageType == ReplacedImageType::PNG) { + PNGHeaderPeek headerPeek; + good = vfs_->Read(file, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); + if (good && headerPeek.IsValidPNGHeader()) { + level.w = headerPeek.Width(); + level.h = headerPeek.Height(); + good = true; + } else { + ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); + good = false; + } + } else { + ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); + } + vfs_->CloseFile(file); + + return good; +} + void ReplacedTexture::Prepare(VFSBackend *vfs) { std::unique_lock lock(mutex_); this->vfs_ = vfs; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index b46261b46b..2e71b92210 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -112,6 +112,8 @@ struct ReplacedTexture { bool IsReady(double budget); bool CopyLevelTo(int level, void *out, int rowPitch); + bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); + protected: void Prepare(VFSBackend *vfs); void PrepareData(int level); diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index a026d31c7b..846146fffc 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -561,7 +561,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey bool good; level.fileRef = fileRef; - good = PopulateLevel(level, false); + good = texture->PopulateLevel(level, false); // We pad files that have been hashrange'd so they are the same texture size. level.w = (level.w * w) / newW; @@ -594,55 +594,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey texture->SetState(ReplacementState::POPULATED); } -bool TextureReplacer::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { - bool good = false; - - if (!level.fileRef) { - if (!ignoreError) - ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); - return false; - } - - size_t fileSize; - VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef, &fileSize); - if (!file) { - return false; - } - - std::string magic; - auto imageType = Identify(vfs_, file, &magic); - - if (imageType == ReplacedImageType::ZIM) { - uint32_t ignore = 0; - struct ZimHeader { - uint32_t magic; - uint32_t w; - uint32_t h; - uint32_t flags; - } header; - good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); - level.w = header.w; - level.h = header.h; - good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; - } else if (imageType == ReplacedImageType::PNG) { - PNGHeaderPeek headerPeek; - good = vfs_->Read(file, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); - if (good && headerPeek.IsValidPNGHeader()) { - level.w = headerPeek.Width(); - level.h = headerPeek.Height(); - good = true; - } else { - ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); - good = false; - } - } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); - } - vfs_->CloseFile(file); - - return good; -} - static bool WriteTextureToPNG(png_imagep image, const Path &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { FILE *fp = File::OpenCFile(filename, "wb"); if (!fp) { diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index bb3c020a98..8c6ee6e60d 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -140,7 +140,6 @@ protected: std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored); std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); - bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); bool enabled_ = false; bool allowVideo_ = false; From 9e8e2e41fa1e320b573713b17476349db4a6c201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 17:43:12 +0100 Subject: [PATCH 271/424] Move most of Populate to ReplacedTexture, although not the cpp --- GPU/Common/ReplacedTexture.h | 9 ++-- GPU/Common/TextureReplacer.cpp | 92 ++++++++++++++++++++++------------ GPU/Common/TextureReplacer.h | 3 +- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 2e71b92210..8ed2250a8b 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -71,6 +71,8 @@ enum class ReplacementState : uint32_t { const char *StateString(ReplacementState state); +struct ReplacementDesc; + // These aren't actually all replaced, they can also represent a placeholder for a not-found // replacement (state_ == NOT_FOUND). struct ReplacedTexture { @@ -112,14 +114,15 @@ struct ReplacedTexture { bool IsReady(double budget); bool CopyLevelTo(int level, void *out, int rowPitch); - bool PopulateLevel(ReplacedTextureLevel &level, bool ignoreError); + void FinishPopulate(const ReplacementDesc &desc); + std::string logId_; -protected: +private: void Prepare(VFSBackend *vfs); void PrepareData(int level); void PurgeIfOlder(double t); - std::string logId_; + bool PopulateLevel(ReplacedTextureLevel & level, bool ignoreError); std::vector levels_; ReplacedLevelsCache *levelData_ = nullptr; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 846146fffc..de5f579587 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -498,19 +498,41 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, return result; } +struct ReplacementDesc { + int newW; + int newH; + u64 cachekey; + u32 hash; + int w; + int h; + std::string hashfiles; + Path basePath; + bool foundAlias; + std::vector filenames; + std::string logId; + ReplacedLevelsCache *cache; +}; + void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey, u32 hash, int w, int h) { - int newW = w; - int newH = h; - LookupHashRange(cachekey >> 32, newW, newH); + ReplacementDesc desc; + desc.newW = w; + desc.newH = h; + desc.w = w; + desc.h = h; + desc.cachekey = cachekey; + desc.hash = hash; + desc.basePath = basePath_; + LookupHashRange(cachekey >> 32, desc.newW, desc.newH); if (ignoreAddress_) { cachekey = cachekey & 0xFFFFFFFFULL; } - bool foundAlias = false; + desc.foundAlias = false; bool ignored = false; - std::string hashfiles = LookupHashFile(cachekey, hash, &foundAlias, &ignored); + desc.hashfiles = LookupHashFile(cachekey, hash, &desc.foundAlias, &ignored); + // Early-out for ignored textures, let's not bother even starting a thread task. if (ignored) { // WARN_LOG(G3D, "Not found/ignored: %s (%d, %d)", hashfiles.c_str(), (int)foundReplacement, (int)ignored); // nothing to do? @@ -518,32 +540,41 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey return; } - std::vector filenames; - - if (!foundAlias) { + if (!desc.foundAlias) { // We'll just need to generate the names for each level. // By default, we look for png since that's also what's dumped. // For other file formats, use the ini to create aliases. - filenames.resize(MAX_MIP_LEVELS); - for (int level = 0; level < filenames.size(); level++) { - filenames[level] = HashName(cachekey, hash, level) + ".png"; + desc.filenames.resize(MAX_MIP_LEVELS); + for (int level = 0; level < desc.filenames.size(); level++) { + desc.filenames[level] = TextureReplacer::HashName(desc.cachekey, desc.hash, level) + ".png"; } - texture->logId_ = filenames[0]; - hashfiles = filenames[0]; // This is used as the key in the data cache. + desc.logId = desc.filenames[0]; + desc.hashfiles = desc.filenames[0]; // This is used as the key in the data cache. } else { - texture->logId_ = hashfiles; - SplitString(hashfiles, '|', filenames); + desc.logId = desc.hashfiles; + SplitString(desc.hashfiles, '|', desc.filenames); } - for (int i = 0; i < std::min(MAX_MIP_LEVELS, (int)filenames.size()); ++i) { - if (filenames[i].empty()) { + desc.cache = &levelCache_[desc.hashfiles]; + + texture->FinishPopulate(desc); +} + +void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { + logId_ = desc.logId; + levelData_ = desc.cache; + + // The rest can be done on the thread. + + for (int i = 0; i < std::min(MAX_MIP_LEVELS, (int)desc.filenames.size()); ++i) { + if (desc.filenames[i].empty()) { // Out of valid mip levels. Bail out. break; } - const Path filename = basePath_ / filenames[i]; + const Path filename = desc.basePath / desc.filenames[i]; - VFSFileReference *fileRef = vfs_->GetFile(filenames[i].c_str()); + VFSFileReference *fileRef = vfs_->GetFile(desc.filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. break; @@ -555,43 +586,42 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey level.file = filename; if (i == 0) { - texture->fmt = Draw::DataFormat::R8G8B8A8_UNORM; + fmt = Draw::DataFormat::R8G8B8A8_UNORM; } bool good; level.fileRef = fileRef; - good = texture->PopulateLevel(level, false); + good = PopulateLevel(level, false); // We pad files that have been hashrange'd so they are the same texture size. - level.w = (level.w * w) / newW; - level.h = (level.h * h) / newH; + level.w = (level.w * desc.w) / desc.newW; + level.h = (level.h * desc.h) / desc.newH; if (good && i != 0) { // Check that the mipmap size is correct. Can't load mips of the wrong size. - if (level.w != (texture->levels_[0].w >> i) || level.h != (texture->levels_[0].h >> i)) { - WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, texture->levels_[0].w >> i, texture->levels_[0].h >> i, i, filename.c_str()); + if (level.w != (levels_[0].w >> i) || level.h != (levels_[0].h >> i)) { + WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, levels_[0].w >> i, levels_[0].h >> i, i, filename.c_str()); good = false; } } if (good) - texture->levels_.push_back(level); + levels_.push_back(level); // Otherwise, we're done loading mips (bad PNG or bad size, either way.) else break; } - if (texture->levels_.empty()) { + if (levels_.empty()) { // Bad. - texture->SetState(ReplacementState::NOT_FOUND); - texture->levelData_ = nullptr; + SetState(ReplacementState::NOT_FOUND); + levelData_ = nullptr; return; } // Populate the data pointer. - texture->levelData_ = &levelCache_[hashfiles]; - texture->SetState(ReplacementState::POPULATED); + SetState(ReplacementState::POPULATED); } static bool WriteTextureToPNG(png_imagep image, const Path &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 8c6ee6e60d..ed0df878c9 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -129,6 +129,8 @@ public: int GetNumTrackedTextures() const { return (int)cache_.size(); } int GetNumCachedReplacedTextures() const { return (int)levelCache_.size(); } + static std::string HashName(u64 cachekey, u32 hash, int level); + protected: bool LoadIni(); bool LoadIniValues(IniFile &ini, bool isOverride = false); @@ -138,7 +140,6 @@ protected: bool LookupHashRange(u32 addr, int &w, int &h); float LookupReduceHashRange(int& w, int& h); std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored); - std::string HashName(u64 cachekey, u32 hash, int level); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); bool enabled_ = false; From ed7947c94bb469d6158f569b0ac6ee6102ed570b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 17:49:30 +0100 Subject: [PATCH 272/424] Finish the move of Populate to ReplacedTexture --- GPU/Common/ReplacedTexture.cpp | 64 ++++++++++++++++++++++++++ GPU/Common/ReplacedTexture.h | 17 ++++++- GPU/Common/TextureReplacer.cpp | 84 +--------------------------------- 3 files changed, 82 insertions(+), 83 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 9ec0fae2bb..8265f19e82 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -101,6 +101,70 @@ bool ReplacedTexture::IsReady(double budget) { return false; } +void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { + logId_ = desc.logId; + levelData_ = desc.cache; + + // TODO: The rest can be done on the thread. + + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc.filenames.size()); ++i) { + if (desc.filenames[i].empty()) { + // Out of valid mip levels. Bail out. + break; + } + + const Path filename = desc.basePath / desc.filenames[i]; + + VFSFileReference *fileRef = vfs_->GetFile(desc.filenames[i].c_str()); + if (!fileRef) { + // If the file doesn't exist, let's just bail immediately here. + break; + } + + // TODO: Here, if we find a file with multiple built-in mipmap levels, + // we'll have to change a bit how things work... + ReplacedTextureLevel level; + level.file = filename; + + if (i == 0) { + fmt = Draw::DataFormat::R8G8B8A8_UNORM; + } + + bool good; + + level.fileRef = fileRef; + good = PopulateLevel(level, false); + + // We pad files that have been hashrange'd so they are the same texture size. + level.w = (level.w * desc.w) / desc.newW; + level.h = (level.h * desc.h) / desc.newH; + + if (good && i != 0) { + // Check that the mipmap size is correct. Can't load mips of the wrong size. + if (level.w != (levels_[0].w >> i) || level.h != (levels_[0].h >> i)) { + WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, levels_[0].w >> i, levels_[0].h >> i, i, filename.c_str()); + good = false; + } + } + + if (good) + levels_.push_back(level); + // Otherwise, we're done loading mips (bad PNG or bad size, either way.) + else + break; + } + + if (levels_.empty()) { + // Bad. + SetState(ReplacementState::NOT_FOUND); + levelData_ = nullptr; + return; + } + + // Populate the data pointer. + SetState(ReplacementState::POPULATED); +} + bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { bool good = false; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 8ed2250a8b..2911c5fef1 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -47,6 +47,8 @@ enum class ReplacedImageType { INVALID, }; +static const int MAX_REPLACEMENT_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP. + // Metadata about a given texture level. struct ReplacedTextureLevel { int w = 0; @@ -71,7 +73,20 @@ enum class ReplacementState : uint32_t { const char *StateString(ReplacementState state); -struct ReplacementDesc; +struct ReplacementDesc { + int newW; + int newH; + uint64_t cachekey; + uint32_t hash; + int w; + int h; + std::string hashfiles; + Path basePath; + bool foundAlias; + std::vector filenames; + std::string logId; + ReplacedLevelsCache *cache; +}; // These aren't actually all replaced, they can also represent a placeholder for a not-found // replacement (state_ == NOT_FOUND). diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index de5f579587..ebe7bb4f25 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -52,7 +52,6 @@ static const std::string INI_FILENAME = "textures.ini"; static const std::string ZIP_FILENAME = "textures.zip"; static const std::string NEW_TEXTURE_DIR = "new/"; static const int VERSION = 1; -static const int MAX_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP. static const double MAX_CACHE_SIZE = 4.0; static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { @@ -498,21 +497,6 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, return result; } -struct ReplacementDesc { - int newW; - int newH; - u64 cachekey; - u32 hash; - int w; - int h; - std::string hashfiles; - Path basePath; - bool foundAlias; - std::vector filenames; - std::string logId; - ReplacedLevelsCache *cache; -}; - void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey, u32 hash, int w, int h) { ReplacementDesc desc; desc.newW = w; @@ -544,7 +528,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey // We'll just need to generate the names for each level. // By default, we look for png since that's also what's dumped. // For other file formats, use the ini to create aliases. - desc.filenames.resize(MAX_MIP_LEVELS); + desc.filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); for (int level = 0; level < desc.filenames.size(); level++) { desc.filenames[level] = TextureReplacer::HashName(desc.cachekey, desc.hash, level) + ".png"; } @@ -560,70 +544,6 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey texture->FinishPopulate(desc); } -void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { - logId_ = desc.logId; - levelData_ = desc.cache; - - // The rest can be done on the thread. - - for (int i = 0; i < std::min(MAX_MIP_LEVELS, (int)desc.filenames.size()); ++i) { - if (desc.filenames[i].empty()) { - // Out of valid mip levels. Bail out. - break; - } - - const Path filename = desc.basePath / desc.filenames[i]; - - VFSFileReference *fileRef = vfs_->GetFile(desc.filenames[i].c_str()); - if (!fileRef) { - // If the file doesn't exist, let's just bail immediately here. - break; - } - - // TODO: Here, if we find a file with multiple built-in mipmap levels, - // we'll have to change a bit how things work... - ReplacedTextureLevel level; - level.file = filename; - - if (i == 0) { - fmt = Draw::DataFormat::R8G8B8A8_UNORM; - } - - bool good; - - level.fileRef = fileRef; - good = PopulateLevel(level, false); - - // We pad files that have been hashrange'd so they are the same texture size. - level.w = (level.w * desc.w) / desc.newW; - level.h = (level.h * desc.h) / desc.newH; - - if (good && i != 0) { - // Check that the mipmap size is correct. Can't load mips of the wrong size. - if (level.w != (levels_[0].w >> i) || level.h != (levels_[0].h >> i)) { - WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, levels_[0].w >> i, levels_[0].h >> i, i, filename.c_str()); - good = false; - } - } - - if (good) - levels_.push_back(level); - // Otherwise, we're done loading mips (bad PNG or bad size, either way.) - else - break; - } - - if (levels_.empty()) { - // Bad. - SetState(ReplacementState::NOT_FOUND); - levelData_ = nullptr; - return; - } - - // Populate the data pointer. - SetState(ReplacementState::POPULATED); -} - static bool WriteTextureToPNG(png_imagep image, const Path &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { FILE *fp = File::OpenCFile(filename, "wb"); if (!fp) { @@ -654,7 +574,7 @@ public: Path filename; Path saveFilename; - bool createSaveDirectory; + bool createSaveDirectory = false; Path saveDirectory; u32 replacedInfoHash = 0; From dad7777b6f6d5554cd3a59acfc33e115dc9d5903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 20:13:10 +0100 Subject: [PATCH 273/424] Heap-allocate the desc --- GPU/Common/ReplacedTexture.cpp | 20 +++++++++-------- GPU/Common/ReplacedTexture.h | 4 ++-- GPU/Common/TextureReplacer.cpp | 41 +++++++++++++++++----------------- 3 files changed, 34 insertions(+), 31 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 8265f19e82..4206734dfb 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -101,21 +101,21 @@ bool ReplacedTexture::IsReady(double budget) { return false; } -void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { - logId_ = desc.logId; - levelData_ = desc.cache; +void ReplacedTexture::FinishPopulate(ReplacementDesc *desc) { + logId_ = desc->logId; + levelData_ = desc->cache; // TODO: The rest can be done on the thread. - for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc.filenames.size()); ++i) { - if (desc.filenames[i].empty()) { + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc->filenames.size()); ++i) { + if (desc->filenames[i].empty()) { // Out of valid mip levels. Bail out. break; } - const Path filename = desc.basePath / desc.filenames[i]; + const Path filename = desc->basePath / desc->filenames[i]; - VFSFileReference *fileRef = vfs_->GetFile(desc.filenames[i].c_str()); + VFSFileReference *fileRef = vfs_->GetFile(desc->filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. break; @@ -136,8 +136,8 @@ void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { good = PopulateLevel(level, false); // We pad files that have been hashrange'd so they are the same texture size. - level.w = (level.w * desc.w) / desc.newW; - level.h = (level.h * desc.h) / desc.newH; + level.w = (level.w * desc->w) / desc->newW; + level.h = (level.h * desc->h) / desc->newH; if (good && i != 0) { // Check that the mipmap size is correct. Can't load mips of the wrong size. @@ -154,6 +154,8 @@ void ReplacedTexture::FinishPopulate(const ReplacementDesc &desc) { break; } + delete desc; + if (levels_.empty()) { // Bad. SetState(ReplacementState::NOT_FOUND); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 2911c5fef1..5ec3950b72 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -129,7 +129,7 @@ struct ReplacedTexture { bool IsReady(double budget); bool CopyLevelTo(int level, void *out, int rowPitch); - void FinishPopulate(const ReplacementDesc &desc); + void FinishPopulate(ReplacementDesc *desc); std::string logId_; private: @@ -148,7 +148,7 @@ private: std::mutex mutex_; Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. - ReplacementState state_ = ReplacementState::UNINITIALIZED; + std::atomic state_ = ReplacementState::UNINITIALIZED; VFSBackend *vfs_ = nullptr; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index ebe7bb4f25..1ce1fd62ca 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -498,23 +498,24 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, } void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey, u32 hash, int w, int h) { - ReplacementDesc desc; - desc.newW = w; - desc.newH = h; - desc.w = w; - desc.h = h; - desc.cachekey = cachekey; - desc.hash = hash; - desc.basePath = basePath_; - LookupHashRange(cachekey >> 32, desc.newW, desc.newH); + // We pass this to a thread, so can't keep it on the stack. + ReplacementDesc *desc = new ReplacementDesc(); + desc->newW = w; + desc->newH = h; + desc->w = w; + desc->h = h; + desc->cachekey = cachekey; + desc->hash = hash; + desc->basePath = basePath_; + LookupHashRange(cachekey >> 32, desc->newW, desc->newH); if (ignoreAddress_) { cachekey = cachekey & 0xFFFFFFFFULL; } - desc.foundAlias = false; + desc->foundAlias = false; bool ignored = false; - desc.hashfiles = LookupHashFile(cachekey, hash, &desc.foundAlias, &ignored); + desc->hashfiles = LookupHashFile(cachekey, hash, &desc->foundAlias, &ignored); // Early-out for ignored textures, let's not bother even starting a thread task. if (ignored) { @@ -524,22 +525,22 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey return; } - if (!desc.foundAlias) { + if (!desc->foundAlias) { // We'll just need to generate the names for each level. // By default, we look for png since that's also what's dumped. // For other file formats, use the ini to create aliases. - desc.filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); - for (int level = 0; level < desc.filenames.size(); level++) { - desc.filenames[level] = TextureReplacer::HashName(desc.cachekey, desc.hash, level) + ".png"; + desc->filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); + for (int level = 0; level < desc->filenames.size(); level++) { + desc->filenames[level] = TextureReplacer::HashName(desc->cachekey, desc->hash, level) + ".png"; } - desc.logId = desc.filenames[0]; - desc.hashfiles = desc.filenames[0]; // This is used as the key in the data cache. + desc->logId = desc->filenames[0]; + desc->hashfiles = desc->filenames[0]; // This is used as the key in the data cache. } else { - desc.logId = desc.hashfiles; - SplitString(desc.hashfiles, '|', desc.filenames); + desc->logId = desc->hashfiles; + SplitString(desc->hashfiles, '|', desc->filenames); } - desc.cache = &levelCache_[desc.hashfiles]; + desc->cache = &levelCache_[desc->hashfiles]; texture->FinishPopulate(desc); } From 9b7a1a2ddcd5e0a90036bd7eee258647ac337ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 20:31:37 +0100 Subject: [PATCH 274/424] Move the "Populate" phase onto the thread --- GPU/Common/ReplacedTexture.cpp | 127 +++++++++++++++++---------------- GPU/Common/ReplacedTexture.h | 1 + 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 4206734dfb..1061abd940 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -90,13 +90,13 @@ bool ReplacedTexture::IsReady(double budget) { _assert_(!threadWaitable_); threadWaitable_ = new LimitedWaitable(); + SetState(ReplacementState::PENDING); g_threadManager.EnqueueTask(new ReplacedTextureTask(vfs_, *this, threadWaitable_)); if (threadWaitable_->WaitFor(budget)) { // If we successfully wait here, we're done. The thread will set state accordingly. _assert_(State() == ReplacementState::ACTIVE || State() == ReplacementState::NOT_FOUND || State() == ReplacementState::CANCEL_INIT); return true; } - SetState(ReplacementState::PENDING); // Still pending on thread. return false; } @@ -104,67 +104,10 @@ bool ReplacedTexture::IsReady(double budget) { void ReplacedTexture::FinishPopulate(ReplacementDesc *desc) { logId_ = desc->logId; levelData_ = desc->cache; - - // TODO: The rest can be done on the thread. - - for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc->filenames.size()); ++i) { - if (desc->filenames[i].empty()) { - // Out of valid mip levels. Bail out. - break; - } - - const Path filename = desc->basePath / desc->filenames[i]; - - VFSFileReference *fileRef = vfs_->GetFile(desc->filenames[i].c_str()); - if (!fileRef) { - // If the file doesn't exist, let's just bail immediately here. - break; - } - - // TODO: Here, if we find a file with multiple built-in mipmap levels, - // we'll have to change a bit how things work... - ReplacedTextureLevel level; - level.file = filename; - - if (i == 0) { - fmt = Draw::DataFormat::R8G8B8A8_UNORM; - } - - bool good; - - level.fileRef = fileRef; - good = PopulateLevel(level, false); - - // We pad files that have been hashrange'd so they are the same texture size. - level.w = (level.w * desc->w) / desc->newW; - level.h = (level.h * desc->h) / desc->newH; - - if (good && i != 0) { - // Check that the mipmap size is correct. Can't load mips of the wrong size. - if (level.w != (levels_[0].w >> i) || level.h != (levels_[0].h >> i)) { - WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, levels_[0].w >> i, levels_[0].h >> i, i, filename.c_str()); - good = false; - } - } - - if (good) - levels_.push_back(level); - // Otherwise, we're done loading mips (bad PNG or bad size, either way.) - else - break; - } - - delete desc; - - if (levels_.empty()) { - // Bad. - SetState(ReplacementState::NOT_FOUND); - levelData_ = nullptr; - return; - } - - // Populate the data pointer. + desc_ = desc; SetState(ReplacementState::POPULATED); + + // TODO: What used to be here is now done on the thread task. } bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { @@ -217,9 +160,69 @@ bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreErro } void ReplacedTexture::Prepare(VFSBackend *vfs) { - std::unique_lock lock(mutex_); this->vfs_ = vfs; + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_->filenames.size()); ++i) { + if (desc_->filenames[i].empty()) { + // Out of valid mip levels. Bail out. + break; + } + + const Path filename = desc_->basePath / desc_->filenames[i]; + + VFSFileReference *fileRef = vfs_->GetFile(desc_->filenames[i].c_str()); + if (!fileRef) { + // If the file doesn't exist, let's just bail immediately here. + break; + } + + // TODO: Here, if we find a file with multiple built-in mipmap levels, + // we'll have to change a bit how things work... + ReplacedTextureLevel level; + level.file = filename; + + if (i == 0) { + fmt = Draw::DataFormat::R8G8B8A8_UNORM; + } + + bool good; + + level.fileRef = fileRef; + good = PopulateLevel(level, false); + + // We pad files that have been hashrange'd so they are the same texture size. + level.w = (level.w * desc_->w) / desc_->newW; + level.h = (level.h * desc_->h) / desc_->newH; + + if (good && i != 0) { + // Check that the mipmap size is correct. Can't load mips of the wrong size. + if (level.w != (levels_[0].w >> i) || level.h != (levels_[0].h >> i)) { + WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, levels_[0].w >> i, levels_[0].h >> i, i, filename.c_str()); + good = false; + } + } + + if (good) + levels_.push_back(level); + // Otherwise, we're done loading mips (bad PNG or bad size, either way.) + else + break; + } + + delete desc_; + desc_ = nullptr; + + if (levels_.empty()) { + // Bad. + SetState(ReplacementState::NOT_FOUND); + levelData_ = nullptr; + return; + } + + // Populate the data pointer. + + std::unique_lock lock(mutex_); + if (State() == ReplacementState::CANCEL_INIT) { return; } diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 5ec3950b72..93ff79b613 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -151,6 +151,7 @@ private: std::atomic state_ = ReplacementState::UNINITIALIZED; VFSBackend *vfs_ = nullptr; + ReplacementDesc *desc_ = nullptr; friend class TextureReplacer; friend class ReplacedTextureTask; From 84c8fee1f23ff29c201fe246d8980eb6f7dd30f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 20:41:43 +0100 Subject: [PATCH 275/424] Interleave calls to Populate / PrepareData --- GPU/Common/ReplacedTexture.cpp | 51 +++++++++++++++------------------- GPU/Common/ReplacedTexture.h | 2 +- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 1061abd940..ac09a4d05e 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -162,7 +162,13 @@ bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreErro void ReplacedTexture::Prepare(VFSBackend *vfs) { this->vfs_ = vfs; + std::unique_lock lock(mutex_); + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_->filenames.size()); ++i) { + if (State() == ReplacementState::CANCEL_INIT) { + break; + } + if (desc_->filenames[i].empty()) { // Out of valid mip levels. Bail out. break; @@ -202,8 +208,13 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { } } - if (good) - levels_.push_back(level); + if (good) { + if (PrepareData(level, i)) { + levels_.push_back(level); + } else { + break; + } + } // Otherwise, we're done loading mips (bad PNG or bad size, either way.) else break; @@ -219,33 +230,18 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { return; } - // Populate the data pointer. - - std::unique_lock lock(mutex_); - - if (State() == ReplacementState::CANCEL_INIT) { - return; - } - - for (int i = 0; i < (int)levels_.size(); ++i) { - if (State() == ReplacementState::CANCEL_INIT) - break; - PrepareData(i); - } + SetState(ReplacementState::ACTIVE); if (threadWaitable_) threadWaitable_->Notify(); } -void ReplacedTexture::PrepareData(int level) { - _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); +bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { _assert_msg_(levelData_ != nullptr, "Level cache not set"); // We must lock around access to levelData_ in case two textures try to load it at once. std::lock_guard guard(levelData_->lock); - const ReplacedTextureLevel &info = levels_[level]; - if (levelData_->data.size() <= level) { levelData_->data.resize(level + 1); } @@ -254,8 +250,7 @@ void ReplacedTexture::PrepareData(int level) { // Already populated from cache. if (!out.empty()) { - SetState(ReplacementState::ACTIVE); - return; + return true; } ReplacedImageType imageType; @@ -276,14 +271,14 @@ void ReplacedTexture::PrepareData(int level) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); SetState(ReplacementState::NOT_FOUND); cleanup(); - return; + return false; } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); - return; + return false; } int w, h, f; @@ -293,7 +288,7 @@ void ReplacedTexture::PrepareData(int level) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); - return; + return false; } out.resize(info.w * info.h * 4); @@ -322,13 +317,13 @@ void ReplacedTexture::PrepareData(int level) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); SetState(ReplacementState::NOT_FOUND); cleanup(); - return; + return false; } if (png.width > (uint32_t)info.w || png.height > (uint32_t)info.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); - return; + return false; } bool checkedAlpha = false; @@ -347,7 +342,7 @@ void ReplacedTexture::PrepareData(int level) { SetState(ReplacementState::NOT_FOUND); cleanup(); out.resize(0); - return; + return false; } png_image_free(&png); @@ -360,8 +355,8 @@ void ReplacedTexture::PrepareData(int level) { } } - SetState(ReplacementState::ACTIVE); cleanup(); + return true; } void ReplacedTexture::PurgeIfOlder(double t) { diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 93ff79b613..ebd4a323d6 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -134,7 +134,7 @@ struct ReplacedTexture { private: void Prepare(VFSBackend *vfs); - void PrepareData(int level); + bool PrepareData(const ReplacedTextureLevel &info, int level); void PurgeIfOlder(double t); bool PopulateLevel(ReplacedTextureLevel & level, bool ignoreError); From 6ece79c3fae7dbb5f267862141a13a02872c5083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 21:06:33 +0100 Subject: [PATCH 276/424] Move PopulateLevel and PrepareData next to each other, for later merging --- GPU/Common/ReplacedTexture.cpp | 98 +++++++++++++++++----------------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index ac09a4d05e..e913534b94 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -110,55 +110,6 @@ void ReplacedTexture::FinishPopulate(ReplacementDesc *desc) { // TODO: What used to be here is now done on the thread task. } -bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { - bool good = false; - - if (!level.fileRef) { - if (!ignoreError) - ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); - return false; - } - - size_t fileSize; - VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef, &fileSize); - if (!file) { - return false; - } - - std::string magic; - auto imageType = Identify(vfs_, file, &magic); - - if (imageType == ReplacedImageType::ZIM) { - uint32_t ignore = 0; - struct ZimHeader { - uint32_t magic; - uint32_t w; - uint32_t h; - uint32_t flags; - } header; - good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); - level.w = header.w; - level.h = header.h; - good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; - } else if (imageType == ReplacedImageType::PNG) { - PNGHeaderPeek headerPeek; - good = vfs_->Read(file, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); - if (good && headerPeek.IsValidPNGHeader()) { - level.w = headerPeek.Width(); - level.h = headerPeek.Height(); - good = true; - } else { - ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); - good = false; - } - } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); - } - vfs_->CloseFile(file); - - return good; -} - void ReplacedTexture::Prepare(VFSBackend *vfs) { this->vfs_ = vfs; @@ -236,6 +187,55 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { threadWaitable_->Notify(); } +bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { + bool good = false; + + if (!level.fileRef) { + if (!ignoreError) + ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); + return false; + } + + size_t fileSize; + VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef, &fileSize); + if (!file) { + return false; + } + + std::string magic; + auto imageType = Identify(vfs_, file, &magic); + + if (imageType == ReplacedImageType::ZIM) { + uint32_t ignore = 0; + struct ZimHeader { + uint32_t magic; + uint32_t w; + uint32_t h; + uint32_t flags; + } header; + good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); + level.w = header.w; + level.h = header.h; + good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; + } else if (imageType == ReplacedImageType::PNG) { + PNGHeaderPeek headerPeek; + good = vfs_->Read(file, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); + if (good && headerPeek.IsValidPNGHeader()) { + level.w = headerPeek.Width(); + level.h = headerPeek.Height(); + good = true; + } else { + ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); + good = false; + } + } else { + ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); + } + vfs_->CloseFile(file); + + return good; +} + bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { _assert_msg_(levelData_ != nullptr, "Level cache not set"); From 265ae5d0e91b4d7246ad28773a645575f4999b89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 23:28:11 +0100 Subject: [PATCH 277/424] Make the two methods more compatible --- GPU/Common/ReplacedTexture.cpp | 85 +++++++++++++++++----------------- GPU/Common/ReplacedTexture.h | 2 +- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index e913534b94..e296f821b6 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -115,6 +115,11 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { std::unique_lock lock(mutex_); + _assert_msg_(levelData_ != nullptr, "Level cache not set"); + + // We must lock around access to levelData_ in case two textures try to load it at once. + std::lock_guard guard(levelData_->lock); + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_->filenames.size()); ++i) { if (State() == ReplacementState::CANCEL_INIT) { break; @@ -145,19 +150,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { bool good; level.fileRef = fileRef; - good = PopulateLevel(level, false); - - // We pad files that have been hashrange'd so they are the same texture size. - level.w = (level.w * desc_->w) / desc_->newW; - level.h = (level.h * desc_->h) / desc_->newH; - - if (good && i != 0) { - // Check that the mipmap size is correct. Can't load mips of the wrong size. - if (level.w != (levels_[0].w >> i) || level.h != (levels_[0].h >> i)) { - WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d, '%s')", level.w, level.h, levels_[0].w >> i, levels_[0].h >> i, i, filename.c_str()); - good = false; - } - } + good = PopulateLevel(level, i, false); if (good) { if (PrepareData(level, i)) { @@ -187,7 +180,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { threadWaitable_->Notify(); } -bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreError) { +bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, int mipLevel, bool ignoreError) { bool good = false; if (!level.fileRef) { @@ -233,20 +226,28 @@ bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, bool ignoreErro } vfs_->CloseFile(file); + // We pad files that have been hashrange'd so they are the same texture size. + level.w = (level.w * desc_->w) / desc_->newW; + level.h = (level.h * desc_->h) / desc_->newH; + + if (good && mipLevel != 0) { + // Check that the mipmap size is correct. Can't load mips of the wrong size. + if (level.w != (levels_[0].w >> mipLevel) || level.h != (levels_[0].h >> mipLevel)) { + WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d)", + level.w, level.h, levels_[0].w >> mipLevel, levels_[0].h >> mipLevel, mipLevel); + good = false; + } + } + return good; } -bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { - _assert_msg_(levelData_ != nullptr, "Level cache not set"); - - // We must lock around access to levelData_ in case two textures try to load it at once. - std::lock_guard guard(levelData_->lock); - - if (levelData_->data.size() <= level) { - levelData_->data.resize(level + 1); +bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &level, int mipLevel) { + if (levelData_->data.size() <= mipLevel) { + levelData_->data.resize(mipLevel + 1); } - std::vector &out = levelData_->data[level]; + std::vector &out = levelData_->data[mipLevel]; // Already populated from cache. if (!out.empty()) { @@ -256,7 +257,7 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { ReplacedImageType imageType; size_t fileSize; - VFSOpenFile *openFile = vfs_->OpenFileForRead(info.fileRef, &fileSize); + VFSOpenFile *openFile = vfs_->OpenFileForRead(level.fileRef, &fileSize); std::string magic; imageType = Identify(vfs_, openFile, &magic); @@ -275,7 +276,7 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", info.file.c_str()); + ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", level.file.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; @@ -284,26 +285,26 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { int w, h, f; uint8_t *image; if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { - if (w > info.w || h > info.h) { - ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); + if (w > level.w || h > level.h) { + ERROR_LOG(G3D, "Texture replacement changed since header read: %s", level.file.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } - out.resize(info.w * info.h * 4); - if (w == info.w) { - memcpy(&out[0], image, info.w * 4 * info.h); + out.resize(level.w * level.h * 4); + if (w == level.w) { + memcpy(&out[0], image, level.w * 4 * level.h); } else { for (int y = 0; y < h; ++y) { - memcpy(&out[info.w * 4 * y], image + w * 4 * y, w * 4); + memcpy(&out[level.w * 4 * y], image + w * 4 * y, w * 4); } } free(image); } - CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], info.w, w, h, 0xFF000000); - if (res == CHECKALPHA_ANY || level == 0) { + CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], level.w, w, h, 0xFF000000); + if (res == CHECKALPHA_ANY || mipLevel == 0) { alphaStatus_ = ReplacedTextureAlpha(res); } } else if (imageType == ReplacedImageType::PNG) { @@ -314,13 +315,13 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { pngdata.resize(fileSize); pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", info.file.c_str(), png.message); + ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", level.file.c_str(), png.message); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } - if (png.width > (uint32_t)info.w || png.height > (uint32_t)info.h) { - ERROR_LOG(G3D, "Texture replacement changed since header read: %s", info.file.c_str()); + if (png.width > (uint32_t)level.w || png.height > (uint32_t)level.h) { + ERROR_LOG(G3D, "Texture replacement changed since header read: %s", level.file.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; @@ -329,16 +330,16 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { bool checkedAlpha = false; if ((png.format & PNG_FORMAT_FLAG_ALPHA) == 0) { // Well, we know for sure it doesn't have alpha. - if (level == 0) { + if (mipLevel == 0) { alphaStatus_ = ReplacedTextureAlpha::FULL; } checkedAlpha = true; } png.format = PNG_FORMAT_RGBA; - out.resize(info.w * info.h * 4); - if (!png_image_finish_read(&png, nullptr, &out[0], info.w * 4, nullptr)) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", info.file.c_str(), png.message); + out.resize(level.w * level.h * 4); + if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { + ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", level.file.c_str(), png.message); SetState(ReplacementState::NOT_FOUND); cleanup(); out.resize(0); @@ -348,8 +349,8 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &info, int level) { if (!checkedAlpha) { // This will only check the hashed bits. - CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], info.w, png.width, png.height, 0xFF000000); - if (res == CHECKALPHA_ANY || level == 0) { + CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], level.w, png.width, png.height, 0xFF000000); + if (res == CHECKALPHA_ANY || mipLevel == 0) { alphaStatus_ = ReplacedTextureAlpha(res); } } diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index ebd4a323d6..98b4a8c941 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -137,7 +137,7 @@ private: bool PrepareData(const ReplacedTextureLevel &info, int level); void PurgeIfOlder(double t); - bool PopulateLevel(ReplacedTextureLevel & level, bool ignoreError); + bool PopulateLevel(ReplacedTextureLevel &level, int mipLevel, bool ignoreError); std::vector levels_; ReplacedLevelsCache *levelData_ = nullptr; From 3dc2463b5529c2f24ec659b3ba54e584611b519f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 23:36:00 +0100 Subject: [PATCH 278/424] Simplify, avoid opening file twice (still rewinding!) --- GPU/Common/ReplacedTexture.cpp | 54 +++++++++++----------------------- GPU/Common/ReplacedTexture.h | 4 +-- 2 files changed, 18 insertions(+), 40 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index e296f821b6..ac5e54f599 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -147,21 +147,14 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { fmt = Draw::DataFormat::R8G8B8A8_UNORM; } - bool good; - level.fileRef = fileRef; - good = PopulateLevel(level, i, false); - if (good) { - if (PrepareData(level, i)) { - levels_.push_back(level); - } else { - break; - } - } - // Otherwise, we're done loading mips (bad PNG or bad size, either way.) - else + if (LoadLevelData(level, i)) { + levels_.push_back(level); + } else { + // Otherwise, we're done loading mips (bad PNG or bad size, either way.) break; + } } delete desc_; @@ -180,23 +173,17 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { threadWaitable_->Notify(); } -bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, int mipLevel, bool ignoreError) { +bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { bool good = false; - if (!level.fileRef) { - if (!ignoreError) - ERROR_LOG(G3D, "Error opening replacement texture file '%s' in textures.zip", level.file.c_str()); - return false; - } - size_t fileSize; - VFSOpenFile *file = vfs_->OpenFileForRead(level.fileRef, &fileSize); - if (!file) { + VFSOpenFile *openFile = vfs_->OpenFileForRead(level.fileRef, &fileSize); + if (!openFile) { return false; } std::string magic; - auto imageType = Identify(vfs_, file, &magic); + ReplacedImageType imageType = Identify(vfs_, openFile, &magic); if (imageType == ReplacedImageType::ZIM) { uint32_t ignore = 0; @@ -206,13 +193,13 @@ bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, int mipLevel, b uint32_t h; uint32_t flags; } header; - good = vfs_->Read(file, &header, sizeof(header)) == sizeof(header); + good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); level.w = header.w; level.h = header.h; good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; } else if (imageType == ReplacedImageType::PNG) { PNGHeaderPeek headerPeek; - good = vfs_->Read(file, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); + good = vfs_->Read(openFile, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); if (good && headerPeek.IsValidPNGHeader()) { level.w = headerPeek.Width(); level.h = headerPeek.Height(); @@ -224,9 +211,8 @@ bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, int mipLevel, b } else { ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); } - vfs_->CloseFile(file); - // We pad files that have been hashrange'd so they are the same texture size. + // Is this really the right place to do it? level.w = (level.w * desc_->w) / desc_->newW; level.h = (level.h * desc_->h) / desc_->newH; @@ -239,10 +225,10 @@ bool ReplacedTexture::PopulateLevel(ReplacedTextureLevel &level, int mipLevel, b } } - return good; -} + if (!good) { + return false; + } -bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &level, int mipLevel) { if (levelData_->data.size() <= mipLevel) { levelData_->data.resize(mipLevel + 1); } @@ -254,18 +240,12 @@ bool ReplacedTexture::PrepareData(const ReplacedTextureLevel &level, int mipLeve return true; } - ReplacedImageType imageType; - - size_t fileSize; - VFSOpenFile *openFile = vfs_->OpenFileForRead(level.fileRef, &fileSize); - - std::string magic; - imageType = Identify(vfs_, openFile, &magic); - auto cleanup = [&] { vfs_->CloseFile(openFile); }; + vfs_->Rewind(openFile); + if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 98b4a8c941..56868d5689 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -134,11 +134,9 @@ struct ReplacedTexture { private: void Prepare(VFSBackend *vfs); - bool PrepareData(const ReplacedTextureLevel &info, int level); + bool LoadLevelData(ReplacedTextureLevel &info, int level); void PurgeIfOlder(double t); - bool PopulateLevel(ReplacedTextureLevel &level, int mipLevel, bool ignoreError); - std::vector levels_; ReplacedLevelsCache *levelData_ = nullptr; From 8e3428438ecd59da127c66ef83fd552aeae28ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 10 Mar 2023 23:58:15 +0100 Subject: [PATCH 279/424] Replacement: Fix mip level loading. Fix bug if LoadIni gets rerun for some reason. --- GPU/Common/TextureCacheCommon.cpp | 3 ++- GPU/Common/TextureReplacer.cpp | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 5c056eb87f..d852267f5c 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2829,8 +2829,9 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (plan.replaceValid) { // We're replacing, so we won't scale. plan.scaleFactor = 1; + // We're ignoring how many levels were specified - instead we just load all available from the replacer. plan.levelsToLoad = plan.replaced->NumLevels(); - plan.levelsToCreate = std::min(plan.levelsToLoad, plan.levelsToCreate); + plan.levelsToCreate = plan.levelsToLoad; // Or more, if we wanted to generate. plan.badMipSizes = false; // But, we still need to create the texture at a larger size. plan.replaced->GetSize(0, &plan.createW, &plan.createH); diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 1ce1fd62ca..0a3889c062 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -191,6 +191,13 @@ bool TextureReplacer::LoadIni() { } vfs_ = dir; + + // If we have stuff loaded from before, need to update the vfs pointers to avoid + // crash on exit. The actual problem is that we tend to call LoadIni a little too much... + for (auto &repl : cache_) { + repl.second->vfs_ = vfs_; + } + INFO_LOG(G3D, "Texture pack activated from '%s'", basePath_.c_str()); // The ini doesn't have to exist for the texture directory or zip to be valid. From f936a6e9cee23d668158ded1693116043447d007 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 26 Feb 2023 19:51:59 +0100 Subject: [PATCH 280/424] Structs and enums and build files --- CMakeLists.txt | 2 + Common/Common.vcxproj | 2 + Common/Common.vcxproj.filters | 6 +++ Common/Data/Format/DDSLoad.cpp | 5 ++ Common/Data/Format/DDSLoad.h | 69 +++++++++++++++++++++++++ Common/GPU/D3D11/thin3d_d3d11.cpp | 7 ++- Common/GPU/D3D9/thin3d_d3d9.cpp | 3 ++ Common/GPU/DataFormat.h | 29 +++++------ Common/GPU/OpenGL/DataFormatGL.cpp | 44 ++++++++++++++++ Common/GPU/Vulkan/thin3d_vulkan.cpp | 28 ++++++++-- Common/GPU/thin3d.cpp | 25 +++++++++ GPU/Common/ReplacedTexture.cpp | 29 +++++++++++ GPU/Common/ReplacedTexture.h | 3 +- GPU/Common/TextureCacheCommon.cpp | 2 + GPU/Common/TextureReplacer.cpp | 25 --------- GPU/D3D11/TextureCacheD3D11.cpp | 13 +++-- UWP/CommonUWP/CommonUWP.vcxproj | 2 + UWP/CommonUWP/CommonUWP.vcxproj.filters | 6 +++ android/jni/Android.mk | 2 + libretro/Makefile.common | 1 + 20 files changed, 252 insertions(+), 51 deletions(-) create mode 100644 Common/Data/Format/DDSLoad.cpp create mode 100644 Common/Data/Format/DDSLoad.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 25505d597c..9056de3389 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -571,6 +571,8 @@ add_library(Common STATIC Common/Data/Format/JSONReader.cpp Common/Data/Format/JSONWriter.h Common/Data/Format/JSONWriter.cpp + Common/Data/Format/DDSLoad.cpp + Common/Data/Format/DDSLoad.h Common/Data/Format/PNGLoad.cpp Common/Data/Format/PNGLoad.h Common/Data/Format/ZIMLoad.cpp diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 8557f133d3..90d8d0d872 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -405,6 +405,7 @@ + @@ -844,6 +845,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 0f40093153..053702cd0a 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -470,6 +470,9 @@ File\VFS + + Data\Format + @@ -890,6 +893,9 @@ File\VFS + + Data\Format + diff --git a/Common/Data/Format/DDSLoad.cpp b/Common/Data/Format/DDSLoad.cpp new file mode 100644 index 0000000000..1d3bdb4d1d --- /dev/null +++ b/Common/Data/Format/DDSLoad.cpp @@ -0,0 +1,5 @@ +#include "Common/Data/Format/DDSLoad.h" + +bool DetectDDSParams(const DDSHeader *header, DDSLoadInfo *info) { + return false; +} diff --git a/Common/Data/Format/DDSLoad.h b/Common/Data/Format/DDSLoad.h new file mode 100644 index 0000000000..9862854b95 --- /dev/null +++ b/Common/Data/Format/DDSLoad.h @@ -0,0 +1,69 @@ +#pragma once + +#include + +// DDSPixelFormat.dwFlags bits +enum { + DDPF_ALPHAPIXELS = 1, // Texture contains alpha data; dwRGBAlphaBitMask contains valid data. + DDPF_ALPHA = 2, // Used in some older DDS files for alpha channel only uncompressed data(dwRGBBitCount contains the alpha channel bitcount; dwABitMask contains valid data) + DDPF_FOURCC = 4, // Texture contains compressed RGB data; dwFourCC contains valid data. 0x4 + DDPF_RGB = 8, // Texture contains uncompressed RGB data; dwRGBBitCount and the RGB masks(dwRBitMask, dwGBitMask, dwBBitMask) contain valid data. 0x40 + DDPF_YUV = 16, //Used in some older DDS files for YUV uncompressed data(dwRGBBitCount contains the YUV bit count; dwRBitMask contains the Y mask, dwGBitMask contains the U mask, dwBBitMask contains the V mask) + DDPF_LUMINANCE = 32, // Used in some older DDS files for single channel color uncompressed data (dwRGBBitCount contains the luminance channel bit count; dwRBitMask contains the channel mask). Can be combined with DDPF_ALPHAPIXELS for a two channel DDS file. +}; + +// dwCaps members +enum { + DDSCAPS_COMPLEX = 8, + DDSCAPS_MIPMAP = 0x400000, + DDSCAPS_TEXTURE = 0x1000, // Required +}; + +// Not using any D3D headers here, this is cross platform and minimal. +// Boiled down from the public documentation. +struct DDSPixelFormat { + uint32_t dwSize; // must be 32 + uint32_t dwFlags; + uint32_t dwFourCC; + uint32_t dwRGBBitCount; + uint32_t dwRBitMask; + uint32_t dwGBitMask; + uint32_t dwBBitMask; + uint32_t dwABitMask; +}; + +struct DDSHeader { + uint32_t dwMagic; // Magic is not technically part of the header struct but convenient to have here when reading the files. + uint32_t dwSize; // must be 124 + uint32_t dwFlags; + uint32_t dwHeight; + uint32_t dwWidth; + uint32_t dwPitchOrLinearSize; // The pitch or number of bytes per scan line in an uncompressed texture; the total number of bytes in the top level texture for a compressed texture + uint32_t dwDepth; // we'll always use 1 here + uint32_t dwMipMapCount; + uint32_t dwReserved1[11]; + DDSPixelFormat ddspf; + uint32_t dwCaps; + uint32_t dwCaps2; // nothing we care about + uint32_t dwCaps3; // unused + uint32_t dwCaps4; // unused + uint32_t dwReserved2; +}; + +// DDS header extension to handle resource arrays, DXGI pixel formats that don't map to the legacy Microsoft DirectDraw pixel format structures, and additional metadata. +struct DDSHeaderDXT10 { + uint32_t dxgiFormat; + uint32_t resourceDimension; // 1d = 2, 2d = 3, 3d = 4. very intuitive + uint32_t miscFlag; + uint32_t arraySize; // we only support 1 here + uint32_t miscFlags2; // sets alpha interpretation, let's not bother +}; + +// Simple DDS parser, suitable for texture replacement packs. +// Doesn't actually load, only does some logic to fill out DDSLoadInfo so the caller can then +// do the actual load with a simple series of memcpys or whatever is appropriate. +struct DDSLoadInfo { + uint32_t bytesToCopy; +}; + +bool DetectDDSParams(const DDSHeader *header, DDSLoadInfo *info); diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp index 120f8db5ea..58d5a59397 100644 --- a/Common/GPU/D3D11/thin3d_d3d11.cpp +++ b/Common/GPU/D3D11/thin3d_d3d11.cpp @@ -491,7 +491,12 @@ static DXGI_FORMAT dataFormatToD3D11(DataFormat format) { case DataFormat::D16: return DXGI_FORMAT_D16_UNORM; case DataFormat::D32F: return DXGI_FORMAT_D32_FLOAT; case DataFormat::D32F_S8: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; - case DataFormat::ETC1: + case DataFormat::BC1_RGBA_UNORM_BLOCK: return DXGI_FORMAT_BC1_UNORM; + case DataFormat::BC2_UNORM_BLOCK: return DXGI_FORMAT_BC2_UNORM; + case DataFormat::BC3_UNORM_BLOCK: return DXGI_FORMAT_BC3_UNORM; + case DataFormat::BC4_UNORM_BLOCK: return DXGI_FORMAT_BC4_UNORM; + case DataFormat::BC5_UNORM_BLOCK: return DXGI_FORMAT_BC5_UNORM; + case DataFormat::BC7_UNORM_BLOCK: return DXGI_FORMAT_BC7_UNORM; default: return DXGI_FORMAT_UNKNOWN; } diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index b130aae436..2a90648abc 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -125,6 +125,9 @@ D3DFORMAT FormatToD3DFMT(DataFormat fmt) { case DataFormat::A1R5G5B5_UNORM_PACK16: return D3DFMT_A1R5G5B5; case DataFormat::D24_S8: return D3DFMT_D24S8; case DataFormat::D16: return D3DFMT_D16; + case DataFormat::BC1_RGBA_UNORM_BLOCK: return D3DFMT_DXT1; + case DataFormat::BC2_UNORM_BLOCK: return D3DFMT_DXT3; // DXT3 is indeed BC2. + case DataFormat::BC3_UNORM_BLOCK: return D3DFMT_DXT5; // DXT5 is indeed BC3 default: return D3DFMT_UNKNOWN; } } diff --git a/Common/GPU/DataFormat.h b/Common/GPU/DataFormat.h index 32463d3a16..6f5cd2bc2e 100644 --- a/Common/GPU/DataFormat.h +++ b/Common/GPU/DataFormat.h @@ -46,22 +46,20 @@ enum class DataFormat : uint8_t { // Block compression formats. // These are modern names for DXT and friends, now patent free. // https://msdn.microsoft.com/en-us/library/bb694531.aspx - BC1_RGBA_UNORM_BLOCK, - BC1_RGBA_SRGB_BLOCK, - BC2_UNORM_BLOCK, // 4-bit straight alpha + DXT1 color. Usually not worth using - BC2_SRGB_BLOCK, - BC3_UNORM_BLOCK, // 3-bit alpha with 2 ref values (+ magic) + DXT1 color - BC3_SRGB_BLOCK, - BC4_UNORM_BLOCK, // 1-channel, same storage as BC3 alpha - BC4_SNORM_BLOCK, - BC5_UNORM_BLOCK, // 2-channel RG, each has same storage as BC3 alpha - BC5_SNORM_BLOCK, - BC6H_UFLOAT_BLOCK, // TODO - BC6H_SFLOAT_BLOCK, - BC7_UNORM_BLOCK, // Highly advanced, very expensive to compress, very good quality. - BC7_SRGB_BLOCK, + BC1_RGBA_UNORM_BLOCK, // 64 bits per 4x4 block. Used by Basis, along with ETC2_R8G8B8_UNORM_BLOCK. + BC2_UNORM_BLOCK, // 4-bit straight alpha + DXT1 color. 128 bits per block. Usually not worth using + BC3_UNORM_BLOCK, // 3-bit alpha with 2 ref values (+ magic) + DXT1 color. 128 bits per block. + BC4_UNORM_BLOCK, // 1-channel, same storage as BC3 alpha. 64 bits per block. + BC5_UNORM_BLOCK, // 2-channel RG, each has same storage as BC3 alpha. 128 bits per block. + BC7_UNORM_BLOCK, // Highly advanced RGBA, very expensive to compress, very good quality. 128 bits per block. - ETC1, + // Ericsson texture compression. + ETC2_R8G8B8_UNORM_BLOCK, // Color-only, 64 bits per 4x4 block. + ETC2_R8G8B8A1_UNORM_BLOCK, // Color + alpha, 128 bits per 4x4 block. + ETC2_R8G8B8A8_UNORM_BLOCK, // Color + alpha, 128 bits per 4x4 block. + + // This is the one ASTC format used by UASTC / basis Universal. + ASTC_4x4_UNORM_BLOCK, S8, D16, @@ -76,6 +74,7 @@ bool DataFormatIsDepthStencil(DataFormat fmt); inline bool DataFormatIsColor(DataFormat fmt) { return !DataFormatIsDepthStencil(fmt); } +bool DataFormatIsBlockCompressed(DataFormat fmt, int *blockSize); // Limited format support for now. const char *DataFormatToString(DataFormat fmt); diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp index 1b2af548d8..5f4e6b17a8 100644 --- a/Common/GPU/OpenGL/DataFormatGL.cpp +++ b/Common/GPU/OpenGL/DataFormatGL.cpp @@ -86,6 +86,50 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin alignment = 16; break; + case DataFormat::BC1_RGBA_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + format = GL_RGB; + type = GL_FLOAT; + alignment = 8; + break; + +#if PPSSPP_PLATFORM(WINDOWS) + case DataFormat::BC7_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; + format = GL_RGBA; + type = GL_FLOAT; + alignment = 16; + break; +#endif + + case DataFormat::ETC2_R8G8B8_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGB8_ETC2; + format = GL_RGB; + type = GL_FLOAT; + alignment = 8; + break; + + case DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + format = GL_RGBA; + type = GL_FLOAT; + alignment = 16; + break; + + case DataFormat::ETC2_R8G8B8A8_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; + format = GL_RGBA; + type = GL_FLOAT; + alignment = 16; + break; + + case DataFormat::ASTC_4x4_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR; + format = GL_RGBA; + type = GL_FLOAT; + alignment = 16; + break; + default: return false; } diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 2d58bebdc8..ce76c90af2 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -560,6 +560,7 @@ private: uint8_t stencilCompareMask_ = 0xFF; }; +// Bits per pixel, not bytes. static int GetBpp(VkFormat format) { switch (format) { case VK_FORMAT_R8G8B8A8_UNORM: @@ -582,6 +583,21 @@ static int GetBpp(VkFormat format) { return 32; case VK_FORMAT_D16_UNORM: return 16; + case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: + return 4; + case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: + case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: + return 8; + case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: + return 8; + case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: + return 4; + case VK_FORMAT_BC2_UNORM_BLOCK: + case VK_FORMAT_BC3_UNORM_BLOCK: + case VK_FORMAT_BC4_UNORM_BLOCK: + case VK_FORMAT_BC5_UNORM_BLOCK: + case VK_FORMAT_BC7_UNORM_BLOCK: + return 8; default: return 0; } @@ -625,13 +641,15 @@ static VkFormat DataFormatToVulkan(DataFormat format) { case DataFormat::BC2_UNORM_BLOCK: return VK_FORMAT_BC2_UNORM_BLOCK; case DataFormat::BC3_UNORM_BLOCK: return VK_FORMAT_BC3_UNORM_BLOCK; case DataFormat::BC4_UNORM_BLOCK: return VK_FORMAT_BC4_UNORM_BLOCK; - case DataFormat::BC4_SNORM_BLOCK: return VK_FORMAT_BC4_SNORM_BLOCK; case DataFormat::BC5_UNORM_BLOCK: return VK_FORMAT_BC5_UNORM_BLOCK; - case DataFormat::BC5_SNORM_BLOCK: return VK_FORMAT_BC5_SNORM_BLOCK; - case DataFormat::BC6H_SFLOAT_BLOCK: return VK_FORMAT_BC6H_SFLOAT_BLOCK; - case DataFormat::BC6H_UFLOAT_BLOCK: return VK_FORMAT_BC6H_UFLOAT_BLOCK; case DataFormat::BC7_UNORM_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK; - case DataFormat::BC7_SRGB_BLOCK: return VK_FORMAT_BC7_SRGB_BLOCK; + + case DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + case DataFormat::ETC2_R8G8B8A8_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + case DataFormat::ETC2_R8G8B8_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + + case DataFormat::ASTC_4x4_UNORM_BLOCK: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; + default: return VK_FORMAT_UNDEFINED; } diff --git a/Common/GPU/thin3d.cpp b/Common/GPU/thin3d.cpp index 83726b7391..f5dc4b452e 100644 --- a/Common/GPU/thin3d.cpp +++ b/Common/GPU/thin3d.cpp @@ -93,6 +93,31 @@ bool DataFormatIsDepthStencil(DataFormat fmt) { } } +// We don't bother listing the formats that are irrelevant for PPSSPP, like BC6 (HDR format) +// or weird-shaped ASTC formats. We only support 4x4 block size formats for now. +// If you pass in a blockSize parameter, it receives byte count that a 4x4 block takes in this format. +bool DataFormatIsBlockCompressed(DataFormat fmt, int *blockSize) { + switch (fmt) { + case DataFormat::BC1_RGBA_UNORM_BLOCK: + case DataFormat::BC4_UNORM_BLOCK: + case DataFormat::ETC2_R8G8B8_UNORM_BLOCK: + if (blockSize) *blockSize = 8; // 64 bits + return true; + case DataFormat::BC2_UNORM_BLOCK: + case DataFormat::BC3_UNORM_BLOCK: + case DataFormat::BC5_UNORM_BLOCK: + case DataFormat::BC7_UNORM_BLOCK: + case DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK: + case DataFormat::ETC2_R8G8B8A8_UNORM_BLOCK: + case DataFormat::ASTC_4x4_UNORM_BLOCK: + if (blockSize) *blockSize = 16; // 128 bits + return true; + default: + if (blockSize) *blockSize = 0; + return false; + } +} + RefCountedObject::~RefCountedObject() { _dbg_assert_(refcount_ == 0xDEDEDE); } diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index ac5e54f599..73c9e67d6e 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -31,6 +31,35 @@ #include "Common/Log.h" #include "Common/TimeUtil.h" +#define MK_FOURCC(str) (str[0] | ((uint8_t)str[1] << 8) | ((uint8_t)str[2] << 16) | ((uint8_t)str[3] << 24)) + +static ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { + if (strncmp((const char *)magic, "ZIMG", 4) == 0) + return ReplacedImageType::ZIM; + if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) + return ReplacedImageType::PNG; + if (strncmp((const char *)magic, "DDS ", 4) == 0) + return ReplacedImageType::DDS; + return ReplacedImageType::INVALID; +} + +static ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { + uint8_t magic[4]; + if (vfs->Read(openFile, magic, 4) != 4) { + *outMagic = "FAIL"; + return ReplacedImageType::INVALID; + } + // Turn the signature into a readable string that we can display in an error message. + *outMagic = std::string((const char *)magic, 4); + for (int i = 0; i < outMagic->size(); i++) { + if ((s8)(*outMagic)[i] < 32) { + (*outMagic)[i] = '_'; + } + } + vfs->Rewind(openFile); + return IdentifyMagic(magic); +} + class ReplacedTextureTask : public Task { public: ReplacedTextureTask(VFSBackend *vfs, ReplacedTexture &tex, LimitedWaitable *w) : vfs_(vfs), tex_(tex), waitable_(w) {} diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 56868d5689..c3891d3668 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -44,6 +44,7 @@ enum class ReplacedTextureHash { enum class ReplacedImageType { PNG, ZIM, + DDS, INVALID, }; @@ -60,8 +61,6 @@ struct ReplacedTextureLevel { VFSFileReference *fileRef = nullptr; }; -ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic); - enum class ReplacementState : uint32_t { UNINITIALIZED, POPULATED, // We located the texture files but have not started the thread. diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index d852267f5c..dbda83389d 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1550,6 +1550,8 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & // Make sure we keep polling. entry->status |= TexCacheEntry::STATUS_TO_REPLACE; break; + default: + break; } replacementTimeThisFrame_ += time_now_d() - replaceStart; return replaced; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 0a3889c062..6c94b76f73 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -54,31 +54,6 @@ static const std::string NEW_TEXTURE_DIR = "new/"; static const int VERSION = 1; static const double MAX_CACHE_SIZE = 4.0; -static inline ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { - if (strncmp((const char *)magic, "ZIMG", 4) == 0) - return ReplacedImageType::ZIM; - if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) - return ReplacedImageType::PNG; - return ReplacedImageType::INVALID; -} - -ReplacedImageType Identify(VFSBackend *vfs, VFSOpenFile *openFile, std::string *outMagic) { - uint8_t magic[4]; - if (vfs->Read(openFile, magic, 4) != 4) { - *outMagic = "FAIL"; - return ReplacedImageType::INVALID; - } - // Turn the signature into a readable string that we can display in an error message. - *outMagic = std::string((const char *)magic, 4); - for (int i = 0; i < outMagic->size(); i++) { - if ((s8)(*outMagic)[i] < 32) { - (*outMagic)[i] = '_'; - } - } - vfs->Rewind(openFile); - return IdentifyMagic(magic); -} - TextureReplacer::TextureReplacer(Draw::DrawContext *draw) { // TODO: Check draw for supported texture formats. } diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 90d1927898..1d2973ae48 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -56,7 +56,7 @@ static const D3D11_INPUT_ELEMENT_DESC g_QuadVertexElements[] = { // NOTE: In the D3D backends, we flip R and B in the shaders, so while these look wrong, they're OK. -Draw::DataFormat FromD3D11Format(u32 fmt) { +static Draw::DataFormat FromD3D11Format(u32 fmt) { switch (fmt) { case DXGI_FORMAT_B4G4R4A4_UNORM: return Draw::DataFormat::A4R4G4B4_UNORM_PACK16; @@ -72,9 +72,16 @@ Draw::DataFormat FromD3D11Format(u32 fmt) { } } -DXGI_FORMAT ToDXGIFormat(Draw::DataFormat fmt) { +static DXGI_FORMAT ToDXGIFormat(Draw::DataFormat fmt) { switch (fmt) { - case Draw::DataFormat::R8G8B8A8_UNORM: default: return DXGI_FORMAT_B8G8R8A8_UNORM; + case Draw::DataFormat::BC1_RGBA_UNORM_BLOCK: return DXGI_FORMAT_BC1_UNORM; + case Draw::DataFormat::BC2_UNORM_BLOCK: return DXGI_FORMAT_BC2_UNORM; + case Draw::DataFormat::BC3_UNORM_BLOCK: return DXGI_FORMAT_BC3_UNORM; + case Draw::DataFormat::BC4_UNORM_BLOCK: return DXGI_FORMAT_BC4_UNORM; + case Draw::DataFormat::BC5_UNORM_BLOCK: return DXGI_FORMAT_BC5_UNORM; + case Draw::DataFormat::BC7_UNORM_BLOCK: return DXGI_FORMAT_BC7_UNORM; + case Draw::DataFormat::R8G8B8A8_UNORM: return DXGI_FORMAT_B8G8R8A8_UNORM; + default: _dbg_assert_(false); return DXGI_FORMAT_UNKNOWN; } } diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 6160d923d6..b6c7e04111 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -272,6 +272,7 @@ + @@ -418,6 +419,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index 40b8f80da4..63bccb6fcf 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -420,6 +420,9 @@ UI + + Data\Format + @@ -778,6 +781,9 @@ UI + + Data\Format + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 57b695f3e5..6ff34b212f 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -163,6 +163,8 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Data/Format/IniFile.cpp \ $(SRC)/Common/Data/Format/JSONReader.cpp \ $(SRC)/Common/Data/Format/JSONWriter.cpp \ + $(SRC)/Common/Data/Format/DDSLoad.cpp \ + $(SRC)/Common/Data/Format/DDSLoad.h \ $(SRC)/Common/Data/Format/PNGLoad.cpp \ $(SRC)/Common/Data/Format/PNGLoad.h \ $(SRC)/Common/Data/Format/ZIMLoad.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 67149d94d4..3908a3bd08 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -261,6 +261,7 @@ SOURCES_CXX += \ $(COMMONDIR)/Data/Format/IniFile.cpp \ $(COMMONDIR)/Data/Format/JSONReader.cpp \ $(COMMONDIR)/Data/Format/JSONWriter.cpp \ + $(COMMONDIR)/Data/Format/DDSLoad.cpp \ $(COMMONDIR)/Data/Format/PNGLoad.cpp \ $(COMMONDIR)/Data/Format/ZIMLoad.cpp \ $(COMMONDIR)/Data/Format/ZIMSave.cpp \ From 6a84d96a3c03c774cf9a8b43e5aa5f5f395fe5ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Mar 2023 11:34:28 +0100 Subject: [PATCH 281/424] Add actual support for DDS textures to the replacer. Vulkan only. --- GPU/Common/ReplacedTexture.cpp | 116 +++++++++++++++++++++++++----- GPU/Common/ReplacedTexture.h | 13 +++- GPU/Common/TextureReplacer.h | 6 -- GPU/Vulkan/TextureCacheVulkan.cpp | 24 ++++++- 4 files changed, 132 insertions(+), 27 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 73c9e67d6e..116a8e2de8 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -23,6 +23,7 @@ #include "GPU/Common/TextureReplacer.h" #include "Common/Data/Format/IniFile.h" +#include "Common/Data/Format/DDSLoad.h" #include "Common/Data/Format/ZIMLoad.h" #include "Common/Data/Format/PNGLoad.h" #include "Common/Thread/ParallelLoop.h" @@ -178,7 +179,16 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { level.fileRef = fileRef; - if (LoadLevelData(level, i)) { + Draw::DataFormat pixelFormat; + if (LoadLevelData(level, i, &pixelFormat)) { + if (i == 0) { + fmt = pixelFormat; + } else { + if (fmt != pixelFormat) { + ERROR_LOG(G3D, "Replacement mipmap %d doesn't have the same pixel format as mipmap 0. Stopping.", i); + break; + } + } levels_.push_back(level); } else { // Otherwise, we're done loading mips (bad PNG or bad size, either way.) @@ -202,7 +212,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { threadWaitable_->Notify(); } -bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { +bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, Draw::DataFormat *pixelFormat) { bool good = false; size_t fileSize; @@ -214,7 +224,55 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { std::string magic; ReplacedImageType imageType = Identify(vfs_, openFile, &magic); - if (imageType == ReplacedImageType::ZIM) { + if (imageType == ReplacedImageType::DDS) { + DDSHeader header; + DDSHeaderDXT10 header10{}; + good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); + + *pixelFormat = Draw::DataFormat::UNDEFINED; + u32 format; + if (good && (header.ddspf.dwFlags & DDPF_FOURCC)) { + char *fcc = (char *)&header.ddspf.dwFourCC; + INFO_LOG(G3D, "DDS fourcc: %c%c%c%c", fcc[0], fcc[1], fcc[2], fcc[3]); + if (header.ddspf.dwFourCC == 'DX10') { + good = good && vfs_->Read(openFile, &header10, sizeof(header10)) == sizeof(header10); + format = header10.dxgiFormat; + switch (format) { + case 98: // DXGI_FORMAT_BC7_UNORM: + case 99: // DXGI_FORMAT_BC7_UNORM_SRGB: + *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; + break; + default: + ERROR_LOG(G3D, "DDS pixel format not supported."); + good = false; + } + } else { + format = header.ddspf.dwFourCC; + // OK, there are a number of possible formats we might have ended up with. We choose just a few + // to support for now. + switch (format) { + case MK_FOURCC("DXT1"): + *pixelFormat = Draw::DataFormat::BC1_RGBA_UNORM_BLOCK; + break; + case MK_FOURCC("DXT3"): + *pixelFormat = Draw::DataFormat::BC2_UNORM_BLOCK; + break; + case MK_FOURCC("DXT5"): + *pixelFormat = Draw::DataFormat::BC3_UNORM_BLOCK; + break; + default: + ERROR_LOG(G3D, "DDS pixel format not supported."); + good = false; + } + } + } else if (good) { + ERROR_LOG(G3D, "DDS non-fourCC format not supported."); + good = false; + } + + level.w = header.dwWidth; + level.h = header.dwHeight; + } else if (imageType == ReplacedImageType::ZIM) { uint32_t ignore = 0; struct ZimHeader { uint32_t magic; @@ -225,7 +283,8 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); level.w = header.w; level.h = header.h; - good = (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; + good = good && (header.flags & ZIM_FORMAT_MASK) == ZIM_RGBA8888; + *pixelFormat = Draw::DataFormat::R8G8B8A8_UNORM; } else if (imageType == ReplacedImageType::PNG) { PNGHeaderPeek headerPeek; good = vfs_->Read(openFile, &headerPeek, sizeof(headerPeek)) == sizeof(headerPeek); @@ -237,6 +296,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); good = false; } + *pixelFormat = Draw::DataFormat::R8G8B8A8_UNORM; } else { ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); } @@ -275,7 +335,18 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { vfs_->Rewind(openFile); - if (imageType == ReplacedImageType::ZIM) { + if (imageType == ReplacedImageType::DDS) { + DDSHeader header; + DDSHeaderDXT10 header10{}; + vfs_->Read(openFile, &header, sizeof(header)); + // For compressed formats (we don't support uncompressed DDS files yet), this is supposed to be the linear size. + size_t bytes = header.dwPitchOrLinearSize; + out.resize(bytes); + size_t read_bytes = vfs_->Read(openFile, &out[0], bytes); + if (read_bytes != bytes) { + WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", bytes, read_bytes); + } + } else if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); @@ -363,6 +434,8 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel) { alphaStatus_ = ReplacedTextureAlpha(res); } } + } else { + WARN_LOG(G3D, "Don't know how to load this image type! %d", (int)imageType); } cleanup(); @@ -419,21 +492,28 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { return false; } - if (rowPitch < info.w * 4) { - ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); - return false; - } - _assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size"); + if (fmt == Draw::DataFormat::R8G8B8A8_UNORM) { + if (rowPitch < info.w * 4) { + ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); + return false; + } - if (rowPitch == info.w * 4) { - ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); + _assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size"); + + if (rowPitch == info.w * 4) { + ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); + } else { + const int MIN_LINES_PER_THREAD = 4; + ParallelRangeLoop(&g_threadManager, [&](int l, int h) { + for (int y = l; y < h; ++y) { + memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); + } + }, 0, info.h, MIN_LINES_PER_THREAD); + } } else { - const int MIN_LINES_PER_THREAD = 4; - ParallelRangeLoop(&g_threadManager, [&](int l, int h) { - for (int y = l; y < h; ++y) { - memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); - } - }, 0, info.h, MIN_LINES_PER_THREAD); + // TODO: Add sanity checks here for other formats? + // Just gonna do a memcpy, slightly scared of the parallel ones. + memcpy(out, data.data(), data.size()); } return true; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index c3891d3668..24bbef6662 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -87,6 +87,12 @@ struct ReplacementDesc { ReplacedLevelsCache *cache; }; +struct ReplacedLevelsCache { + std::mutex lock; + std::vector> data; + double lastUsed = 0.0; +}; + // These aren't actually all replaced, they can also represent a placeholder for a not-found // replacement (state_ == NOT_FOUND). struct ReplacedTexture { @@ -111,6 +117,11 @@ struct ReplacedTexture { *h = levels_[level].h; } + int GetLevelDataSize(int level) const { + _dbg_assert_(State() == ReplacementState::ACTIVE); + return (int)levelData_->data[level].size(); + } + int NumLevels() const { _dbg_assert_(State() == ReplacementState::ACTIVE); return (int)levels_.size(); @@ -133,7 +144,7 @@ struct ReplacedTexture { private: void Prepare(VFSBackend *vfs); - bool LoadLevelData(ReplacedTextureLevel &info, int level); + bool LoadLevelData(ReplacedTextureLevel &info, int level, Draw::DataFormat *pixelFormat); void PurgeIfOlder(double t); std::vector levels_; diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index ed0df878c9..4766351b2a 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -48,12 +48,6 @@ struct SavedTextureCacheData { double lastTimeSaved = 0.0; }; -struct ReplacedLevelsCache { - std::mutex lock; - std::vector> data; - double lastUsed = 0.0; -}; - struct ReplacementCacheKey { u64 cachekey; u32 hash; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 2ec829f511..20a8345c84 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -405,7 +405,14 @@ static Draw::DataFormat FromVulkanFormat(VkFormat fmt) { static VkFormat ToVulkanFormat(Draw::DataFormat fmt) { switch (fmt) { - case Draw::DataFormat::R8G8B8A8_UNORM: default: return VULKAN_8888_FORMAT; + case Draw::DataFormat::BC1_RGBA_UNORM_BLOCK: return VK_FORMAT_BC1_RGBA_UNORM_BLOCK; + case Draw::DataFormat::BC2_UNORM_BLOCK: return VK_FORMAT_BC2_UNORM_BLOCK; + case Draw::DataFormat::BC3_UNORM_BLOCK: return VK_FORMAT_BC3_UNORM_BLOCK; + case Draw::DataFormat::BC4_UNORM_BLOCK: return VK_FORMAT_BC4_UNORM_BLOCK; + case Draw::DataFormat::BC5_UNORM_BLOCK: return VK_FORMAT_BC5_UNORM_BLOCK; + case Draw::DataFormat::BC7_UNORM_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK; + case Draw::DataFormat::R8G8B8A8_UNORM: return VULKAN_8888_FORMAT; + default: _assert_msg_(false, "Bad texture pixel format"); return VULKAN_8888_FORMAT; } } @@ -442,8 +449,15 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // Any texture scaling is gonna move away from the original 16-bit format, if any. VkFormat actualFmt = plan.scaleFactor > 1 ? VULKAN_8888_FORMAT : dstFmt; + bool bcFormat = false; + int bcAlign = 0; if (plan.replaceValid) { - actualFmt = ToVulkanFormat(plan.replaced->Format()); + Draw::DataFormat fmt = plan.replaced->Format(); + bcFormat = Draw::DataFormatIsBlockCompressed(fmt, &bcAlign); + actualFmt = ToVulkanFormat(fmt); + if (actualFmt != VULKAN_8888_FORMAT) { + actualFmt = actualFmt; + } } bool computeUpload = false; @@ -570,6 +584,12 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { bool dataScaled = true; if (plan.replaceValid) { + int bufferRowLength = byteStride; + if (bcFormat) { + // For block compressed formats, we just set the upload size to the data size.. + uploadSize = plan.replaced->GetLevelDataSize(plan.baseLevelSrc + i); + bufferRowLength = mipWidth; + } // Directly load the replaced image. data = pushBuffer->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); double replaceStart = time_now_d(); From a98d2d5ecfee21e315ff751934baa85b9f5c4df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Mar 2023 11:42:41 +0100 Subject: [PATCH 282/424] Mac buildfix --- Common/GPU/OpenGL/DataFormatGL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp index 5f4e6b17a8..c53190bae2 100644 --- a/Common/GPU/OpenGL/DataFormatGL.cpp +++ b/Common/GPU/OpenGL/DataFormatGL.cpp @@ -86,6 +86,7 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin alignment = 16; break; +#if PPSSPP_PLATFORM(WINDOWS) case DataFormat::BC1_RGBA_UNORM_BLOCK: internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; format = GL_RGB; @@ -93,7 +94,6 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin alignment = 8; break; -#if PPSSPP_PLATFORM(WINDOWS) case DataFormat::BC7_UNORM_BLOCK: internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; format = GL_RGBA; From 996b685294b8fab54b588ad6a0c685e63485da56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Mar 2023 12:22:20 +0100 Subject: [PATCH 283/424] Fix BC7 textures --- GPU/Common/ReplacedTexture.cpp | 56 +++++++++++++++++++++++----------- GPU/Common/ReplacedTexture.h | 1 + 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 116a8e2de8..692a03465f 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -206,15 +206,26 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { return; } + levelData_->fmt = fmt; SetState(ReplacementState::ACTIVE); if (threadWaitable_) threadWaitable_->Notify(); } +inline uint32_t RoundUpTo4(uint32_t value) { + return (value + 3) & ~3; +} + bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, Draw::DataFormat *pixelFormat) { bool good = false; + if (levelData_->data.size() <= mipLevel) { + levelData_->data.resize(mipLevel + 1); + } + + std::vector &out = levelData_->data[mipLevel]; + size_t fileSize; VFSOpenFile *openFile = vfs_->OpenFileForRead(level.fileRef, &fileSize); if (!openFile) { @@ -224,6 +235,10 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D std::string magic; ReplacedImageType imageType = Identify(vfs_, openFile, &magic); + int ddsBytesToRead = 0; // Used by the DDS reader only. + bool ddsDX10 = false; + int numMips = 1; + if (imageType == ReplacedImageType::DDS) { DDSHeader header; DDSHeaderDXT10 header10{}; @@ -234,19 +249,22 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D if (good && (header.ddspf.dwFlags & DDPF_FOURCC)) { char *fcc = (char *)&header.ddspf.dwFourCC; INFO_LOG(G3D, "DDS fourcc: %c%c%c%c", fcc[0], fcc[1], fcc[2], fcc[3]); - if (header.ddspf.dwFourCC == 'DX10') { + if (header.ddspf.dwFourCC == MK_FOURCC("DX10")) { + ddsDX10 = true; good = good && vfs_->Read(openFile, &header10, sizeof(header10)) == sizeof(header10); format = header10.dxgiFormat; switch (format) { case 98: // DXGI_FORMAT_BC7_UNORM: case 99: // DXGI_FORMAT_BC7_UNORM_SRGB: + ddsBytesToRead = RoundUpTo4(header.dwWidth) * RoundUpTo4(header.dwHeight); // 1 byte per pixel so this should be right. *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; break; default: - ERROR_LOG(G3D, "DDS pixel format not supported."); + ERROR_LOG(G3D, "DXGI pixel format %d not supported.", header10.dxgiFormat); good = false; } } else { + ddsBytesToRead = header.dwPitchOrLinearSize; format = header.ddspf.dwFourCC; // OK, there are a number of possible formats we might have ended up with. We choose just a few // to support for now. @@ -272,6 +290,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D level.w = header.dwWidth; level.h = header.dwHeight; + numMips = header.dwMipMapCount; } else if (imageType == ReplacedImageType::ZIM) { uint32_t ignore = 0; struct ZimHeader { @@ -301,6 +320,16 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); } + if (numMips > 1) { + WARN_LOG(G3D, "File contains more than one mip level. Ignoring for now."); + } + + // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. + if (!out.empty()) { + *pixelFormat = levelData_->fmt; + return true; + } + // Is this really the right place to do it? level.w = (level.w * desc_->w) / desc_->newW; level.h = (level.h * desc_->h) / desc_->newH; @@ -318,17 +347,6 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D return false; } - if (levelData_->data.size() <= mipLevel) { - levelData_->data.resize(mipLevel + 1); - } - - std::vector &out = levelData_->data[mipLevel]; - - // Already populated from cache. - if (!out.empty()) { - return true; - } - auto cleanup = [&] { vfs_->CloseFile(openFile); }; @@ -339,12 +357,14 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D DDSHeader header; DDSHeaderDXT10 header10{}; vfs_->Read(openFile, &header, sizeof(header)); + if (ddsDX10) { + vfs_->Read(openFile, &header10, sizeof(header10)); + } // For compressed formats (we don't support uncompressed DDS files yet), this is supposed to be the linear size. - size_t bytes = header.dwPitchOrLinearSize; - out.resize(bytes); - size_t read_bytes = vfs_->Read(openFile, &out[0], bytes); - if (read_bytes != bytes) { - WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", bytes, read_bytes); + out.resize(ddsBytesToRead); + size_t read_bytes = vfs_->Read(openFile, &out[0], ddsBytesToRead); + if (read_bytes != ddsBytesToRead) { + WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", ddsBytesToRead, read_bytes); } } else if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 24bbef6662..264525b0c3 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -88,6 +88,7 @@ struct ReplacementDesc { }; struct ReplacedLevelsCache { + Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; std::mutex lock; std::vector> data; double lastUsed = 0.0; From d95cd73c2c843e0babcda9d530b012c0175c1ab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Mar 2023 21:46:01 +0100 Subject: [PATCH 284/424] Address a round of feedback --- GPU/Common/ReplacedTexture.cpp | 10 ++++++++-- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Common/TextureReplacer.cpp | 5 +++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 692a03465f..9340ec4ed8 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -88,18 +88,24 @@ private: bool ReplacedTexture::IsReady(double budget) { _assert_(vfs_ != nullptr); + double now = time_now_d(); + switch (State()) { case ReplacementState::ACTIVE: case ReplacementState::NOT_FOUND: if (threadWaitable_) { if (!threadWaitable_->WaitFor(budget)) { + lastUsed_ = now; return false; } // Successfully waited! Can get rid of it. threadWaitable_->WaitAndRelease(); threadWaitable_ = nullptr; + if (levelData_) { + levelData_->lastUsed = now; + } } - lastUsed_ = time_now_d(); + lastUsed_ = now; return true; case ReplacementState::UNINITIALIZED: // _dbg_assert_(false); @@ -112,7 +118,7 @@ bool ReplacedTexture::IsReady(double budget) { break; } - lastUsed_ = time_now_d(); + lastUsed_ = now; // Let's not even start a new texture if we're already behind. if (budget < 0.0) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index dbda83389d..3a7d149cba 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1514,7 +1514,7 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & return nullptr; } - if ((entry->status & TexCacheEntry::STATUS_VIDEO) && replacer_.AllowVideo()) { + if ((entry->status & TexCacheEntry::STATUS_VIDEO) && !replacer_.AllowVideo()) { return nullptr; } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 6c94b76f73..94bf8c4126 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -216,8 +216,6 @@ bool TextureReplacer::LoadIniValues(IniFile &ini, bool isOverride) { bool filenameWarning = false; if (ini.HasSection("hashes")) { - aliases_.clear(); - auto hashes = ini.GetOrCreateSection("hashes")->ToMap(); // Format: hashname = filename.png bool checkFilenames = g_Config.bSaveNewTextures && !g_Config.bIgnoreTextureFilenames && !vfsIsZip_; @@ -693,6 +691,9 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl #endif if (slash != hashfile.npos) { // Does this ever happen? + // Answer: An alias could be used to save a texture in a subfolder of newTextureDir_ + // (i.e. if you had the hash and purged out your pngs to redump them), although I guess this usage is probably uncommon. - unknown + // Create any directory structure as needed. task->saveDirectory = newTextureDir_ / hashfile.substr(0, slash); task->createSaveDirectory = true; From 95ae2d91f9d0c9d53b133cbd0164cb37c19e0fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Mar 2023 21:51:39 +0100 Subject: [PATCH 285/424] Couple of more GL enums --- Common/GPU/OpenGL/DataFormatGL.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp index c53190bae2..16529d9f5a 100644 --- a/Common/GPU/OpenGL/DataFormatGL.cpp +++ b/Common/GPU/OpenGL/DataFormatGL.cpp @@ -93,7 +93,18 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin type = GL_FLOAT; alignment = 8; break; - + case DataFormat::BC2_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + format = GL_RGBA; + type = GL_FLOAT; + alignment = 16; + break; + case DataFormat::BC3_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; + format = GL_RGBA; + type = GL_FLOAT; + alignment = 16; + break; case DataFormat::BC7_UNORM_BLOCK: internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; format = GL_RGBA; From 7e4dc23bcc971b1d5fd00e80f4fdfbc3beab586e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Mar 2023 23:55:16 +0100 Subject: [PATCH 286/424] Fix BC textures in D3D11 - except that they're red/blue swapped. Ugh. --- GPU/D3D11/TextureCacheD3D11.cpp | 22 ++++++++++++++-------- GPU/D3D11/TextureCacheD3D11.h | 2 -- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 1d2973ae48..2c73ab0054 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -168,7 +168,6 @@ TextureCacheD3D11::~TextureCacheD3D11() { } void TextureCacheD3D11::SetFramebufferManager(FramebufferManagerD3D11 *fbManager) { - framebufferManagerD3D11_ = fbManager; framebufferManager_ = fbManager; } @@ -312,24 +311,31 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { u8 *data = nullptr; int stride = 0; - int bpp = 0; - // For UpdateSubresource, we can't decode directly into the texture so we allocate a buffer :( - // NOTE: Could reuse it between levels or textures! + int dataSize; if (plan.replaceValid) { - bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); + int blockSize = 0; + if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { + stride = mipWidth * 4; // This stride value doesn't quite make sense to me, but it works. + dataSize = plan.replaced->GetLevelDataSize(i); + } else { + int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); + stride = std::max(mipWidth * bpp, 16); + dataSize = stride * mipHeight; + } } else { + int bpp = 0; if (plan.scaleFactor > 1) { bpp = 4; } else { bpp = dstFmt == DXGI_FORMAT_B8G8R8A8_UNORM ? 4 : 2; } + stride = std::max(mipWidth * bpp, 16); + dataSize = stride * mipHeight; } - stride = std::max(mipWidth * bpp, 16); - if (plan.depth == 1) { - data = (u8 *)AllocateAlignedMemory(stride * mipHeight, 16); + data = (u8 *)AllocateAlignedMemory(dataSize, 16); subresData[i].pSysMem = data; subresData[i].SysMemPitch = stride; subresData[i].SysMemSlicePitch = 0; diff --git a/GPU/D3D11/TextureCacheD3D11.h b/GPU/D3D11/TextureCacheD3D11.h index 53c150a9e4..31f29c68bb 100644 --- a/GPU/D3D11/TextureCacheD3D11.h +++ b/GPU/D3D11/TextureCacheD3D11.h @@ -83,8 +83,6 @@ private: ID3D11ShaderResourceView *lastBoundTexture; ID3D11Buffer *depalConstants_; - - FramebufferManagerD3D11 *framebufferManagerD3D11_; }; DXGI_FORMAT GetClutDestFormatD3D11(GEPaletteFormat format); From b687f1bba867e609eef251b5a287acb134e4906c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 00:14:06 +0100 Subject: [PATCH 287/424] Implement basic block compression support for OpenGL (without feature checks so far) --- Common/GPU/OpenGL/GLQueueRunner.cpp | 17 +++++++++++++---- GPU/GLES/TextureCacheGLES.cpp | 21 +++++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 4908fcd12d..eb6ee441a6 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -387,14 +387,23 @@ void GLQueueRunner::RunInitSteps(const std::vector &steps, bool ski // For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage. + int blockSize = 0; + bool bc = Draw::DataFormatIsBlockCompressed(step.texture_image.format, &blockSize); + GLenum internalFormat, format, type; int alignment; Thin3DFormatToGLFormatAndType(step.texture_image.format, internalFormat, format, type, alignment); if (step.texture_image.depth == 1) { - glTexImage2D(tex->target, - step.texture_image.level, internalFormat, - step.texture_image.width, step.texture_image.height, 0, - format, type, step.texture_image.data); + if (bc) { + int dataSize = ((step.texture_image.width + 3) & ~3) * ((step.texture_image.height + 3) & ~3) * blockSize / 16; + glCompressedTexImage2D(tex->target, step.texture_image.level, internalFormat, + step.texture_image.width, step.texture_image.height, 0, dataSize, step.texture_image.data); + } else { + glTexImage2D(tex->target, + step.texture_image.level, internalFormat, + step.texture_image.width, step.texture_image.height, 0, + format, type, step.texture_image.data); + } } else { glTexImage3D(tex->target, step.texture_image.level, internalFormat, diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index d44a883bcc..b5d8fdd63e 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -292,20 +292,33 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { u8 *data = nullptr; int stride = 0; - int bpp; + int dataSize; + + bool bc = false; if (plan.replaceValid) { - bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); + int blockSize = 0; + if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { + stride = mipWidth * 4; + dataSize = plan.replaced->GetLevelDataSize(i); + bc = true; + } else { + int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); + stride = std::max(mipWidth * bpp, 16); + dataSize = stride * mipHeight; + } } else { + int bpp = 0; if (plan.scaleFactor > 1) { bpp = 4; } else { bpp = (int)Draw::DataFormatSizeInBytes(dstFmt); } + stride = std::max(mipWidth * bpp, 16); + dataSize = stride * mipHeight; } - stride = mipWidth * bpp; - data = (u8 *)AllocateAlignedMemory(stride * mipHeight, 16); + data = (u8 *)AllocateAlignedMemory(dataSize, 16); if (!data) { ERROR_LOG(G3D, "Ran out of RAM trying to allocate a temporary texture upload buffer (%dx%d)", mipWidth, mipHeight); From f2673c8f7bc41bd351a490196e45566edc9c83a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 10:17:46 +0100 Subject: [PATCH 288/424] Change BGRA to be a texture-specific flag. Fixes R/B swap in DDS textures in D3D11. --- GPU/Common/ReplacedTexture.cpp | 2 +- GPU/Common/TextureCacheCommon.cpp | 11 +++++++---- GPU/Common/TextureCacheCommon.h | 3 +-- GPU/D3D11/TextureCacheD3D11.cpp | 7 ++++++- GPU/Directx9/TextureCacheDX9.cpp | 8 ++++++-- 5 files changed, 21 insertions(+), 10 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 9340ec4ed8..c6cd617fb5 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -254,7 +254,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D u32 format; if (good && (header.ddspf.dwFlags & DDPF_FOURCC)) { char *fcc = (char *)&header.ddspf.dwFourCC; - INFO_LOG(G3D, "DDS fourcc: %c%c%c%c", fcc[0], fcc[1], fcc[2], fcc[3]); + // INFO_LOG(G3D, "DDS fourcc: %c%c%c%c", fcc[0], fcc[1], fcc[2], fcc[3]); if (header.ddspf.dwFourCC == MK_FOURCC("DX10")) { ddsDX10 = true; good = good && vfs_->Read(openFile, &header10, sizeof(header10)) == sizeof(header10); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 3a7d149cba..9410fdb813 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -447,11 +447,9 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { gstate_c.SetNeedShaderTexclamp(false); gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; - bool isBgraTexture = isBgraBackend_ && !hasClutGPU; - gstate_c.SetTextureIsBGRA(isBgraTexture); - if (entryIter != cache_.end()) { entry = entryIter->second.get(); + // Validate the texture still matches the cache entry. bool match = entry->Matches(dim, texFormat, maxLevel); const char *reason = "different params"; @@ -540,7 +538,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { switch (replaced->State()) { case ReplacementState::NOT_FOUND: // Didn't find a replacement, so stop looking. - WARN_LOG(G3D, "No replacement for texture %dx%d", w0, h0); + // DEBUG_LOG(G3D, "No replacement for texture %dx%d", w0, h0); entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; if (g_Config.bSaveNewTextures) { // Load it once more to actually save it. Since we don't set STATUS_TO_REPLACE, we won't end up looping. @@ -567,6 +565,8 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { gstate_c.curTextureHeight = h; gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0); gstate_c.SetTextureIsArray(false); + gstate_c.SetTextureIsBGRA((entry->status & TexCacheEntry::STATUS_BGRA) != 0); + if (rehash) { // Update in case any of these changed. entry->sizeInRAM = (textureBitsPerPixel[texFormat] * bufw * h / 2) / 8; @@ -661,6 +661,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { entry->dim = dim; entry->format = texFormat; entry->maxLevel = maxLevel; + entry->status &= ~TexCacheEntry::STATUS_BGRA; // This would overestimate the size in many case so we underestimate instead // to avoid excessive clearing caused by cache invalidations. @@ -2119,12 +2120,14 @@ void TextureCacheCommon::ApplyTexture() { gstate_c.SetTextureFullAlpha(false); gstate_c.SetTextureIs3D(false); gstate_c.SetTextureIsArray(false); + gstate_c.SetTextureIsBGRA(false); } else { entry->lastFrame = gpuStats.numFlips; BindTexture(entry); gstate_c.SetTextureFullAlpha(entry->GetAlphaStatus() == TexCacheEntry::STATUS_ALPHA_FULL); gstate_c.SetTextureIs3D((entry->status & TexCacheEntry::STATUS_3D) != 0); gstate_c.SetTextureIsArray(false); + gstate_c.SetTextureIsBGRA((entry->status & TexCacheEntry::STATUS_BGRA) != 0); } } diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index ff44e35664..f50b042d89 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -151,6 +151,7 @@ struct TexCacheEntry { STATUS_CLUT_GPU = 0x8000, STATUS_VIDEO = 0x10000, + STATUS_BGRA = 0x20000, }; // TexStatus enum flag combination. @@ -511,8 +512,6 @@ protected: bool nextNeedsChange_; bool nextNeedsRebuild_; - bool isBgraBackend_ = false; - u32 *expandClut_; }; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 2c73ab0054..487e4337ac 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -148,7 +148,6 @@ TextureCacheD3D11::TextureCacheD3D11(Draw::DrawContext *draw, Draw2D *draw2D) device_ = (ID3D11Device *)draw->GetNativeObject(Draw::NativeObject::DEVICE); context_ = (ID3D11DeviceContext *)draw->GetNativeObject(Draw::NativeObject::CONTEXT); - isBgraBackend_ = true; lastBoundTexture = INVALID_TEX; D3D11_BUFFER_DESC desc{ sizeof(DepthPushConstants), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE }; @@ -414,6 +413,12 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (plan.replaceValid) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); + + if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) { + entry->status |= TexCacheEntry::STATUS_BGRA; + } + } else { + entry->status |= TexCacheEntry::STATUS_BGRA; } } diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index dc1ed423d6..7ded196c82 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -71,8 +71,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { TextureCacheDX9::TextureCacheDX9(Draw::DrawContext *draw, Draw2D *draw2D) : TextureCacheCommon(draw, draw2D) { lastBoundTexture = INVALID_TEX; - isBgraBackend_ = true; - device_ = (LPDIRECT3DDEVICE9)draw->GetNativeObject(Draw::NativeObject::DEVICE); deviceEx_ = (LPDIRECT3DDEVICE9EX)draw->GetNativeObject(Draw::NativeObject::DEVICE_EX); D3DCAPS9 pCaps; @@ -322,6 +320,12 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { if (plan.replaceValid) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); + + if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) { + entry->status |= TexCacheEntry::STATUS_BGRA; + } + } else { + entry->status |= TexCacheEntry::STATUS_BGRA; } } From b44e879d219f96359962f8270f5380cf7eb09a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 11:37:17 +0100 Subject: [PATCH 289/424] Support DXT1/3/5 (BC1,2,3) in D3D9 --- Common/GPU/D3D9/thin3d_d3d9.cpp | 1 + GPU/Common/ReplacedTexture.cpp | 8 ++++---- GPU/D3D11/TextureCacheD3D11.cpp | 32 +++++++++++++------------------- GPU/Directx9/TextureCacheDX9.cpp | 22 ++++++++++------------ 4 files changed, 28 insertions(+), 35 deletions(-) diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 2a90648abc..0326a22305 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -1592,6 +1592,7 @@ uint32_t D3D9Context::GetDataFormatSupport(DataFormat fmt) const { case DataFormat::BC1_RGBA_UNORM_BLOCK: case DataFormat::BC2_UNORM_BLOCK: case DataFormat::BC3_UNORM_BLOCK: + // DXT1, DXT3, DXT5. return FMT_TEXTURE; default: return 0; diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index c6cd617fb5..fde44d0508 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -297,6 +297,10 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D level.w = header.dwWidth; level.h = header.dwHeight; numMips = header.dwMipMapCount; + + if (numMips > 1) { + WARN_LOG(G3D, "DDS file contains more than one mip level. Ignoring for now."); + } } else if (imageType == ReplacedImageType::ZIM) { uint32_t ignore = 0; struct ZimHeader { @@ -326,10 +330,6 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); } - if (numMips > 1) { - WARN_LOG(G3D, "File contains more than one mip level. Ignoring for now."); - } - // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. if (!out.empty()) { *pixelFormat = levelData_->fmt; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 487e4337ac..d23b41d4ab 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -58,17 +58,11 @@ static const D3D11_INPUT_ELEMENT_DESC g_QuadVertexElements[] = { static Draw::DataFormat FromD3D11Format(u32 fmt) { switch (fmt) { - case DXGI_FORMAT_B4G4R4A4_UNORM: - return Draw::DataFormat::A4R4G4B4_UNORM_PACK16; - case DXGI_FORMAT_B5G5R5A1_UNORM: - return Draw::DataFormat::A1R5G5B5_UNORM_PACK16; - case DXGI_FORMAT_B5G6R5_UNORM: - return Draw::DataFormat::R5G6B5_UNORM_PACK16; - case DXGI_FORMAT_R8_UNORM: - return Draw::DataFormat::R8_UNORM; - case DXGI_FORMAT_B8G8R8A8_UNORM: - default: - return Draw::DataFormat::R8G8B8A8_UNORM; + case DXGI_FORMAT_B4G4R4A4_UNORM: return Draw::DataFormat::A4R4G4B4_UNORM_PACK16; + case DXGI_FORMAT_B5G5R5A1_UNORM: return Draw::DataFormat::A1R5G5B5_UNORM_PACK16; + case DXGI_FORMAT_B5G6R5_UNORM: return Draw::DataFormat::R5G6B5_UNORM_PACK16; + case DXGI_FORMAT_R8_UNORM: return Draw::DataFormat::R8_UNORM; + case DXGI_FORMAT_B8G8R8A8_UNORM: default: return Draw::DataFormat::R8G8B8A8_UNORM; } } @@ -281,14 +275,6 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { ID3D11Resource *texture = DxTex(entry); _assert_(texture == nullptr); - int tw; - int th; - plan.GetMipSize(0, &tw, &th); - if (tw > 16384) - tw = 16384; - if (th > 16384) - th = 16384; - // The PSP only supports 8 mip levels, but we support 12 in the texture replacer (4k textures down to 1). D3D11_SUBRESOURCE_DATA subresData[12]{}; @@ -355,6 +341,14 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { LoadTextureLevel(*entry, data, stride, plan, srcLevel, texFmt, TexDecodeFlags{}); } + int tw; + int th; + plan.GetMipSize(0, &tw, &th); + if (tw > 16384) + tw = 16384; + if (th > 16384) + th = 16384; + if (plan.depth == 1) { // We don't yet have mip generation, so clamp the number of levels to the ones we can load directly. levels = std::min(plan.levelsToCreate, plan.levelsToLoad); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 7ded196c82..55433f5c1b 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -40,23 +40,21 @@ Draw::DataFormat FromD3D9Format(u32 fmt) { switch (fmt) { - case D3DFMT_A4R4G4B4: - return Draw::DataFormat::B4G4R4A4_UNORM_PACK16; - case D3DFMT_A1R5G5B5: - return Draw::DataFormat::A1R5G5B5_UNORM_PACK16; - case D3DFMT_R5G6B5: - return Draw::DataFormat::R5G6B5_UNORM_PACK16; - case D3DFMT_A8: - return Draw::DataFormat::R8_UNORM; - case D3DFMT_A8R8G8B8: - default: - return Draw::DataFormat::R8G8B8A8_UNORM; + case D3DFMT_A4R4G4B4: return Draw::DataFormat::B4G4R4A4_UNORM_PACK16; + case D3DFMT_A1R5G5B5: return Draw::DataFormat::A1R5G5B5_UNORM_PACK16; + case D3DFMT_R5G6B5: return Draw::DataFormat::R5G6B5_UNORM_PACK16; + case D3DFMT_A8: return Draw::DataFormat::R8_UNORM; + case D3DFMT_A8R8G8B8: default: return Draw::DataFormat::R8G8B8A8_UNORM; } } D3DFORMAT ToD3D9Format(Draw::DataFormat fmt) { switch (fmt) { - case Draw::DataFormat::R8G8B8A8_UNORM: default: return D3DFMT_A8R8G8B8; + case Draw::DataFormat::BC1_RGBA_UNORM_BLOCK: return D3DFMT_DXT1; + case Draw::DataFormat::BC2_UNORM_BLOCK: return D3DFMT_DXT3; + case Draw::DataFormat::BC3_UNORM_BLOCK: return D3DFMT_DXT5; + case Draw::DataFormat::R8G8B8A8_UNORM: return D3DFMT_A8R8G8B8; + default: _dbg_assert_(false); return D3DFMT_A8R8G8B8; } } From 25fbfd7a891a7afc36cac4a6ca12bcb59f6411b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 12:18:55 +0100 Subject: [PATCH 290/424] Finish up OpenGL compressed texture format checks. Show in dev screen --- Common/GPU/D3D9/thin3d_d3d9.cpp | 2 +- Common/GPU/OpenGL/DataFormatGL.cpp | 12 +++++++++ Common/GPU/OpenGL/GLFeatures.cpp | 40 +++++++++++++++++++++++++++++- Common/GPU/OpenGL/GLFeatures.h | 13 ++++++++++ Common/GPU/OpenGL/thin3d_gl.cpp | 18 +++++++++++++- UI/DevScreens.cpp | 10 ++++++++ 6 files changed, 92 insertions(+), 3 deletions(-) diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp index 0326a22305..a560a78fe3 100644 --- a/Common/GPU/D3D9/thin3d_d3d9.cpp +++ b/Common/GPU/D3D9/thin3d_d3d9.cpp @@ -113,7 +113,7 @@ static const D3DSTENCILOP stencilOpToD3D9[] = { D3DSTENCILOP_DECR, }; -D3DFORMAT FormatToD3DFMT(DataFormat fmt) { +static D3DFORMAT FormatToD3DFMT(DataFormat fmt) { switch (fmt) { case DataFormat::R16_UNORM: return D3DFMT_L16; // closest match, should be a fine substitution if we ignore channels except R. case DataFormat::R8G8B8A8_UNORM: return D3DFMT_A8R8G8B8; diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp index 16529d9f5a..67a4fdbc72 100644 --- a/Common/GPU/OpenGL/DataFormatGL.cpp +++ b/Common/GPU/OpenGL/DataFormatGL.cpp @@ -105,6 +105,18 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin type = GL_FLOAT; alignment = 16; break; + case DataFormat::BC4_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RED_RGTC1; + format = GL_R; + type = GL_FLOAT; + alignment = 16; + break; + case DataFormat::BC5_UNORM_BLOCK: + internalFormat = GL_COMPRESSED_RG_RGTC2; + format = GL_RG; + type = GL_FLOAT; + alignment = 16; + break; case DataFormat::BC7_UNORM_BLOCK: internalFormat = GL_COMPRESSED_RGBA_BPTC_UNORM; format = GL_RGBA; diff --git a/Common/GPU/OpenGL/GLFeatures.cpp b/Common/GPU/OpenGL/GLFeatures.cpp index 96bc41a6e3..802ae1b28f 100644 --- a/Common/GPU/OpenGL/GLFeatures.cpp +++ b/Common/GPU/OpenGL/GLFeatures.cpp @@ -182,7 +182,9 @@ bool CheckGLExtensions() { gl_extensions.gpuVendor = GPU_VENDOR_IMGTEC; } else if (vendor == "Qualcomm") { gl_extensions.gpuVendor = GPU_VENDOR_QUALCOMM; - sscanf(renderer, "Adreno (TM) %d", &gl_extensions.modelNumber); + if (1 != sscanf(renderer, "Adreno (TM) %d", &gl_extensions.modelNumber)) { + gl_extensions.modelNumber = 300; // or what should we default to? + } } else if (vendor == "Broadcom") { gl_extensions.gpuVendor = GPU_VENDOR_BROADCOM; // Just for reference: Galaxy Y has renderer == "VideoCore IV HW" @@ -378,6 +380,12 @@ bool CheckGLExtensions() { gl_extensions.ARB_explicit_attrib_location = g_set_gl_extensions.count("GL_ARB_explicit_attrib_location") != 0; gl_extensions.ARB_texture_non_power_of_two = g_set_gl_extensions.count("GL_ARB_texture_non_power_of_two") != 0; gl_extensions.ARB_shader_stencil_export = g_set_gl_extensions.count("GL_ARB_shader_stencil_export") != 0; + gl_extensions.ARB_texture_compression_bptc = g_set_gl_extensions.count("GL_ARB_texture_compression_bptc") != 0; + gl_extensions.ARB_texture_compression_rgtc = g_set_gl_extensions.count("GL_ARB_texture_compression_rgtc") != 0; + gl_extensions.KHR_texture_compression_astc_ldr = g_set_gl_extensions.count("GL_KHR_texture_compression_astc_ldr") != 0; + gl_extensions.EXT_texture_compression_s3tc = g_set_gl_extensions.count("GL_EXT_texture_compression_s3tc") != 0; + gl_extensions.OES_texture_compression_astc = g_set_gl_extensions.count("GL_OES_texture_compression_astc") != 0; + if (gl_extensions.IsGLES) { gl_extensions.EXT_blend_func_extended = g_set_gl_extensions.count("GL_EXT_blend_func_extended") != 0; gl_extensions.OES_texture_npot = g_set_gl_extensions.count("GL_OES_texture_npot") != 0; @@ -575,6 +583,36 @@ bool CheckGLExtensions() { gl_extensions.EXT_clip_cull_distance = false; } + // Check the old query API. It doesn't seem to be very reliable (can miss stuff). + GLint numCompressedFormats = 0; + glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &numCompressedFormats); + GLint *compressedFormats = new GLint[numCompressedFormats]; + if (numCompressedFormats > 0) { + glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, compressedFormats); + for (int i = 0; i < numCompressedFormats; i++) { + switch (compressedFormats[i]) { + case GL_COMPRESSED_RGB8_ETC2: gl_extensions.supportsETC2 = true; break; + case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: gl_extensions.supportsASTC = true; break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: gl_extensions.supportsBC123 = true; break; + case GL_COMPRESSED_RGBA_BPTC_UNORM: gl_extensions.supportsBC7 = true; break; + } + } + } + + // Enable additional formats based on extensions. + if (gl_extensions.EXT_texture_compression_s3tc) gl_extensions.supportsBC123 = true; + if (gl_extensions.ARB_texture_compression_bptc) gl_extensions.supportsBC7 = true; + if (gl_extensions.ARB_texture_compression_rgtc) gl_extensions.supportsBC45 = true; + if (gl_extensions.KHR_texture_compression_astc_ldr) gl_extensions.supportsASTC = true; + if (gl_extensions.OES_texture_compression_astc) gl_extensions.supportsASTC = true; + + // Now, disable known-emulated texture formats. + if (gl_extensions.gpuVendor == GPU_VENDOR_NVIDIA && !gl_extensions.IsGLES) { + gl_extensions.supportsETC2 = false; + gl_extensions.supportsASTC = false; + } + delete[] compressedFormats; + ProcessGPUFeatures(); int error = glGetError(); diff --git a/Common/GPU/OpenGL/GLFeatures.h b/Common/GPU/OpenGL/GLFeatures.h index fe72d037b2..04df20f87f 100644 --- a/Common/GPU/OpenGL/GLFeatures.h +++ b/Common/GPU/OpenGL/GLFeatures.h @@ -52,6 +52,7 @@ struct GLExtensions { bool OES_copy_image; bool OES_texture_float; bool OES_texture_3D; + bool OES_texture_compression_astc; // ARB bool ARB_framebuffer_object; @@ -73,8 +74,14 @@ struct GLExtensions { bool ARB_texture_non_power_of_two; bool ARB_stencil_texturing; bool ARB_shader_stencil_export; + bool ARB_texture_compression_bptc; + bool ARB_texture_compression_rgtc; + + // KHR + bool KHR_texture_compression_astc_ldr; // EXT + bool EXT_texture_compression_s3tc; bool EXT_swap_control_tear; bool EXT_discard_framebuffer; bool EXT_unpack_subimage; // always supported on desktop and ES3 @@ -115,6 +122,12 @@ struct GLExtensions { int maxVertexTextureUnits; + bool supportsETC2; + bool supportsBC123; + bool supportsBC45; + bool supportsBC7; + bool supportsASTC; + // greater-or-equal than bool VersionGEThan(int major, int minor, int sub = 0); int GLSLVersion(); diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp index 5cb85ac9c7..0f04ee0415 100644 --- a/Common/GPU/OpenGL/thin3d_gl.cpp +++ b/Common/GPU/OpenGL/thin3d_gl.cpp @@ -1556,7 +1556,23 @@ uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const { case DataFormat::BC1_RGBA_UNORM_BLOCK: case DataFormat::BC2_UNORM_BLOCK: case DataFormat::BC3_UNORM_BLOCK: - return FMT_TEXTURE; + return gl_extensions.supportsBC123 ? FMT_TEXTURE : 0; + + case DataFormat::BC4_UNORM_BLOCK: + case DataFormat::BC5_UNORM_BLOCK: + return gl_extensions.supportsBC45 ? FMT_TEXTURE : 0; + + case DataFormat::BC7_UNORM_BLOCK: + return gl_extensions.supportsBC7 ? FMT_TEXTURE : 0; + + case DataFormat::ASTC_4x4_UNORM_BLOCK: + return gl_extensions.supportsASTC ? FMT_TEXTURE : 0; + + case DataFormat::ETC2_R8G8B8_UNORM_BLOCK: + case DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK: + case DataFormat::ETC2_R8G8B8A8_UNORM_BLOCK: + return gl_extensions.supportsETC2 ? FMT_TEXTURE : 0; + default: return 0; } diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index 82cb3c159e..f54480ef51 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -554,6 +554,16 @@ void SystemInfoScreen::CreateViews() { } } deviceSpecs->Add(new InfoItem(si->T("Depth buffer format"), DataFormatToString(draw->GetDeviceCaps().preferredDepthBufferFormat))); + + std::string texCompressionFormats; + // Simple non-detailed summary of supported tex compression formats. + if (draw->GetDataFormatSupport(Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK)) texCompressionFormats += "ETC2 "; + if (draw->GetDataFormatSupport(Draw::DataFormat::ASTC_4x4_UNORM_BLOCK)) texCompressionFormats += "ASTC "; + if (draw->GetDataFormatSupport(Draw::DataFormat::BC1_RGBA_UNORM_BLOCK)) texCompressionFormats += "BC1,2,3 "; + if (draw->GetDataFormatSupport(Draw::DataFormat::BC4_UNORM_BLOCK)) texCompressionFormats += "BC4,5 "; + if (draw->GetDataFormatSupport(Draw::DataFormat::BC7_UNORM_BLOCK)) texCompressionFormats += "BC7 "; + deviceSpecs->Add(new InfoItem(si->T("Compressed texture formats"), texCompressionFormats)); + deviceSpecs->Add(new ItemHeader(si->T("OS Information"))); deviceSpecs->Add(new InfoItem(si->T("Memory Page Size"), StringFromFormat(si->T("%d bytes"), GetMemoryProtectPageSize()))); deviceSpecs->Add(new InfoItem(si->T("RW/RX exclusive"), PlatformIsWXExclusive() ? di->T("Active") : di->T("Inactive"))); From ddab8fc0db3a5327ebe803915917ee3bc6b19922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 12:26:26 +0100 Subject: [PATCH 291/424] langtool: Update, fix clippy warnings, just because --- Tools/langtool/Cargo.lock | 16 ++++++++-------- Tools/langtool/Cargo.toml | 2 +- Tools/langtool/src/main.rs | 12 ++++++------ Tools/langtool/src/section.rs | 10 ++++------ 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/Tools/langtool/Cargo.lock b/Tools/langtool/Cargo.lock index 5cd7e28f37..70ea905488 100644 --- a/Tools/langtool/Cargo.lock +++ b/Tools/langtool/Cargo.lock @@ -76,9 +76,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.139" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] name = "proc-macro-error" @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-segmentation" diff --git a/Tools/langtool/Cargo.toml b/Tools/langtool/Cargo.toml index b18910d38f..42ef423cf6 100644 --- a/Tools/langtool/Cargo.toml +++ b/Tools/langtool/Cargo.toml @@ -5,4 +5,4 @@ name = "langtool" version = "0.1.0" [dependencies] -structopt = "0.3" +structopt = "0.3.26" diff --git a/Tools/langtool/src/main.rs b/Tools/langtool/src/main.rs index 45b79e50f7..f18060959c 100644 --- a/Tools/langtool/src/main.rs +++ b/Tools/langtool/src/main.rs @@ -100,7 +100,7 @@ fn move_key(target_ini: &mut IniFile, old: &str, new: &str, key: &str) -> io::Re fn remove_key(target_ini: &mut IniFile, section: &str, key: &str) -> io::Result<()> { if let Some(old_section) = target_ini.get_section_mut(section) { - let _ = old_section.remove_line(key); + old_section.remove_line(key); } else { println!("No section {}", section); } @@ -109,7 +109,7 @@ fn remove_key(target_ini: &mut IniFile, section: &str, key: &str) -> io::Result< fn add_new_key(target_ini: &mut IniFile, section: &str, key: &str) -> io::Result<()> { if let Some(section) = target_ini.get_section_mut(section) { - let _ = section.insert_line_if_missing(&format!("{} = {}", key, key)); + section.insert_line_if_missing(&format!("{} = {}", key, key)); } else { println!("No section {}", section); } @@ -118,7 +118,7 @@ fn add_new_key(target_ini: &mut IniFile, section: &str, key: &str) -> io::Result fn rename_key(target_ini: &mut IniFile, section: &str, old: &str, new: &str) -> io::Result<()> { if let Some(section) = target_ini.get_section_mut(section) { - let _ = section.rename_key(old, new); + section.rename_key(old, new); } else { println!("No section {}", section); } @@ -178,13 +178,13 @@ fn main() { match opt.cmd { Command::CopyMissingLines {} => { - copy_missing_lines(&reference_ini, &mut target_ini).unwrap(); + copy_missing_lines(reference_ini, &mut target_ini).unwrap(); } Command::CommentUnknownLines {} => { - deal_with_unknown_lines(&reference_ini, &mut target_ini, false).unwrap(); + deal_with_unknown_lines(reference_ini, &mut target_ini, false).unwrap(); } Command::RemoveUnknownLines {} => { - deal_with_unknown_lines(&reference_ini, &mut target_ini, true).unwrap(); + deal_with_unknown_lines(reference_ini, &mut target_ini, true).unwrap(); } Command::SortSection { ref section } => sort_section(&mut target_ini, section).unwrap(), Command::RenameKey { diff --git a/Tools/langtool/src/section.rs b/Tools/langtool/src/section.rs index 0ccfad7a48..1884957a53 100644 --- a/Tools/langtool/src/section.rs +++ b/Tools/langtool/src/section.rs @@ -20,7 +20,7 @@ impl Section { continue; }; - if prefix.eq_ignore_ascii_case(&key) { + if prefix.eq_ignore_ascii_case(key) { remove_index = Some(index); break; } @@ -140,11 +140,9 @@ impl Section { if prefix.starts_with("Font") || prefix.starts_with('#') { return true; } - if !other.lines.iter().any(|line| line.starts_with(prefix)) { - false - } else { - true - } + + // keeps the line if this expression returns true. + other.lines.iter().any(|line| line.starts_with(prefix)) }); } } From c04acaf5c1f9d257129249e4c060fe9ba01595fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 12:28:02 +0100 Subject: [PATCH 292/424] Add new translation string --- assets/lang/ar_AE.ini | 1 + assets/lang/az_AZ.ini | 1 + assets/lang/bg_BG.ini | 1 + assets/lang/ca_ES.ini | 1 + assets/lang/cz_CZ.ini | 1 + assets/lang/da_DK.ini | 1 + assets/lang/de_DE.ini | 1 + assets/lang/dr_ID.ini | 1 + assets/lang/en_US.ini | 1 + assets/lang/es_ES.ini | 1 + assets/lang/es_LA.ini | 1 + assets/lang/fa_IR.ini | 1 + assets/lang/fi_FI.ini | 1 + assets/lang/fr_FR.ini | 1 + assets/lang/gl_ES.ini | 1 + assets/lang/gr_EL.ini | 1 + assets/lang/he_IL.ini | 1 + assets/lang/he_IL_invert.ini | 1 + assets/lang/hr_HR.ini | 1 + assets/lang/hu_HU.ini | 1 + assets/lang/id_ID.ini | 1 + assets/lang/it_IT.ini | 1 + assets/lang/ja_JP.ini | 1 + assets/lang/jv_ID.ini | 1 + assets/lang/ko_KR.ini | 1 + assets/lang/lo_LA.ini | 1 + assets/lang/lt-LT.ini | 1 + assets/lang/ms_MY.ini | 1 + assets/lang/nl_NL.ini | 1 + assets/lang/no_NO.ini | 1 + assets/lang/pl_PL.ini | 1 + assets/lang/pt_BR.ini | 1 + assets/lang/pt_PT.ini | 1 + assets/lang/ro_RO.ini | 1 + assets/lang/ru_RU.ini | 1 + assets/lang/sv_SE.ini | 1 + assets/lang/tg_PH.ini | 1 + assets/lang/th_TH.ini | 1 + assets/lang/tr_TR.ini | 1 + assets/lang/uk_UA.ini | 1 + assets/lang/vi_VN.ini | 1 + assets/lang/zh_CN.ini | 1 + assets/lang/zh_TW.ini | 1 + 43 files changed, 43 insertions(+) diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 699e53ef3d..446b1695a3 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -1042,6 +1042,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index b030b67e94..e29291f540 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index 8dbf12e598..eecca5adbd 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 64b19aba26..586ea03f97 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index da88a9b085..998107a1b9 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index b94cc282b7..41869365cc 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index 2ac1e3b203..9d00fdb672 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Erstellungskonfig. Build Configuration = Erstellungskonfiguration Built by = Erstellt von +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Kerne CPU Extensions = CPU Erweiterungen diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index ed04d0f8aa..94bf9792a1 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index a896053141..f716c73452 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -1051,6 +1051,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 93920a9973..63effcd9ad 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1035,6 +1035,7 @@ Board = Placa Build Config = Info. de la compilación Build Configuration = Info. de la compilación Built by = Compilado por +Compressed texture formats = Compressed texture formats Core Context = Contexto de núcleo Cores = Núcleos CPU Extensions = Extensiones CPU diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 85ff013e98..c8185aeb8a 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1034,6 +1034,7 @@ Board = Placa Build Config = Info. de la compilación Build Configuration = Info. de la compilación Built by = Compilado por +Compressed texture formats = Compressed texture formats Core Context = Contexto de núcleo Cores = Núcleos CPU Extensions = Extensiones de CPU diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 1e26d0e635..cfb06573aa 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index cb4a69e71e..c08b051054 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 084c9d650d..cc6910abd2 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1025,6 +1025,7 @@ Board = Carte Build Config = Config de compilation Build Configuration = Configuration de compilation Built by = Compilé par +Compressed texture formats = Compressed texture formats Core Context = Contexte de cœur Cores = Coeurs CPU Extensions = Extensions CPU diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index cfc7d3987f..21a4b5910d 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index c4ac45e86b..1018f93940 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Πυρήνες CPU Extensions = Επεκτάσεις CPU diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index c2f1943fb7..e07fec542d 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 6f50014db9..97aa9296be 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 6c3cb6a9ac..53c3ba984a 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1034,6 +1034,7 @@ Board = Ploča Build Config = Konfig građe Build Configuration = Konfiguracija građe Built by = Građeno od +Compressed texture formats = Compressed texture formats Core Context = Kontekst jezgre Cores = Jezgre CPU Extensions = CPU nastavci diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 401245991b..f0e7a5019d 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1034,6 +1034,7 @@ Board = Alaplap Build Config = Build konfig Build Configuration = Build konfiguráció Built by = Buildelte: +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Magok CPU Extensions = CPU kiterjesztések diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index e93b4b551e..3b475db105 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1034,6 +1034,7 @@ Board = Papan Build Config = Konfigurasi pembuatan Build Configuration = Konfigurasi pembuatan Built by = Dibuat oleh +Compressed texture formats = Compressed texture formats Core Context = Konteks inti Cores = Inti CPU Extensions = Ekstensi CPU diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 9e01656cce..b1a4cd4526 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1035,6 +1035,7 @@ Board = Scheda Build Config = Config della build Build Configuration = Configurazione della build Built by = Compilato da +Compressed texture formats = Compressed texture formats Core Context = Contesto del core Cores = Core CPU Extensions = Estensioni della CPU diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 81910315c6..597962ad61 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = ビルド設定 Build Configuration = ビルド設定 Built by = ビルド作成者 +Compressed texture formats = Compressed texture formats Core Context = コアコンテキスト Cores = コア数 CPU Extensions = CPU拡張 diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 90993b2ef8..88661aba4a 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index ce40dbb90d..e02490c1fb 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1027,6 +1027,7 @@ Board = 보드 Build Config = 빌드 구성 Build Configuration = 빌드 구성 Built by = 빌더 +Compressed texture formats = Compressed texture formats Core Context = 코어 컨텍스트 Cores = 코어 CPU Extensions = CPU 확장 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index e821e31861..92099f2b5a 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 3079809344..2e3d08a249 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 932dc4ce79..1d8c739be5 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 17931d0d2b..e1f86e1cf8 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Bouw Build Configuration = Bouwconfiguratie Built by = Gebouwd door +Compressed texture formats = Compressed texture formats Core Context = Corecontext Cores = Cores CPU Extensions = CPU-extensies diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 78564c313c..69a27e25c7 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 482bea9be3..afaa3d12b5 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1034,6 +1034,7 @@ Board = Płyta główna Build Config = Konfiguracja wersji Build Configuration = Konfiguracja Wersji Built by = Zbudowane przez +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Rdzenie CPU Extensions = Rozszerzenia CPU diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index f7963e1dff..7779d4fb65 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -1051,6 +1051,7 @@ Board = Placa Build Config = Configuração do build Build Configuration = Configuração do build Built by = Compilado por +Compressed texture formats = Compressed texture formats Core Context = Contexto do núcleo Cores = Núcleos CPU Extensions = Extensões da CPU diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index a3f2984a78..3aeaeddb86 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -1051,6 +1051,7 @@ Board = Placa Build Config = Definições da build Build Configuration = Definições da build Built by = Compilado por +Compressed texture formats = Compressed texture formats Core Context = Contexto do núcleo Cores = Núcleos CPU Extensions = Extensões da CPU diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index a7c1e774f1..1f1f8bfffe 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index a33f26ff75..b42de7589c 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1034,6 +1034,7 @@ Board = Плата Build Config = Конфиг сборки Build Configuration = Конфигурация сборки Built by = Собрано +Compressed texture formats = Compressed texture formats Core Context = Контекст ядра Cores = Ядра CPU Extensions = Расширения ЦП diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index b9768f7c40..33fb006f19 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index 472813cd6b..e8dac4a33e 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1034,6 +1034,7 @@ Board = Board Build Config = Build config Build Configuration = Build Configuration Built by = Built by +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Cores CPU Extensions = CPU extensions diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 7f626c743c..94e6a2aca1 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1038,6 +1038,7 @@ Board = ชื่อบอร์ด Build Config = การกำหนดค่า Build Configuration = การกำหนดค่าที่ถูกสร้างไว้ Built by = สร้างโดย +Compressed texture formats = Compressed texture formats Core Context = บริบทของแกน Cores = จำนวนแกน CPU Extensions = ส่วนขยายซีพียู diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index ae7edf0cf8..29e2bdf498 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1035,6 +1035,7 @@ Board = Board Build Config = Yapı konfigürasyonu Build Configuration = Yapı konfigürasyonu Built by = Tarafından yapıldı +Compressed texture formats = Compressed texture formats Core Context = Core context Cores = Çekirdekler CPU Extensions = CPU uzantıları diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index c4ec4fc6ca..3a7a7dac29 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1034,6 +1034,7 @@ Board = Плата Build Config = Конфіг збірки Build Configuration = Конфігурація збірки Built by = Побудував +Compressed texture formats = Compressed texture formats Core Context = Контекст ядра Cores = Ядра CPU Extensions = Розширення CPU diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index e521a0d4be..fe04d93c6b 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1034,6 +1034,7 @@ Board = Bảng Build Config = Xây dựng Build Configuration = Xây dựng cấu hình Built by = Xây dựng bởi +Compressed texture formats = Compressed texture formats Core Context = Bối cảnh cốt lõi Cores = Cốt lõi CPU Extensions = tiện ích CPU diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 0c6796ad2d..fce8d07ded 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1028,6 +1028,7 @@ Board = 主板 Build Config = 编译配置 Build Configuration = 编译配置 Built by = 编译者 +Compressed texture formats = Compressed texture formats Core Context = 核心上下文 Cores = 核心数 CPU Extensions = CPU 扩展 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 6915f757ee..7c17ef4702 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1027,6 +1027,7 @@ Board = 主機板 Build Config = 組建組態 Build Configuration = 組建組態 Built by = 建置者 +Compressed texture formats = Compressed texture formats Core Context = 核心內容 Cores = 核心數 CPU Extensions = CPU 擴充 From 983f8176dd28b136c1306c80d593cbbcad06ea33 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 12 Mar 2023 14:41:17 +0100 Subject: [PATCH 293/424] OpenXR - Enable user to switch between topdown and fps camera --- Common/VR/PPSSPPVR.cpp | 43 ++++++++++++++++++++++++++------------- Core/Config.cpp | 1 + Core/Config.h | 1 + UI/GameSettingsScreen.cpp | 2 ++ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/Common/VR/PPSSPPVR.cpp b/Common/VR/PPSSPPVR.cpp index f39f1bcc1d..ec575be938 100644 --- a/Common/VR/PPSSPPVR.cpp +++ b/Common/VR/PPSSPPVR.cpp @@ -366,14 +366,14 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { for (auto& axis : device.second) { switch(axis.first) { case JOYSTICK_AXIS_X: - if (axis.second < -0.75f) g_Config.fCameraSide -= 0.05f; - if (axis.second > 0.75f) g_Config.fCameraSide += 0.05f; - g_Config.fCameraSide = clampFloat(g_Config.fCameraSide, -50.0f, 50.0f); + if (axis.second < -0.75f) g_Config.fCameraSide -= 0.1f; + if (axis.second > 0.75f) g_Config.fCameraSide += 0.1f; + g_Config.fCameraSide = clampFloat(g_Config.fCameraSide, -150.0f, 150.0f); break; case JOYSTICK_AXIS_Y: - if (axis.second > 0.75f) g_Config.fCameraHeight -= 0.05f; - if (axis.second < -0.75f) g_Config.fCameraHeight += 0.05f; - g_Config.fCameraHeight = clampFloat(g_Config.fCameraHeight, -50.0f, 50.0f); + if (axis.second > 0.75f) g_Config.fCameraHeight -= 0.1f; + if (axis.second < -0.75f) g_Config.fCameraHeight += 0.1f; + g_Config.fCameraHeight = clampFloat(g_Config.fCameraHeight, -150.0f, 150.0f); break; case JOYSTICK_AXIS_Z: if (axis.second < -0.75f) g_Config.fHeadUpDisplayScale -= 0.01f; @@ -383,7 +383,7 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) { case JOYSTICK_AXIS_RZ: if (axis.second > 0.75f) g_Config.fCameraDistance -= 0.1f; if (axis.second < -0.75f) g_Config.fCameraDistance += 0.1f; - g_Config.fCameraDistance = clampFloat(g_Config.fCameraDistance, -50.0f, 50.0f); + g_Config.fCameraDistance = clampFloat(g_Config.fCameraDistance, -150.0f, 150.0f); break; } } @@ -665,6 +665,21 @@ bool StartVRRender() { invView = XrPosef_Inverse(invView); } + // apply camera pitch offset + XrVector3f positionOffset = {g_Config.fCameraSide, g_Config.fCameraHeight, g_Config.fCameraDistance}; + if (!flatScreen) { + float pitchOffset = 0; + if (g_Config.iCameraPitch == 1) { + pitchOffset = 90; + positionOffset = {positionOffset.x, positionOffset.z, -positionOffset.y}; + } else if (g_Config.iCameraPitch == 2) { + pitchOffset = -90; + positionOffset = {positionOffset.x, -positionOffset.z, positionOffset.y}; + } + XrQuaternionf rotationOffset = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, ToRadians(pitchOffset)); + invView.orientation = XrQuaternionf_Multiply(rotationOffset, invView.orientation); + } + // decompose rotation XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation); float mPitch = mx * ToRadians(rotation.x); @@ -685,14 +700,14 @@ bool StartVRRender() { memcpy(&M, M, sizeof(float) * 16); // Apply 6Dof head movement - if (!flatScreen && g_Config.bEnable6DoF) { + if (!flatScreen && g_Config.bEnable6DoF && !g_Config.bHeadRotationEnabled && (g_Config.iCameraPitch == 0)) { M[3] -= invViewTransform[0].position.x * (vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f) * scale; M[7] -= invViewTransform[0].position.y * (vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f) * scale; M[11] -= invViewTransform[0].position.z * (vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f) * scale; } // Camera adjust - distance - if (fabsf(g_Config.fCameraDistance) > 0.0f) { - XrVector3f forward = {0.0f, 0.0f, g_Config.fCameraDistance * scale}; + if (fabsf(positionOffset.z) > 0.0f) { + XrVector3f forward = {0.0f, 0.0f, positionOffset.z * scale}; forward = XrQuaternionf_Rotate(invView.orientation, forward); forward = XrVector3f_ScalarMultiply(forward, vrMirroring[VR_MIRRORING_AXIS_Z] ? -1.0f : 1.0f); M[3] += forward.x; @@ -700,8 +715,8 @@ bool StartVRRender() { M[11] += forward.z; } // Camera adjust - height - if (fabsf(g_Config.fCameraHeight) > 0.0f) { - XrVector3f up = {0.0f, -g_Config.fCameraHeight * scale, 0.0f}; + if (fabsf(positionOffset.y) > 0.0f) { + XrVector3f up = {0.0f, -positionOffset.y * scale, 0.0f}; up = XrQuaternionf_Rotate(invView.orientation, up); up = XrVector3f_ScalarMultiply(up, vrMirroring[VR_MIRRORING_AXIS_Y] ? -1.0f : 1.0f); M[3] += up.x; @@ -709,8 +724,8 @@ bool StartVRRender() { M[11] += up.z; } // Camera adjust - side - if (fabsf(g_Config.fCameraSide) > 0.0f) { - XrVector3f side = {-g_Config.fCameraSide * scale, 0.0f, 0.0f}; + if (fabsf(positionOffset.x) > 0.0f) { + XrVector3f side = {-positionOffset.x * scale, 0.0f, 0.0f}; side = XrQuaternionf_Rotate(invView.orientation, side); side = XrVector3f_ScalarMultiply(side, vrMirroring[VR_MIRRORING_AXIS_X] ? -1.0f : 1.0f); M[3] += side.x; diff --git a/Core/Config.cpp b/Core/Config.cpp index cce0b9d7cb..835ef26344 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1147,6 +1147,7 @@ static const ConfigSetting vrSettings[] = { ConfigSetting("VRCameraDistance", &g_Config.fCameraDistance, 0.0f), ConfigSetting("VRCameraHeight", &g_Config.fCameraHeight, 0.0f), ConfigSetting("VRCameraSide", &g_Config.fCameraSide, 0.0f), + ConfigSetting("VRCameraPitch", &g_Config.iCameraPitch, 0), ConfigSetting("VRCanvasDistance", &g_Config.fCanvasDistance, 12.0f), ConfigSetting("VRFieldOfView", &g_Config.fFieldOfViewPercentage, 100.0f), ConfigSetting("VRHeadUpDisplayScale", &g_Config.fHeadUpDisplayScale, 0.3f), diff --git a/Core/Config.h b/Core/Config.h index 38f90902a0..9642abdeb0 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -472,6 +472,7 @@ public: float fHeadRotationScale; bool bHeadRotationEnabled; bool bHeadRotationSmoothing; + int iCameraPitch; // Debugger int iDisasmWindowX; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 0ef3060135..6d8d0af62e 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1151,6 +1151,8 @@ void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) { vrSettings->Add(new CheckBox(&g_Config.bEnableMotions, vr->T("Map controller movements to keys"))); PopupSliderChoiceFloat *vrMotions = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMotionLength, 0.3f, 1.0f, vr->T("Motion needed to generate action"), 0.1f, screenManager(), vr->T("m"))); vrMotions->SetEnabledPtr(&g_Config.bEnableMotions); + static const char *cameraPitchModes[] = { "Disabled", "Top view -> First person", "First person -> Top view" }; + vrSettings->Add(new PopupMultiChoice(&g_Config.iCameraPitch, vr->T("Modify camera type"), cameraPitchModes, 0, 3, "", screenManager())); } UI::LinearLayout *GameSettingsScreen::AddTab(const char *tag, const std::string &title, bool isSearch) { From a4b5641f118298135bc6b62edffa872aa81558a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 13:19:01 +0100 Subject: [PATCH 294/424] Add compressed texture format support checks --- Common/GPU/OpenGL/GLFeatures.cpp | 4 ++++ GPU/Common/ReplacedTexture.cpp | 12 ++++++++++-- GPU/Common/ReplacedTexture.h | 8 ++++++++ GPU/Common/TextureReplacer.cpp | 7 ++++++- GPU/Common/TextureReplacer.h | 3 ++- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Common/GPU/OpenGL/GLFeatures.cpp b/Common/GPU/OpenGL/GLFeatures.cpp index 802ae1b28f..847778e514 100644 --- a/Common/GPU/OpenGL/GLFeatures.cpp +++ b/Common/GPU/OpenGL/GLFeatures.cpp @@ -593,8 +593,12 @@ bool CheckGLExtensions() { switch (compressedFormats[i]) { case GL_COMPRESSED_RGB8_ETC2: gl_extensions.supportsETC2 = true; break; case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: gl_extensions.supportsASTC = true; break; +#if !PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(MAC) case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: gl_extensions.supportsBC123 = true; break; +#endif +#if PPSSPP_PLATFORM(WINDOWS) case GL_COMPRESSED_RGBA_BPTC_UNORM: gl_extensions.supportsBC7 = true; break; +#endif } } } diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index fde44d0508..646bc19f06 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -262,14 +262,22 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D switch (format) { case 98: // DXGI_FORMAT_BC7_UNORM: case 99: // DXGI_FORMAT_BC7_UNORM_SRGB: + if (!desc_->formatSupport.bc7) { + WARN_LOG(G3D, "BC1-3 formats not supported, skipping texture"); + good = false; + } ddsBytesToRead = RoundUpTo4(header.dwWidth) * RoundUpTo4(header.dwHeight); // 1 byte per pixel so this should be right. *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; break; default: - ERROR_LOG(G3D, "DXGI pixel format %d not supported.", header10.dxgiFormat); + WARN_LOG(G3D, "DXGI pixel format %d not supported.", header10.dxgiFormat); good = false; } } else { + if (!desc_->formatSupport.bc123) { + WARN_LOG(G3D, "BC1-3 formats not supported"); + good = false; + } ddsBytesToRead = header.dwPitchOrLinearSize; format = header.ddspf.dwFourCC; // OK, there are a number of possible formats we might have ended up with. We choose just a few @@ -370,7 +378,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D out.resize(ddsBytesToRead); size_t read_bytes = vfs_->Read(openFile, &out[0], ddsBytesToRead); if (read_bytes != ddsBytesToRead) { - WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", ddsBytesToRead, read_bytes); + WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", ddsBytesToRead, (int)read_bytes); } } else if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 264525b0c3..54b24b4bb6 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -72,6 +72,13 @@ enum class ReplacementState : uint32_t { const char *StateString(ReplacementState state); +struct GPUFormatSupport { + bool bc123; + bool astc; + bool bc7; + bool etc2; +}; + struct ReplacementDesc { int newW; int newH; @@ -85,6 +92,7 @@ struct ReplacementDesc { std::vector filenames; std::string logId; ReplacedLevelsCache *cache; + GPUFormatSupport formatSupport; }; struct ReplacedLevelsCache { diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 94bf8c4126..1a073f4558 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -55,7 +55,11 @@ static const int VERSION = 1; static const double MAX_CACHE_SIZE = 4.0; TextureReplacer::TextureReplacer(Draw::DrawContext *draw) { - // TODO: Check draw for supported texture formats. + // We don't want to keep the draw object around, so extract the info we need. + if (draw->GetDataFormatSupport(Draw::DataFormat::BC3_UNORM_BLOCK)) formatSupport_.bc123 = true; + if (draw->GetDataFormatSupport(Draw::DataFormat::ASTC_4x4_UNORM_BLOCK)) formatSupport_.astc = true; + if (draw->GetDataFormatSupport(Draw::DataFormat::BC7_UNORM_BLOCK)) formatSupport_.bc7 = true; + if (draw->GetDataFormatSupport(Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK)) formatSupport_.etc2 = true; } TextureReplacer::~TextureReplacer() { @@ -487,6 +491,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey desc->cachekey = cachekey; desc->hash = hash; desc->basePath = basePath_; + desc->formatSupport = formatSupport_; LookupHashRange(cachekey >> 32, desc->newW, desc->newH); if (ignoreAddress_) { diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 4766351b2a..5fecf5020f 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -93,7 +93,7 @@ enum class ReplacerDecimateMode { class TextureReplacer { public: - // The draw context will be checked for supported texture formats. + // The draw context is checked for supported texture formats. TextureReplacer(Draw::DrawContext *draw); ~TextureReplacer(); @@ -152,6 +152,7 @@ protected: VFSBackend *vfs_ = nullptr; bool vfsIsZip_ = false; + GPUFormatSupport formatSupport_{}; typedef std::pair WidthHeightPair; std::unordered_map hashranges_; From aaa83897fe00e2a011e070117e45cf23a15e5ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 13:30:28 +0100 Subject: [PATCH 295/424] Some code moving, tweaks --- GPU/Common/ReplacedTexture.cpp | 60 +++++++++++++++++----------------- UI/DevScreens.cpp | 4 +-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 646bc19f06..214b57bc9c 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -84,6 +84,36 @@ private: LimitedWaitable *waitable_; }; +ReplacedTexture::~ReplacedTexture() { + if (threadWaitable_) { + SetState(ReplacementState::CANCEL_INIT); + + std::unique_lock lock(mutex_); + threadWaitable_->WaitAndRelease(); + threadWaitable_ = nullptr; + } + + for (auto &level : levels_) { + vfs_->ReleaseFile(level.fileRef); + level.fileRef = nullptr; + } +} + +void ReplacedTexture::PurgeIfOlder(double t) { + if (threadWaitable_ && !threadWaitable_->WaitFor(0.0)) + return; + if (lastUsed_ >= t) + return; + + if (levelData_->lastUsed < t) { + // We have to lock since multiple textures might reference this same data. + std::lock_guard guard(levelData_->lock); + levelData_->data.clear(); + // This means we have to reload. If we never purge any, there's no need. + SetState(ReplacementState::POPULATED); + } +} + // This can only return true if ACTIVE or NOT_FOUND. bool ReplacedTexture::IsReady(double budget) { _assert_(vfs_ != nullptr); @@ -476,36 +506,6 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D return true; } -void ReplacedTexture::PurgeIfOlder(double t) { - if (threadWaitable_ && !threadWaitable_->WaitFor(0.0)) - return; - if (lastUsed_ >= t) - return; - - if (levelData_->lastUsed < t) { - // We have to lock since multiple textures might reference this same data. - std::lock_guard guard(levelData_->lock); - levelData_->data.clear(); - // This means we have to reload. If we never purge any, there's no need. - SetState(ReplacementState::POPULATED); - } -} - -ReplacedTexture::~ReplacedTexture() { - if (threadWaitable_) { - SetState(ReplacementState::CANCEL_INIT); - - std::unique_lock lock(mutex_); - threadWaitable_->WaitAndRelease(); - threadWaitable_ = nullptr; - } - - for (auto &level : levels_) { - vfs_->ReleaseFile(level.fileRef); - level.fileRef = nullptr; - } -} - bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index f54480ef51..d02791a59d 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -559,8 +559,8 @@ void SystemInfoScreen::CreateViews() { // Simple non-detailed summary of supported tex compression formats. if (draw->GetDataFormatSupport(Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK)) texCompressionFormats += "ETC2 "; if (draw->GetDataFormatSupport(Draw::DataFormat::ASTC_4x4_UNORM_BLOCK)) texCompressionFormats += "ASTC "; - if (draw->GetDataFormatSupport(Draw::DataFormat::BC1_RGBA_UNORM_BLOCK)) texCompressionFormats += "BC1,2,3 "; - if (draw->GetDataFormatSupport(Draw::DataFormat::BC4_UNORM_BLOCK)) texCompressionFormats += "BC4,5 "; + if (draw->GetDataFormatSupport(Draw::DataFormat::BC1_RGBA_UNORM_BLOCK)) texCompressionFormats += "BC1-3 "; + if (draw->GetDataFormatSupport(Draw::DataFormat::BC4_UNORM_BLOCK)) texCompressionFormats += "BC4-5 "; if (draw->GetDataFormatSupport(Draw::DataFormat::BC7_UNORM_BLOCK)) texCompressionFormats += "BC7 "; deviceSpecs->Add(new InfoItem(si->T("Compressed texture formats"), texCompressionFormats)); From b595a1dc4d87a07eb1c5bc2320f75cb4c969edb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 16:14:42 +0100 Subject: [PATCH 296/424] Prepare LoadLevelData for loading multiple mips. --- GPU/Common/ReplacedTexture.cpp | 35 ++++++++++++++++------------------ GPU/Common/ReplacedTexture.h | 3 +-- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 214b57bc9c..d07c18cac1 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -196,27 +196,18 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { break; } - const Path filename = desc_->basePath / desc_->filenames[i]; - VFSFileReference *fileRef = vfs_->GetFile(desc_->filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. break; } - // TODO: Here, if we find a file with multiple built-in mipmap levels, - // we'll have to change a bit how things work... - ReplacedTextureLevel level; - level.file = filename; - if (i == 0) { fmt = Draw::DataFormat::R8G8B8A8_UNORM; } - level.fileRef = fileRef; - Draw::DataFormat pixelFormat; - if (LoadLevelData(level, i, &pixelFormat)) { + if (LoadLevelData(fileRef, desc_->filenames[i], i, &pixelFormat)) { if (i == 0) { fmt = pixelFormat; } else { @@ -225,7 +216,6 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { break; } } - levels_.push_back(level); } else { // Otherwise, we're done loading mips (bad PNG or bad size, either way.) break; @@ -253,7 +243,11 @@ inline uint32_t RoundUpTo4(uint32_t value) { return (value + 3) & ~3; } -bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, Draw::DataFormat *pixelFormat) { +// Returns true if Prepare should keep calling this to load more levels. +bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int mipLevel, Draw::DataFormat *pixelFormat) { + ReplacedTextureLevel level; + level.fileRef = fileRef; + bool good = false; if (levelData_->data.size() <= mipLevel) { @@ -360,12 +354,12 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D level.h = headerPeek.Height(); good = true; } else { - ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", level.file.ToVisualString().c_str()); + ERROR_LOG(G3D, "Could not get PNG dimensions: %s (zip)", filename.c_str()); good = false; } *pixelFormat = Draw::DataFormat::R8G8B8A8_UNORM; } else { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", level.file.ToVisualString().c_str(), magic.c_str()); + ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", filename.c_str(), magic.c_str()); } // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. @@ -420,7 +414,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", level.file.c_str()); + ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", filename.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; @@ -430,7 +424,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D uint8_t *image; if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > level.w || h > level.h) { - ERROR_LOG(G3D, "Texture replacement changed since header read: %s", level.file.c_str()); + ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; @@ -459,13 +453,13 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D pngdata.resize(fileSize); pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { - ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", level.file.c_str(), png.message); + ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", filename.c_str(), png.message); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } if (png.width > (uint32_t)level.w || png.height > (uint32_t)level.h) { - ERROR_LOG(G3D, "Texture replacement changed since header read: %s", level.file.c_str()); + ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); SetState(ReplacementState::NOT_FOUND); cleanup(); return false; @@ -483,7 +477,7 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D out.resize(level.w * level.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { - ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", level.file.c_str(), png.message); + ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); SetState(ReplacementState::NOT_FOUND); cleanup(); out.resize(0); @@ -503,6 +497,9 @@ bool ReplacedTexture::LoadLevelData(ReplacedTextureLevel &level, int mipLevel, D } cleanup(); + + levels_.push_back(level); + return true; } diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 54b24b4bb6..0eccb0ab7f 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -54,7 +54,6 @@ static const int MAX_REPLACEMENT_MIP_LEVELS = 12; // 12 should be plenty, 8 is struct ReplacedTextureLevel { int w = 0; int h = 0; - Path file; // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. @@ -153,7 +152,7 @@ struct ReplacedTexture { private: void Prepare(VFSBackend *vfs); - bool LoadLevelData(ReplacedTextureLevel &info, int level, Draw::DataFormat *pixelFormat); + bool LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat); void PurgeIfOlder(double t); std::vector levels_; From b2c5c7845a9981fe7577c4340ff7617e8c82ee72 Mon Sep 17 00:00:00 2001 From: Lubos Date: Sun, 12 Mar 2023 19:22:31 +0100 Subject: [PATCH 297/424] OpenXR - World unit scale for SSX defined --- assets/compatvr.ini | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assets/compatvr.ini b/assets/compatvr.ini index 7159a0b650..55c2f84291 100644 --- a/assets/compatvr.ini +++ b/assets/compatvr.ini @@ -608,6 +608,12 @@ ULES01402 = 10.0 ULJM05812 = 10.0 ULUS10513 = 10.0 +# SSX On Tour +ULES00192 = 50.0 +ULJM05063 = 50.0 +ULJM05389 = 50.0 +ULUS10042 = 50.0 + # Star Trek: Tactical Assault ULES00623 = 0.01 ULUS10150 = 0.01 From 5ce48a51c170dfef85498a5f834c992117bb24b2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Mar 2023 13:01:08 -0700 Subject: [PATCH 298/424] unittest: Prevent assert running without AVX. Running unittests shouldn't require the host to have AVX. --- unittest/TestX64Emitter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unittest/TestX64Emitter.cpp b/unittest/TestX64Emitter.cpp index 14f1a003c2..52433cdb91 100644 --- a/unittest/TestX64Emitter.cpp +++ b/unittest/TestX64Emitter.cpp @@ -2,6 +2,7 @@ #if PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(X86) +#include "Common/CPUDetect.h" #include "Common/x64Emitter.h" #include "Core/MIPS/x86/RegCacheFPU.h" #include "Core/MIPS/x86/Jit.h" @@ -33,6 +34,9 @@ bool TestX64Emitter() { u32 code[512]; XEmitter emitter((u8 *)code); + bool prevAVX = cpu_info.bAVX; + cpu_info.bAVX = true; + prevStart = emitter.GetCodePointer(); emitter.VADDSD(XMM0, XMM1, R(XMM7)); RET(CheckLast(emitter, "vaddsd xmm0, xmm1, xmm7")); @@ -41,6 +45,8 @@ bool TestX64Emitter() { emitter.VMULSD(XMM0, XMM1, R(XMM7)); RET(CheckLast(emitter, "vmulsd xmm0, xmm1, xmm7")); + cpu_info.bAVX = prevAVX; + // Just for checking. PrintLast(emitter); return true; From 7e910b7d658c9f7cf78f410deb98acf1ad4580b2 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Mar 2023 13:34:10 -0700 Subject: [PATCH 299/424] Headless: Allow @listfile to run multiple. Just for easy debugging of a long list of tests. --- headless/Headless.cpp | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 9f9da25825..ec6e75b076 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -264,6 +264,28 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const return passed; } +std::vector ReadFromListFile(const std::string &listFilename) { + std::vector testFilenames; + char temp[2048]{}; + + if (listFilename == "-") { + while (scanf("%2047s", temp) == 1) + testFilenames.push_back(temp); + } else { + FILE *fp = File::OpenCFile(Path(listFilename), "rt"); + if (!fp) { + fprintf(stderr, "Unable to open '%s' as a list file\n", listFilename.c_str()); + return testFilenames; + } + + while (fscanf(fp, "%2047s", temp) == 1) + testFilenames.push_back(temp); + fclose(fp); + } + + return testFilenames; +} + int main(int argc, const char* argv[]) { PROFILE_INIT(); @@ -363,16 +385,8 @@ int main(int argc, const char* argv[]) testFilenames.push_back(argv[i]); } - // TODO: Allow a filename here? - if (testFilenames.size() == 1 && testFilenames[0] == "@-") - { - testFilenames.clear(); - char temp[2048]; - temp[2047] = '\0'; - - while (scanf("%2047s", temp) == 1) - testFilenames.push_back(temp); - } + if (testFilenames.size() == 1 && testFilenames[0][0] == '@') + testFilenames = ReadFromListFile(testFilenames[0].substr(1)); if (testFilenames.empty()) return printUsage(argv[0], argc <= 1 ? NULL : "No executables specified"); From c127ff47a34d489ba1c657d09d8359a08feb8183 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Mar 2023 13:34:41 -0700 Subject: [PATCH 300/424] Headless: Load assets from parent dir on Windows. This is the default debug setting in our MSVC project, so make it easy. --- headless/WindowsHeadlessHost.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 406f234d7d..60c701e33b 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -71,6 +71,7 @@ void WindowsHeadlessHost::LoadNativeAssets() g_VFS.Register("", new DirectoryReader(Path("assets"))); g_VFS.Register("", new DirectoryReader(Path(""))); g_VFS.Register("", new DirectoryReader(Path(".."))); + g_VFS.Register("", new DirectoryReader(Path("../assets"))); g_VFS.Register("", new DirectoryReader(Path("../Windows/assets"))); g_VFS.Register("", new DirectoryReader(Path("../Windows"))); } From b1b8fc65cfb0a922eb67ed882767efec4c63b3c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 19:20:01 +0100 Subject: [PATCH 301/424] Error handling fixes (close the file). --- GPU/Common/ReplacedTexture.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index d07c18cac1..d8803a5f8a 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -364,6 +364,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. if (!out.empty()) { + vfs_->CloseFile(openFile); *pixelFormat = levelData_->fmt; return true; } @@ -382,6 +383,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } if (!good) { + vfs_->CloseFile(openFile); return false; } From f88633b69650087bd1d0a37d71ca4ea51bfbbf24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 23:04:50 +0100 Subject: [PATCH 302/424] Add support for loading multiple mipmaps from DDS files. --- GPU/Common/ReplacedTexture.cpp | 68 +++++++++++++++++++------------ GPU/Vulkan/TextureCacheVulkan.cpp | 6 +-- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index d8803a5f8a..3cd62638af 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -245,19 +245,15 @@ inline uint32_t RoundUpTo4(uint32_t value) { // Returns true if Prepare should keep calling this to load more levels. bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int mipLevel, Draw::DataFormat *pixelFormat) { - ReplacedTextureLevel level; - level.fileRef = fileRef; - bool good = false; if (levelData_->data.size() <= mipLevel) { levelData_->data.resize(mipLevel + 1); } - std::vector &out = levelData_->data[mipLevel]; - + ReplacedTextureLevel level; size_t fileSize; - VFSOpenFile *openFile = vfs_->OpenFileForRead(level.fileRef, &fileSize); + VFSOpenFile *openFile = vfs_->OpenFileForRead(fileRef, &fileSize); if (!openFile) { return false; } @@ -265,7 +261,6 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string std::string magic; ReplacedImageType imageType = Identify(vfs_, openFile, &magic); - int ddsBytesToRead = 0; // Used by the DDS reader only. bool ddsDX10 = false; int numMips = 1; @@ -290,7 +285,6 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string WARN_LOG(G3D, "BC1-3 formats not supported, skipping texture"); good = false; } - ddsBytesToRead = RoundUpTo4(header.dwWidth) * RoundUpTo4(header.dwHeight); // 1 byte per pixel so this should be right. *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; break; default: @@ -302,7 +296,6 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string WARN_LOG(G3D, "BC1-3 formats not supported"); good = false; } - ddsBytesToRead = header.dwPitchOrLinearSize; format = header.ddspf.dwFourCC; // OK, there are a number of possible formats we might have ended up with. We choose just a few // to support for now. @@ -329,10 +322,6 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string level.w = header.dwWidth; level.h = header.dwHeight; numMips = header.dwMipMapCount; - - if (numMips > 1) { - WARN_LOG(G3D, "DDS file contains more than one mip level. Ignoring for now."); - } } else if (imageType == ReplacedImageType::ZIM) { uint32_t ignore = 0; struct ZimHeader { @@ -362,8 +351,9 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", filename.c_str(), magic.c_str()); } + // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. - if (!out.empty()) { + if (!levelData_->data[mipLevel].empty()) { vfs_->CloseFile(openFile); *pixelFormat = levelData_->fmt; return true; @@ -393,6 +383,8 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string vfs_->Rewind(openFile); + level.fileRef = fileRef; + if (imageType == ReplacedImageType::DDS) { DDSHeader header; DDSHeaderDXT10 header10{}; @@ -400,13 +392,32 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string if (ddsDX10) { vfs_->Read(openFile, &header10, sizeof(header10)); } - // For compressed formats (we don't support uncompressed DDS files yet), this is supposed to be the linear size. - out.resize(ddsBytesToRead); - size_t read_bytes = vfs_->Read(openFile, &out[0], ddsBytesToRead); - if (read_bytes != ddsBytesToRead) { - WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", ddsBytesToRead, (int)read_bytes); + + int blockSize = 0; + bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); + _dbg_assert_(bc); + + levelData_->data.resize(numMips); + + // A DDS File can contain multiple mipmaps. + for (int i = 0; i < numMips; i++) { + std::vector &out = levelData_->data[mipLevel + i]; + + int bytesToRead = RoundUpTo4(level.w) * RoundUpTo4(level.h) * blockSize / 16; + out.resize(bytesToRead); + + size_t read_bytes = vfs_->Read(openFile, &out[0], bytesToRead); + if (read_bytes != bytesToRead) { + WARN_LOG(G3D, "DDS: Expected %d bytes, got %d", bytesToRead, (int)read_bytes); + } + + levels_.push_back(level); + level.w /= 2; + level.h /= 2; + level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. } } else if (imageType == ReplacedImageType::ZIM) { + std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); @@ -424,6 +435,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string int w, h, f; uint8_t *image; + std::vector &out = levelData_->data[mipLevel]; if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > level.w || h > level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); @@ -441,11 +453,14 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } } free(image); - } - CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], level.w, w, h, 0xFF000000); - if (res == CHECKALPHA_ANY || mipLevel == 0) { - alphaStatus_ = ReplacedTextureAlpha(res); + CheckAlphaResult res = CheckAlpha32Rect((u32 *)&out[0], level.w, w, h, 0xFF000000); + if (res == CHECKALPHA_ANY || mipLevel == 0) { + alphaStatus_ = ReplacedTextureAlpha(res); + } + levels_.push_back(level); + } else { + good = false; } } else if (imageType == ReplacedImageType::PNG) { png_image png = {}; @@ -477,6 +492,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } png.format = PNG_FORMAT_RGBA; + std::vector &out = levelData_->data[mipLevel]; out.resize(level.w * level.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); @@ -494,15 +510,15 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string alphaStatus_ = ReplacedTextureAlpha(res); } } + + levels_.push_back(level); } else { WARN_LOG(G3D, "Don't know how to load this image type! %d", (int)imageType); } cleanup(); - levels_.push_back(level); - - return true; + return good; } bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 20a8345c84..6417bb8491 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -584,11 +584,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { bool dataScaled = true; if (plan.replaceValid) { - int bufferRowLength = byteStride; + int rowLength = pixelStride; if (bcFormat) { // For block compressed formats, we just set the upload size to the data size.. uploadSize = plan.replaced->GetLevelDataSize(plan.baseLevelSrc + i); - bufferRowLength = mipWidth; + rowLength = (mipWidth + 3) & ~3; } // Directly load the replaced image. data = pushBuffer->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); @@ -600,7 +600,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { replacementTimeThisFrame_ += time_now_d() - replaceStart; VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, "Copy Upload (replaced): %dx%d", mipWidth, mipHeight); - entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, pixelStride); + entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, rowLength); VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); } else { if (plan.depth != 1) { From 1860a73d58b8bbb265eef8acdd4cf8dcfa0a0ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 23:14:20 +0100 Subject: [PATCH 303/424] Address feedback from previous PR --- Common/Thread/ParallelLoop.cpp | 6 +++--- GPU/Common/ReplacedTexture.cpp | 3 +-- GPU/Common/TextureCacheCommon.cpp | 4 ++-- GPU/Vulkan/TextureCacheVulkan.cpp | 3 --- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Common/Thread/ParallelLoop.cpp b/Common/Thread/ParallelLoop.cpp index 18ec756e4e..2b5f8b0606 100644 --- a/Common/Thread/ParallelLoop.cpp +++ b/Common/Thread/ParallelLoop.cpp @@ -111,8 +111,8 @@ void ParallelRangeLoop(ThreadManager *threadMan, const std::functionstatus |= TexCacheEntry::STATUS_TO_REPLACE; break; - default: - break; + default: + break; } replacementTimeThisFrame_ += time_now_d() - replaceStart; return replaced; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 6417bb8491..e18fd7c5d5 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -455,9 +455,6 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { Draw::DataFormat fmt = plan.replaced->Format(); bcFormat = Draw::DataFormatIsBlockCompressed(fmt, &bcAlign); actualFmt = ToVulkanFormat(fmt); - if (actualFmt != VULKAN_8888_FORMAT) { - actualFmt = actualFmt; - } } bool computeUpload = false; From c32e3f89f122e8b7d9bd0ba5ab09bdb7b6eb643f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 23:31:51 +0100 Subject: [PATCH 304/424] D3D11 mipmap stride fix --- GPU/D3D11/TextureCacheD3D11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index d23b41d4ab..ffdf94c61a 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -301,7 +301,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (plan.replaceValid) { int blockSize = 0; if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { - stride = mipWidth * 4; // This stride value doesn't quite make sense to me, but it works. + stride = ((mipWidth + 3) & ~3) * 4; // This stride value doesn't quite make sense to me, but it works. dataSize = plan.replaced->GetLevelDataSize(i); } else { int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); From 2a20c5757f99805e5b097f43da7eb20cb080b73c Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Mar 2023 16:46:19 -0700 Subject: [PATCH 305/424] Build: Fix build on Visual Studio 2019. --- GPU/Common/ReplacedTexture.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index d07c18cac1..5e6a606b39 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include #include "ppsspp_config.h" #include From 9f04d09fb4c3f471452557a619cd8d81915d95b6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 12 Mar 2023 16:46:51 -0700 Subject: [PATCH 306/424] Headless: Use a single method for assets paths. There were multiple ways and this likely makes more sense. --- headless/Headless.cpp | 31 ++++++++++++++++++++----------- headless/SDLHeadlessHost.cpp | 8 -------- headless/SDLHeadlessHost.h | 2 -- headless/WindowsHeadlessHost.cpp | 12 ------------ headless/WindowsHeadlessHost.h | 2 -- 5 files changed, 20 insertions(+), 35 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index ec6e75b076..d6cef79416 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -474,21 +474,27 @@ int main(int argc, const char* argv[]) InitSysDirectories(); #endif + Path executablePath = File::GetExeDirectory(); #if !PPSSPP_PLATFORM(ANDROID) && !PPSSPP_PLATFORM(WINDOWS) g_Config.memStickDirectory = Path(std::string(getenv("HOME"))) / ".ppsspp"; - g_Config.flash0Directory = File::GetExeDirectory() / "assets/flash0"; + g_Config.flash0Directory = executablePath / "assets/flash0"; #endif // Try to find the flash0 directory. Often this is from a subdirectory. - for (int i = 0; i < 4 && !File::Exists(g_Config.flash0Directory); ++i) { - if (File::Exists(g_Config.flash0Directory / ".." / "assets/flash0")) - g_Config.flash0Directory = g_Config.flash0Directory / ".." / "assets/flash0"; - else - g_Config.flash0Directory = g_Config.flash0Directory / ".." / ".." / "flash0"; + Path nextPath = executablePath; + for (int i = 0; i < 5; ++i) { + if (File::Exists(nextPath / "assets/flash0")) { + g_Config.flash0Directory = nextPath / "assets/flash0"; +#if !PPSSPP_PLATFORM(ANDROID) + g_VFS.Register("", new DirectoryReader(nextPath / "assets")); +#endif + break; + } + + if (!nextPath.CanNavigateUp()) + break; + nextPath = nextPath.NavigateUp(); } - // Or else, maybe in the executable's dir. - if (!File::Exists(g_Config.flash0Directory)) - g_Config.flash0Directory = File::GetExeDirectory() / "assets/flash0"; if (screenshotFilename) headlessHost->SetComparisonScreenshot(Path(std::string(screenshotFilename)), testOptions.maxScreenshotError); @@ -502,8 +508,11 @@ int main(int argc, const char* argv[]) if (File::Exists(Path("/data/app/org.ppsspp.ppsspp.apk"))) { g_VFS.Register("", ZipFileReader::Create(Path("/data/app/org.ppsspp.ppsspp.apk"), "assets/")); } -#elif !PPSSPP_PLATFORM(WINDOWS) - g_VFS.Register("", new DirectoryReader(g_Config.flash0Directory / "..")); +#elif PPSSPP_PLATFORM(LINUX) + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/local/share/games/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/ppsspp/assets"))); + g_VFS.Register("", new DirectoryReader(Path("/usr/share/games/ppsspp/assets"))); #endif UpdateUIState(UISTATE_INGAME); diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index cd81eb2dd2..f26150feeb 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -99,12 +99,6 @@ private: SDL_GLContext glContext_; }; -void SDLHeadlessHost::LoadNativeAssets() { - g_VFS.Register("", new DirectoryReader(Path("assets"))); - g_VFS.Register("", new DirectoryReader(Path(""))); - g_VFS.Register("", new DirectoryReader(Path(".."))); -} - bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) { SDL_Init(SDL_INIT_VIDEO); @@ -203,8 +197,6 @@ bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext * }); th.detach(); - LoadNativeAssets(); - threadState_ = RenderThreadState::START_REQUESTED; while (threadState_ == RenderThreadState::START_REQUESTED || threadState_ == RenderThreadState::STARTING) sleep_ms(1); diff --git a/headless/SDLHeadlessHost.h b/headless/SDLHeadlessHost.h index 3907f3ab5e..47d92f509c 100644 --- a/headless/SDLHeadlessHost.h +++ b/headless/SDLHeadlessHost.h @@ -36,8 +36,6 @@ public: void SwapBuffers() override; protected: - void LoadNativeAssets(); - enum class RenderThreadState { IDLE, START_REQUESTED, diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index 60c701e33b..c190a8872b 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -66,16 +66,6 @@ HWND CreateHiddenWindow() { return CreateWindowEx(0, L"PPSSPPHeadless", L"PPSSPPHeadless", style, CW_USEDEFAULT, CW_USEDEFAULT, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, NULL, NULL); } -void WindowsHeadlessHost::LoadNativeAssets() -{ - g_VFS.Register("", new DirectoryReader(Path("assets"))); - g_VFS.Register("", new DirectoryReader(Path(""))); - g_VFS.Register("", new DirectoryReader(Path(".."))); - g_VFS.Register("", new DirectoryReader(Path("../assets"))); - g_VFS.Register("", new DirectoryReader(Path("../Windows/assets"))); - g_VFS.Register("", new DirectoryReader(Path("../Windows"))); -} - void WindowsHeadlessHost::SendDebugOutput(const std::string &output) { fwrite(output.data(), sizeof(char), output.length(), stdout); @@ -152,8 +142,6 @@ bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsConte th.detach(); } - LoadNativeAssets(); - if (needRenderThread) { threadState_ = RenderThreadState::START_REQUESTED; while (threadState_ == RenderThreadState::START_REQUESTED || threadState_ == RenderThreadState::STARTING) diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index 907b20cdf6..b0a3d3901c 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -37,8 +37,6 @@ public: void SendDebugOutput(const std::string &output) override; protected: - void LoadNativeAssets(); - enum class RenderThreadState { IDLE, START_REQUESTED, From 32e8ab3b5d024706fa8cdc215c19cc3c1f045ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 12 Mar 2023 23:50:30 +0100 Subject: [PATCH 307/424] Import all of basisu_transcoder, set up build --- CMakeLists.txt | 24 +- Common/Common.vcxproj | 20 + Common/Common.vcxproj.filters | 59 + GPU/Common/ReplacedTexture.cpp | 2 + android/jni/Android.mk | 1 + ext/basis_universal/basisu.h | 478 + ext/basis_universal/basisu_containers.h | 1986 ++ ext/basis_universal/basisu_containers_impl.h | 315 + ext/basis_universal/basisu_file_headers.h | 142 + ext/basis_universal/basisu_transcoder.cpp | 17479 ++++++++++++++++ ext/basis_universal/basisu_transcoder.h | 936 + .../basisu_transcoder_internal.h | 796 + .../basisu_transcoder_tables_astc.inc | 481 + .../basisu_transcoder_tables_astc_0_255.inc | 481 + .../basisu_transcoder_tables_atc_55.inc | 481 + .../basisu_transcoder_tables_atc_56.inc | 481 + .../basisu_transcoder_tables_bc7_m5_alpha.inc | 49 + .../basisu_transcoder_tables_bc7_m5_color.inc | 481 + .../basisu_transcoder_tables_dxt1_5.inc | 494 + .../basisu_transcoder_tables_dxt1_6.inc | 494 + .../basisu_transcoder_tables_pvrtc2_45.inc | 481 + ...sisu_transcoder_tables_pvrtc2_alpha_33.inc | 481 + ext/basis_universal/basisu_transcoder_uastc.h | 293 + libretro/Makefile.common | 3 + 24 files changed, 26937 insertions(+), 1 deletion(-) create mode 100644 ext/basis_universal/basisu.h create mode 100644 ext/basis_universal/basisu_containers.h create mode 100644 ext/basis_universal/basisu_containers_impl.h create mode 100644 ext/basis_universal/basisu_file_headers.h create mode 100644 ext/basis_universal/basisu_transcoder.cpp create mode 100644 ext/basis_universal/basisu_transcoder.h create mode 100644 ext/basis_universal/basisu_transcoder_internal.h create mode 100644 ext/basis_universal/basisu_transcoder_tables_astc.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_astc_0_255.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_atc_55.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_atc_56.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_bc7_m5_alpha.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_bc7_m5_color.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_dxt1_5.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_dxt1_6.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_pvrtc2_45.inc create mode 100644 ext/basis_universal/basisu_transcoder_tables_pvrtc2_alpha_33.inc create mode 100644 ext/basis_universal/basisu_transcoder_uastc.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9056de3389..36dbf12c73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1099,6 +1099,28 @@ else() include_directories(ext/libpng17) endif() +add_library(basis_universal STATIC + ext/basis_universal/basisu.h + ext/basis_universal/basisu_containers.h + ext/basis_universal/basisu_containers_impl.h + ext/basis_universal/basisu_file_headers.h + ext/basis_universal/basisu_transcoder.cpp + ext/basis_universal/basisu_transcoder.h + ext/basis_universal/basisu_transcoder_internal.h + ext/basis_universal/basisu_transcoder_tables_astc.inc + ext/basis_universal/basisu_transcoder_tables_astc_0_255.inc + ext/basis_universal/basisu_transcoder_tables_atc_55.inc + ext/basis_universal/basisu_transcoder_tables_atc_56.inc + ext/basis_universal/basisu_transcoder_tables_bc7_m5_alpha.inc + ext/basis_universal/basisu_transcoder_tables_bc7_m5_color.inc + ext/basis_universal/basisu_transcoder_tables_dxt1_5.inc + ext/basis_universal/basisu_transcoder_tables_dxt1_6.inc + ext/basis_universal/basisu_transcoder_tables_pvrtc2_45.inc + ext/basis_universal/basisu_transcoder_tables_pvrtc2_alpha_33.inc + ext/basis_universal/basisu_transcoder_uastc.h +) +set(BASISU_LIBRARIES basis_universal) + set(nativeExtra) set(nativeExtraLibs) @@ -1362,7 +1384,7 @@ if(ANDROID OR (LINUX AND ARM_DEVICE) OR (LINUX AND RISCV64)) set(ATOMIC_LIB atomic) endif() -target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARIES} ${ZLIB_LIBRARY} vma gason udis86 ${RT_LIB} ${nativeExtraLibs} ${ATOMIC_LIB} Common) +target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARIES} ${BASISU_LIBRARIES} ${ZLIB_LIBRARY} vma gason udis86 ${RT_LIB} ${nativeExtraLibs} ${ATOMIC_LIB} Common) if(TARGET Ext::GLEW) target_link_libraries(native Ext::GLEW) endif() diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 90d8d0d872..c066494c66 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -377,6 +377,13 @@ + + + + + + + @@ -577,6 +584,7 @@ + NotUsing NotUsing @@ -1034,6 +1042,18 @@ {f761046e-6c38-4428-a5f1-38391a37bb34} + + + + + + + + + + + + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 053702cd0a..cce4e7656a 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -473,6 +473,27 @@ Data\Format + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + @@ -896,6 +917,9 @@ Data\Format + + ext\basis_universal + @@ -1003,10 +1027,45 @@ {9d1c29fd-8ac7-4475-8ea6-c8c759b695fe} + + {d6d5f6e0-1c72-496b-af11-6d52d5123033} + ext\libpng17 + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + \ No newline at end of file diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 3fe5579175..f2497ae9b5 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -20,6 +20,8 @@ #include +#include "ext/basis_universal/basisu_transcoder.h" + #include "GPU/Common/ReplacedTexture.h" #include "GPU/Common/TextureReplacer.h" diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 6ff34b212f..61aaefc181 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -103,6 +103,7 @@ EXT_FILES := \ $(SRC)/ext/libpng17/pngwrite.c \ $(SRC)/ext/libpng17/pngwtran.c \ $(SRC)/ext/libpng17/pngwutil.c \ + $(SRC)/ext/basis_universal/basisu_transcoder.cpp \ $(SRC)/ext/jpge/jpgd.cpp \ $(SRC)/ext/jpge/jpge.cpp \ $(SRC)/ext/sha1/sha1.cpp \ diff --git a/ext/basis_universal/basisu.h b/ext/basis_universal/basisu.h new file mode 100644 index 0000000000..1230b59ec6 --- /dev/null +++ b/ext/basis_universal/basisu.h @@ -0,0 +1,478 @@ +// basisu.h +// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved. +// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef _MSC_VER + + #pragma warning (disable : 4201) + #pragma warning (disable : 4127) // warning C4127: conditional expression is constant + #pragma warning (disable : 4530) // C++ exception handler used, but unwind semantics are not enabled. + + // Slamming this off always for v1.16 because we've gotten rid of most std containers. + #ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL + #define BASISU_NO_ITERATOR_DEBUG_LEVEL (1) + #endif + + #ifndef BASISU_NO_ITERATOR_DEBUG_LEVEL + //#define _HAS_ITERATOR_DEBUGGING 0 + + #if defined(_DEBUG) || defined(DEBUG) + // This is madness, but we need to disable iterator debugging in debug builds or the encoder is unsable because MSVC's iterator debugging implementation is totally broken. + #ifndef _ITERATOR_DEBUG_LEVEL + #define _ITERATOR_DEBUG_LEVEL 1 + #endif + #ifndef _SECURE_SCL + #define _SECURE_SCL 1 + #endif + #else // defined(_DEBUG) || defined(DEBUG) + #ifndef _SECURE_SCL + #define _SECURE_SCL 0 + #endif + #ifndef _ITERATOR_DEBUG_LEVEL + #define _ITERATOR_DEBUG_LEVEL 0 + #endif + #endif // defined(_DEBUG) || defined(DEBUG) + + #endif // BASISU_NO_ITERATOR_DEBUG_LEVEL + +#endif // _MSC_VER + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "basisu_containers.h" + +#ifdef max +#undef max +#endif + +#ifdef min +#undef min +#endif + +#ifdef _WIN32 +#define strcasecmp _stricmp +#endif + +// Set to one to enable debug printf()'s when any errors occur, for development/debugging. Especially useful for WebGL development. +#ifndef BASISU_FORCE_DEVEL_MESSAGES +#define BASISU_FORCE_DEVEL_MESSAGES 0 +#endif + +#define BASISU_NOTE_UNUSED(x) (void)(x) +#define BASISU_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) +#define BASISU_NO_EQUALS_OR_COPY_CONSTRUCT(x) x(const x &) = delete; x& operator= (const x &) = delete; +#define BASISU_ASSUME(x) static_assert(x, #x); +#define BASISU_OFFSETOF(s, m) offsetof(s, m) +#define BASISU_STRINGIZE(x) #x +#define BASISU_STRINGIZE2(x) BASISU_STRINGIZE(x) + +#if BASISU_FORCE_DEVEL_MESSAGES + #define BASISU_DEVEL_ERROR(...) do { basisu::debug_printf(__VA_ARGS__); } while(0) +#else + #define BASISU_DEVEL_ERROR(...) +#endif + +namespace basisu +{ + // Types/utilities + +#ifdef _WIN32 + const char BASISU_PATH_SEPERATOR_CHAR = '\\'; +#else + const char BASISU_PATH_SEPERATOR_CHAR = '/'; +#endif + + typedef basisu::vector uint8_vec; + typedef basisu::vector int16_vec; + typedef basisu::vector uint16_vec; + typedef basisu::vector uint_vec; + typedef basisu::vector uint64_vec; + typedef basisu::vector int_vec; + typedef basisu::vector bool_vec; + + void enable_debug_printf(bool enabled); + void debug_printf(const char *pFmt, ...); + + + template inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); } + + template inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; } + + template inline S maximum(S a, S b) { return (a > b) ? a : b; } + template inline S maximum(S a, S b, S c) { return maximum(maximum(a, b), c); } + template inline S maximum(S a, S b, S c, S d) { return maximum(maximum(maximum(a, b), c), d); } + + template inline S minimum(S a, S b) { return (a < b) ? a : b; } + template inline S minimum(S a, S b, S c) { return minimum(minimum(a, b), c); } + template inline S minimum(S a, S b, S c, S d) { return minimum(minimum(minimum(a, b), c), d); } + + inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; } + inline float saturate(float value) { return clampf(value, 0, 1.0f); } + inline uint8_t minimumub(uint8_t a, uint8_t b) { return (a < b) ? a : b; } + inline uint32_t minimumu(uint32_t a, uint32_t b) { return (a < b) ? a : b; } + inline int32_t minimumi(int32_t a, int32_t b) { return (a < b) ? a : b; } + inline float minimumf(float a, float b) { return (a < b) ? a : b; } + inline uint8_t maximumub(uint8_t a, uint8_t b) { return (a > b) ? a : b; } + inline uint32_t maximumu(uint32_t a, uint32_t b) { return (a > b) ? a : b; } + inline int32_t maximumi(int32_t a, int32_t b) { return (a > b) ? a : b; } + inline float maximumf(float a, float b) { return (a > b) ? a : b; } + inline int squarei(int i) { return i * i; } + inline float squaref(float i) { return i * i; } + template inline T square(T a) { return a * a; } + + template inline S clamp(S value, S low, S high) { return (value < low) ? low : ((value > high) ? high : value); } + + inline uint32_t iabs(int32_t i) { return (i < 0) ? static_cast(-i) : static_cast(i); } + inline uint64_t iabs64(int64_t i) { return (i < 0) ? static_cast(-i) : static_cast(i); } + + template inline void clear_vector(T &vec) { vec.erase(vec.begin(), vec.end()); } + template inline typename T::value_type *enlarge_vector(T &vec, size_t n) { size_t cs = vec.size(); vec.resize(cs + n); return &vec[cs]; } + + inline bool is_pow2(uint32_t x) { return x && ((x & (x - 1U)) == 0U); } + inline bool is_pow2(uint64_t x) { return x && ((x & (x - 1U)) == 0U); } + + template inline T open_range_check(T v, T minv, T maxv) { assert(v >= minv && v < maxv); BASISU_NOTE_UNUSED(minv); BASISU_NOTE_UNUSED(maxv); return v; } + template inline T open_range_check(T v, T maxv) { assert(v < maxv); BASISU_NOTE_UNUSED(maxv); return v; } + + inline uint32_t total_bits(uint32_t v) { uint32_t l = 0; for ( ; v > 0U; ++l) v >>= 1; return l; } + + template inline T saturate(T val) { return clamp(val, 0.0f, 1.0f); } + + template inline void append_vector(T &vec, const R *pObjs, size_t n) + { + if (n) + { + if (vec.size()) + { + assert((pObjs + n) <= vec.begin() || (pObjs >= vec.end())); + } + const size_t cur_s = vec.size(); + vec.resize(cur_s + n); + memcpy(&vec[cur_s], pObjs, sizeof(R) * n); + } + } + + template inline void append_vector(T &vec, const T &other_vec) + { + assert(&vec != &other_vec); + if (other_vec.size()) + append_vector(vec, &other_vec[0], other_vec.size()); + } + + template inline void vector_ensure_element_is_valid(T &vec, size_t idx) + { + if (idx >= vec.size()) + vec.resize(idx + 1); + } + + template inline void vector_sort(T &vec) + { + if (vec.size()) + std::sort(vec.begin(), vec.end()); + } + + template inline bool unordered_set_contains(T& set, const U&obj) + { + return set.find(obj) != set.end(); + } + + template int vector_find(const T &vec, const typename T::value_type &obj) + { + assert(vec.size() <= INT_MAX); + for (size_t i = 0; i < vec.size(); i++) + if (vec[i] == obj) + return static_cast(i); + return -1; + } + + template void vector_set_all(T &vec, const typename T::value_type &obj) + { + for (size_t i = 0; i < vec.size(); i++) + vec[i] = obj; + } + + inline uint64_t read_be64(const void *p) + { + uint64_t val = 0; + for (uint32_t i = 0; i < 8; i++) + val |= (static_cast(static_cast(p)[7 - i]) << (i * 8)); + return val; + } + + inline void write_be64(void *p, uint64_t x) + { + for (uint32_t i = 0; i < 8; i++) + static_cast(p)[7 - i] = static_cast(x >> (i * 8)); + } + + static inline uint16_t byteswap16(uint16_t x) { return static_cast((x << 8) | (x >> 8)); } + static inline uint32_t byteswap32(uint32_t x) { return ((x << 24) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | (x >> 24)); } + + inline uint32_t floor_log2i(uint32_t v) + { + uint32_t b = 0; + for (; v > 1U; ++b) + v >>= 1; + return b; + } + + inline uint32_t ceil_log2i(uint32_t v) + { + uint32_t b = floor_log2i(v); + if ((b != 32) && (v > (1U << b))) + ++b; + return b; + } + + inline int posmod(int x, int y) + { + if (x >= 0) + return (x < y) ? x : (x % y); + int m = (-x) % y; + return (m != 0) ? (y - m) : m; + } + + inline bool do_excl_ranges_overlap(int la, int ha, int lb, int hb) + { + assert(la < ha && lb < hb); + if ((ha <= lb) || (la >= hb)) return false; + return true; + } + + static inline uint32_t read_le_dword(const uint8_t *pBytes) + { + return (pBytes[3] << 24U) | (pBytes[2] << 16U) | (pBytes[1] << 8U) | (pBytes[0]); + } + + static inline void write_le_dword(uint8_t* pBytes, uint32_t val) + { + pBytes[0] = (uint8_t)val; + pBytes[1] = (uint8_t)(val >> 8U); + pBytes[2] = (uint8_t)(val >> 16U); + pBytes[3] = (uint8_t)(val >> 24U); + } + + // Always little endian 1-8 byte unsigned int + template + struct packed_uint + { + uint8_t m_bytes[NumBytes]; + + inline packed_uint() { static_assert(NumBytes <= sizeof(uint64_t), "Invalid NumBytes"); } + inline packed_uint(uint64_t v) { *this = v; } + inline packed_uint(const packed_uint& other) { *this = other; } + + inline packed_uint& operator= (uint64_t v) + { + for (uint32_t i = 0; i < NumBytes; i++) + m_bytes[i] = static_cast(v >> (i * 8)); + return *this; + } + + inline packed_uint& operator= (const packed_uint& rhs) + { + memcpy(m_bytes, rhs.m_bytes, sizeof(m_bytes)); + return *this; + } + + inline operator uint32_t() const + { + switch (NumBytes) + { + case 1: + { + return m_bytes[0]; + } + case 2: + { + return (m_bytes[1] << 8U) | m_bytes[0]; + } + case 3: + { + return (m_bytes[2] << 16U) | (m_bytes[1] << 8U) | m_bytes[0]; + } + case 4: + { + return read_le_dword(m_bytes); + } + case 5: + { + uint32_t l = read_le_dword(m_bytes); + uint32_t h = m_bytes[4]; + return static_cast(l) | (static_cast(h) << 32U); + } + case 6: + { + uint32_t l = read_le_dword(m_bytes); + uint32_t h = (m_bytes[5] << 8U) | m_bytes[4]; + return static_cast(l) | (static_cast(h) << 32U); + } + case 7: + { + uint32_t l = read_le_dword(m_bytes); + uint32_t h = (m_bytes[6] << 16U) | (m_bytes[5] << 8U) | m_bytes[4]; + return static_cast(l) | (static_cast(h) << 32U); + } + case 8: + { + uint32_t l = read_le_dword(m_bytes); + uint32_t h = read_le_dword(m_bytes + 4); + return static_cast(l) | (static_cast(h) << 32U); + } + default: + { + assert(0); + return 0; + } + } + } + }; + + enum eZero { cZero }; + enum eNoClamp { cNoClamp }; + + // Rice/Huffman entropy coding + + // This is basically Deflate-style canonical Huffman, except we allow for a lot more symbols. + enum + { + cHuffmanMaxSupportedCodeSize = 16, cHuffmanMaxSupportedInternalCodeSize = 31, + cHuffmanFastLookupBits = 10, + cHuffmanMaxSymsLog2 = 14, cHuffmanMaxSyms = 1 << cHuffmanMaxSymsLog2, + + // Small zero runs + cHuffmanSmallZeroRunSizeMin = 3, cHuffmanSmallZeroRunSizeMax = 10, cHuffmanSmallZeroRunExtraBits = 3, + + // Big zero run + cHuffmanBigZeroRunSizeMin = 11, cHuffmanBigZeroRunSizeMax = 138, cHuffmanBigZeroRunExtraBits = 7, + + // Small non-zero run + cHuffmanSmallRepeatSizeMin = 3, cHuffmanSmallRepeatSizeMax = 6, cHuffmanSmallRepeatExtraBits = 2, + + // Big non-zero run + cHuffmanBigRepeatSizeMin = 7, cHuffmanBigRepeatSizeMax = 134, cHuffmanBigRepeatExtraBits = 7, + + cHuffmanTotalCodelengthCodes = 21, cHuffmanSmallZeroRunCode = 17, cHuffmanBigZeroRunCode = 18, cHuffmanSmallRepeatCode = 19, cHuffmanBigRepeatCode = 20 + }; + + static const uint8_t g_huffman_sorted_codelength_codes[] = { cHuffmanSmallZeroRunCode, cHuffmanBigZeroRunCode, cHuffmanSmallRepeatCode, cHuffmanBigRepeatCode, 0, 8, 7, 9, 6, 0xA, 5, 0xB, 4, 0xC, 3, 0xD, 2, 0xE, 1, 0xF, 0x10 }; + const uint32_t cHuffmanTotalSortedCodelengthCodes = sizeof(g_huffman_sorted_codelength_codes) / sizeof(g_huffman_sorted_codelength_codes[0]); + + // GPU texture formats + + enum class texture_format + { + cInvalidTextureFormat = -1, + + // Block-based formats + cETC1, // ETC1 + cETC1S, // ETC1 (subset: diff colors only, no subblocks) + cETC2_RGB, // ETC2 color block (basisu doesn't support ETC2 planar/T/H modes - just basic ETC1) + cETC2_RGBA, // ETC2 EAC alpha block followed by ETC2 color block + cETC2_ALPHA, // ETC2 EAC alpha block + cBC1, // DXT1 + cBC3, // DXT5 (BC4/DXT5A block followed by a BC1/DXT1 block) + cBC4, // DXT5A + cBC5, // 3DC/DXN (two BC4/DXT5A blocks) + cBC7, + cASTC4x4, // LDR only + cPVRTC1_4_RGB, + cPVRTC1_4_RGBA, + cATC_RGB, + cATC_RGBA_INTERPOLATED_ALPHA, + cFXT1_RGB, + cPVRTC2_4_RGBA, + cETC2_R11_EAC, + cETC2_RG11_EAC, + cUASTC4x4, + cBC1_NV, + cBC1_AMD, + + // Uncompressed/raw pixels + cRGBA32, + cRGB565, + cBGR565, + cRGBA4444, + cABGR4444 + }; + + inline uint32_t get_bytes_per_block(texture_format fmt) + { + switch (fmt) + { + case texture_format::cETC1: + case texture_format::cETC1S: + case texture_format::cETC2_RGB: + case texture_format::cETC2_ALPHA: + case texture_format::cBC1: + case texture_format::cBC1_NV: + case texture_format::cBC1_AMD: + case texture_format::cBC4: + case texture_format::cPVRTC1_4_RGB: + case texture_format::cPVRTC1_4_RGBA: + case texture_format::cATC_RGB: + case texture_format::cPVRTC2_4_RGBA: + case texture_format::cETC2_R11_EAC: + return 8; + case texture_format::cRGBA32: + return sizeof(uint32_t) * 16; + default: + break; + } + return 16; + } + + inline uint32_t get_qwords_per_block(texture_format fmt) + { + return get_bytes_per_block(fmt) >> 3; + } + + inline uint32_t get_block_width(texture_format fmt) + { + BASISU_NOTE_UNUSED(fmt); + switch (fmt) + { + case texture_format::cFXT1_RGB: + return 8; + default: + break; + } + return 4; + } + + inline uint32_t get_block_height(texture_format fmt) + { + BASISU_NOTE_UNUSED(fmt); + return 4; + } + +} // namespace basisu + diff --git a/ext/basis_universal/basisu_containers.h b/ext/basis_universal/basisu_containers.h new file mode 100644 index 0000000000..d123ce4788 --- /dev/null +++ b/ext/basis_universal/basisu_containers.h @@ -0,0 +1,1986 @@ +// basisu_containers.h +#pragma once + +#undef new + +#include +#include +#include +#include +#include + +#if defined(__linux__) && !defined(ANDROID) +// Only for malloc_usable_size() in basisu_containers_impl.h +#include +#define HAS_MALLOC_USABLE_SIZE 1 +#endif + +// Set to 1 to always check vector operator[], front(), and back() even in release. +#define BASISU_VECTOR_FORCE_CHECKING 0 + +// If 1, the vector container will not query the CRT to get the size of resized memory blocks. +#define BASISU_VECTOR_DETERMINISTIC 1 + +#ifdef _MSC_VER +#define BASISU_FORCE_INLINE __forceinline +#else +#define BASISU_FORCE_INLINE inline +#endif + +namespace basisu +{ + enum { cInvalidIndex = -1 }; + + namespace helpers + { + inline bool is_power_of_2(uint32_t x) { return x && ((x & (x - 1U)) == 0U); } + inline bool is_power_of_2(uint64_t x) { return x && ((x & (x - 1U)) == 0U); } + template const T& minimum(const T& a, const T& b) { return (b < a) ? b : a; } + template const T& maximum(const T& a, const T& b) { return (a < b) ? b : a; } + + inline uint32_t floor_log2i(uint32_t v) + { + uint32_t l = 0; + while (v > 1U) + { + v >>= 1; + l++; + } + return l; + } + + inline uint32_t next_pow2(uint32_t val) + { + val--; + val |= val >> 16; + val |= val >> 8; + val |= val >> 4; + val |= val >> 2; + val |= val >> 1; + return val + 1; + } + + inline uint64_t next_pow2(uint64_t val) + { + val--; + val |= val >> 32; + val |= val >> 16; + val |= val >> 8; + val |= val >> 4; + val |= val >> 2; + val |= val >> 1; + return val + 1; + } + } // namespace helpers + + template + inline T* construct(T* p) + { + return new (static_cast(p)) T; + } + + template + inline T* construct(T* p, const U& init) + { + return new (static_cast(p)) T(init); + } + + template + inline void construct_array(T* p, size_t n) + { + T* q = p + n; + for (; p != q; ++p) + new (static_cast(p)) T; + } + + template + inline void construct_array(T* p, size_t n, const U& init) + { + T* q = p + n; + for (; p != q; ++p) + new (static_cast(p)) T(init); + } + + template + inline void destruct(T* p) + { + (void)p; + p->~T(); + } + + template inline void destruct_array(T* p, size_t n) + { + T* q = p + n; + for (; p != q; ++p) + p->~T(); + } + + template struct int_traits { enum { cMin = INT32_MIN, cMax = INT32_MAX, cSigned = true }; }; + + template<> struct int_traits { enum { cMin = INT8_MIN, cMax = INT8_MAX, cSigned = true }; }; + template<> struct int_traits { enum { cMin = INT16_MIN, cMax = INT16_MAX, cSigned = true }; }; + template<> struct int_traits { enum { cMin = INT32_MIN, cMax = INT32_MAX, cSigned = true }; }; + + template<> struct int_traits { enum { cMin = 0, cMax = UINT8_MAX, cSigned = false }; }; + template<> struct int_traits { enum { cMin = 0, cMax = UINT16_MAX, cSigned = false }; }; + template<> struct int_traits { enum { cMin = 0, cMax = UINT32_MAX, cSigned = false }; }; + + template + struct scalar_type + { + enum { cFlag = false }; + static inline void construct(T* p) { basisu::construct(p); } + static inline void construct(T* p, const T& init) { basisu::construct(p, init); } + static inline void construct_array(T* p, size_t n) { basisu::construct_array(p, n); } + static inline void destruct(T* p) { basisu::destruct(p); } + static inline void destruct_array(T* p, size_t n) { basisu::destruct_array(p, n); } + }; + + template struct scalar_type + { + enum { cFlag = true }; + static inline void construct(T** p) { memset(p, 0, sizeof(T*)); } + static inline void construct(T** p, T* init) { *p = init; } + static inline void construct_array(T** p, size_t n) { memset(p, 0, sizeof(T*) * n); } + static inline void destruct(T** p) { p; } + static inline void destruct_array(T** p, size_t n) { p, n; } + }; + +#define BASISU_DEFINE_BUILT_IN_TYPE(X) \ + template<> struct scalar_type { \ + enum { cFlag = true }; \ + static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \ + static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \ + static inline void construct_array(X* p, size_t n) { memset(p, 0, sizeof(X) * n); } \ + static inline void destruct(X* p) { p; } \ + static inline void destruct_array(X* p, size_t n) { p, n; } }; + + BASISU_DEFINE_BUILT_IN_TYPE(bool) + BASISU_DEFINE_BUILT_IN_TYPE(char) + BASISU_DEFINE_BUILT_IN_TYPE(unsigned char) + BASISU_DEFINE_BUILT_IN_TYPE(short) + BASISU_DEFINE_BUILT_IN_TYPE(unsigned short) + BASISU_DEFINE_BUILT_IN_TYPE(int) + BASISU_DEFINE_BUILT_IN_TYPE(unsigned int) + BASISU_DEFINE_BUILT_IN_TYPE(long) + BASISU_DEFINE_BUILT_IN_TYPE(unsigned long) +#ifdef __GNUC__ + BASISU_DEFINE_BUILT_IN_TYPE(long long) + BASISU_DEFINE_BUILT_IN_TYPE(unsigned long long) +#else + BASISU_DEFINE_BUILT_IN_TYPE(__int64) + BASISU_DEFINE_BUILT_IN_TYPE(unsigned __int64) +#endif + BASISU_DEFINE_BUILT_IN_TYPE(float) + BASISU_DEFINE_BUILT_IN_TYPE(double) + BASISU_DEFINE_BUILT_IN_TYPE(long double) + +#undef BASISU_DEFINE_BUILT_IN_TYPE + + template + struct bitwise_movable { enum { cFlag = false }; }; + +#define BASISU_DEFINE_BITWISE_MOVABLE(Q) template<> struct bitwise_movable { enum { cFlag = true }; }; + + template + struct bitwise_copyable { enum { cFlag = false }; }; + +#define BASISU_DEFINE_BITWISE_COPYABLE(Q) template<> struct bitwise_copyable { enum { cFlag = true }; }; + +#define BASISU_IS_POD(T) __is_pod(T) + +#define BASISU_IS_SCALAR_TYPE(T) (scalar_type::cFlag) + +#if defined(__GNUC__) && __GNUC__<5 + #define BASISU_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__) +#else + #define BASISU_IS_TRIVIALLY_COPYABLE(...) std::is_trivially_copyable<__VA_ARGS__>::value +#endif + +// TODO: clean this up +#define BASISU_IS_BITWISE_COPYABLE(T) (BASISU_IS_SCALAR_TYPE(T) || BASISU_IS_POD(T) || BASISU_IS_TRIVIALLY_COPYABLE(T) || (bitwise_copyable::cFlag)) + +#define BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(T) (BASISU_IS_BITWISE_COPYABLE(T) || (bitwise_movable::cFlag)) + +#define BASISU_HAS_DESTRUCTOR(T) ((!scalar_type::cFlag) && (!__is_pod(T))) + + typedef char(&yes_t)[1]; + typedef char(&no_t)[2]; + + template yes_t class_test(int U::*); + template no_t class_test(...); + + template struct is_class + { + enum { value = (sizeof(class_test(0)) == sizeof(yes_t)) }; + }; + + template struct is_pointer + { + enum { value = false }; + }; + + template struct is_pointer + { + enum { value = true }; + }; + + struct empty_type { }; + + BASISU_DEFINE_BITWISE_COPYABLE(empty_type); + BASISU_DEFINE_BITWISE_MOVABLE(empty_type); + + template struct rel_ops + { + friend bool operator!=(const T& x, const T& y) { return (!(x == y)); } + friend bool operator> (const T& x, const T& y) { return (y < x); } + friend bool operator<=(const T& x, const T& y) { return (!(y < x)); } + friend bool operator>=(const T& x, const T& y) { return (!(x < y)); } + }; + + struct elemental_vector + { + void* m_p; + uint32_t m_size; + uint32_t m_capacity; + + typedef void (*object_mover)(void* pDst, void* pSrc, uint32_t num); + + bool increase_capacity(uint32_t min_new_capacity, bool grow_hint, uint32_t element_size, object_mover pRelocate, bool nofail); + }; + + template + class vector : public rel_ops< vector > + { + public: + typedef T* iterator; + typedef const T* const_iterator; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + + inline vector() : + m_p(NULL), + m_size(0), + m_capacity(0) + { + } + + inline vector(uint32_t n, const T& init) : + m_p(NULL), + m_size(0), + m_capacity(0) + { + increase_capacity(n, false); + construct_array(m_p, n, init); + m_size = n; + } + + inline vector(const vector& other) : + m_p(NULL), + m_size(0), + m_capacity(0) + { + increase_capacity(other.m_size, false); + + m_size = other.m_size; + + if (BASISU_IS_BITWISE_COPYABLE(T)) + { + if ((m_p) && (other.m_p)) + memcpy(m_p, other.m_p, m_size * sizeof(T)); + } + else + { + T* pDst = m_p; + const T* pSrc = other.m_p; + for (uint32_t i = m_size; i > 0; i--) + construct(pDst++, *pSrc++); + } + } + + inline explicit vector(size_t size) : + m_p(NULL), + m_size(0), + m_capacity(0) + { + resize(size); + } + + inline ~vector() + { + if (m_p) + { + scalar_type::destruct_array(m_p, m_size); + free(m_p); + } + } + + inline vector& operator= (const vector& other) + { + if (this == &other) + return *this; + + if (m_capacity >= other.m_size) + resize(0); + else + { + clear(); + increase_capacity(other.m_size, false); + } + + if (BASISU_IS_BITWISE_COPYABLE(T)) + { + if ((m_p) && (other.m_p)) + memcpy(m_p, other.m_p, other.m_size * sizeof(T)); + } + else + { + T* pDst = m_p; + const T* pSrc = other.m_p; + for (uint32_t i = other.m_size; i > 0; i--) + construct(pDst++, *pSrc++); + } + + m_size = other.m_size; + + return *this; + } + + BASISU_FORCE_INLINE const T* begin() const { return m_p; } + BASISU_FORCE_INLINE T* begin() { return m_p; } + + BASISU_FORCE_INLINE const T* end() const { return m_p + m_size; } + BASISU_FORCE_INLINE T* end() { return m_p + m_size; } + + BASISU_FORCE_INLINE bool empty() const { return !m_size; } + BASISU_FORCE_INLINE uint32_t size() const { return m_size; } + BASISU_FORCE_INLINE uint32_t size_in_bytes() const { return m_size * sizeof(T); } + BASISU_FORCE_INLINE uint32_t capacity() const { return m_capacity; } + + // operator[] will assert on out of range indices, but in final builds there is (and will never be) any range checking on this method. + //BASISU_FORCE_INLINE const T& operator[] (uint32_t i) const { assert(i < m_size); return m_p[i]; } + //BASISU_FORCE_INLINE T& operator[] (uint32_t i) { assert(i < m_size); return m_p[i]; } + +#if !BASISU_VECTOR_FORCE_CHECKING + BASISU_FORCE_INLINE const T& operator[] (size_t i) const { assert(i < m_size); return m_p[i]; } + BASISU_FORCE_INLINE T& operator[] (size_t i) { assert(i < m_size); return m_p[i]; } +#else + BASISU_FORCE_INLINE const T& operator[] (size_t i) const + { + if (i >= m_size) + { + fprintf(stderr, "operator[] invalid index: %u, max entries %u, type size %u\n", (uint32_t)i, m_size, (uint32_t)sizeof(T)); + abort(); + } + return m_p[i]; + } + BASISU_FORCE_INLINE T& operator[] (size_t i) + { + if (i >= m_size) + { + fprintf(stderr, "operator[] invalid index: %u, max entries %u, type size %u\n", (uint32_t)i, m_size, (uint32_t)sizeof(T)); + abort(); + } + return m_p[i]; + } +#endif + + // at() always includes range checking, even in final builds, unlike operator []. + // The first element is returned if the index is out of range. + BASISU_FORCE_INLINE const T& at(size_t i) const { assert(i < m_size); return (i >= m_size) ? m_p[0] : m_p[i]; } + BASISU_FORCE_INLINE T& at(size_t i) { assert(i < m_size); return (i >= m_size) ? m_p[0] : m_p[i]; } + +#if !BASISU_VECTOR_FORCE_CHECKING + BASISU_FORCE_INLINE const T& front() const { assert(m_size); return m_p[0]; } + BASISU_FORCE_INLINE T& front() { assert(m_size); return m_p[0]; } + + BASISU_FORCE_INLINE const T& back() const { assert(m_size); return m_p[m_size - 1]; } + BASISU_FORCE_INLINE T& back() { assert(m_size); return m_p[m_size - 1]; } +#else + BASISU_FORCE_INLINE const T& front() const + { + if (!m_size) + { + fprintf(stderr, "front: vector is empty, type size %u\n", (uint32_t)sizeof(T)); + abort(); + } + return m_p[0]; + } + BASISU_FORCE_INLINE T& front() + { + if (!m_size) + { + fprintf(stderr, "front: vector is empty, type size %u\n", (uint32_t)sizeof(T)); + abort(); + } + return m_p[0]; + } + + BASISU_FORCE_INLINE const T& back() const + { + if(!m_size) + { + fprintf(stderr, "back: vector is empty, type size %u\n", (uint32_t)sizeof(T)); + abort(); + } + return m_p[m_size - 1]; + } + BASISU_FORCE_INLINE T& back() + { + if (!m_size) + { + fprintf(stderr, "back: vector is empty, type size %u\n", (uint32_t)sizeof(T)); + abort(); + } + return m_p[m_size - 1]; + } +#endif + + BASISU_FORCE_INLINE const T* get_ptr() const { return m_p; } + BASISU_FORCE_INLINE T* get_ptr() { return m_p; } + + BASISU_FORCE_INLINE const T* data() const { return m_p; } + BASISU_FORCE_INLINE T* data() { return m_p; } + + // clear() sets the container to empty, then frees the allocated block. + inline void clear() + { + if (m_p) + { + scalar_type::destruct_array(m_p, m_size); + free(m_p); + m_p = NULL; + m_size = 0; + m_capacity = 0; + } + } + + inline void clear_no_destruction() + { + if (m_p) + { + free(m_p); + m_p = NULL; + m_size = 0; + m_capacity = 0; + } + } + + inline void reserve(size_t new_capacity_size_t) + { + if (new_capacity_size_t > UINT32_MAX) + { + assert(0); + return; + } + + uint32_t new_capacity = (uint32_t)new_capacity_size_t; + + if (new_capacity > m_capacity) + increase_capacity(new_capacity, false); + else if (new_capacity < m_capacity) + { + // Must work around the lack of a "decrease_capacity()" method. + // This case is rare enough in practice that it's probably not worth implementing an optimized in-place resize. + vector tmp; + tmp.increase_capacity(helpers::maximum(m_size, new_capacity), false); + tmp = *this; + swap(tmp); + } + } + + inline bool try_reserve(size_t new_capacity_size_t) + { + if (new_capacity_size_t > UINT32_MAX) + { + assert(0); + return false; + } + + uint32_t new_capacity = (uint32_t)new_capacity_size_t; + + if (new_capacity > m_capacity) + { + if (!increase_capacity(new_capacity, false)) + return false; + } + else if (new_capacity < m_capacity) + { + // Must work around the lack of a "decrease_capacity()" method. + // This case is rare enough in practice that it's probably not worth implementing an optimized in-place resize. + vector tmp; + tmp.increase_capacity(helpers::maximum(m_size, new_capacity), false); + tmp = *this; + swap(tmp); + } + + return true; + } + + // resize(0) sets the container to empty, but does not free the allocated block. + inline void resize(size_t new_size_size_t, bool grow_hint = false) + { + if (new_size_size_t > UINT32_MAX) + { + assert(0); + return; + } + + uint32_t new_size = (uint32_t)new_size_size_t; + + if (m_size != new_size) + { + if (new_size < m_size) + scalar_type::destruct_array(m_p + new_size, m_size - new_size); + else + { + if (new_size > m_capacity) + increase_capacity(new_size, (new_size == (m_size + 1)) || grow_hint); + + scalar_type::construct_array(m_p + m_size, new_size - m_size); + } + + m_size = new_size; + } + } + + inline bool try_resize(size_t new_size_size_t, bool grow_hint = false) + { + if (new_size_size_t > UINT32_MAX) + { + assert(0); + return false; + } + + uint32_t new_size = (uint32_t)new_size_size_t; + + if (m_size != new_size) + { + if (new_size < m_size) + scalar_type::destruct_array(m_p + new_size, m_size - new_size); + else + { + if (new_size > m_capacity) + { + if (!increase_capacity(new_size, (new_size == (m_size + 1)) || grow_hint, true)) + return false; + } + + scalar_type::construct_array(m_p + m_size, new_size - m_size); + } + + m_size = new_size; + } + + return true; + } + + // If size >= capacity/2, reset() sets the container's size to 0 but doesn't free the allocated block (because the container may be similarly loaded in the future). + // Otherwise it blows away the allocated block. See http://www.codercorner.com/blog/?p=494 + inline void reset() + { + if (m_size >= (m_capacity >> 1)) + resize(0); + else + clear(); + } + + inline T* enlarge(uint32_t i) + { + uint32_t cur_size = m_size; + resize(cur_size + i, true); + return get_ptr() + cur_size; + } + + inline T* try_enlarge(uint32_t i) + { + uint32_t cur_size = m_size; + if (!try_resize(cur_size + i, true)) + return NULL; + return get_ptr() + cur_size; + } + + BASISU_FORCE_INLINE void push_back(const T& obj) + { + assert(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size))); + + if (m_size >= m_capacity) + increase_capacity(m_size + 1, true); + + scalar_type::construct(m_p + m_size, obj); + m_size++; + } + + inline bool try_push_back(const T& obj) + { + assert(!m_p || (&obj < m_p) || (&obj >= (m_p + m_size))); + + if (m_size >= m_capacity) + { + if (!increase_capacity(m_size + 1, true, true)) + return false; + } + + scalar_type::construct(m_p + m_size, obj); + m_size++; + + return true; + } + + inline void push_back_value(T obj) + { + if (m_size >= m_capacity) + increase_capacity(m_size + 1, true); + + scalar_type::construct(m_p + m_size, obj); + m_size++; + } + + inline void pop_back() + { + assert(m_size); + + if (m_size) + { + m_size--; + scalar_type::destruct(&m_p[m_size]); + } + } + + inline void insert(uint32_t index, const T* p, uint32_t n) + { + assert(index <= m_size); + if (!n) + return; + + const uint32_t orig_size = m_size; + resize(m_size + n, true); + + const uint32_t num_to_move = orig_size - index; + + if (BASISU_IS_BITWISE_COPYABLE(T)) + { + // This overwrites the destination object bits, but bitwise copyable means we don't need to worry about destruction. + memmove(m_p + index + n, m_p + index, sizeof(T) * num_to_move); + } + else + { + const T* pSrc = m_p + orig_size - 1; + T* pDst = const_cast(pSrc) + n; + + for (uint32_t i = 0; i < num_to_move; i++) + { + assert((pDst - m_p) < (int)m_size); + *pDst-- = *pSrc--; + } + } + + T* pDst = m_p + index; + + if (BASISU_IS_BITWISE_COPYABLE(T)) + { + // This copies in the new bits, overwriting the existing objects, which is OK for copyable types that don't need destruction. + memcpy(pDst, p, sizeof(T) * n); + } + else + { + for (uint32_t i = 0; i < n; i++) + { + assert((pDst - m_p) < (int)m_size); + *pDst++ = *p++; + } + } + } + + inline void insert(T* p, const T& obj) + { + int64_t ofs = p - begin(); + if ((ofs < 0) || (ofs > UINT32_MAX)) + { + assert(0); + return; + } + + insert((uint32_t)ofs, &obj, 1); + } + + // push_front() isn't going to be very fast - it's only here for usability. + inline void push_front(const T& obj) + { + insert(0, &obj, 1); + } + + vector& append(const vector& other) + { + if (other.m_size) + insert(m_size, &other[0], other.m_size); + return *this; + } + + vector& append(const T* p, uint32_t n) + { + if (n) + insert(m_size, p, n); + return *this; + } + + inline void erase(uint32_t start, uint32_t n) + { + assert((start + n) <= m_size); + if ((start + n) > m_size) + return; + + if (!n) + return; + + const uint32_t num_to_move = m_size - (start + n); + + T* pDst = m_p + start; + + const T* pSrc = m_p + start + n; + + if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(T)) + { + // This test is overly cautious. + if ((!BASISU_IS_BITWISE_COPYABLE(T)) || (BASISU_HAS_DESTRUCTOR(T))) + { + // Type has been marked explictly as bitwise movable, which means we can move them around but they may need to be destructed. + // First destroy the erased objects. + scalar_type::destruct_array(pDst, n); + } + + // Copy "down" the objects to preserve, filling in the empty slots. + memmove(pDst, pSrc, num_to_move * sizeof(T)); + } + else + { + // Type is not bitwise copyable or movable. + // Move them down one at a time by using the equals operator, and destroying anything that's left over at the end. + T* pDst_end = pDst + num_to_move; + while (pDst != pDst_end) + *pDst++ = *pSrc++; + + scalar_type::destruct_array(pDst_end, n); + } + + m_size -= n; + } + + inline void erase(uint32_t index) + { + erase(index, 1); + } + + inline void erase(T* p) + { + assert((p >= m_p) && (p < (m_p + m_size))); + erase(static_cast(p - m_p)); + } + + inline void erase(T *pFirst, T *pEnd) + { + assert(pFirst <= pEnd); + assert(pFirst >= begin() && pFirst <= end()); + assert(pEnd >= begin() && pEnd <= end()); + + int64_t ofs = pFirst - begin(); + if ((ofs < 0) || (ofs > UINT32_MAX)) + { + assert(0); + return; + } + + int64_t n = pEnd - pFirst; + if ((n < 0) || (n > UINT32_MAX)) + { + assert(0); + return; + } + + erase((uint32_t)ofs, (uint32_t)n); + } + + void erase_unordered(uint32_t index) + { + assert(index < m_size); + + if ((index + 1) < m_size) + (*this)[index] = back(); + + pop_back(); + } + + inline bool operator== (const vector& rhs) const + { + if (m_size != rhs.m_size) + return false; + else if (m_size) + { + if (scalar_type::cFlag) + return memcmp(m_p, rhs.m_p, sizeof(T) * m_size) == 0; + else + { + const T* pSrc = m_p; + const T* pDst = rhs.m_p; + for (uint32_t i = m_size; i; i--) + if (!(*pSrc++ == *pDst++)) + return false; + } + } + + return true; + } + + inline bool operator< (const vector& rhs) const + { + const uint32_t min_size = helpers::minimum(m_size, rhs.m_size); + + const T* pSrc = m_p; + const T* pSrc_end = m_p + min_size; + const T* pDst = rhs.m_p; + + while ((pSrc < pSrc_end) && (*pSrc == *pDst)) + { + pSrc++; + pDst++; + } + + if (pSrc < pSrc_end) + return *pSrc < *pDst; + + return m_size < rhs.m_size; + } + + inline void swap(vector& other) + { + std::swap(m_p, other.m_p); + std::swap(m_size, other.m_size); + std::swap(m_capacity, other.m_capacity); + } + + inline void sort() + { + std::sort(begin(), end()); + } + + inline void unique() + { + if (!empty()) + { + sort(); + + resize(std::unique(begin(), end()) - begin()); + } + } + + inline void reverse() + { + uint32_t j = m_size >> 1; + for (uint32_t i = 0; i < j; i++) + std::swap(m_p[i], m_p[m_size - 1 - i]); + } + + inline int find(const T& key) const + { + const T* p = m_p; + const T* p_end = m_p + m_size; + + uint32_t index = 0; + + while (p != p_end) + { + if (key == *p) + return index; + + p++; + index++; + } + + return cInvalidIndex; + } + + inline int find_sorted(const T& key) const + { + if (m_size) + { + // Uniform binary search - Knuth Algorithm 6.2.1 U, unrolled twice. + int i = ((m_size + 1) >> 1) - 1; + int m = m_size; + + for (; ; ) + { + assert(i >= 0 && i < (int)m_size); + const T* pKey_i = m_p + i; + int cmp = key < *pKey_i; +#if defined(_DEBUG) || defined(DEBUG) + int cmp2 = *pKey_i < key; + assert((cmp != cmp2) || (key == *pKey_i)); +#endif + if ((!cmp) && (key == *pKey_i)) return i; + m >>= 1; + if (!m) break; + cmp = -cmp; + i += (((m + 1) >> 1) ^ cmp) - cmp; + if (i < 0) + break; + + assert(i >= 0 && i < (int)m_size); + pKey_i = m_p + i; + cmp = key < *pKey_i; +#if defined(_DEBUG) || defined(DEBUG) + cmp2 = *pKey_i < key; + assert((cmp != cmp2) || (key == *pKey_i)); +#endif + if ((!cmp) && (key == *pKey_i)) return i; + m >>= 1; + if (!m) break; + cmp = -cmp; + i += (((m + 1) >> 1) ^ cmp) - cmp; + if (i < 0) + break; + } + } + + return cInvalidIndex; + } + + template + inline int find_sorted(const T& key, Q less_than) const + { + if (m_size) + { + // Uniform binary search - Knuth Algorithm 6.2.1 U, unrolled twice. + int i = ((m_size + 1) >> 1) - 1; + int m = m_size; + + for (; ; ) + { + assert(i >= 0 && i < (int)m_size); + const T* pKey_i = m_p + i; + int cmp = less_than(key, *pKey_i); + if ((!cmp) && (!less_than(*pKey_i, key))) return i; + m >>= 1; + if (!m) break; + cmp = -cmp; + i += (((m + 1) >> 1) ^ cmp) - cmp; + if (i < 0) + break; + + assert(i >= 0 && i < (int)m_size); + pKey_i = m_p + i; + cmp = less_than(key, *pKey_i); + if ((!cmp) && (!less_than(*pKey_i, key))) return i; + m >>= 1; + if (!m) break; + cmp = -cmp; + i += (((m + 1) >> 1) ^ cmp) - cmp; + if (i < 0) + break; + } + } + + return cInvalidIndex; + } + + inline uint32_t count_occurences(const T& key) const + { + uint32_t c = 0; + + const T* p = m_p; + const T* p_end = m_p + m_size; + + while (p != p_end) + { + if (key == *p) + c++; + + p++; + } + + return c; + } + + inline void set_all(const T& o) + { + if ((sizeof(T) == 1) && (scalar_type::cFlag)) + memset(m_p, *reinterpret_cast(&o), m_size); + else + { + T* pDst = m_p; + T* pDst_end = pDst + m_size; + while (pDst != pDst_end) + *pDst++ = o; + } + } + + // Caller assumes ownership of the heap block associated with the container. Container is cleared. + inline void* assume_ownership() + { + T* p = m_p; + m_p = NULL; + m_size = 0; + m_capacity = 0; + return p; + } + + // Caller is granting ownership of the indicated heap block. + // Block must have size constructed elements, and have enough room for capacity elements. + // The block must have been allocated using malloc(). + // Important: This method is used in Basis Universal. If you change how this container allocates memory, you'll need to change any users of this method. + inline bool grant_ownership(T* p, uint32_t size, uint32_t capacity) + { + // To to prevent the caller from obviously shooting themselves in the foot. + if (((p + capacity) > m_p) && (p < (m_p + m_capacity))) + { + // Can grant ownership of a block inside the container itself! + assert(0); + return false; + } + + if (size > capacity) + { + assert(0); + return false; + } + + if (!p) + { + if (capacity) + { + assert(0); + return false; + } + } + else if (!capacity) + { + assert(0); + return false; + } + + clear(); + m_p = p; + m_size = size; + m_capacity = capacity; + return true; + } + + private: + T* m_p; + uint32_t m_size; + uint32_t m_capacity; + + template struct is_vector { enum { cFlag = false }; }; + template struct is_vector< vector > { enum { cFlag = true }; }; + + static void object_mover(void* pDst_void, void* pSrc_void, uint32_t num) + { + T* pSrc = static_cast(pSrc_void); + T* const pSrc_end = pSrc + num; + T* pDst = static_cast(pDst_void); + + while (pSrc != pSrc_end) + { + // placement new + new (static_cast(pDst)) T(*pSrc); + pSrc->~T(); + ++pSrc; + ++pDst; + } + } + + inline bool increase_capacity(uint32_t min_new_capacity, bool grow_hint, bool nofail = false) + { + return reinterpret_cast(this)->increase_capacity( + min_new_capacity, grow_hint, sizeof(T), + (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(T) || (is_vector::cFlag)) ? NULL : object_mover, nofail); + } + }; + + template struct bitwise_movable< vector > { enum { cFlag = true }; }; + + // Hash map + + template + struct hasher + { + inline size_t operator() (const T& key) const { return static_cast(key); } + }; + + template + struct equal_to + { + inline bool operator()(const T& a, const T& b) const { return a == b; } + }; + + // Important: The Hasher and Equals objects must be bitwise movable! + template, typename Equals = equal_to > + class hash_map + { + public: + class iterator; + class const_iterator; + + private: + friend class iterator; + friend class const_iterator; + + enum state + { + cStateInvalid = 0, + cStateValid = 1 + }; + + enum + { + cMinHashSize = 4U + }; + + public: + typedef hash_map hash_map_type; + typedef std::pair value_type; + typedef Key key_type; + typedef Value referent_type; + typedef Hasher hasher_type; + typedef Equals equals_type; + + hash_map() : + m_hash_shift(32), m_num_valid(0), m_grow_threshold(0) + { + } + + hash_map(const hash_map& other) : + m_values(other.m_values), + m_hash_shift(other.m_hash_shift), + m_hasher(other.m_hasher), + m_equals(other.m_equals), + m_num_valid(other.m_num_valid), + m_grow_threshold(other.m_grow_threshold) + { + } + + hash_map& operator= (const hash_map& other) + { + if (this == &other) + return *this; + + clear(); + + m_values = other.m_values; + m_hash_shift = other.m_hash_shift; + m_num_valid = other.m_num_valid; + m_grow_threshold = other.m_grow_threshold; + m_hasher = other.m_hasher; + m_equals = other.m_equals; + + return *this; + } + + inline ~hash_map() + { + clear(); + } + + const Equals& get_equals() const { return m_equals; } + Equals& get_equals() { return m_equals; } + + void set_equals(const Equals& equals) { m_equals = equals; } + + const Hasher& get_hasher() const { return m_hasher; } + Hasher& get_hasher() { return m_hasher; } + + void set_hasher(const Hasher& hasher) { m_hasher = hasher; } + + inline void clear() + { + if (!m_values.empty()) + { + if (BASISU_HAS_DESTRUCTOR(Key) || BASISU_HAS_DESTRUCTOR(Value)) + { + node* p = &get_node(0); + node* p_end = p + m_values.size(); + + uint32_t num_remaining = m_num_valid; + while (p != p_end) + { + if (p->state) + { + destruct_value_type(p); + num_remaining--; + if (!num_remaining) + break; + } + + p++; + } + } + + m_values.clear_no_destruction(); + + m_hash_shift = 32; + m_num_valid = 0; + m_grow_threshold = 0; + } + } + + inline void reset() + { + if (!m_num_valid) + return; + + if (BASISU_HAS_DESTRUCTOR(Key) || BASISU_HAS_DESTRUCTOR(Value)) + { + node* p = &get_node(0); + node* p_end = p + m_values.size(); + + uint32_t num_remaining = m_num_valid; + while (p != p_end) + { + if (p->state) + { + destruct_value_type(p); + p->state = cStateInvalid; + + num_remaining--; + if (!num_remaining) + break; + } + + p++; + } + } + else if (sizeof(node) <= 32) + { + memset(&m_values[0], 0, m_values.size_in_bytes()); + } + else + { + node* p = &get_node(0); + node* p_end = p + m_values.size(); + + uint32_t num_remaining = m_num_valid; + while (p != p_end) + { + if (p->state) + { + p->state = cStateInvalid; + + num_remaining--; + if (!num_remaining) + break; + } + + p++; + } + } + + m_num_valid = 0; + } + + inline uint32_t size() + { + return m_num_valid; + } + + inline uint32_t get_table_size() + { + return m_values.size(); + } + + inline bool empty() + { + return !m_num_valid; + } + + inline void reserve(uint32_t new_capacity) + { + uint64_t new_hash_size = helpers::maximum(1U, new_capacity); + + new_hash_size = new_hash_size * 2ULL; + + if (!helpers::is_power_of_2(new_hash_size)) + new_hash_size = helpers::next_pow2(new_hash_size); + + new_hash_size = helpers::maximum(cMinHashSize, new_hash_size); + + new_hash_size = helpers::minimum(0x80000000UL, new_hash_size); + + if (new_hash_size > m_values.size()) + rehash((uint32_t)new_hash_size); + } + + class iterator + { + friend class hash_map; + friend class hash_map::const_iterator; + + public: + inline iterator() : m_pTable(NULL), m_index(0) { } + inline iterator(hash_map_type& table, uint32_t index) : m_pTable(&table), m_index(index) { } + inline iterator(const iterator& other) : m_pTable(other.m_pTable), m_index(other.m_index) { } + + inline iterator& operator= (const iterator& other) + { + m_pTable = other.m_pTable; + m_index = other.m_index; + return *this; + } + + // post-increment + inline iterator operator++(int) + { + iterator result(*this); + ++*this; + return result; + } + + // pre-increment + inline iterator& operator++() + { + probe(); + return *this; + } + + inline value_type& operator*() const { return *get_cur(); } + inline value_type* operator->() const { return get_cur(); } + + inline bool operator == (const iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); } + inline bool operator != (const iterator& b) const { return !(*this == b); } + inline bool operator == (const const_iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); } + inline bool operator != (const const_iterator& b) const { return !(*this == b); } + + private: + hash_map_type* m_pTable; + uint32_t m_index; + + inline value_type* get_cur() const + { + assert(m_pTable && (m_index < m_pTable->m_values.size())); + assert(m_pTable->get_node_state(m_index) == cStateValid); + + return &m_pTable->get_node(m_index); + } + + inline void probe() + { + assert(m_pTable); + m_index = m_pTable->find_next(m_index); + } + }; + + class const_iterator + { + friend class hash_map; + friend class hash_map::iterator; + + public: + inline const_iterator() : m_pTable(NULL), m_index(0) { } + inline const_iterator(const hash_map_type& table, uint32_t index) : m_pTable(&table), m_index(index) { } + inline const_iterator(const iterator& other) : m_pTable(other.m_pTable), m_index(other.m_index) { } + inline const_iterator(const const_iterator& other) : m_pTable(other.m_pTable), m_index(other.m_index) { } + + inline const_iterator& operator= (const const_iterator& other) + { + m_pTable = other.m_pTable; + m_index = other.m_index; + return *this; + } + + inline const_iterator& operator= (const iterator& other) + { + m_pTable = other.m_pTable; + m_index = other.m_index; + return *this; + } + + // post-increment + inline const_iterator operator++(int) + { + const_iterator result(*this); + ++*this; + return result; + } + + // pre-increment + inline const_iterator& operator++() + { + probe(); + return *this; + } + + inline const value_type& operator*() const { return *get_cur(); } + inline const value_type* operator->() const { return get_cur(); } + + inline bool operator == (const const_iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); } + inline bool operator != (const const_iterator& b) const { return !(*this == b); } + inline bool operator == (const iterator& b) const { return (m_pTable == b.m_pTable) && (m_index == b.m_index); } + inline bool operator != (const iterator& b) const { return !(*this == b); } + + private: + const hash_map_type* m_pTable; + uint32_t m_index; + + inline const value_type* get_cur() const + { + assert(m_pTable && (m_index < m_pTable->m_values.size())); + assert(m_pTable->get_node_state(m_index) == cStateValid); + + return &m_pTable->get_node(m_index); + } + + inline void probe() + { + assert(m_pTable); + m_index = m_pTable->find_next(m_index); + } + }; + + inline const_iterator begin() const + { + if (!m_num_valid) + return end(); + + return const_iterator(*this, find_next(UINT32_MAX)); + } + + inline const_iterator end() const + { + return const_iterator(*this, m_values.size()); + } + + inline iterator begin() + { + if (!m_num_valid) + return end(); + + return iterator(*this, find_next(UINT32_MAX)); + } + + inline iterator end() + { + return iterator(*this, m_values.size()); + } + + // insert_result.first will always point to inserted key/value (or the already existing key/value). + // insert_resutt.second will be true if a new key/value was inserted, or false if the key already existed (in which case first will point to the already existing value). + typedef std::pair insert_result; + + inline insert_result insert(const Key& k, const Value& v = Value()) + { + insert_result result; + if (!insert_no_grow(result, k, v)) + { + grow(); + + // This must succeed. + if (!insert_no_grow(result, k, v)) + { + fprintf(stderr, "insert() failed"); + abort(); + } + } + + return result; + } + + inline insert_result insert(const value_type& v) + { + return insert(v.first, v.second); + } + + inline const_iterator find(const Key& k) const + { + return const_iterator(*this, find_index(k)); + } + + inline iterator find(const Key& k) + { + return iterator(*this, find_index(k)); + } + + inline bool erase(const Key& k) + { + uint32_t i = find_index(k); + + if (i >= m_values.size()) + return false; + + node* pDst = &get_node(i); + destruct_value_type(pDst); + pDst->state = cStateInvalid; + + m_num_valid--; + + for (; ; ) + { + uint32_t r, j = i; + + node* pSrc = pDst; + + do + { + if (!i) + { + i = m_values.size() - 1; + pSrc = &get_node(i); + } + else + { + i--; + pSrc--; + } + + if (!pSrc->state) + return true; + + r = hash_key(pSrc->first); + + } while ((i <= r && r < j) || (r < j && j < i) || (j < i && i <= r)); + + move_node(pDst, pSrc); + + pDst = pSrc; + } + } + + inline void swap(hash_map_type& other) + { + m_values.swap(other.m_values); + std::swap(m_hash_shift, other.m_hash_shift); + std::swap(m_num_valid, other.m_num_valid); + std::swap(m_grow_threshold, other.m_grow_threshold); + std::swap(m_hasher, other.m_hasher); + std::swap(m_equals, other.m_equals); + } + + private: + struct node : public value_type + { + uint8_t state; + }; + + static inline void construct_value_type(value_type* pDst, const Key& k, const Value& v) + { + if (BASISU_IS_BITWISE_COPYABLE(Key)) + memcpy(&pDst->first, &k, sizeof(Key)); + else + scalar_type::construct(&pDst->first, k); + + if (BASISU_IS_BITWISE_COPYABLE(Value)) + memcpy(&pDst->second, &v, sizeof(Value)); + else + scalar_type::construct(&pDst->second, v); + } + + static inline void construct_value_type(value_type* pDst, const value_type* pSrc) + { + if ((BASISU_IS_BITWISE_COPYABLE(Key)) && (BASISU_IS_BITWISE_COPYABLE(Value))) + { + memcpy(pDst, pSrc, sizeof(value_type)); + } + else + { + if (BASISU_IS_BITWISE_COPYABLE(Key)) + memcpy(&pDst->first, &pSrc->first, sizeof(Key)); + else + scalar_type::construct(&pDst->first, pSrc->first); + + if (BASISU_IS_BITWISE_COPYABLE(Value)) + memcpy(&pDst->second, &pSrc->second, sizeof(Value)); + else + scalar_type::construct(&pDst->second, pSrc->second); + } + } + + static inline void destruct_value_type(value_type* p) + { + scalar_type::destruct(&p->first); + scalar_type::destruct(&p->second); + } + + // Moves *pSrc to *pDst efficiently. + // pDst should NOT be constructed on entry. + static inline void move_node(node* pDst, node* pSrc, bool update_src_state = true) + { + assert(!pDst->state); + + if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Key) && BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Value)) + { + memcpy(pDst, pSrc, sizeof(node)); + } + else + { + if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Key)) + memcpy(&pDst->first, &pSrc->first, sizeof(Key)); + else + { + scalar_type::construct(&pDst->first, pSrc->first); + scalar_type::destruct(&pSrc->first); + } + + if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Value)) + memcpy(&pDst->second, &pSrc->second, sizeof(Value)); + else + { + scalar_type::construct(&pDst->second, pSrc->second); + scalar_type::destruct(&pSrc->second); + } + + pDst->state = cStateValid; + } + + if (update_src_state) + pSrc->state = cStateInvalid; + } + + struct raw_node + { + inline raw_node() + { + node* p = reinterpret_cast(this); + p->state = cStateInvalid; + } + + inline ~raw_node() + { + node* p = reinterpret_cast(this); + if (p->state) + hash_map_type::destruct_value_type(p); + } + + inline raw_node(const raw_node& other) + { + node* pDst = reinterpret_cast(this); + const node* pSrc = reinterpret_cast(&other); + + if (pSrc->state) + { + hash_map_type::construct_value_type(pDst, pSrc); + pDst->state = cStateValid; + } + else + pDst->state = cStateInvalid; + } + + inline raw_node& operator= (const raw_node& rhs) + { + if (this == &rhs) + return *this; + + node* pDst = reinterpret_cast(this); + const node* pSrc = reinterpret_cast(&rhs); + + if (pSrc->state) + { + if (pDst->state) + { + pDst->first = pSrc->first; + pDst->second = pSrc->second; + } + else + { + hash_map_type::construct_value_type(pDst, pSrc); + pDst->state = cStateValid; + } + } + else if (pDst->state) + { + hash_map_type::destruct_value_type(pDst); + pDst->state = cStateInvalid; + } + + return *this; + } + + uint8_t m_bits[sizeof(node)]; + }; + + typedef basisu::vector node_vector; + + node_vector m_values; + uint32_t m_hash_shift; + + Hasher m_hasher; + Equals m_equals; + + uint32_t m_num_valid; + + uint32_t m_grow_threshold; + + inline uint32_t hash_key(const Key& k) const + { + assert((1U << (32U - m_hash_shift)) == m_values.size()); + + uint32_t hash = static_cast(m_hasher(k)); + + // Fibonacci hashing + hash = (2654435769U * hash) >> m_hash_shift; + + assert(hash < m_values.size()); + return hash; + } + + inline const node& get_node(uint32_t index) const + { + return *reinterpret_cast(&m_values[index]); + } + + inline node& get_node(uint32_t index) + { + return *reinterpret_cast(&m_values[index]); + } + + inline state get_node_state(uint32_t index) const + { + return static_cast(get_node(index).state); + } + + inline void set_node_state(uint32_t index, bool valid) + { + get_node(index).state = valid; + } + + inline void grow() + { + uint64_t n = m_values.size() * 3ULL; // was * 2 + + if (!helpers::is_power_of_2(n)) + n = helpers::next_pow2(n); + + if (n > 0x80000000UL) + n = 0x80000000UL; + + rehash(helpers::maximum(cMinHashSize, (uint32_t)n)); + } + + inline void rehash(uint32_t new_hash_size) + { + assert(new_hash_size >= m_num_valid); + assert(helpers::is_power_of_2(new_hash_size)); + + if ((new_hash_size < m_num_valid) || (new_hash_size == m_values.size())) + return; + + hash_map new_map; + new_map.m_values.resize(new_hash_size); + new_map.m_hash_shift = 32U - helpers::floor_log2i(new_hash_size); + assert(new_hash_size == (1U << (32U - new_map.m_hash_shift))); + new_map.m_grow_threshold = UINT_MAX; + + node* pNode = reinterpret_cast(m_values.begin()); + node* pNode_end = pNode + m_values.size(); + + while (pNode != pNode_end) + { + if (pNode->state) + { + new_map.move_into(pNode); + + if (new_map.m_num_valid == m_num_valid) + break; + } + + pNode++; + } + + new_map.m_grow_threshold = (new_hash_size + 1U) >> 1U; + + m_values.clear_no_destruction(); + m_hash_shift = 32; + + swap(new_map); + } + + inline uint32_t find_next(uint32_t index) const + { + index++; + + if (index >= m_values.size()) + return index; + + const node* pNode = &get_node(index); + + for (; ; ) + { + if (pNode->state) + break; + + if (++index >= m_values.size()) + break; + + pNode++; + } + + return index; + } + + inline uint32_t find_index(const Key& k) const + { + if (m_num_valid) + { + uint32_t index = hash_key(k); + const node* pNode = &get_node(index); + + if (pNode->state) + { + if (m_equals(pNode->first, k)) + return index; + + const uint32_t orig_index = index; + + for (; ; ) + { + if (!index) + { + index = m_values.size() - 1; + pNode = &get_node(index); + } + else + { + index--; + pNode--; + } + + if (index == orig_index) + break; + + if (!pNode->state) + break; + + if (m_equals(pNode->first, k)) + return index; + } + } + } + + return m_values.size(); + } + + inline bool insert_no_grow(insert_result& result, const Key& k, const Value& v = Value()) + { + if (!m_values.size()) + return false; + + uint32_t index = hash_key(k); + node* pNode = &get_node(index); + + if (pNode->state) + { + if (m_equals(pNode->first, k)) + { + result.first = iterator(*this, index); + result.second = false; + return true; + } + + const uint32_t orig_index = index; + + for (; ; ) + { + if (!index) + { + index = m_values.size() - 1; + pNode = &get_node(index); + } + else + { + index--; + pNode--; + } + + if (orig_index == index) + return false; + + if (!pNode->state) + break; + + if (m_equals(pNode->first, k)) + { + result.first = iterator(*this, index); + result.second = false; + return true; + } + } + } + + if (m_num_valid >= m_grow_threshold) + return false; + + construct_value_type(pNode, k, v); + + pNode->state = cStateValid; + + m_num_valid++; + assert(m_num_valid <= m_values.size()); + + result.first = iterator(*this, index); + result.second = true; + + return true; + } + + inline void move_into(node* pNode) + { + uint32_t index = hash_key(pNode->first); + node* pDst_node = &get_node(index); + + if (pDst_node->state) + { + const uint32_t orig_index = index; + + for (; ; ) + { + if (!index) + { + index = m_values.size() - 1; + pDst_node = &get_node(index); + } + else + { + index--; + pDst_node--; + } + + if (index == orig_index) + { + assert(false); + return; + } + + if (!pDst_node->state) + break; + } + } + + move_node(pDst_node, pNode, false); + + m_num_valid++; + } + }; + + template + struct bitwise_movable< hash_map > { enum { cFlag = true }; }; + +#if BASISU_HASHMAP_TEST + extern void hash_map_test(); +#endif + +} // namespace basisu + +namespace std +{ + template + inline void swap(basisu::vector& a, basisu::vector& b) + { + a.swap(b); + } + + template + inline void swap(basisu::hash_map& a, basisu::hash_map& b) + { + a.swap(b); + } + +} // namespace std diff --git a/ext/basis_universal/basisu_containers_impl.h b/ext/basis_universal/basisu_containers_impl.h new file mode 100644 index 0000000000..d5cb61569b --- /dev/null +++ b/ext/basis_universal/basisu_containers_impl.h @@ -0,0 +1,315 @@ +// basisu_containers_impl.h +// Do not include directly + +#ifdef _MSC_VER +#pragma warning (disable:4127) // warning C4127: conditional expression is constant +#endif + +namespace basisu +{ + bool elemental_vector::increase_capacity(uint32_t min_new_capacity, bool grow_hint, uint32_t element_size, object_mover pMover, bool nofail) + { + assert(m_size <= m_capacity); + + if (sizeof(void *) == sizeof(uint64_t)) + assert(min_new_capacity < (0x400000000ULL / element_size)); + else + assert(min_new_capacity < (0x7FFF0000U / element_size)); + + if (m_capacity >= min_new_capacity) + return true; + + size_t new_capacity = min_new_capacity; + if ((grow_hint) && (!helpers::is_power_of_2((uint64_t)new_capacity))) + { + new_capacity = (size_t)helpers::next_pow2((uint64_t)new_capacity); + + assert(new_capacity && (new_capacity > m_capacity)); + + if (new_capacity < min_new_capacity) + { + if (nofail) + return false; + fprintf(stderr, "vector too large\n"); + abort(); + } + } + + const size_t desired_size = element_size * new_capacity; + size_t actual_size = 0; + if (!pMover) + { + void* new_p = realloc(m_p, desired_size); + if (!new_p) + { + if (nofail) + return false; + + char buf[256]; +#ifdef _MSC_VER + sprintf_s(buf, sizeof(buf), "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size); +#else + sprintf(buf, "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size); +#endif + fprintf(stderr, "%s", buf); + abort(); + } + +#if BASISU_VECTOR_DETERMINISTIC + actual_size = desired_size; +#elif defined(_MSC_VER) + actual_size = _msize(new_p); +#elif HAS_MALLOC_USABLE_SIZE + actual_size = malloc_usable_size(new_p); +#else + actual_size = desired_size; +#endif + m_p = new_p; + } + else + { + void* new_p = malloc(desired_size); + if (!new_p) + { + if (nofail) + return false; + + char buf[256]; +#ifdef _MSC_VER + sprintf_s(buf, sizeof(buf), "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size); +#else + sprintf(buf, "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size); +#endif + fprintf(stderr, "%s", buf); + abort(); + } + +#if BASISU_VECTOR_DETERMINISTIC + actual_size = desired_size; +#elif defined(_MSC_VER) + actual_size = _msize(new_p); +#elif HAS_MALLOC_USABLE_SIZE + actual_size = malloc_usable_size(new_p); +#else + actual_size = desired_size; +#endif + + (*pMover)(new_p, m_p, m_size); + + if (m_p) + free(m_p); + + m_p = new_p; + } + + if (actual_size > desired_size) + m_capacity = static_cast(actual_size / element_size); + else + m_capacity = static_cast(new_capacity); + + return true; + } + +#if BASISU_HASHMAP_TEST + +#define HASHMAP_TEST_VERIFY(c) do { if (!(c)) handle_hashmap_test_verify_failure(__LINE__); } while(0) + + static void handle_hashmap_test_verify_failure(int line) + { + fprintf(stderr, "HASHMAP_TEST_VERIFY() faild on line %i\n", line); + abort(); + } + + class counted_obj + { + public: + counted_obj(uint32_t v = 0) : + m_val(v) + { + m_count++; + } + + counted_obj(const counted_obj& obj) : + m_val(obj.m_val) + { + m_count++; + } + + ~counted_obj() + { + assert(m_count > 0); + m_count--; + } + + static uint32_t m_count; + + uint32_t m_val; + + operator size_t() const { return m_val; } + + bool operator== (const counted_obj& rhs) const { return m_val == rhs.m_val; } + bool operator== (const uint32_t rhs) const { return m_val == rhs; } + + }; + + uint32_t counted_obj::m_count; + + static uint32_t urand32() + { + uint32_t a = rand(); + uint32_t b = rand() << 15; + uint32_t c = rand() << (32 - 15); + return a ^ b ^ c; + } + + static int irand32(int l, int h) + { + assert(l < h); + if (l >= h) + return l; + + uint32_t range = static_cast(h - l); + + uint32_t rnd = urand32(); + + uint32_t rnd_range = static_cast((((uint64_t)range) * ((uint64_t)rnd)) >> 32U); + + int result = l + rnd_range; + assert((result >= l) && (result < h)); + return result; + } + + void hash_map_test() + { + { + basisu::hash_map k; + basisu::hash_map l; + std::swap(k, l); + + k.begin(); + k.end(); + k.clear(); + k.empty(); + k.erase(0); + k.insert(0, 1); + k.find(0); + k.get_equals(); + k.get_hasher(); + k.get_table_size(); + k.reset(); + k.reserve(1); + k = l; + k.set_equals(l.get_equals()); + k.set_hasher(l.get_hasher()); + k.get_table_size(); + } + + uint32_t seed = 0; + for (; ; ) + { + seed++; + + typedef basisu::hash_map my_hash_map; + my_hash_map m; + + const uint32_t n = irand32(0, 100000); + + printf("%u\n", n); + + srand(seed); // r1.seed(seed); + + basisu::vector q; + + uint32_t count = 0; + for (uint32_t i = 0; i < n; i++) + { + uint32_t v = urand32() & 0x7FFFFFFF; + my_hash_map::insert_result res = m.insert(counted_obj(v), counted_obj(v ^ 0xdeadbeef)); + if (res.second) + { + count++; + q.push_back(v); + } + } + + HASHMAP_TEST_VERIFY(m.size() == count); + + srand(seed); + + my_hash_map cm(m); + m.clear(); + m = cm; + cm.reset(); + + for (uint32_t i = 0; i < n; i++) + { + uint32_t v = urand32() & 0x7FFFFFFF; + my_hash_map::const_iterator it = m.find(counted_obj(v)); + HASHMAP_TEST_VERIFY(it != m.end()); + HASHMAP_TEST_VERIFY(it->first == v); + HASHMAP_TEST_VERIFY(it->second == (v ^ 0xdeadbeef)); + } + + for (uint32_t t = 0; t < 2; t++) + { + const uint32_t nd = irand32(1, q.size() + 1); + for (uint32_t i = 0; i < nd; i++) + { + uint32_t p = irand32(0, q.size()); + + int k = q[p]; + if (k >= 0) + { + q[p] = -k - 1; + + bool s = m.erase(counted_obj(k)); + HASHMAP_TEST_VERIFY(s); + } + } + + typedef basisu::hash_map uint_hash_set; + uint_hash_set s; + + for (uint32_t i = 0; i < q.size(); i++) + { + int v = q[i]; + + if (v >= 0) + { + my_hash_map::const_iterator it = m.find(counted_obj(v)); + HASHMAP_TEST_VERIFY(it != m.end()); + HASHMAP_TEST_VERIFY(it->first == (uint32_t)v); + HASHMAP_TEST_VERIFY(it->second == ((uint32_t)v ^ 0xdeadbeef)); + + s.insert(v); + } + else + { + my_hash_map::const_iterator it = m.find(counted_obj(-v - 1)); + HASHMAP_TEST_VERIFY(it == m.end()); + } + } + + uint32_t found_count = 0; + for (my_hash_map::const_iterator it = m.begin(); it != m.end(); ++it) + { + HASHMAP_TEST_VERIFY(it->second == ((uint32_t)it->first ^ 0xdeadbeef)); + + uint_hash_set::const_iterator fit(s.find((uint32_t)it->first)); + HASHMAP_TEST_VERIFY(fit != s.end()); + + HASHMAP_TEST_VERIFY(fit->first == it->first); + + found_count++; + } + + HASHMAP_TEST_VERIFY(found_count == s.size()); + } + + HASHMAP_TEST_VERIFY(counted_obj::m_count == m.size() * 2); + } + } + +#endif // BASISU_HASHMAP_TEST + +} // namespace basisu diff --git a/ext/basis_universal/basisu_file_headers.h b/ext/basis_universal/basisu_file_headers.h new file mode 100644 index 0000000000..4316d738e6 --- /dev/null +++ b/ext/basis_universal/basisu_file_headers.h @@ -0,0 +1,142 @@ +// basis_file_headers.h +// Copyright (C) 2019-2020 Binomial LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once +#include "basisu_transcoder_internal.h" + +namespace basist +{ + // Slice desc header flags + enum basis_slice_desc_flags + { + cSliceDescFlagsHasAlpha = 1, + + // Video only: Frame doesn't refer to previous frame (no usage of conditional replenishment pred symbols) + // Currently the first frame is always an I-Frame, all subsequent frames are P-Frames. This will eventually be changed to periodic I-Frames. + cSliceDescFlagsFrameIsIFrame = 2 + }; + +#pragma pack(push) +#pragma pack(1) + struct basis_slice_desc + { + basisu::packed_uint<3> m_image_index; // The index of the source image provided to the encoder (will always appear in order from first to last, first image index is 0, no skipping allowed) + basisu::packed_uint<1> m_level_index; // The mipmap level index (mipmaps will always appear from largest to smallest) + basisu::packed_uint<1> m_flags; // enum basis_slice_desc_flags + + basisu::packed_uint<2> m_orig_width; // The original image width (may not be a multiple of 4 pixels) + basisu::packed_uint<2> m_orig_height; // The original image height (may not be a multiple of 4 pixels) + + basisu::packed_uint<2> m_num_blocks_x; // The slice's block X dimensions. Each block is 4x4 pixels. The slice's pixel resolution may or may not be a power of 2. + basisu::packed_uint<2> m_num_blocks_y; // The slice's block Y dimensions. + + basisu::packed_uint<4> m_file_ofs; // Offset from the start of the file to the start of the slice's data + basisu::packed_uint<4> m_file_size; // The size of the compressed slice data in bytes + + basisu::packed_uint<2> m_slice_data_crc16; // The CRC16 of the compressed slice data, for extra-paranoid use cases + }; + + // File header files + enum basis_header_flags + { + // Always set for ETC1S files. Not set for UASTC files. + cBASISHeaderFlagETC1S = 1, + + // Set if the texture had to be Y flipped before encoding. The actual interpretation of this (is Y up or down?) is up to the user. + cBASISHeaderFlagYFlipped = 2, + + // Set if any slices contain alpha (for ETC1S, if the odd slices contain alpha data) + cBASISHeaderFlagHasAlphaSlices = 4, + + // For ETC1S files, this will be true if the file utilizes a codebook from another .basis file. + cBASISHeaderFlagUsesGlobalCodebook = 8, + + // Set if the texture data is sRGB, otherwise it's linear. + // In reality, we have no idea if the texture data is actually linear or sRGB. This is the m_perceptual parameter passed to the compressor. + cBASISHeaderFlagSRGB = 16, + }; + + // The image type field attempts to describe how to interpret the image data in a Basis file. + // The encoder library doesn't really do anything special or different with these texture types, this is mostly here for the benefit of the user. + // We do make sure the various constraints are followed (2DArray/cubemap/videoframes/volume implies that each image has the same resolution and # of mipmap levels, etc., cubemap implies that the # of image slices is a multiple of 6) + enum basis_texture_type + { + cBASISTexType2D = 0, // An arbitrary array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image may have a different resolution and # of mipmap levels + cBASISTexType2DArray = 1, // An array of 2D RGB or RGBA images with optional mipmaps, array size = # images, each image has the same resolution and mipmap levels + cBASISTexTypeCubemapArray = 2, // an array of cubemap levels, total # of images must be divisable by 6, in X+, X-, Y+, Y-, Z+, Z- order, with optional mipmaps + cBASISTexTypeVideoFrames = 3, // An array of 2D video frames, with optional mipmaps, # frames = # images, each image has the same resolution and # of mipmap levels + cBASISTexTypeVolume = 4, // A 3D texture with optional mipmaps, Z dimension = # images, each image has the same resolution and # of mipmap levels + + cBASISTexTypeTotal + }; + + enum + { + cBASISMaxUSPerFrame = 0xFFFFFF + }; + + enum class basis_tex_format + { + cETC1S = 0, + cUASTC4x4 = 1 + }; + + struct basis_file_header + { + enum + { + cBASISSigValue = ('B' << 8) | 's', + cBASISFirstVersion = 0x10 + }; + + basisu::packed_uint<2> m_sig; // 2 byte file signature + basisu::packed_uint<2> m_ver; // Baseline file version + basisu::packed_uint<2> m_header_size; // Header size in bytes, sizeof(basis_file_header) + basisu::packed_uint<2> m_header_crc16; // CRC16 of the remaining header data + + basisu::packed_uint<4> m_data_size; // The total size of all data after the header + basisu::packed_uint<2> m_data_crc16; // The CRC16 of all data after the header + + basisu::packed_uint<3> m_total_slices; // The total # of compressed slices (1 slice per image, or 2 for alpha .basis files) + + basisu::packed_uint<3> m_total_images; // The total # of images + + basisu::packed_uint<1> m_tex_format; // enum basis_tex_format + basisu::packed_uint<2> m_flags; // enum basist::header_flags + basisu::packed_uint<1> m_tex_type; // enum basist::basis_texture_type + basisu::packed_uint<3> m_us_per_frame; // Framerate of video, in microseconds per frame + + basisu::packed_uint<4> m_reserved; // For future use + basisu::packed_uint<4> m_userdata0; // For client use + basisu::packed_uint<4> m_userdata1; // For client use + + basisu::packed_uint<2> m_total_endpoints; // The number of endpoints in the endpoint codebook + basisu::packed_uint<4> m_endpoint_cb_file_ofs; // The compressed endpoint codebook's file offset relative to the start of the file + basisu::packed_uint<3> m_endpoint_cb_file_size; // The compressed endpoint codebook's size in bytes + + basisu::packed_uint<2> m_total_selectors; // The number of selectors in the endpoint codebook + basisu::packed_uint<4> m_selector_cb_file_ofs; // The compressed selectors codebook's file offset relative to the start of the file + basisu::packed_uint<3> m_selector_cb_file_size; // The compressed selector codebook's size in bytes + + basisu::packed_uint<4> m_tables_file_ofs; // The file offset of the compressed Huffman codelength tables, for decompressing slices + basisu::packed_uint<4> m_tables_file_size; // The file size in bytes of the compressed huffman codelength tables + + basisu::packed_uint<4> m_slice_desc_file_ofs; // The file offset to the slice description array, usually follows the header + + basisu::packed_uint<4> m_extended_file_ofs; // The file offset of the "extended" header and compressed data, for future use + basisu::packed_uint<4> m_extended_file_size; // The file size in bytes of the "extended" header and compressed data, for future use + }; +#pragma pack (pop) + +} // namespace basist diff --git a/ext/basis_universal/basisu_transcoder.cpp b/ext/basis_universal/basisu_transcoder.cpp new file mode 100644 index 0000000000..b5bef83c29 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder.cpp @@ -0,0 +1,17479 @@ +// basisu_transcoder.cpp +// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "basisu_transcoder.h" +#include +#include "basisu_containers_impl.h" + +#ifndef BASISD_IS_BIG_ENDIAN +// TODO: This doesn't work on OSX. How can this be so difficult? +//#if defined(__BIG_ENDIAN__) || defined(_BIG_ENDIAN) || defined(BIG_ENDIAN) +// #define BASISD_IS_BIG_ENDIAN (1) +//#else + #define BASISD_IS_BIG_ENDIAN (0) +//#endif +#endif + +#ifndef BASISD_USE_UNALIGNED_WORD_READS + #ifdef __EMSCRIPTEN__ + // Can't use unaligned loads/stores with WebAssembly. + #define BASISD_USE_UNALIGNED_WORD_READS (0) + #elif defined(_M_AMD64) || defined(_M_IX86) || defined(__i386__) || defined(__x86_64__) + #define BASISD_USE_UNALIGNED_WORD_READS (1) + #else + #define BASISD_USE_UNALIGNED_WORD_READS (0) + #endif +#endif + +// Using unaligned loads and stores causes errors when using UBSan. Jam it off. +#if defined(__has_feature) +#if __has_feature(undefined_behavior_sanitizer) +#undef BASISD_USE_UNALIGNED_WORD_READS +#define BASISD_USE_UNALIGNED_WORD_READS 0 +#endif +#endif + +#define BASISD_SUPPORTED_BASIS_VERSION (0x13) + +#ifndef BASISD_SUPPORT_KTX2 + #error Must have defined BASISD_SUPPORT_KTX2 +#endif + +#ifndef BASISD_SUPPORT_KTX2_ZSTD +#error Must have defined BASISD_SUPPORT_KTX2_ZSTD +#endif + +// Set to 1 for fuzz testing. This will disable all CRC16 checks on headers and compressed data. +#ifndef BASISU_NO_HEADER_OR_DATA_CRC16_CHECKS + #define BASISU_NO_HEADER_OR_DATA_CRC16_CHECKS 0 +#endif + +#ifndef BASISD_SUPPORT_DXT1 + #define BASISD_SUPPORT_DXT1 1 +#endif + +#ifndef BASISD_SUPPORT_DXT5A + #define BASISD_SUPPORT_DXT5A 1 +#endif + +// Disable all BC7 transcoders if necessary (useful when cross compiling to Javascript) +#if defined(BASISD_SUPPORT_BC7) && !BASISD_SUPPORT_BC7 + #ifndef BASISD_SUPPORT_BC7_MODE5 + #define BASISD_SUPPORT_BC7_MODE5 0 + #endif +#endif // !BASISD_SUPPORT_BC7 + +// BC7 mode 5 supports both opaque and opaque+alpha textures, and uses less memory BC1. +#ifndef BASISD_SUPPORT_BC7_MODE5 + #define BASISD_SUPPORT_BC7_MODE5 1 +#endif + +#ifndef BASISD_SUPPORT_PVRTC1 + #define BASISD_SUPPORT_PVRTC1 1 +#endif + +#ifndef BASISD_SUPPORT_ETC2_EAC_A8 + #define BASISD_SUPPORT_ETC2_EAC_A8 1 +#endif + +// Set BASISD_SUPPORT_UASTC to 0 to completely disable support for transcoding UASTC files. +#ifndef BASISD_SUPPORT_UASTC + #define BASISD_SUPPORT_UASTC 1 +#endif + +#ifndef BASISD_SUPPORT_ASTC + #define BASISD_SUPPORT_ASTC 1 +#endif + +// Note that if BASISD_SUPPORT_ATC is enabled, BASISD_SUPPORT_DXT5A should also be enabled for alpha support. +#ifndef BASISD_SUPPORT_ATC + #define BASISD_SUPPORT_ATC 1 +#endif + +// Support for ETC2 EAC R11 and ETC2 EAC RG11 +#ifndef BASISD_SUPPORT_ETC2_EAC_RG11 + #define BASISD_SUPPORT_ETC2_EAC_RG11 1 +#endif + +// If BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY is 1, opaque blocks will be transcoded to ASTC at slightly higher quality (higher than BC1), but the transcoder tables will be 2x as large. +// This impacts grayscale and grayscale+alpha textures the most. +#ifndef BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY + #ifdef __EMSCRIPTEN__ + // Let's assume size matters more than quality when compiling with emscripten. + #define BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY 0 + #else + // Compiling native, so an extra 64K lookup table is probably acceptable. + #define BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY 1 + #endif +#endif + +#ifndef BASISD_SUPPORT_FXT1 + #define BASISD_SUPPORT_FXT1 1 +#endif + +#ifndef BASISD_SUPPORT_PVRTC2 + #define BASISD_SUPPORT_PVRTC2 1 +#endif + +#if BASISD_SUPPORT_PVRTC2 + #if !BASISD_SUPPORT_ATC + #error BASISD_SUPPORT_ATC must be 1 if BASISD_SUPPORT_PVRTC2 is 1 + #endif +#endif + +#if BASISD_SUPPORT_ATC + #if !BASISD_SUPPORT_DXT5A + #error BASISD_SUPPORT_DXT5A must be 1 if BASISD_SUPPORT_ATC is 1 + #endif +#endif + +#define BASISD_WRITE_NEW_BC7_MODE5_TABLES 0 +#define BASISD_WRITE_NEW_DXT1_TABLES 0 +#define BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES 0 +#define BASISD_WRITE_NEW_ASTC_TABLES 0 +#define BASISD_WRITE_NEW_ATC_TABLES 0 +#define BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES 0 + +#ifndef BASISD_ENABLE_DEBUG_FLAGS + #define BASISD_ENABLE_DEBUG_FLAGS 0 +#endif + +// If KTX2 support is enabled, we may need Zstd for decompression of supercompressed UASTC files. Include this header. +#if BASISD_SUPPORT_KTX2 + // If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded. + #if BASISD_SUPPORT_KTX2_ZSTD + // We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError() + #include "../zstd/lib/zstd.h" + #endif +#endif + +namespace basisu +{ + bool g_debug_printf; + + void enable_debug_printf(bool enabled) + { + g_debug_printf = enabled; + } + + void debug_printf(const char* pFmt, ...) + { +#if BASISU_FORCE_DEVEL_MESSAGES + g_debug_printf = true; +#endif + if (g_debug_printf) + { + va_list args; + va_start(args, pFmt); + vprintf(pFmt, args); + va_end(args); + } + } +} // namespace basisu + +namespace basist +{ + +#if BASISD_ENABLE_DEBUG_FLAGS + static uint32_t g_debug_flags = 0; +#endif + + uint32_t get_debug_flags() + { +#if BASISD_ENABLE_DEBUG_FLAGS + return g_debug_flags; +#else + return 0; +#endif + } + + void set_debug_flags(uint32_t f) + { + BASISU_NOTE_UNUSED(f); +#if BASISD_ENABLE_DEBUG_FLAGS + g_debug_flags = f; +#endif + } + + inline uint16_t byteswap_uint16(uint16_t v) + { + return static_cast((v >> 8) | (v << 8)); + } + + static inline int32_t clampi(int32_t value, int32_t low, int32_t high) { if (value < low) value = low; else if (value > high) value = high; return value; } + static inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; } + static inline float saturate(float value) { return clampf(value, 0, 1.0f); } + + static inline uint8_t mul_8(uint32_t v, uint32_t q) { v = v * q + 128; return (uint8_t)((v + (v >> 8)) >> 8); } + + uint16_t crc16(const void* r, size_t size, uint16_t crc) + { + crc = ~crc; + + const uint8_t* p = static_cast(r); + for (; size; --size) + { + const uint16_t q = *p++ ^ (crc >> 8); + uint16_t k = (q >> 4) ^ q; + crc = (((crc << 8) ^ k) ^ (k << 5)) ^ (k << 12); + } + + return static_cast(~crc); + } + + enum etc_constants + { + cETC1BytesPerBlock = 8U, + + cETC1SelectorBits = 2U, + cETC1SelectorValues = 1U << cETC1SelectorBits, + cETC1SelectorMask = cETC1SelectorValues - 1U, + + cETC1BlockShift = 2U, + cETC1BlockSize = 1U << cETC1BlockShift, + + cETC1LSBSelectorIndicesBitOffset = 0, + cETC1MSBSelectorIndicesBitOffset = 16, + + cETC1FlipBitOffset = 32, + cETC1DiffBitOffset = 33, + + cETC1IntenModifierNumBits = 3, + cETC1IntenModifierValues = 1 << cETC1IntenModifierNumBits, + cETC1RightIntenModifierTableBitOffset = 34, + cETC1LeftIntenModifierTableBitOffset = 37, + + // Base+Delta encoding (5 bit bases, 3 bit delta) + cETC1BaseColorCompNumBits = 5, + cETC1BaseColorCompMax = 1 << cETC1BaseColorCompNumBits, + + cETC1DeltaColorCompNumBits = 3, + cETC1DeltaColorComp = 1 << cETC1DeltaColorCompNumBits, + cETC1DeltaColorCompMax = 1 << cETC1DeltaColorCompNumBits, + + cETC1BaseColor5RBitOffset = 59, + cETC1BaseColor5GBitOffset = 51, + cETC1BaseColor5BBitOffset = 43, + + cETC1DeltaColor3RBitOffset = 56, + cETC1DeltaColor3GBitOffset = 48, + cETC1DeltaColor3BBitOffset = 40, + + // Absolute (non-delta) encoding (two 4-bit per component bases) + cETC1AbsColorCompNumBits = 4, + cETC1AbsColorCompMax = 1 << cETC1AbsColorCompNumBits, + + cETC1AbsColor4R1BitOffset = 60, + cETC1AbsColor4G1BitOffset = 52, + cETC1AbsColor4B1BitOffset = 44, + + cETC1AbsColor4R2BitOffset = 56, + cETC1AbsColor4G2BitOffset = 48, + cETC1AbsColor4B2BitOffset = 40, + + cETC1ColorDeltaMin = -4, + cETC1ColorDeltaMax = 3, + + // Delta3: + // 0 1 2 3 4 5 6 7 + // 000 001 010 011 100 101 110 111 + // 0 1 2 3 -4 -3 -2 -1 + }; + +#define DECLARE_ETC1_INTEN_TABLE(name, N) \ + static const int name[cETC1IntenModifierValues][cETC1SelectorValues] = \ + { \ + { N * -8, N * -2, N * 2, N * 8 },{ N * -17, N * -5, N * 5, N * 17 },{ N * -29, N * -9, N * 9, N * 29 },{ N * -42, N * -13, N * 13, N * 42 }, \ + { N * -60, N * -18, N * 18, N * 60 },{ N * -80, N * -24, N * 24, N * 80 },{ N * -106, N * -33, N * 33, N * 106 },{ N * -183, N * -47, N * 47, N * 183 } \ + }; + + DECLARE_ETC1_INTEN_TABLE(g_etc1_inten_tables, 1); + DECLARE_ETC1_INTEN_TABLE(g_etc1_inten_tables16, 16); + DECLARE_ETC1_INTEN_TABLE(g_etc1_inten_tables48, 3 * 16); + + //const uint8_t g_etc1_to_selector_index[cETC1SelectorValues] = { 2, 3, 1, 0 }; + const uint8_t g_selector_index_to_etc1[cETC1SelectorValues] = { 3, 2, 0, 1 }; + + static const uint8_t g_etc_5_to_8[32] = { 0, 8, 16, 24, 33, 41, 49, 57, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 198, 206, 214, 222, 231, 239, 247, 255 }; + + struct decoder_etc_block + { + // big endian uint64: + // bit ofs: 56 48 40 32 24 16 8 0 + // byte ofs: b0, b1, b2, b3, b4, b5, b6, b7 + union + { + uint64_t m_uint64; + + uint32_t m_uint32[2]; + + uint8_t m_bytes[8]; + + struct + { + signed m_dred2 : 3; + uint32_t m_red1 : 5; + + signed m_dgreen2 : 3; + uint32_t m_green1 : 5; + + signed m_dblue2 : 3; + uint32_t m_blue1 : 5; + + uint32_t m_flip : 1; + uint32_t m_diff : 1; + uint32_t m_cw2 : 3; + uint32_t m_cw1 : 3; + + uint32_t m_selectors; + } m_differential; + }; + + inline void clear() + { + assert(sizeof(*this) == 8); + basisu::clear_obj(*this); + } + + inline void set_byte_bits(uint32_t ofs, uint32_t num, uint32_t bits) + { + assert((ofs + num) <= 64U); + assert(num && (num < 32U)); + assert((ofs >> 3) == ((ofs + num - 1) >> 3)); + assert(bits < (1U << num)); + const uint32_t byte_ofs = 7 - (ofs >> 3); + const uint32_t byte_bit_ofs = ofs & 7; + const uint32_t mask = (1 << num) - 1; + m_bytes[byte_ofs] &= ~(mask << byte_bit_ofs); + m_bytes[byte_ofs] |= (bits << byte_bit_ofs); + } + + inline void set_flip_bit(bool flip) + { + m_bytes[3] &= ~1; + m_bytes[3] |= static_cast(flip); + } + + inline void set_diff_bit(bool diff) + { + m_bytes[3] &= ~2; + m_bytes[3] |= (static_cast(diff) << 1); + } + + // Sets intensity modifier table (0-7) used by subblock subblock_id (0 or 1) + inline void set_inten_table(uint32_t subblock_id, uint32_t t) + { + assert(subblock_id < 2); + assert(t < 8); + const uint32_t ofs = subblock_id ? 2 : 5; + m_bytes[3] &= ~(7 << ofs); + m_bytes[3] |= (t << ofs); + } + + // Selector "val" ranges from 0-3 and is a direct index into g_etc1_inten_tables. + inline void set_selector(uint32_t x, uint32_t y, uint32_t val) + { + assert((x | y | val) < 4); + const uint32_t bit_index = x * 4 + y; + + uint8_t* p = &m_bytes[7 - (bit_index >> 3)]; + + const uint32_t byte_bit_ofs = bit_index & 7; + const uint32_t mask = 1 << byte_bit_ofs; + + static const uint8_t s_selector_index_to_etc1[4] = { 3, 2, 0, 1 }; + const uint32_t etc1_val = s_selector_index_to_etc1[val]; + + const uint32_t lsb = etc1_val & 1; + const uint32_t msb = etc1_val >> 1; + + p[0] &= ~mask; + p[0] |= (lsb << byte_bit_ofs); + + p[-2] &= ~mask; + p[-2] |= (msb << byte_bit_ofs); + } + + // Returned encoded selector value ranges from 0-3 (this is NOT a direct index into g_etc1_inten_tables, see get_selector()) + inline uint32_t get_raw_selector(uint32_t x, uint32_t y) const + { + assert((x | y) < 4); + + const uint32_t bit_index = x * 4 + y; + const uint32_t byte_bit_ofs = bit_index & 7; + const uint8_t* p = &m_bytes[7 - (bit_index >> 3)]; + const uint32_t lsb = (p[0] >> byte_bit_ofs) & 1; + const uint32_t msb = (p[-2] >> byte_bit_ofs) & 1; + const uint32_t val = lsb | (msb << 1); + + return val; + } + + // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables. + inline uint32_t get_selector(uint32_t x, uint32_t y) const + { + static const uint8_t s_etc1_to_selector_index[cETC1SelectorValues] = { 2, 3, 1, 0 }; + return s_etc1_to_selector_index[get_raw_selector(x, y)]; + } + + inline void set_raw_selector_bits(uint32_t bits) + { + m_bytes[4] = static_cast(bits); + m_bytes[5] = static_cast(bits >> 8); + m_bytes[6] = static_cast(bits >> 16); + m_bytes[7] = static_cast(bits >> 24); + } + + inline bool are_all_selectors_the_same() const + { + uint32_t v = *reinterpret_cast(&m_bytes[4]); + + if ((v == 0xFFFFFFFF) || (v == 0xFFFF) || (!v) || (v == 0xFFFF0000)) + return true; + + return false; + } + + inline void set_raw_selector_bits(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3) + { + m_bytes[4] = byte0; + m_bytes[5] = byte1; + m_bytes[6] = byte2; + m_bytes[7] = byte3; + } + + inline uint32_t get_raw_selector_bits() const + { + return m_bytes[4] | (m_bytes[5] << 8) | (m_bytes[6] << 16) | (m_bytes[7] << 24); + } + + inline void set_base4_color(uint32_t idx, uint16_t c) + { + if (idx) + { + set_byte_bits(cETC1AbsColor4R2BitOffset, 4, (c >> 8) & 15); + set_byte_bits(cETC1AbsColor4G2BitOffset, 4, (c >> 4) & 15); + set_byte_bits(cETC1AbsColor4B2BitOffset, 4, c & 15); + } + else + { + set_byte_bits(cETC1AbsColor4R1BitOffset, 4, (c >> 8) & 15); + set_byte_bits(cETC1AbsColor4G1BitOffset, 4, (c >> 4) & 15); + set_byte_bits(cETC1AbsColor4B1BitOffset, 4, c & 15); + } + } + + inline void set_base5_color(uint16_t c) + { + set_byte_bits(cETC1BaseColor5RBitOffset, 5, (c >> 10) & 31); + set_byte_bits(cETC1BaseColor5GBitOffset, 5, (c >> 5) & 31); + set_byte_bits(cETC1BaseColor5BBitOffset, 5, c & 31); + } + + void set_delta3_color(uint16_t c) + { + set_byte_bits(cETC1DeltaColor3RBitOffset, 3, (c >> 6) & 7); + set_byte_bits(cETC1DeltaColor3GBitOffset, 3, (c >> 3) & 7); + set_byte_bits(cETC1DeltaColor3BBitOffset, 3, c & 7); + } + + void set_block_color4(const color32& c0_unscaled, const color32& c1_unscaled) + { + set_diff_bit(false); + + set_base4_color(0, pack_color4(c0_unscaled, false)); + set_base4_color(1, pack_color4(c1_unscaled, false)); + } + + void set_block_color5(const color32& c0_unscaled, const color32& c1_unscaled) + { + set_diff_bit(true); + + set_base5_color(pack_color5(c0_unscaled, false)); + + int dr = c1_unscaled.r - c0_unscaled.r; + int dg = c1_unscaled.g - c0_unscaled.g; + int db = c1_unscaled.b - c0_unscaled.b; + + set_delta3_color(pack_delta3(dr, dg, db)); + } + + bool set_block_color5_check(const color32& c0_unscaled, const color32& c1_unscaled) + { + set_diff_bit(true); + + set_base5_color(pack_color5(c0_unscaled, false)); + + int dr = c1_unscaled.r - c0_unscaled.r; + int dg = c1_unscaled.g - c0_unscaled.g; + int db = c1_unscaled.b - c0_unscaled.b; + + if (((dr < cETC1ColorDeltaMin) || (dr > cETC1ColorDeltaMax)) || + ((dg < cETC1ColorDeltaMin) || (dg > cETC1ColorDeltaMax)) || + ((db < cETC1ColorDeltaMin) || (db > cETC1ColorDeltaMax))) + return false; + + set_delta3_color(pack_delta3(dr, dg, db)); + + return true; + } + + inline uint32_t get_byte_bits(uint32_t ofs, uint32_t num) const + { + assert((ofs + num) <= 64U); + assert(num && (num <= 8U)); + assert((ofs >> 3) == ((ofs + num - 1) >> 3)); + const uint32_t byte_ofs = 7 - (ofs >> 3); + const uint32_t byte_bit_ofs = ofs & 7; + return (m_bytes[byte_ofs] >> byte_bit_ofs) & ((1 << num) - 1); + } + + inline uint16_t get_base5_color() const + { + const uint32_t r = get_byte_bits(cETC1BaseColor5RBitOffset, 5); + const uint32_t g = get_byte_bits(cETC1BaseColor5GBitOffset, 5); + const uint32_t b = get_byte_bits(cETC1BaseColor5BBitOffset, 5); + return static_cast(b | (g << 5U) | (r << 10U)); + } + + inline uint16_t get_base4_color(uint32_t idx) const + { + uint32_t r, g, b; + if (idx) + { + r = get_byte_bits(cETC1AbsColor4R2BitOffset, 4); + g = get_byte_bits(cETC1AbsColor4G2BitOffset, 4); + b = get_byte_bits(cETC1AbsColor4B2BitOffset, 4); + } + else + { + r = get_byte_bits(cETC1AbsColor4R1BitOffset, 4); + g = get_byte_bits(cETC1AbsColor4G1BitOffset, 4); + b = get_byte_bits(cETC1AbsColor4B1BitOffset, 4); + } + return static_cast(b | (g << 4U) | (r << 8U)); + } + + inline color32 get_base5_color_unscaled() const + { + return color32(m_differential.m_red1, m_differential.m_green1, m_differential.m_blue1, 255); + } + + inline bool get_flip_bit() const + { + return (m_bytes[3] & 1) != 0; + } + + inline bool get_diff_bit() const + { + return (m_bytes[3] & 2) != 0; + } + + inline uint32_t get_inten_table(uint32_t subblock_id) const + { + assert(subblock_id < 2); + const uint32_t ofs = subblock_id ? 2 : 5; + return (m_bytes[3] >> ofs) & 7; + } + + inline uint16_t get_delta3_color() const + { + const uint32_t r = get_byte_bits(cETC1DeltaColor3RBitOffset, 3); + const uint32_t g = get_byte_bits(cETC1DeltaColor3GBitOffset, 3); + const uint32_t b = get_byte_bits(cETC1DeltaColor3BBitOffset, 3); + return static_cast(b | (g << 3U) | (r << 6U)); + } + + void get_block_colors(color32* pBlock_colors, uint32_t subblock_index) const + { + color32 b; + + if (get_diff_bit()) + { + if (subblock_index) + unpack_color5(b, get_base5_color(), get_delta3_color(), true, 255); + else + unpack_color5(b, get_base5_color(), true); + } + else + { + b = unpack_color4(get_base4_color(subblock_index), true, 255); + } + + const int* pInten_table = g_etc1_inten_tables[get_inten_table(subblock_index)]; + + pBlock_colors[0].set_noclamp_rgba(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255); + pBlock_colors[1].set_noclamp_rgba(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255); + pBlock_colors[2].set_noclamp_rgba(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255); + pBlock_colors[3].set_noclamp_rgba(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255); + } + + static uint16_t pack_color4(const color32& color, bool scaled, uint32_t bias = 127U) + { + return pack_color4(color.r, color.g, color.b, scaled, bias); + } + + static uint16_t pack_color4(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias = 127U) + { + if (scaled) + { + r = (r * 15U + bias) / 255U; + g = (g * 15U + bias) / 255U; + b = (b * 15U + bias) / 255U; + } + + r = basisu::minimum(r, 15U); + g = basisu::minimum(g, 15U); + b = basisu::minimum(b, 15U); + + return static_cast(b | (g << 4U) | (r << 8U)); + } + + static uint16_t pack_color5(const color32& color, bool scaled, uint32_t bias = 127U) + { + return pack_color5(color.r, color.g, color.b, scaled, bias); + } + + static uint16_t pack_color5(uint32_t r, uint32_t g, uint32_t b, bool scaled, uint32_t bias = 127U) + { + if (scaled) + { + r = (r * 31U + bias) / 255U; + g = (g * 31U + bias) / 255U; + b = (b * 31U + bias) / 255U; + } + + r = basisu::minimum(r, 31U); + g = basisu::minimum(g, 31U); + b = basisu::minimum(b, 31U); + + return static_cast(b | (g << 5U) | (r << 10U)); + } + + uint16_t pack_delta3(const color32& color) + { + return pack_delta3(color.r, color.g, color.b); + } + + uint16_t pack_delta3(int r, int g, int b) + { + assert((r >= cETC1ColorDeltaMin) && (r <= cETC1ColorDeltaMax)); + assert((g >= cETC1ColorDeltaMin) && (g <= cETC1ColorDeltaMax)); + assert((b >= cETC1ColorDeltaMin) && (b <= cETC1ColorDeltaMax)); + if (r < 0) r += 8; + if (g < 0) g += 8; + if (b < 0) b += 8; + return static_cast(b | (g << 3) | (r << 6)); + } + + static void unpack_delta3(int& r, int& g, int& b, uint16_t packed_delta3) + { + r = (packed_delta3 >> 6) & 7; + g = (packed_delta3 >> 3) & 7; + b = packed_delta3 & 7; + if (r >= 4) r -= 8; + if (g >= 4) g -= 8; + if (b >= 4) b -= 8; + } + + static color32 unpack_color5(uint16_t packed_color5, bool scaled, uint32_t alpha) + { + uint32_t b = packed_color5 & 31U; + uint32_t g = (packed_color5 >> 5U) & 31U; + uint32_t r = (packed_color5 >> 10U) & 31U; + + if (scaled) + { + b = (b << 3U) | (b >> 2U); + g = (g << 3U) | (g >> 2U); + r = (r << 3U) | (r >> 2U); + } + + assert(alpha <= 255); + + return color32(cNoClamp, r, g, b, alpha); + } + + static void unpack_color5(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color5, bool scaled) + { + color32 c(unpack_color5(packed_color5, scaled, 0)); + r = c.r; + g = c.g; + b = c.b; + } + + static void unpack_color5(color32& result, uint16_t packed_color5, bool scaled) + { + result = unpack_color5(packed_color5, scaled, 255); + } + + static bool unpack_color5(color32& result, uint16_t packed_color5, uint16_t packed_delta3, bool scaled, uint32_t alpha) + { + int dr, dg, db; + unpack_delta3(dr, dg, db, packed_delta3); + + int r = ((packed_color5 >> 10U) & 31U) + dr; + int g = ((packed_color5 >> 5U) & 31U) + dg; + int b = (packed_color5 & 31U) + db; + + bool success = true; + if (static_cast(r | g | b) > 31U) + { + success = false; + r = basisu::clamp(r, 0, 31); + g = basisu::clamp(g, 0, 31); + b = basisu::clamp(b, 0, 31); + } + + if (scaled) + { + b = (b << 3U) | (b >> 2U); + g = (g << 3U) | (g >> 2U); + r = (r << 3U) | (r >> 2U); + } + + result.set_noclamp_rgba(r, g, b, basisu::minimum(alpha, 255U)); + return success; + } + + static color32 unpack_color4(uint16_t packed_color4, bool scaled, uint32_t alpha) + { + uint32_t b = packed_color4 & 15U; + uint32_t g = (packed_color4 >> 4U) & 15U; + uint32_t r = (packed_color4 >> 8U) & 15U; + + if (scaled) + { + b = (b << 4U) | b; + g = (g << 4U) | g; + r = (r << 4U) | r; + } + + return color32(cNoClamp, r, g, b, basisu::minimum(alpha, 255U)); + } + + static void unpack_color4(uint32_t& r, uint32_t& g, uint32_t& b, uint16_t packed_color4, bool scaled) + { + color32 c(unpack_color4(packed_color4, scaled, 0)); + r = c.r; + g = c.g; + b = c.b; + } + + static void get_diff_subblock_colors(color32* pDst, uint16_t packed_color5, uint32_t table_idx) + { + assert(table_idx < cETC1IntenModifierValues); + const int* pInten_modifer_table = &g_etc1_inten_tables[table_idx][0]; + + uint32_t r, g, b; + unpack_color5(r, g, b, packed_color5, true); + + const int ir = static_cast(r), ig = static_cast(g), ib = static_cast(b); + + const int y0 = pInten_modifer_table[0]; + pDst[0].set(clamp255(ir + y0), clamp255(ig + y0), clamp255(ib + y0), 255); + + const int y1 = pInten_modifer_table[1]; + pDst[1].set(clamp255(ir + y1), clamp255(ig + y1), clamp255(ib + y1), 255); + + const int y2 = pInten_modifer_table[2]; + pDst[2].set(clamp255(ir + y2), clamp255(ig + y2), clamp255(ib + y2), 255); + + const int y3 = pInten_modifer_table[3]; + pDst[3].set(clamp255(ir + y3), clamp255(ig + y3), clamp255(ib + y3), 255); + } + + static int clamp255(int x) + { + if (x & 0xFFFFFF00) + { + if (x < 0) + x = 0; + else if (x > 255) + x = 255; + } + + return x; + } + + static void get_block_colors5(color32* pBlock_colors, const color32& base_color5, uint32_t inten_table) + { + color32 b(base_color5); + + b.r = (b.r << 3) | (b.r >> 2); + b.g = (b.g << 3) | (b.g >> 2); + b.b = (b.b << 3) | (b.b >> 2); + + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + pBlock_colors[0].set(clamp255(b.r + pInten_table[0]), clamp255(b.g + pInten_table[0]), clamp255(b.b + pInten_table[0]), 255); + pBlock_colors[1].set(clamp255(b.r + pInten_table[1]), clamp255(b.g + pInten_table[1]), clamp255(b.b + pInten_table[1]), 255); + pBlock_colors[2].set(clamp255(b.r + pInten_table[2]), clamp255(b.g + pInten_table[2]), clamp255(b.b + pInten_table[2]), 255); + pBlock_colors[3].set(clamp255(b.r + pInten_table[3]), clamp255(b.g + pInten_table[3]), clamp255(b.b + pInten_table[3]), 255); + } + + static void get_block_color5(const color32& base_color5, uint32_t inten_table, uint32_t index, uint32_t& r, uint32_t &g, uint32_t &b) + { + assert(index < 4); + + uint32_t br = (base_color5.r << 3) | (base_color5.r >> 2); + uint32_t bg = (base_color5.g << 3) | (base_color5.g >> 2); + uint32_t bb = (base_color5.b << 3) | (base_color5.b >> 2); + + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + r = clamp255(br + pInten_table[index]); + g = clamp255(bg + pInten_table[index]); + b = clamp255(bb + pInten_table[index]); + } + + static void get_block_color5_r(const color32& base_color5, uint32_t inten_table, uint32_t index, uint32_t &r) + { + assert(index < 4); + + uint32_t br = (base_color5.r << 3) | (base_color5.r >> 2); + + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + r = clamp255(br + pInten_table[index]); + } + + static void get_block_colors5_g(int* pBlock_colors, const color32& base_color5, uint32_t inten_table) + { + const int g = (base_color5.g << 3) | (base_color5.g >> 2); + + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + pBlock_colors[0] = clamp255(g + pInten_table[0]); + pBlock_colors[1] = clamp255(g + pInten_table[1]); + pBlock_colors[2] = clamp255(g + pInten_table[2]); + pBlock_colors[3] = clamp255(g + pInten_table[3]); + } + + static void get_block_colors5_bounds(color32* pBlock_colors, const color32& base_color5, uint32_t inten_table, uint32_t l = 0, uint32_t h = 3) + { + color32 b(base_color5); + + b.r = (b.r << 3) | (b.r >> 2); + b.g = (b.g << 3) | (b.g >> 2); + b.b = (b.b << 3) | (b.b >> 2); + + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + pBlock_colors[0].set(clamp255(b.r + pInten_table[l]), clamp255(b.g + pInten_table[l]), clamp255(b.b + pInten_table[l]), 255); + pBlock_colors[1].set(clamp255(b.r + pInten_table[h]), clamp255(b.g + pInten_table[h]), clamp255(b.b + pInten_table[h]), 255); + } + + static void get_block_colors5_bounds_g(uint32_t* pBlock_colors, const color32& base_color5, uint32_t inten_table, uint32_t l = 0, uint32_t h = 3) + { + color32 b(base_color5); + + b.g = (b.g << 3) | (b.g >> 2); + + const int* pInten_table = g_etc1_inten_tables[inten_table]; + + pBlock_colors[0] = clamp255(b.g + pInten_table[l]); + pBlock_colors[1] = clamp255(b.g + pInten_table[h]); + } + }; + + enum dxt_constants + { + cDXT1SelectorBits = 2U, cDXT1SelectorValues = 1U << cDXT1SelectorBits, cDXT1SelectorMask = cDXT1SelectorValues - 1U, + cDXT5SelectorBits = 3U, cDXT5SelectorValues = 1U << cDXT5SelectorBits, cDXT5SelectorMask = cDXT5SelectorValues - 1U, + }; + + static const uint8_t g_etc1_x_selector_unpack[4][256] = + { + { + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, + }, + { + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, + 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, + 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, 2, 2, 3, 3, + }, + + { + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, + }, + + { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, + } + }; + + struct dxt1_block + { + enum { cTotalEndpointBytes = 2, cTotalSelectorBytes = 4 }; + + uint8_t m_low_color[cTotalEndpointBytes]; + uint8_t m_high_color[cTotalEndpointBytes]; + uint8_t m_selectors[cTotalSelectorBytes]; + + inline void clear() { basisu::clear_obj(*this); } + + inline uint32_t get_high_color() const { return m_high_color[0] | (m_high_color[1] << 8U); } + inline uint32_t get_low_color() const { return m_low_color[0] | (m_low_color[1] << 8U); } + inline void set_low_color(uint16_t c) { m_low_color[0] = static_cast(c & 0xFF); m_low_color[1] = static_cast((c >> 8) & 0xFF); } + inline void set_high_color(uint16_t c) { m_high_color[0] = static_cast(c & 0xFF); m_high_color[1] = static_cast((c >> 8) & 0xFF); } + inline uint32_t get_selector(uint32_t x, uint32_t y) const { assert((x < 4U) && (y < 4U)); return (m_selectors[y] >> (x * cDXT1SelectorBits)) & cDXT1SelectorMask; } + inline void set_selector(uint32_t x, uint32_t y, uint32_t val) { assert((x < 4U) && (y < 4U) && (val < 4U)); m_selectors[y] &= (~(cDXT1SelectorMask << (x * cDXT1SelectorBits))); m_selectors[y] |= (val << (x * cDXT1SelectorBits)); } + + static uint16_t pack_color(const color32& color, bool scaled, uint32_t bias = 127U) + { + uint32_t r = color.r, g = color.g, b = color.b; + if (scaled) + { + r = (r * 31U + bias) / 255U; + g = (g * 63U + bias) / 255U; + b = (b * 31U + bias) / 255U; + } + return static_cast(basisu::minimum(b, 31U) | (basisu::minimum(g, 63U) << 5U) | (basisu::minimum(r, 31U) << 11U)); + } + + static uint16_t pack_unscaled_color(uint32_t r, uint32_t g, uint32_t b) { return static_cast(b | (g << 5U) | (r << 11U)); } + }; + + struct dxt_selector_range + { + uint32_t m_low; + uint32_t m_high; + }; + + struct etc1_to_dxt1_56_solution + { + uint8_t m_lo; + uint8_t m_hi; + uint16_t m_err; + }; + +#if BASISD_SUPPORT_DXT1 + static dxt_selector_range g_etc1_to_dxt1_selector_ranges[] = + { + { 0, 3 }, + + { 1, 3 }, + { 0, 2 }, + + { 1, 2 }, + + { 2, 3 }, + { 0, 1 }, + }; + + const uint32_t NUM_ETC1_TO_DXT1_SELECTOR_RANGES = sizeof(g_etc1_to_dxt1_selector_ranges) / sizeof(g_etc1_to_dxt1_selector_ranges[0]); + + static uint32_t g_etc1_to_dxt1_selector_range_index[4][4]; + + const uint32_t NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS = 10; + static const uint8_t g_etc1_to_dxt1_selector_mappings[NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS][4] = + { + { 0, 0, 1, 1 }, + { 0, 0, 1, 2 }, + { 0, 0, 1, 3 }, + { 0, 0, 2, 3 }, + { 0, 1, 1, 1 }, + { 0, 1, 2, 2 }, + { 0, 1, 2, 3 }, + { 0, 2, 3, 3 }, + { 1, 2, 2, 2 }, + { 1, 2, 3, 3 }, + }; + + static uint8_t g_etc1_to_dxt1_selector_mappings_raw_dxt1_256[NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS][256]; + static uint8_t g_etc1_to_dxt1_selector_mappings_raw_dxt1_inv_256[NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS][256]; + + static const etc1_to_dxt1_56_solution g_etc1_to_dxt_6[32 * 8 * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS * NUM_ETC1_TO_DXT1_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_dxt1_6.inc" + }; + + static const etc1_to_dxt1_56_solution g_etc1_to_dxt_5[32 * 8 * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS * NUM_ETC1_TO_DXT1_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_dxt1_5.inc" + }; +#endif // BASISD_SUPPORT_DXT1 + +#if BASISD_SUPPORT_DXT1 || BASISD_SUPPORT_UASTC + // First saw the idea for optimal BC1 single-color block encoding using lookup tables in ryg_dxt. + struct bc1_match_entry + { + uint8_t m_hi; + uint8_t m_lo; + }; + static bc1_match_entry g_bc1_match5_equals_1[256], g_bc1_match6_equals_1[256]; // selector 1, allow equals hi/lo + static bc1_match_entry g_bc1_match5_equals_0[256], g_bc1_match6_equals_0[256]; // selector 0, allow equals hi/lo + + static void prepare_bc1_single_color_table(bc1_match_entry* pTable, const uint8_t* pExpand, int size0, int size1, int sel) + { + for (int i = 0; i < 256; i++) + { + int lowest_e = 256; + for (int lo = 0; lo < size0; lo++) + { + for (int hi = 0; hi < size1; hi++) + { + const int lo_e = pExpand[lo], hi_e = pExpand[hi]; + int e; + + if (sel == 1) + { + // Selector 1 + e = basisu::iabs(((hi_e * 2 + lo_e) / 3) - i); + e += (basisu::iabs(hi_e - lo_e) * 3) / 100; + } + else + { + assert(sel == 0); + + // Selector 0 + e = basisu::iabs(hi_e - i); + } + + if (e < lowest_e) + { + pTable[i].m_hi = static_cast(hi); + pTable[i].m_lo = static_cast(lo); + + lowest_e = e; + } + + } // hi + } // lo + } + } +#endif + +#if BASISD_WRITE_NEW_DXT1_TABLES + static void create_etc1_to_dxt1_5_conversion_table() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_dxt1_5.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1_to_dxt1_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1_to_dxt1_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 31; hi++) + { + for (uint32_t lo = 0; lo <= 31; lo++) + { + //if (lo == hi) continue; + + uint32_t colors[4]; + + colors[0] = (lo << 3) | (lo >> 2); + colors[3] = (hi << 3) | (hi >> 2); + + colors[1] = (colors[0] * 2 + colors[3]) / 3; + colors[2] = (colors[3] * 2 + colors[0]) / 3; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1_to_dxt1_selector_mappings[m][s]]; + + total_err += err * err; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + assert(best_err <= 0xFFFF); + + //table[g + inten * 32].m_solutions[sr][m].m_lo = static_cast(best_lo); + //table[g + inten * 32].m_solutions[sr][m].m_hi = static_cast(best_hi); + //table[g + inten * 32].m_solutions[sr][m].m_err = static_cast(best_err); + + //assert(best_lo != best_hi); + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); + } + + static void create_etc1_to_dxt1_6_conversion_table() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_dxt1_6.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1_to_dxt1_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1_to_dxt1_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 63; hi++) + { + for (uint32_t lo = 0; lo <= 63; lo++) + { + //if (lo == hi) continue; + + uint32_t colors[4]; + + colors[0] = (lo << 2) | (lo >> 4); + colors[3] = (hi << 2) | (hi >> 4); + + colors[1] = (colors[0] * 2 + colors[3]) / 3; + colors[2] = (colors[3] * 2 + colors[0]) / 3; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1_to_dxt1_selector_mappings[m][s]]; + + total_err += err * err; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + assert(best_err <= 0xFFFF); + + //table[g + inten * 32].m_solutions[sr][m].m_lo = static_cast(best_lo); + //table[g + inten * 32].m_solutions[sr][m].m_hi = static_cast(best_hi); + //table[g + inten * 32].m_solutions[sr][m].m_err = static_cast(best_err); + + //assert(best_lo != best_hi); + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + + } // m + } // sr + } // g + } // inten + + fclose(pFile); + } +#endif + + +#if BASISD_SUPPORT_UASTC || BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_ETC2_EAC_RG11 + static const int8_t g_eac_modifier_table[16][8] = + { + { -3, -6, -9, -15, 2, 5, 8, 14 }, + { -3, -7, -10, -13, 2, 6, 9, 12 }, + { -2, -5, -8, -13, 1, 4, 7, 12 }, + { -2, -4, -6, -13, 1, 3, 5, 12 }, + { -3, -6, -8, -12, 2, 5, 7, 11 }, + { -3, -7, -9, -11, 2, 6, 8, 10 }, + { -4, -7, -8, -11, 3, 6, 7, 10 }, + { -3, -5, -8, -11, 2, 4, 7, 10 }, + + { -2, -6, -8, -10, 1, 5, 7, 9 }, + { -2, -5, -8, -10, 1, 4, 7, 9 }, + { -2, -4, -8, -10, 1, 3, 7, 9 }, + { -2, -5, -7, -10, 1, 4, 6, 9 }, + { -3, -4, -7, -10, 2, 3, 6, 9 }, + { -1, -2, -3, -10, 0, 1, 2, 9 }, // entry 13 + { -4, -6, -8, -9, 3, 5, 7, 8 }, + { -3, -5, -7, -9, 2, 4, 6, 8 } + }; + + // Used by ETC2 EAC A8 and ETC2 EAC R11/RG11. + struct eac_block + { + uint16_t m_base : 8; + + uint16_t m_table : 4; + uint16_t m_multiplier : 4; + + uint8_t m_selectors[6]; + + uint32_t get_selector(uint32_t x, uint32_t y) const + { + assert((x < 4) && (y < 4)); + + const uint32_t ofs = 45 - (y + x * 4) * 3; + + const uint64_t pixels = get_selector_bits(); + + return (pixels >> ofs) & 7; + } + + void set_selector(uint32_t x, uint32_t y, uint32_t s) + { + assert((x < 4) && (y < 4) && (s < 8)); + + const uint32_t ofs = 45 - (y + x * 4) * 3; + + uint64_t pixels = get_selector_bits(); + + pixels &= ~(7ULL << ofs); + pixels |= (static_cast(s) << ofs); + + set_selector_bits(pixels); + } + + uint64_t get_selector_bits() const + { + uint64_t pixels = ((uint64_t)m_selectors[0] << 40) | ((uint64_t)m_selectors[1] << 32) | + ((uint64_t)m_selectors[2] << 24) | + ((uint64_t)m_selectors[3] << 16) | ((uint64_t)m_selectors[4] << 8) | m_selectors[5]; + return pixels; + } + + void set_selector_bits(uint64_t pixels) + { + m_selectors[0] = (uint8_t)(pixels >> 40); + m_selectors[1] = (uint8_t)(pixels >> 32); + m_selectors[2] = (uint8_t)(pixels >> 24); + m_selectors[3] = (uint8_t)(pixels >> 16); + m_selectors[4] = (uint8_t)(pixels >> 8); + m_selectors[5] = (uint8_t)(pixels); + } + }; + +#endif // #if BASISD_SUPPORT_UASTC BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_ETC2_EAC_RG11 + +#if BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_ETC2_EAC_RG11 + static const dxt_selector_range s_etc2_eac_selector_ranges[] = + { + { 0, 3 }, + + { 1, 3 }, + { 0, 2 }, + + { 1, 2 }, + }; + + const uint32_t NUM_ETC2_EAC_SELECTOR_RANGES = sizeof(s_etc2_eac_selector_ranges) / sizeof(s_etc2_eac_selector_ranges[0]); + + struct etc1_g_to_eac_conversion + { + uint8_t m_base; + uint8_t m_table_mul; // mul*16+table + uint16_t m_trans; // translates ETC1 selectors to ETC2_EAC_A8 + }; +#endif // BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_ETC2_EAC_RG11 + +#if BASISD_SUPPORT_ETC2_EAC_A8 + +#if BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES + struct pack_eac_a8_results + { + uint32_t m_base; + uint32_t m_table; + uint32_t m_multiplier; + basisu::vector m_selectors; + basisu::vector m_selectors_temp; + }; + + static uint64_t pack_eac_a8_exhaustive(pack_eac_a8_results& results, const uint8_t* pPixels, uint32_t num_pixels) + { + results.m_selectors.resize(num_pixels); + results.m_selectors_temp.resize(num_pixels); + + uint64_t best_err = UINT64_MAX; + + for (uint32_t base_color = 0; base_color < 256; base_color++) + { + for (uint32_t multiplier = 1; multiplier < 16; multiplier++) + { + for (uint32_t table = 0; table < 16; table++) + { + uint64_t total_err = 0; + + for (uint32_t i = 0; i < num_pixels; i++) + { + const int a = pPixels[i]; + + uint32_t best_s_err = UINT32_MAX; + uint32_t best_s = 0; + for (uint32_t s = 0; s < 8; s++) + { + int v = (int)multiplier * g_eac_modifier_table[table][s] + (int)base_color; + if (v < 0) + v = 0; + else if (v > 255) + v = 255; + + uint32_t err = abs(a - v); + if (err < best_s_err) + { + best_s_err = err; + best_s = s; + } + } + + results.m_selectors_temp[i] = static_cast(best_s); + + total_err += best_s_err * best_s_err; + if (total_err >= best_err) + break; + } + + if (total_err < best_err) + { + best_err = total_err; + results.m_base = base_color; + results.m_multiplier = multiplier; + results.m_table = table; + results.m_selectors.swap(results.m_selectors_temp); + } + + } // table + + } // multiplier + + } // base_color + + return best_err; + } +#endif // BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES + + static +#if !BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES + const +#endif + etc1_g_to_eac_conversion s_etc1_g_to_etc2_a8[32 * 8][NUM_ETC2_EAC_SELECTOR_RANGES] = + { + { { 0,1,3328 },{ 0,1,3328 },{ 0,1,256 },{ 0,1,256 } }, + { { 0,226,3936 },{ 0,226,3936 },{ 0,81,488 },{ 0,81,488 } }, + { { 6,178,4012 },{ 6,178,4008 },{ 0,146,501 },{ 0,130,496 } }, + { { 14,178,4012 },{ 14,178,4008 },{ 8,146,501 },{ 6,82,496 } }, + { { 23,178,4012 },{ 23,178,4008 },{ 17,146,501 },{ 3,228,496 } }, + { { 31,178,4012 },{ 31,178,4008 },{ 25,146,501 },{ 11,228,496 } }, + { { 39,178,4012 },{ 39,178,4008 },{ 33,146,501 },{ 19,228,496 } }, + { { 47,178,4012 },{ 47,178,4008 },{ 41,146,501 },{ 27,228,496 } }, + { { 56,178,4012 },{ 56,178,4008 },{ 50,146,501 },{ 36,228,496 } }, + { { 64,178,4012 },{ 64,178,4008 },{ 58,146,501 },{ 44,228,496 } }, + { { 72,178,4012 },{ 72,178,4008 },{ 66,146,501 },{ 52,228,496 } }, + { { 80,178,4012 },{ 80,178,4008 },{ 74,146,501 },{ 60,228,496 } }, + { { 89,178,4012 },{ 89,178,4008 },{ 83,146,501 },{ 69,228,496 } }, + { { 97,178,4012 },{ 97,178,4008 },{ 91,146,501 },{ 77,228,496 } }, + { { 105,178,4012 },{ 105,178,4008 },{ 99,146,501 },{ 85,228,496 } }, + { { 113,178,4012 },{ 113,178,4008 },{ 107,146,501 },{ 93,228,496 } }, + { { 122,178,4012 },{ 122,178,4008 },{ 116,146,501 },{ 102,228,496 } }, + { { 130,178,4012 },{ 130,178,4008 },{ 124,146,501 },{ 110,228,496 } }, + { { 138,178,4012 },{ 138,178,4008 },{ 132,146,501 },{ 118,228,496 } }, + { { 146,178,4012 },{ 146,178,4008 },{ 140,146,501 },{ 126,228,496 } }, + { { 155,178,4012 },{ 155,178,4008 },{ 149,146,501 },{ 135,228,496 } }, + { { 163,178,4012 },{ 163,178,4008 },{ 157,146,501 },{ 143,228,496 } }, + { { 171,178,4012 },{ 171,178,4008 },{ 165,146,501 },{ 151,228,496 } }, + { { 179,178,4012 },{ 179,178,4008 },{ 173,146,501 },{ 159,228,496 } }, + { { 188,178,4012 },{ 188,178,4008 },{ 182,146,501 },{ 168,228,496 } }, + { { 196,178,4012 },{ 196,178,4008 },{ 190,146,501 },{ 176,228,496 } }, + { { 204,178,4012 },{ 204,178,4008 },{ 198,146,501 },{ 184,228,496 } }, + { { 212,178,4012 },{ 212,178,4008 },{ 206,146,501 },{ 192,228,496 } }, + { { 221,178,4012 },{ 221,178,4008 },{ 215,146,501 },{ 201,228,496 } }, + { { 229,178,4012 },{ 229,178,4008 },{ 223,146,501 },{ 209,228,496 } }, + { { 235,66,4012 },{ 221,100,4008 },{ 231,146,501 },{ 217,228,496 } }, + { { 211,102,4085 },{ 118,31,4080 },{ 211,102,501 },{ 118,31,496 } }, + { { 1,2,3328 },{ 1,2,3328 },{ 0,1,320 },{ 0,1,320 } }, + { { 7,162,3905 },{ 7,162,3904 },{ 1,17,480 },{ 1,17,480 } }, + { { 15,162,3906 },{ 15,162,3904 },{ 1,117,352 },{ 1,117,352 } }, + { { 23,162,3906 },{ 23,162,3904 },{ 5,34,500 },{ 4,53,424 } }, + { { 32,162,3906 },{ 32,162,3904 },{ 14,34,500 },{ 3,69,424 } }, + { { 40,162,3906 },{ 40,162,3904 },{ 22,34,500 },{ 1,133,496 } }, + { { 48,162,3906 },{ 48,162,3904 },{ 30,34,500 },{ 4,85,496 } }, + { { 56,162,3906 },{ 56,162,3904 },{ 38,34,500 },{ 12,85,496 } }, + { { 65,162,3906 },{ 65,162,3904 },{ 47,34,500 },{ 1,106,424 } }, + { { 73,162,3906 },{ 73,162,3904 },{ 55,34,500 },{ 9,106,424 } }, + { { 81,162,3906 },{ 81,162,3904 },{ 63,34,500 },{ 7,234,496 } }, + { { 89,162,3906 },{ 89,162,3904 },{ 71,34,500 },{ 15,234,496 } }, + { { 98,162,3906 },{ 98,162,3904 },{ 80,34,500 },{ 24,234,496 } }, + { { 106,162,3906 },{ 106,162,3904 },{ 88,34,500 },{ 32,234,496 } }, + { { 114,162,3906 },{ 114,162,3904 },{ 96,34,500 },{ 40,234,496 } }, + { { 122,162,3906 },{ 122,162,3904 },{ 104,34,500 },{ 48,234,496 } }, + { { 131,162,3906 },{ 131,162,3904 },{ 113,34,500 },{ 57,234,496 } }, + { { 139,162,3906 },{ 139,162,3904 },{ 121,34,500 },{ 65,234,496 } }, + { { 147,162,3906 },{ 147,162,3904 },{ 129,34,500 },{ 73,234,496 } }, + { { 155,162,3906 },{ 155,162,3904 },{ 137,34,500 },{ 81,234,496 } }, + { { 164,162,3906 },{ 164,162,3904 },{ 146,34,500 },{ 90,234,496 } }, + { { 172,162,3906 },{ 172,162,3904 },{ 154,34,500 },{ 98,234,496 } }, + { { 180,162,3906 },{ 180,162,3904 },{ 162,34,500 },{ 106,234,496 } }, + { { 188,162,3906 },{ 188,162,3904 },{ 170,34,500 },{ 114,234,496 } }, + { { 197,162,3906 },{ 197,162,3904 },{ 179,34,500 },{ 123,234,496 } }, + { { 205,162,3906 },{ 205,162,3904 },{ 187,34,500 },{ 131,234,496 } }, + { { 213,162,3906 },{ 213,162,3904 },{ 195,34,500 },{ 139,234,496 } }, + { { 221,162,3906 },{ 221,162,3904 },{ 203,34,500 },{ 147,234,496 } }, + { { 230,162,3906 },{ 230,162,3904 },{ 212,34,500 },{ 156,234,496 } }, + { { 238,162,3906 },{ 174,106,4008 },{ 220,34,500 },{ 164,234,496 } }, + { { 240,178,4001 },{ 182,106,4008 },{ 228,34,500 },{ 172,234,496 } }, + { { 166,108,4085 },{ 115,31,4080 },{ 166,108,501 },{ 115,31,496 } }, + { { 1,68,3328 },{ 1,68,3328 },{ 0,17,384 },{ 0,17,384 } }, + { { 1,148,3904 },{ 1,148,3904 },{ 1,2,384 },{ 1,2,384 } }, + { { 21,18,3851 },{ 21,18,3848 },{ 1,50,488 },{ 1,50,488 } }, + { { 27,195,3851 },{ 29,18,3848 },{ 0,67,488 },{ 0,67,488 } }, + { { 34,195,3907 },{ 38,18,3848 },{ 20,66,482 },{ 0,3,496 } }, + { { 42,195,3907 },{ 46,18,3848 },{ 28,66,482 },{ 2,6,424 } }, + { { 50,195,3907 },{ 54,18,3848 },{ 36,66,482 },{ 4,22,424 } }, + { { 58,195,3907 },{ 62,18,3848 },{ 44,66,482 },{ 3,73,424 } }, + { { 67,195,3907 },{ 71,18,3848 },{ 53,66,482 },{ 3,22,496 } }, + { { 75,195,3907 },{ 79,18,3848 },{ 61,66,482 },{ 2,137,496 } }, + { { 83,195,3907 },{ 87,18,3848 },{ 69,66,482 },{ 1,89,496 } }, + { { 91,195,3907 },{ 95,18,3848 },{ 77,66,482 },{ 9,89,496 } }, + { { 100,195,3907 },{ 104,18,3848 },{ 86,66,482 },{ 18,89,496 } }, + { { 108,195,3907 },{ 112,18,3848 },{ 94,66,482 },{ 26,89,496 } }, + { { 116,195,3907 },{ 120,18,3848 },{ 102,66,482 },{ 34,89,496 } }, + { { 124,195,3907 },{ 128,18,3848 },{ 110,66,482 },{ 42,89,496 } }, + { { 133,195,3907 },{ 137,18,3848 },{ 119,66,482 },{ 51,89,496 } }, + { { 141,195,3907 },{ 145,18,3848 },{ 127,66,482 },{ 59,89,496 } }, + { { 149,195,3907 },{ 153,18,3848 },{ 135,66,482 },{ 67,89,496 } }, + { { 157,195,3907 },{ 161,18,3848 },{ 143,66,482 },{ 75,89,496 } }, + { { 166,195,3907 },{ 170,18,3848 },{ 152,66,482 },{ 84,89,496 } }, + { { 174,195,3907 },{ 178,18,3848 },{ 160,66,482 },{ 92,89,496 } }, + { { 182,195,3907 },{ 186,18,3848 },{ 168,66,482 },{ 100,89,496 } }, + { { 190,195,3907 },{ 194,18,3848 },{ 176,66,482 },{ 108,89,496 } }, + { { 199,195,3907 },{ 203,18,3848 },{ 185,66,482 },{ 117,89,496 } }, + { { 207,195,3907 },{ 211,18,3848 },{ 193,66,482 },{ 125,89,496 } }, + { { 215,195,3907 },{ 219,18,3848 },{ 201,66,482 },{ 133,89,496 } }, + { { 223,195,3907 },{ 227,18,3848 },{ 209,66,482 },{ 141,89,496 } }, + { { 231,195,3907 },{ 168,89,4008 },{ 218,66,482 },{ 150,89,496 } }, + { { 236,18,3907 },{ 176,89,4008 },{ 226,66,482 },{ 158,89,496 } }, + { { 158,90,4085 },{ 103,31,4080 },{ 158,90,501 },{ 103,31,496 } }, + { { 166,90,4085 },{ 111,31,4080 },{ 166,90,501 },{ 111,31,496 } }, + { { 0,70,3328 },{ 0,70,3328 },{ 0,45,256 },{ 0,45,256 } }, + { { 0,117,3904 },{ 0,117,3904 },{ 0,35,384 },{ 0,35,384 } }, + { { 13,165,3905 },{ 13,165,3904 },{ 3,221,416 },{ 3,221,416 } }, + { { 21,165,3906 },{ 21,165,3904 },{ 11,221,416 },{ 11,221,416 } }, + { { 30,165,3906 },{ 30,165,3904 },{ 7,61,352 },{ 7,61,352 } }, + { { 38,165,3906 },{ 38,165,3904 },{ 2,125,352 },{ 2,125,352 } }, + { { 46,165,3906 },{ 46,165,3904 },{ 2,37,500 },{ 10,125,352 } }, + { { 54,165,3906 },{ 54,165,3904 },{ 10,37,500 },{ 5,61,424 } }, + { { 63,165,3906 },{ 63,165,3904 },{ 19,37,500 },{ 1,189,424 } }, + { { 4,254,4012 },{ 71,165,3904 },{ 27,37,500 },{ 9,189,424 } }, + { { 12,254,4012 },{ 79,165,3904 },{ 35,37,500 },{ 4,77,424 } }, + { { 20,254,4012 },{ 87,165,3904 },{ 43,37,500 },{ 12,77,424 } }, + { { 29,254,4012 },{ 96,165,3904 },{ 52,37,500 },{ 8,93,424 } }, + { { 37,254,4012 },{ 104,165,3904 },{ 60,37,500 },{ 3,141,496 } }, + { { 45,254,4012 },{ 112,165,3904 },{ 68,37,500 },{ 11,141,496 } }, + { { 53,254,4012 },{ 120,165,3904 },{ 76,37,500 },{ 6,93,496 } }, + { { 62,254,4012 },{ 129,165,3904 },{ 85,37,500 },{ 15,93,496 } }, + { { 70,254,4012 },{ 137,165,3904 },{ 93,37,500 },{ 23,93,496 } }, + { { 78,254,4012 },{ 145,165,3904 },{ 101,37,500 },{ 31,93,496 } }, + { { 86,254,4012 },{ 153,165,3904 },{ 109,37,500 },{ 39,93,496 } }, + { { 95,254,4012 },{ 162,165,3904 },{ 118,37,500 },{ 48,93,496 } }, + { { 103,254,4012 },{ 170,165,3904 },{ 126,37,500 },{ 56,93,496 } }, + { { 111,254,4012 },{ 178,165,3904 },{ 134,37,500 },{ 64,93,496 } }, + { { 119,254,4012 },{ 186,165,3904 },{ 142,37,500 },{ 72,93,496 } }, + { { 128,254,4012 },{ 195,165,3904 },{ 151,37,500 },{ 81,93,496 } }, + { { 136,254,4012 },{ 203,165,3904 },{ 159,37,500 },{ 89,93,496 } }, + { { 212,165,3906 },{ 136,77,4008 },{ 167,37,500 },{ 97,93,496 } }, + { { 220,165,3394 },{ 131,93,4008 },{ 175,37,500 },{ 105,93,496 } }, + { { 214,181,4001 },{ 140,93,4008 },{ 184,37,500 },{ 114,93,496 } }, + { { 222,181,4001 },{ 148,93,4008 },{ 192,37,500 },{ 122,93,496 } }, + { { 114,95,4085 },{ 99,31,4080 },{ 114,95,501 },{ 99,31,496 } }, + { { 122,95,4085 },{ 107,31,4080 },{ 122,95,501 },{ 107,31,496 } }, + { { 0,102,3840 },{ 0,102,3840 },{ 0,18,384 },{ 0,18,384 } }, + { { 5,167,3904 },{ 5,167,3904 },{ 0,13,256 },{ 0,13,256 } }, + { { 4,54,3968 },{ 4,54,3968 },{ 1,67,448 },{ 1,67,448 } }, + { { 30,198,3850 },{ 30,198,3848 },{ 0,3,480 },{ 0,3,480 } }, + { { 39,198,3850 },{ 39,198,3848 },{ 3,52,488 },{ 3,52,488 } }, + { { 47,198,3851 },{ 47,198,3848 },{ 3,4,488 },{ 3,4,488 } }, + { { 55,198,3851 },{ 55,198,3848 },{ 1,70,488 },{ 1,70,488 } }, + { { 54,167,3906 },{ 63,198,3848 },{ 3,22,488 },{ 3,22,488 } }, + { { 62,167,3906 },{ 72,198,3848 },{ 24,118,488 },{ 0,6,496 } }, + { { 70,167,3906 },{ 80,198,3848 },{ 32,118,488 },{ 2,89,488 } }, + { { 78,167,3906 },{ 88,198,3848 },{ 40,118,488 },{ 1,73,496 } }, + { { 86,167,3906 },{ 96,198,3848 },{ 48,118,488 },{ 0,28,424 } }, + { { 95,167,3906 },{ 105,198,3848 },{ 57,118,488 },{ 9,28,424 } }, + { { 103,167,3906 },{ 113,198,3848 },{ 65,118,488 },{ 5,108,496 } }, + { { 111,167,3906 },{ 121,198,3848 },{ 73,118,488 },{ 13,108,496 } }, + { { 119,167,3906 },{ 129,198,3848 },{ 81,118,488 },{ 21,108,496 } }, + { { 128,167,3906 },{ 138,198,3848 },{ 90,118,488 },{ 6,28,496 } }, + { { 136,167,3906 },{ 146,198,3848 },{ 98,118,488 },{ 14,28,496 } }, + { { 144,167,3906 },{ 154,198,3848 },{ 106,118,488 },{ 22,28,496 } }, + { { 152,167,3906 },{ 162,198,3848 },{ 114,118,488 },{ 30,28,496 } }, + { { 161,167,3906 },{ 171,198,3848 },{ 123,118,488 },{ 39,28,496 } }, + { { 169,167,3906 },{ 179,198,3848 },{ 131,118,488 },{ 47,28,496 } }, + { { 177,167,3906 },{ 187,198,3848 },{ 139,118,488 },{ 55,28,496 } }, + { { 185,167,3906 },{ 195,198,3848 },{ 147,118,488 },{ 63,28,496 } }, + { { 194,167,3906 },{ 120,12,4008 },{ 156,118,488 },{ 72,28,496 } }, + { { 206,198,3907 },{ 116,28,4008 },{ 164,118,488 },{ 80,28,496 } }, + { { 214,198,3907 },{ 124,28,4008 },{ 172,118,488 },{ 88,28,496 } }, + { { 222,198,3395 },{ 132,28,4008 },{ 180,118,488 },{ 96,28,496 } }, + { { 207,134,4001 },{ 141,28,4008 },{ 189,118,488 },{ 105,28,496 } }, + { { 95,30,4085 },{ 86,31,4080 },{ 95,30,501 },{ 86,31,496 } }, + { { 103,30,4085 },{ 94,31,4080 },{ 103,30,501 },{ 94,31,496 } }, + { { 111,30,4085 },{ 102,31,4080 },{ 111,30,501 },{ 102,31,496 } }, + { { 0,104,3840 },{ 0,104,3840 },{ 0,18,448 },{ 0,18,448 } }, + { { 4,39,3904 },{ 4,39,3904 },{ 0,4,384 },{ 0,4,384 } }, + { { 0,56,3968 },{ 0,56,3968 },{ 0,84,448 },{ 0,84,448 } }, + { { 6,110,3328 },{ 6,110,3328 },{ 0,20,448 },{ 0,20,448 } }, + { { 41,200,3850 },{ 41,200,3848 },{ 1,4,480 },{ 1,4,480 } }, + { { 49,200,3850 },{ 49,200,3848 },{ 1,8,416 },{ 1,8,416 } }, + { { 57,200,3851 },{ 57,200,3848 },{ 1,38,488 },{ 1,38,488 } }, + { { 65,200,3851 },{ 65,200,3848 },{ 1,120,488 },{ 1,120,488 } }, + { { 74,200,3851 },{ 74,200,3848 },{ 2,72,488 },{ 2,72,488 } }, + { { 69,6,3907 },{ 82,200,3848 },{ 2,24,488 },{ 2,24,488 } }, + { { 77,6,3907 },{ 90,200,3848 },{ 26,120,488 },{ 10,24,488 } }, + { { 97,63,3330 },{ 98,200,3848 },{ 34,120,488 },{ 2,8,496 } }, + { { 106,63,3330 },{ 107,200,3848 },{ 43,120,488 },{ 3,92,488 } }, + { { 114,63,3330 },{ 115,200,3848 },{ 51,120,488 },{ 11,92,488 } }, + { { 122,63,3330 },{ 123,200,3848 },{ 59,120,488 },{ 7,76,496 } }, + { { 130,63,3330 },{ 131,200,3848 },{ 67,120,488 },{ 15,76,496 } }, + { { 139,63,3330 },{ 140,200,3848 },{ 76,120,488 },{ 24,76,496 } }, + { { 147,63,3330 },{ 148,200,3848 },{ 84,120,488 },{ 32,76,496 } }, + { { 155,63,3330 },{ 156,200,3848 },{ 92,120,488 },{ 40,76,496 } }, + { { 163,63,3330 },{ 164,200,3848 },{ 100,120,488 },{ 48,76,496 } }, + { { 172,63,3330 },{ 173,200,3848 },{ 109,120,488 },{ 57,76,496 } }, + { { 184,6,3851 },{ 181,200,3848 },{ 117,120,488 },{ 65,76,496 } }, + { { 192,6,3851 },{ 133,28,3936 },{ 125,120,488 },{ 73,76,496 } }, + { { 189,200,3907 },{ 141,28,3936 },{ 133,120,488 },{ 81,76,496 } }, + { { 198,200,3907 },{ 138,108,4000 },{ 142,120,488 },{ 90,76,496 } }, + { { 206,200,3907 },{ 146,108,4000 },{ 150,120,488 },{ 98,76,496 } }, + { { 214,200,3395 },{ 154,108,4000 },{ 158,120,488 },{ 106,76,496 } }, + { { 190,136,4001 },{ 162,108,4000 },{ 166,120,488 },{ 114,76,496 } }, + { { 123,30,4076 },{ 87,15,4080 },{ 123,30,492 },{ 87,15,496 } }, + { { 117,110,4084 },{ 80,31,4080 },{ 117,110,500 },{ 80,31,496 } }, + { { 125,110,4084 },{ 88,31,4080 },{ 125,110,500 },{ 88,31,496 } }, + { { 133,110,4084 },{ 96,31,4080 },{ 133,110,500 },{ 96,31,496 } }, + { { 9,56,3904 },{ 9,56,3904 },{ 0,67,448 },{ 0,67,448 } }, + { { 1,8,3904 },{ 1,8,3904 },{ 1,84,448 },{ 1,84,448 } }, + { { 1,124,3904 },{ 1,124,3904 },{ 0,39,384 },{ 0,39,384 } }, + { { 9,124,3904 },{ 9,124,3904 },{ 1,4,448 },{ 1,4,448 } }, + { { 6,76,3904 },{ 6,76,3904 },{ 0,70,448 },{ 0,70,448 } }, + { { 62,6,3859 },{ 62,6,3856 },{ 2,38,480 },{ 2,38,480 } }, + { { 70,6,3859 },{ 70,6,3856 },{ 5,43,416 },{ 5,43,416 } }, + { { 78,6,3859 },{ 78,6,3856 },{ 2,11,416 },{ 2,11,416 } }, + { { 87,6,3859 },{ 87,6,3856 },{ 0,171,488 },{ 0,171,488 } }, + { { 67,8,3906 },{ 95,6,3856 },{ 8,171,488 },{ 8,171,488 } }, + { { 75,8,3907 },{ 103,6,3856 },{ 5,123,488 },{ 5,123,488 } }, + { { 83,8,3907 },{ 111,6,3856 },{ 2,75,488 },{ 2,75,488 } }, + { { 92,8,3907 },{ 120,6,3856 },{ 0,27,488 },{ 0,27,488 } }, + { { 100,8,3907 },{ 128,6,3856 },{ 8,27,488 },{ 8,27,488 } }, + { { 120,106,3843 },{ 136,6,3856 },{ 100,6,387 },{ 16,27,488 } }, + { { 128,106,3843 },{ 144,6,3856 },{ 108,6,387 },{ 2,11,496 } }, + { { 137,106,3843 },{ 153,6,3856 },{ 117,6,387 },{ 11,11,496 } }, + { { 145,106,3843 },{ 161,6,3856 },{ 125,6,387 },{ 19,11,496 } }, + { { 163,8,3851 },{ 137,43,3904 },{ 133,6,387 },{ 27,11,496 } }, + { { 171,8,3851 },{ 101,11,4000 },{ 141,6,387 },{ 35,11,496 } }, + { { 180,8,3851 },{ 110,11,4000 },{ 150,6,387 },{ 44,11,496 } }, + { { 188,8,3851 },{ 118,11,4000 },{ 158,6,387 },{ 52,11,496 } }, + { { 172,72,3907 },{ 126,11,4000 },{ 166,6,387 },{ 60,11,496 } }, + { { 174,6,3971 },{ 134,11,4000 },{ 174,6,387 },{ 68,11,496 } }, + { { 183,6,3971 },{ 143,11,4000 },{ 183,6,387 },{ 77,11,496 } }, + { { 191,6,3971 },{ 151,11,4000 },{ 191,6,387 },{ 85,11,496 } }, + { { 199,6,3971 },{ 159,11,4000 },{ 199,6,387 },{ 93,11,496 } }, + { { 92,12,4084 },{ 69,15,4080 },{ 92,12,500 },{ 69,15,496 } }, + { { 101,12,4084 },{ 78,15,4080 },{ 101,12,500 },{ 78,15,496 } }, + { { 109,12,4084 },{ 86,15,4080 },{ 109,12,500 },{ 86,15,496 } }, + { { 117,12,4084 },{ 79,31,4080 },{ 117,12,500 },{ 79,31,496 } }, + { { 125,12,4084 },{ 87,31,4080 },{ 125,12,500 },{ 87,31,496 } }, + { { 71,8,3602 },{ 71,8,3600 },{ 2,21,384 },{ 2,21,384 } }, + { { 79,8,3611 },{ 79,8,3608 },{ 0,69,448 },{ 0,69,448 } }, + { { 87,8,3611 },{ 87,8,3608 },{ 0,23,384 },{ 0,23,384 } }, + { { 95,8,3611 },{ 95,8,3608 },{ 1,5,448 },{ 1,5,448 } }, + { { 104,8,3611 },{ 104,8,3608 },{ 0,88,448 },{ 0,88,448 } }, + { { 112,8,3611 },{ 112,8,3608 },{ 0,72,448 },{ 0,72,448 } }, + { { 120,8,3611 },{ 121,8,3608 },{ 36,21,458 },{ 36,21,456 } }, + { { 133,47,3091 },{ 129,8,3608 },{ 44,21,458 },{ 44,21,456 } }, + { { 142,47,3091 },{ 138,8,3608 },{ 53,21,459 },{ 53,21,456 } }, + { { 98,12,3850 },{ 98,12,3848 },{ 61,21,459 },{ 61,21,456 } }, + { { 106,12,3850 },{ 106,12,3848 },{ 10,92,480 },{ 69,21,456 } }, + { { 114,12,3851 },{ 114,12,3848 },{ 18,92,480 },{ 77,21,456 } }, + { { 87,12,3906 },{ 87,12,3904 },{ 3,44,488 },{ 86,21,456 } }, + { { 95,12,3906 },{ 95,12,3904 },{ 11,44,488 },{ 94,21,456 } }, + { { 103,12,3906 },{ 103,12,3904 },{ 19,44,488 },{ 102,21,456 } }, + { { 111,12,3907 },{ 111,12,3904 },{ 27,44,489 },{ 110,21,456 } }, + { { 120,12,3907 },{ 120,12,3904 },{ 36,44,489 },{ 119,21,456 } }, + { { 128,12,3907 },{ 128,12,3904 },{ 44,44,489 },{ 127,21,456 } }, + { { 136,12,3907 },{ 136,12,3904 },{ 52,44,489 },{ 135,21,456 } }, + { { 144,12,3907 },{ 144,12,3904 },{ 60,44,489 },{ 143,21,456 } }, + { { 153,12,3907 },{ 153,12,3904 },{ 69,44,490 },{ 152,21,456 } }, + { { 161,12,3395 },{ 149,188,3968 },{ 77,44,490 },{ 160,21,456 } }, + { { 169,12,3395 },{ 198,21,3928 },{ 85,44,490 },{ 168,21,456 } }, + { { 113,95,4001 },{ 201,69,3992 },{ 125,8,483 },{ 176,21,456 } }, + { { 122,95,4001 },{ 200,21,3984 },{ 134,8,483 },{ 185,21,456 } }, + { { 142,8,4067 },{ 208,21,3984 },{ 142,8,483 },{ 193,21,456 } }, + { { 151,8,4067 },{ 47,15,4080 },{ 151,8,483 },{ 47,15,496 } }, + { { 159,8,4067 },{ 55,15,4080 },{ 159,8,483 },{ 55,15,496 } }, + { { 168,8,4067 },{ 64,15,4080 },{ 168,8,483 },{ 64,15,496 } }, + { { 160,40,4075 },{ 72,15,4080 },{ 160,40,491 },{ 72,15,496 } }, + { { 168,40,4075 },{ 80,15,4080 },{ 168,40,491 },{ 80,15,496 } }, + { { 144,8,4082 },{ 88,15,4080 },{ 144,8,498 },{ 88,15,496 } } + }; +#endif // BASISD_SUPPORT_ETC2_EAC_A8 + +#if BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES + static void create_etc2_eac_a8_conversion_table() + { + FILE* pFile = fopen("basisu_decoder_tables_etc2_eac_a8.inc", "w"); + + for (uint32_t inten = 0; inten < 8; inten++) + { + for (uint32_t base = 0; base < 32; base++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(base, base, base, 255), false), inten); + + fprintf(pFile, "{"); + + for (uint32_t sel_range = 0; sel_range < NUM_ETC2_EAC_SELECTOR_RANGES; sel_range++) + { + const uint32_t low_selector = s_etc2_eac_selector_ranges[sel_range].m_low; + const uint32_t high_selector = s_etc2_eac_selector_ranges[sel_range].m_high; + + // We have a ETC1 base color and intensity, and a used selector range from low_selector-high_selector. + // Now find the best ETC2 EAC A8 base/table/multiplier that fits these colors. + + uint8_t pixels[4]; + uint32_t num_pixels = 0; + for (uint32_t s = low_selector; s <= high_selector; s++) + pixels[num_pixels++] = block_colors[s].g; + + pack_eac_a8_results pack_results; + pack_eac_a8_exhaustive(pack_results, pixels, num_pixels); + + etc1_g_to_eac_conversion& c = s_etc1_g_to_etc2_a8[base + inten * 32][sel_range]; + + c.m_base = pack_results.m_base; + c.m_table_mul = pack_results.m_table * 16 + pack_results.m_multiplier; + c.m_trans = 0; + + for (uint32_t s = 0; s < 4; s++) + { + if ((s < low_selector) || (s > high_selector)) + continue; + + uint32_t etc2_selector = pack_results.m_selectors[s - low_selector]; + + c.m_trans |= (etc2_selector << (s * 3)); + } + + fprintf(pFile, "{%u,%u,%u}", c.m_base, c.m_table_mul, c.m_trans); + if (sel_range < (NUM_ETC2_EAC_SELECTOR_RANGES - 1)) + fprintf(pFile, ","); + } + + fprintf(pFile, "},\n"); + } + } + + fclose(pFile); + } +#endif + +#if BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES + struct pack_eac_r11_results + { + uint32_t m_base; + uint32_t m_table; + uint32_t m_multiplier; + basisu::vector m_selectors; + basisu::vector m_selectors_temp; + }; + + static uint64_t pack_eac_r11_exhaustive(pack_eac_r11_results& results, const uint8_t* pPixels, uint32_t num_pixels) + { + results.m_selectors.resize(num_pixels); + results.m_selectors_temp.resize(num_pixels); + + uint64_t best_err = UINT64_MAX; + + for (uint32_t base_color = 0; base_color < 256; base_color++) + { + for (uint32_t multiplier = 0; multiplier < 16; multiplier++) + { + for (uint32_t table = 0; table < 16; table++) + { + uint64_t total_err = 0; + + for (uint32_t i = 0; i < num_pixels; i++) + { + // Convert 8-bit input to 11-bits + const int a = (pPixels[i] * 2047 + 128) / 255; + + uint32_t best_s_err = UINT32_MAX; + uint32_t best_s = 0; + for (uint32_t s = 0; s < 8; s++) + { + int v = (int)(multiplier ? (multiplier * 8) : 1) * g_eac_modifier_table[table][s] + (int)base_color * 8 + 4; + if (v < 0) + v = 0; + else if (v > 2047) + v = 2047; + + uint32_t err = abs(a - v); + if (err < best_s_err) + { + best_s_err = err; + best_s = s; + } + } + + results.m_selectors_temp[i] = static_cast(best_s); + + total_err += best_s_err * best_s_err; + if (total_err >= best_err) + break; + } + + if (total_err < best_err) + { + best_err = total_err; + results.m_base = base_color; + results.m_multiplier = multiplier; + results.m_table = table; + results.m_selectors.swap(results.m_selectors_temp); + } + + } // table + + } // multiplier + + } // base_color + + return best_err; + } + + static void create_etc2_eac_r11_conversion_table() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_decoder_tables_etc2_eac_r11.inc", "w"); + + for (uint32_t inten = 0; inten < 8; inten++) + { + for (uint32_t base = 0; base < 32; base++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(base, base, base, 255), false), inten); + + fprintf(pFile, "{"); + + for (uint32_t sel_range = 0; sel_range < NUM_ETC2_EAC_SELECTOR_RANGES; sel_range++) + { + const uint32_t low_selector = s_etc2_eac_selector_ranges[sel_range].m_low; + const uint32_t high_selector = s_etc2_eac_selector_ranges[sel_range].m_high; + + // We have a ETC1 base color and intensity, and a used selector range from low_selector-high_selector. + // Now find the best ETC2 EAC R11 base/table/multiplier that fits these colors. + + uint8_t pixels[4]; + uint32_t num_pixels = 0; + for (uint32_t s = low_selector; s <= high_selector; s++) + pixels[num_pixels++] = block_colors[s].g; + + pack_eac_r11_results pack_results; + pack_eac_r11_exhaustive(pack_results, pixels, num_pixels); + + etc1_g_to_eac_conversion c; + + c.m_base = (uint8_t)pack_results.m_base; + c.m_table_mul = (uint8_t)(pack_results.m_table * 16 + pack_results.m_multiplier); + c.m_trans = 0; + + for (uint32_t s = 0; s < 4; s++) + { + if ((s < low_selector) || (s > high_selector)) + continue; + + uint32_t etc2_selector = pack_results.m_selectors[s - low_selector]; + + c.m_trans |= (etc2_selector << (s * 3)); + } + + fprintf(pFile, "{%u,%u,%u}", c.m_base, c.m_table_mul, c.m_trans); + if (sel_range < (NUM_ETC2_EAC_SELECTOR_RANGES - 1)) + fprintf(pFile, ","); + } + + fprintf(pFile, "},\n"); + } + } + + fclose(pFile); + } +#endif // BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES + +#if BASISD_WRITE_NEW_ASTC_TABLES + static void create_etc1_to_astc_conversion_table_0_47(); + static void create_etc1_to_astc_conversion_table_0_255(); +#endif + +#if BASISD_SUPPORT_ASTC + static void transcoder_init_astc(); +#endif + +#if BASISD_WRITE_NEW_BC7_MODE5_TABLES + static void create_etc1_to_bc7_m5_color_conversion_table(); + static void create_etc1_to_bc7_m5_alpha_conversion_table(); +#endif + +#if BASISD_SUPPORT_BC7_MODE5 + static void transcoder_init_bc7_mode5(); +#endif + +#if BASISD_WRITE_NEW_ATC_TABLES + static void create_etc1s_to_atc_conversion_tables(); +#endif + +#if BASISD_SUPPORT_ATC + static void transcoder_init_atc(); +#endif + +#if BASISD_SUPPORT_PVRTC2 + static void transcoder_init_pvrtc2(); +#endif + +#if BASISD_SUPPORT_UASTC + void uastc_init(); +#endif + + static bool g_transcoder_initialized; + + // Library global initialization. Requires ~9 milliseconds when compiled and executed natively on a Core i7 2.2 GHz. + // If this is too slow, these computed tables can easilky be moved to be compiled in. + void basisu_transcoder_init() + { + if (g_transcoder_initialized) + { + BASISU_DEVEL_ERROR("basisu_transcoder::basisu_transcoder_init: Called more than once\n"); + return; + } + + BASISU_DEVEL_ERROR("basisu_transcoder::basisu_transcoder_init: Initializing (this is not an error)\n"); + +#if BASISD_SUPPORT_UASTC + uastc_init(); +#endif + +#if BASISD_SUPPORT_ASTC + transcoder_init_astc(); +#endif + +#if BASISD_WRITE_NEW_ASTC_TABLES + create_etc1_to_astc_conversion_table_0_47(); + create_etc1_to_astc_conversion_table_0_255(); + exit(0); +#endif + +#if BASISD_WRITE_NEW_BC7_MODE5_TABLES + create_etc1_to_bc7_m5_color_conversion_table(); + create_etc1_to_bc7_m5_alpha_conversion_table(); + exit(0); +#endif + +#if BASISD_WRITE_NEW_DXT1_TABLES + create_etc1_to_dxt1_5_conversion_table(); + create_etc1_to_dxt1_6_conversion_table(); + exit(0); +#endif + +#if BASISD_WRITE_NEW_ETC2_EAC_A8_TABLES + create_etc2_eac_a8_conversion_table(); + exit(0); +#endif + +#if BASISD_WRITE_NEW_ATC_TABLES + create_etc1s_to_atc_conversion_tables(); + exit(0); +#endif + +#if BASISD_WRITE_NEW_ETC2_EAC_R11_TABLES + create_etc2_eac_r11_conversion_table(); + exit(0); +#endif + +#if BASISD_SUPPORT_DXT1 || BASISD_SUPPORT_UASTC + uint8_t bc1_expand5[32]; + for (int i = 0; i < 32; i++) + bc1_expand5[i] = static_cast((i << 3) | (i >> 2)); + prepare_bc1_single_color_table(g_bc1_match5_equals_1, bc1_expand5, 32, 32, 1); + prepare_bc1_single_color_table(g_bc1_match5_equals_0, bc1_expand5, 1, 32, 0); + + uint8_t bc1_expand6[64]; + for (int i = 0; i < 64; i++) + bc1_expand6[i] = static_cast((i << 2) | (i >> 4)); + prepare_bc1_single_color_table(g_bc1_match6_equals_1, bc1_expand6, 64, 64, 1); + prepare_bc1_single_color_table(g_bc1_match6_equals_0, bc1_expand6, 1, 64, 0); + +#if 0 + for (uint32_t i = 0; i < 256; i++) + { + printf("%u %u %u\n", i, (i * 63 + 127) / 255, g_bc1_match6_equals_0[i].m_hi); + } + exit(0); +#endif + +#endif + +#if BASISD_SUPPORT_DXT1 + for (uint32_t i = 0; i < NUM_ETC1_TO_DXT1_SELECTOR_RANGES; i++) + { + uint32_t l = g_etc1_to_dxt1_selector_ranges[i].m_low; + uint32_t h = g_etc1_to_dxt1_selector_ranges[i].m_high; + g_etc1_to_dxt1_selector_range_index[l][h] = i; + } + + for (uint32_t sm = 0; sm < NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS; sm++) + { + uint8_t etc1_to_dxt1_selector_mappings_raw_dxt1[4]; + uint8_t etc1_to_dxt1_selector_mappings_raw_dxt1_inv[4]; + + for (uint32_t j = 0; j < 4; j++) + { + static const uint8_t s_linear_dxt1_to_dxt1[4] = { 0, 2, 3, 1 }; + static const uint8_t s_dxt1_inverted_xlat[4] = { 1, 0, 3, 2 }; + + etc1_to_dxt1_selector_mappings_raw_dxt1[j] = (uint8_t)s_linear_dxt1_to_dxt1[g_etc1_to_dxt1_selector_mappings[sm][j]]; + etc1_to_dxt1_selector_mappings_raw_dxt1_inv[j] = (uint8_t)s_dxt1_inverted_xlat[etc1_to_dxt1_selector_mappings_raw_dxt1[j]]; + } + + for (uint32_t i = 0; i < 256; i++) + { + uint32_t k = 0, k_inv = 0; + for (uint32_t s = 0; s < 4; s++) + { + k |= (etc1_to_dxt1_selector_mappings_raw_dxt1[(i >> (s * 2)) & 3] << (s * 2)); + k_inv |= (etc1_to_dxt1_selector_mappings_raw_dxt1_inv[(i >> (s * 2)) & 3] << (s * 2)); + } + g_etc1_to_dxt1_selector_mappings_raw_dxt1_256[sm][i] = (uint8_t)k; + g_etc1_to_dxt1_selector_mappings_raw_dxt1_inv_256[sm][i] = (uint8_t)k_inv; + } + } +#endif + +#if BASISD_SUPPORT_BC7_MODE5 + transcoder_init_bc7_mode5(); +#endif + +#if BASISD_SUPPORT_ATC + transcoder_init_atc(); +#endif + +#if BASISD_SUPPORT_PVRTC2 + transcoder_init_pvrtc2(); +#endif + + g_transcoder_initialized = true; + } + +#if BASISD_SUPPORT_DXT1 + static void convert_etc1s_to_dxt1(dxt1_block* pDst_block, const endpoint *pEndpoints, const selector* pSelector, bool use_threecolor_blocks) + { +#if !BASISD_WRITE_NEW_DXT1_TABLES + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (low_selector == high_selector) + { + uint32_t r, g, b; + decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b); + + uint32_t mask = 0xAA; + uint32_t max16 = (g_bc1_match5_equals_1[r].m_hi << 11) | (g_bc1_match6_equals_1[g].m_hi << 5) | g_bc1_match5_equals_1[b].m_hi; + uint32_t min16 = (g_bc1_match5_equals_1[r].m_lo << 11) | (g_bc1_match6_equals_1[g].m_lo << 5) | g_bc1_match5_equals_1[b].m_lo; + + if ((!use_threecolor_blocks) && (min16 == max16)) + { + // This is an annoying edge case that impacts BC3. + // This is to guarantee that BC3 blocks never use punchthrough alpha (3 color) mode, which isn't supported on some (all?) GPU's. + mask = 0; + + // Make l > h + if (min16 > 0) + min16--; + else + { + // l = h = 0 + assert(min16 == max16 && max16 == 0); + + max16 = 1; + min16 = 0; + mask = 0x55; + } + + assert(max16 > min16); + } + + if (max16 < min16) + { + std::swap(max16, min16); + mask ^= 0x55; + } + + pDst_block->set_low_color(static_cast(max16)); + pDst_block->set_high_color(static_cast(min16)); + pDst_block->m_selectors[0] = static_cast(mask); + pDst_block->m_selectors[1] = static_cast(mask); + pDst_block->m_selectors[2] = static_cast(mask); + pDst_block->m_selectors[3] = static_cast(mask); + + return; + } + else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3)) + { + color32 block_colors[4]; + + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + const uint32_t r0 = block_colors[0].r; + const uint32_t g0 = block_colors[0].g; + const uint32_t b0 = block_colors[0].b; + + const uint32_t r1 = block_colors[3].r; + const uint32_t g1 = block_colors[3].g; + const uint32_t b1 = block_colors[3].b; + + uint32_t max16 = (g_bc1_match5_equals_0[r0].m_hi << 11) | (g_bc1_match6_equals_0[g0].m_hi << 5) | g_bc1_match5_equals_0[b0].m_hi; + uint32_t min16 = (g_bc1_match5_equals_0[r1].m_hi << 11) | (g_bc1_match6_equals_0[g1].m_hi << 5) | g_bc1_match5_equals_0[b1].m_hi; + + uint32_t l = 0, h = 1; + + if (min16 == max16) + { + // Make l > h + if (min16 > 0) + { + min16--; + + l = 0; + h = 0; + } + else + { + // l = h = 0 + assert(min16 == max16 && max16 == 0); + + max16 = 1; + min16 = 0; + + l = 1; + h = 1; + } + + assert(max16 > min16); + } + + if (max16 < min16) + { + std::swap(max16, min16); + l = 1; + h = 0; + } + + pDst_block->set_low_color((uint16_t)max16); + pDst_block->set_high_color((uint16_t)min16); + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + pDst_block->set_selector(x, y, (s == 3) ? h : l); + } + } + + return; + } + + const uint32_t selector_range_table = g_etc1_to_dxt1_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_dxt1_56_solution* pTable_r = &g_etc1_to_dxt_5[(inten_table * 32 + base_color.r) * (NUM_ETC1_TO_DXT1_SELECTOR_RANGES * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS]; + const etc1_to_dxt1_56_solution* pTable_g = &g_etc1_to_dxt_6[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_DXT1_SELECTOR_RANGES * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS]; + const etc1_to_dxt1_56_solution* pTable_b = &g_etc1_to_dxt_5[(inten_table * 32 + base_color.b) * (NUM_ETC1_TO_DXT1_SELECTOR_RANGES * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS]; + + uint32_t best_err = UINT_MAX; + uint32_t best_mapping = 0; + + assert(NUM_ETC1_TO_DXT1_SELECTOR_MAPPINGS == 10); +#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } } + DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4); + DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9); +#undef DO_ITER + + uint32_t l = dxt1_block::pack_unscaled_color(pTable_r[best_mapping].m_lo, pTable_g[best_mapping].m_lo, pTable_b[best_mapping].m_lo); + uint32_t h = dxt1_block::pack_unscaled_color(pTable_r[best_mapping].m_hi, pTable_g[best_mapping].m_hi, pTable_b[best_mapping].m_hi); + + const uint8_t* pSelectors_xlat_256 = &g_etc1_to_dxt1_selector_mappings_raw_dxt1_256[best_mapping][0]; + + if (l < h) + { + std::swap(l, h); + pSelectors_xlat_256 = &g_etc1_to_dxt1_selector_mappings_raw_dxt1_inv_256[best_mapping][0]; + } + + pDst_block->set_low_color(static_cast(l)); + pDst_block->set_high_color(static_cast(h)); + + if (l == h) + { + uint8_t mask = 0; + + if (!use_threecolor_blocks) + { + // This is an annoying edge case that impacts BC3. + + // Make l > h + if (h > 0) + h--; + else + { + // l = h = 0 + assert(l == h && h == 0); + + h = 0; + l = 1; + mask = 0x55; + } + + assert(l > h); + pDst_block->set_low_color(static_cast(l)); + pDst_block->set_high_color(static_cast(h)); + } + + pDst_block->m_selectors[0] = mask; + pDst_block->m_selectors[1] = mask; + pDst_block->m_selectors[2] = mask; + pDst_block->m_selectors[3] = mask; + + return; + } + + pDst_block->m_selectors[0] = pSelectors_xlat_256[pSelector->m_selectors[0]]; + pDst_block->m_selectors[1] = pSelectors_xlat_256[pSelector->m_selectors[1]]; + pDst_block->m_selectors[2] = pSelectors_xlat_256[pSelector->m_selectors[2]]; + pDst_block->m_selectors[3] = pSelectors_xlat_256[pSelector->m_selectors[3]]; +#endif + } + +#if BASISD_ENABLE_DEBUG_FLAGS + static void convert_etc1s_to_dxt1_vis(dxt1_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector, bool use_threecolor_blocks) + { + convert_etc1s_to_dxt1(pDst_block, pEndpoints, pSelector, use_threecolor_blocks); + + if (g_debug_flags & cDebugFlagVisBC1Sels) + { + uint32_t l = dxt1_block::pack_unscaled_color(31, 63, 31); + uint32_t h = dxt1_block::pack_unscaled_color(0, 0, 0); + pDst_block->set_low_color(static_cast(l)); + pDst_block->set_high_color(static_cast(h)); + } + else if (g_debug_flags & cDebugFlagVisBC1Endpoints) + { + for (uint32_t y = 0; y < 4; y++) + for (uint32_t x = 0; x < 4; x++) + pDst_block->set_selector(x, y, (y < 2) ? 0 : 1); + } + } +#endif +#endif + +#if BASISD_SUPPORT_FXT1 + struct fxt1_block + { + union + { + struct + { + uint64_t m_t00 : 2; + uint64_t m_t01 : 2; + uint64_t m_t02 : 2; + uint64_t m_t03 : 2; + uint64_t m_t04 : 2; + uint64_t m_t05 : 2; + uint64_t m_t06 : 2; + uint64_t m_t07 : 2; + uint64_t m_t08 : 2; + uint64_t m_t09 : 2; + uint64_t m_t10 : 2; + uint64_t m_t11 : 2; + uint64_t m_t12 : 2; + uint64_t m_t13 : 2; + uint64_t m_t14 : 2; + uint64_t m_t15 : 2; + uint64_t m_t16 : 2; + uint64_t m_t17 : 2; + uint64_t m_t18 : 2; + uint64_t m_t19 : 2; + uint64_t m_t20 : 2; + uint64_t m_t21 : 2; + uint64_t m_t22 : 2; + uint64_t m_t23 : 2; + uint64_t m_t24 : 2; + uint64_t m_t25 : 2; + uint64_t m_t26 : 2; + uint64_t m_t27 : 2; + uint64_t m_t28 : 2; + uint64_t m_t29 : 2; + uint64_t m_t30 : 2; + uint64_t m_t31 : 2; + } m_lo; + uint64_t m_lo_bits; + uint8_t m_sels[8]; + }; + union + { + struct + { +#ifdef BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING + uint64_t m_b1 : 5; + uint64_t m_g1 : 5; + uint64_t m_r1 : 5; + uint64_t m_b0 : 5; + uint64_t m_g0 : 5; + uint64_t m_r0 : 5; + uint64_t m_b3 : 5; + uint64_t m_g3 : 5; + uint64_t m_r3 : 5; + uint64_t m_b2 : 5; + uint64_t m_g2 : 5; + uint64_t m_r2 : 5; +#else + uint64_t m_b0 : 5; + uint64_t m_g0 : 5; + uint64_t m_r0 : 5; + uint64_t m_b1 : 5; + uint64_t m_g1 : 5; + uint64_t m_r1 : 5; + uint64_t m_b2 : 5; + uint64_t m_g2 : 5; + uint64_t m_r2 : 5; + uint64_t m_b3 : 5; + uint64_t m_g3 : 5; + uint64_t m_r3 : 5; +#endif + uint64_t m_alpha : 1; + uint64_t m_glsb : 2; + uint64_t m_mode : 1; + } m_hi; + uint64_t m_hi_bits; + }; + }; + + static uint8_t conv_dxt1_to_fxt1_sels(uint32_t sels) + { + static uint8_t s_conv_table[16] = { 0, 3, 1, 2, 12, 15, 13, 14, 4, 7, 5, 6, 8, 11, 9, 10 }; + return s_conv_table[sels & 15] | (s_conv_table[sels >> 4] << 4); + } + + static void convert_etc1s_to_fxt1(void *pDst, const endpoint *pEndpoints, const selector *pSelectors, uint32_t fxt1_subblock) + { + fxt1_block* pBlock = static_cast(pDst); + + // CC_MIXED is basically DXT1 with different encoding tricks. + // So transcode ETC1S to DXT1, then transcode that to FXT1 which is easy and nearly lossless. + // (It's not completely lossless because FXT1 rounds in its color lerps while DXT1 doesn't, but it should be good enough.) + dxt1_block blk; + convert_etc1s_to_dxt1(&blk, pEndpoints, pSelectors, false); + + const uint32_t l = blk.get_low_color(); + const uint32_t h = blk.get_high_color(); + + color32 color0((l >> 11) & 31, (l >> 5) & 63, l & 31, 255); + color32 color1((h >> 11) & 31, (h >> 5) & 63, h & 31, 255); + + uint32_t g0 = color0.g & 1; + uint32_t g1 = color1.g & 1; + + color0.g >>= 1; + color1.g >>= 1; + + blk.m_selectors[0] = conv_dxt1_to_fxt1_sels(blk.m_selectors[0]); + blk.m_selectors[1] = conv_dxt1_to_fxt1_sels(blk.m_selectors[1]); + blk.m_selectors[2] = conv_dxt1_to_fxt1_sels(blk.m_selectors[2]); + blk.m_selectors[3] = conv_dxt1_to_fxt1_sels(blk.m_selectors[3]); + + if ((blk.get_selector(0, 0) >> 1) != (g0 ^ g1)) + { + std::swap(color0, color1); + std::swap(g0, g1); + + blk.m_selectors[0] ^= 0xFF; + blk.m_selectors[1] ^= 0xFF; + blk.m_selectors[2] ^= 0xFF; + blk.m_selectors[3] ^= 0xFF; + } + + if (fxt1_subblock == 0) + { + pBlock->m_hi.m_mode = 1; + pBlock->m_hi.m_alpha = 0; + pBlock->m_hi.m_glsb = g1 | (g1 << 1); + pBlock->m_hi.m_r0 = color0.r; + pBlock->m_hi.m_g0 = color0.g; + pBlock->m_hi.m_b0 = color0.b; + pBlock->m_hi.m_r1 = color1.r; + pBlock->m_hi.m_g1 = color1.g; + pBlock->m_hi.m_b1 = color1.b; + pBlock->m_hi.m_r2 = color0.r; + pBlock->m_hi.m_g2 = color0.g; + pBlock->m_hi.m_b2 = color0.b; + pBlock->m_hi.m_r3 = color1.r; + pBlock->m_hi.m_g3 = color1.g; + pBlock->m_hi.m_b3 = color1.b; + pBlock->m_sels[0] = blk.m_selectors[0]; + pBlock->m_sels[1] = blk.m_selectors[1]; + pBlock->m_sels[2] = blk.m_selectors[2]; + pBlock->m_sels[3] = blk.m_selectors[3]; + + static const uint8_t s_border_dup[4] = { 0, 85, 170, 255 }; + pBlock->m_sels[4] = s_border_dup[blk.m_selectors[0] >> 6]; + pBlock->m_sels[5] = s_border_dup[blk.m_selectors[1] >> 6]; + pBlock->m_sels[6] = s_border_dup[blk.m_selectors[2] >> 6]; + pBlock->m_sels[7] = s_border_dup[blk.m_selectors[3] >> 6]; + } + else + { + pBlock->m_hi.m_glsb = (pBlock->m_hi.m_glsb & 1) | (g1 << 1); + pBlock->m_hi.m_r2 = color0.r; + pBlock->m_hi.m_g2 = color0.g; + pBlock->m_hi.m_b2 = color0.b; + pBlock->m_hi.m_r3 = color1.r; + pBlock->m_hi.m_g3 = color1.g; + pBlock->m_hi.m_b3 = color1.b; + pBlock->m_sels[4] = blk.m_selectors[0]; + pBlock->m_sels[5] = blk.m_selectors[1]; + pBlock->m_sels[6] = blk.m_selectors[2]; + pBlock->m_sels[7] = blk.m_selectors[3]; + } + } +#endif // BASISD_SUPPORT_FXT1 +#if BASISD_SUPPORT_DXT5A + static dxt_selector_range s_dxt5a_selector_ranges[] = + { + { 0, 3 }, + + { 1, 3 }, + { 0, 2 }, + + { 1, 2 }, + }; + + const uint32_t NUM_DXT5A_SELECTOR_RANGES = sizeof(s_dxt5a_selector_ranges) / sizeof(s_dxt5a_selector_ranges[0]); + + struct etc1_g_to_dxt5a_conversion + { + uint8_t m_lo, m_hi; + uint16_t m_trans; + }; + + static etc1_g_to_dxt5a_conversion g_etc1_g_to_dxt5a[32 * 8][NUM_DXT5A_SELECTOR_RANGES] = + { + { { 8, 0, 393 },{ 8, 0, 392 },{ 2, 0, 9 },{ 2, 0, 8 }, }, { { 6, 16, 710 },{ 16, 6, 328 },{ 0, 10, 96 },{ 10, 6, 8 }, }, + { { 28, 5, 1327 },{ 24, 14, 328 },{ 8, 18, 96 },{ 18, 14, 8 }, }, { { 36, 13, 1327 },{ 32, 22, 328 },{ 16, 26, 96 },{ 26, 22, 8 }, }, + { { 45, 22, 1327 },{ 41, 31, 328 },{ 25, 35, 96 },{ 35, 31, 8 }, }, { { 53, 30, 1327 },{ 49, 39, 328 },{ 33, 43, 96 },{ 43, 39, 8 }, }, + { { 61, 38, 1327 },{ 57, 47, 328 },{ 41, 51, 96 },{ 51, 47, 8 }, }, { { 69, 46, 1327 },{ 65, 55, 328 },{ 49, 59, 96 },{ 59, 55, 8 }, }, + { { 78, 55, 1327 },{ 74, 64, 328 },{ 58, 68, 96 },{ 68, 64, 8 }, }, { { 86, 63, 1327 },{ 82, 72, 328 },{ 66, 76, 96 },{ 76, 72, 8 }, }, + { { 94, 71, 1327 },{ 90, 80, 328 },{ 74, 84, 96 },{ 84, 80, 8 }, }, { { 102, 79, 1327 },{ 98, 88, 328 },{ 82, 92, 96 },{ 92, 88, 8 }, }, + { { 111, 88, 1327 },{ 107, 97, 328 },{ 91, 101, 96 },{ 101, 97, 8 }, }, { { 119, 96, 1327 },{ 115, 105, 328 },{ 99, 109, 96 },{ 109, 105, 8 }, }, + { { 127, 104, 1327 },{ 123, 113, 328 },{ 107, 117, 96 },{ 117, 113, 8 }, }, { { 135, 112, 1327 },{ 131, 121, 328 },{ 115, 125, 96 },{ 125, 121, 8 }, }, + { { 144, 121, 1327 },{ 140, 130, 328 },{ 124, 134, 96 },{ 134, 130, 8 }, }, { { 152, 129, 1327 },{ 148, 138, 328 },{ 132, 142, 96 },{ 142, 138, 8 }, }, + { { 160, 137, 1327 },{ 156, 146, 328 },{ 140, 150, 96 },{ 150, 146, 8 }, }, { { 168, 145, 1327 },{ 164, 154, 328 },{ 148, 158, 96 },{ 158, 154, 8 }, }, + { { 177, 154, 1327 },{ 173, 163, 328 },{ 157, 167, 96 },{ 167, 163, 8 }, }, { { 185, 162, 1327 },{ 181, 171, 328 },{ 165, 175, 96 },{ 175, 171, 8 }, }, + { { 193, 170, 1327 },{ 189, 179, 328 },{ 173, 183, 96 },{ 183, 179, 8 }, }, { { 201, 178, 1327 },{ 197, 187, 328 },{ 181, 191, 96 },{ 191, 187, 8 }, }, + { { 210, 187, 1327 },{ 206, 196, 328 },{ 190, 200, 96 },{ 200, 196, 8 }, }, { { 218, 195, 1327 },{ 214, 204, 328 },{ 198, 208, 96 },{ 208, 204, 8 }, }, + { { 226, 203, 1327 },{ 222, 212, 328 },{ 206, 216, 96 },{ 216, 212, 8 }, }, { { 234, 211, 1327 },{ 230, 220, 328 },{ 214, 224, 96 },{ 224, 220, 8 }, }, + { { 243, 220, 1327 },{ 239, 229, 328 },{ 223, 233, 96 },{ 233, 229, 8 }, }, { { 251, 228, 1327 },{ 247, 237, 328 },{ 231, 241, 96 },{ 241, 237, 8 }, }, + { { 239, 249, 3680 },{ 245, 249, 3648 },{ 239, 249, 96 },{ 249, 245, 8 }, }, { { 247, 253, 4040 },{ 255, 253, 8 },{ 247, 253, 456 },{ 255, 253, 8 }, }, + { { 5, 17, 566 },{ 5, 17, 560 },{ 5, 0, 9 },{ 5, 0, 8 }, }, { { 25, 0, 313 },{ 25, 3, 328 },{ 13, 0, 49 },{ 13, 3, 8 }, }, + { { 39, 0, 1329 },{ 33, 11, 328 },{ 11, 21, 70 },{ 21, 11, 8 }, }, { { 47, 7, 1329 },{ 41, 19, 328 },{ 29, 7, 33 },{ 29, 19, 8 }, }, + { { 50, 11, 239 },{ 50, 28, 328 },{ 38, 16, 33 },{ 38, 28, 8 }, }, { { 92, 13, 2423 },{ 58, 36, 328 },{ 46, 24, 33 },{ 46, 36, 8 }, }, + { { 100, 21, 2423 },{ 66, 44, 328 },{ 54, 32, 33 },{ 54, 44, 8 }, }, { { 86, 7, 1253 },{ 74, 52, 328 },{ 62, 40, 33 },{ 62, 52, 8 }, }, + { { 95, 16, 1253 },{ 83, 61, 328 },{ 71, 49, 33 },{ 71, 61, 8 }, }, { { 103, 24, 1253 },{ 91, 69, 328 },{ 79, 57, 33 },{ 79, 69, 8 }, }, + { { 111, 32, 1253 },{ 99, 77, 328 },{ 87, 65, 33 },{ 87, 77, 8 }, }, { { 119, 40, 1253 },{ 107, 85, 328 },{ 95, 73, 33 },{ 95, 85, 8 }, }, + { { 128, 49, 1253 },{ 116, 94, 328 },{ 104, 82, 33 },{ 104, 94, 8 }, }, { { 136, 57, 1253 },{ 124, 102, 328 },{ 112, 90, 33 },{ 112, 102, 8 }, }, + { { 144, 65, 1253 },{ 132, 110, 328 },{ 120, 98, 33 },{ 120, 110, 8 }, }, { { 152, 73, 1253 },{ 140, 118, 328 },{ 128, 106, 33 },{ 128, 118, 8 }, }, + { { 161, 82, 1253 },{ 149, 127, 328 },{ 137, 115, 33 },{ 137, 127, 8 }, }, { { 169, 90, 1253 },{ 157, 135, 328 },{ 145, 123, 33 },{ 145, 135, 8 }, }, + { { 177, 98, 1253 },{ 165, 143, 328 },{ 153, 131, 33 },{ 153, 143, 8 }, }, { { 185, 106, 1253 },{ 173, 151, 328 },{ 161, 139, 33 },{ 161, 151, 8 }, }, + { { 194, 115, 1253 },{ 182, 160, 328 },{ 170, 148, 33 },{ 170, 160, 8 }, }, { { 202, 123, 1253 },{ 190, 168, 328 },{ 178, 156, 33 },{ 178, 168, 8 }, }, + { { 210, 131, 1253 },{ 198, 176, 328 },{ 186, 164, 33 },{ 186, 176, 8 }, }, { { 218, 139, 1253 },{ 206, 184, 328 },{ 194, 172, 33 },{ 194, 184, 8 }, }, + { { 227, 148, 1253 },{ 215, 193, 328 },{ 203, 181, 33 },{ 203, 193, 8 }, }, { { 235, 156, 1253 },{ 223, 201, 328 },{ 211, 189, 33 },{ 211, 201, 8 }, }, + { { 243, 164, 1253 },{ 231, 209, 328 },{ 219, 197, 33 },{ 219, 209, 8 }, }, { { 183, 239, 867 },{ 239, 217, 328 },{ 227, 205, 33 },{ 227, 217, 8 }, }, + { { 254, 214, 1329 },{ 248, 226, 328 },{ 236, 214, 33 },{ 236, 226, 8 }, }, { { 222, 244, 3680 },{ 234, 244, 3648 },{ 244, 222, 33 },{ 244, 234, 8 }, }, + { { 230, 252, 3680 },{ 242, 252, 3648 },{ 252, 230, 33 },{ 252, 242, 8 }, }, { { 238, 250, 4040 },{ 255, 250, 8 },{ 238, 250, 456 },{ 255, 250, 8 }, }, + { { 9, 29, 566 },{ 9, 29, 560 },{ 9, 0, 9 },{ 9, 0, 8 }, }, { { 17, 37, 566 },{ 17, 37, 560 },{ 17, 0, 9 },{ 17, 0, 8 }, }, + { { 45, 0, 313 },{ 45, 0, 312 },{ 25, 0, 49 },{ 25, 7, 8 }, }, { { 14, 63, 2758 },{ 5, 53, 784 },{ 15, 33, 70 },{ 33, 15, 8 }, }, + { { 71, 6, 1329 },{ 72, 4, 1328 },{ 42, 4, 33 },{ 42, 24, 8 }, }, { { 70, 3, 239 },{ 70, 2, 232 },{ 50, 12, 33 },{ 50, 32, 8 }, }, + { { 0, 98, 2842 },{ 78, 10, 232 },{ 58, 20, 33 },{ 58, 40, 8 }, }, { { 97, 27, 1329 },{ 86, 18, 232 },{ 66, 28, 33 },{ 66, 48, 8 }, }, + { { 0, 94, 867 },{ 95, 27, 232 },{ 75, 37, 33 },{ 75, 57, 8 }, }, { { 8, 102, 867 },{ 103, 35, 232 },{ 83, 45, 33 },{ 83, 65, 8 }, }, + { { 12, 112, 867 },{ 111, 43, 232 },{ 91, 53, 33 },{ 91, 73, 8 }, }, { { 139, 2, 1253 },{ 119, 51, 232 },{ 99, 61, 33 },{ 99, 81, 8 }, }, + { { 148, 13, 1253 },{ 128, 60, 232 },{ 108, 70, 33 },{ 108, 90, 8 }, }, { { 156, 21, 1253 },{ 136, 68, 232 },{ 116, 78, 33 },{ 116, 98, 8 }, }, + { { 164, 29, 1253 },{ 144, 76, 232 },{ 124, 86, 33 },{ 124, 106, 8 }, }, { { 172, 37, 1253 },{ 152, 84, 232 },{ 132, 94, 33 },{ 132, 114, 8 }, }, + { { 181, 46, 1253 },{ 161, 93, 232 },{ 141, 103, 33 },{ 141, 123, 8 }, }, { { 189, 54, 1253 },{ 169, 101, 232 },{ 149, 111, 33 },{ 149, 131, 8 }, }, + { { 197, 62, 1253 },{ 177, 109, 232 },{ 157, 119, 33 },{ 157, 139, 8 }, }, { { 205, 70, 1253 },{ 185, 117, 232 },{ 165, 127, 33 },{ 165, 147, 8 }, }, + { { 214, 79, 1253 },{ 194, 126, 232 },{ 174, 136, 33 },{ 174, 156, 8 }, }, { { 222, 87, 1253 },{ 202, 134, 232 },{ 182, 144, 33 },{ 182, 164, 8 }, }, + { { 230, 95, 1253 },{ 210, 142, 232 },{ 190, 152, 33 },{ 190, 172, 8 }, }, { { 238, 103, 1253 },{ 218, 150, 232 },{ 198, 160, 33 },{ 198, 180, 8 }, }, + { { 247, 112, 1253 },{ 227, 159, 232 },{ 207, 169, 33 },{ 207, 189, 8 }, }, { { 255, 120, 1253 },{ 235, 167, 232 },{ 215, 177, 33 },{ 215, 197, 8 }, }, + { { 146, 243, 867 },{ 243, 175, 232 },{ 223, 185, 33 },{ 223, 205, 8 }, }, { { 184, 231, 3682 },{ 203, 251, 784 },{ 231, 193, 33 },{ 231, 213, 8 }, }, + { { 193, 240, 3682 },{ 222, 240, 3648 },{ 240, 202, 33 },{ 240, 222, 8 }, }, { { 255, 210, 169 },{ 230, 248, 3648 },{ 248, 210, 33 },{ 248, 230, 8 }, }, + { { 218, 238, 4040 },{ 255, 238, 8 },{ 218, 238, 456 },{ 255, 238, 8 }, }, { { 226, 246, 4040 },{ 255, 246, 8 },{ 226, 246, 456 },{ 255, 246, 8 }, }, + { { 13, 42, 566 },{ 13, 42, 560 },{ 13, 0, 9 },{ 13, 0, 8 }, }, { { 50, 0, 329 },{ 50, 0, 328 },{ 21, 0, 9 },{ 21, 0, 8 }, }, + { { 29, 58, 566 },{ 67, 2, 1352 },{ 3, 29, 70 },{ 29, 3, 8 }, }, { { 10, 79, 2758 },{ 76, 11, 1352 },{ 11, 37, 70 },{ 37, 11, 8 }, }, + { { 7, 75, 790 },{ 7, 75, 784 },{ 20, 46, 70 },{ 46, 20, 8 }, }, { { 15, 83, 790 },{ 97, 1, 1328 },{ 28, 54, 70 },{ 54, 28, 8 }, }, + { { 101, 7, 1329 },{ 105, 9, 1328 },{ 62, 0, 39 },{ 62, 36, 8 }, }, { { 99, 1, 239 },{ 99, 3, 232 },{ 1, 71, 98 },{ 70, 44, 8 }, }, + { { 107, 11, 239 },{ 108, 12, 232 },{ 10, 80, 98 },{ 79, 53, 8 }, }, { { 115, 19, 239 },{ 116, 20, 232 },{ 18, 88, 98 },{ 87, 61, 8 }, }, + { { 123, 27, 239 },{ 124, 28, 232 },{ 26, 96, 98 },{ 95, 69, 8 }, }, { { 131, 35, 239 },{ 132, 36, 232 },{ 34, 104, 98 },{ 103, 77, 8 }, }, + { { 140, 44, 239 },{ 141, 45, 232 },{ 43, 113, 98 },{ 112, 86, 8 }, }, { { 148, 52, 239 },{ 149, 53, 232 },{ 51, 121, 98 },{ 120, 94, 8 }, }, + { { 156, 60, 239 },{ 157, 61, 232 },{ 59, 129, 98 },{ 128, 102, 8 }, }, { { 164, 68, 239 },{ 165, 69, 232 },{ 67, 137, 98 },{ 136, 110, 8 }, }, + { { 173, 77, 239 },{ 174, 78, 232 },{ 76, 146, 98 },{ 145, 119, 8 }, }, { { 181, 85, 239 },{ 182, 86, 232 },{ 84, 154, 98 },{ 153, 127, 8 }, }, + { { 189, 93, 239 },{ 190, 94, 232 },{ 92, 162, 98 },{ 161, 135, 8 }, }, { { 197, 101, 239 },{ 198, 102, 232 },{ 100, 170, 98 },{ 169, 143, 8 }, }, + { { 206, 110, 239 },{ 207, 111, 232 },{ 109, 179, 98 },{ 178, 152, 8 }, }, { { 214, 118, 239 },{ 215, 119, 232 },{ 117, 187, 98 },{ 186, 160, 8 }, }, + { { 222, 126, 239 },{ 223, 127, 232 },{ 125, 195, 98 },{ 194, 168, 8 }, }, { { 230, 134, 239 },{ 231, 135, 232 },{ 133, 203, 98 },{ 202, 176, 8 }, }, + { { 239, 143, 239 },{ 240, 144, 232 },{ 142, 212, 98 },{ 211, 185, 8 }, }, { { 247, 151, 239 },{ 180, 248, 784 },{ 150, 220, 98 },{ 219, 193, 8 }, }, + { { 159, 228, 3682 },{ 201, 227, 3648 },{ 158, 228, 98 },{ 227, 201, 8 }, }, { { 181, 249, 3928 },{ 209, 235, 3648 },{ 166, 236, 98 },{ 235, 209, 8 }, }, + { { 255, 189, 169 },{ 218, 244, 3648 },{ 175, 245, 98 },{ 244, 218, 8 }, }, { { 197, 226, 4040 },{ 226, 252, 3648 },{ 183, 253, 98 },{ 252, 226, 8 }, }, + { { 205, 234, 4040 },{ 255, 234, 8 },{ 205, 234, 456 },{ 255, 234, 8 }, }, { { 213, 242, 4040 },{ 255, 242, 8 },{ 213, 242, 456 },{ 255, 242, 8 }, }, + { { 18, 60, 566 },{ 18, 60, 560 },{ 18, 0, 9 },{ 18, 0, 8 }, }, { { 26, 68, 566 },{ 26, 68, 560 },{ 26, 0, 9 },{ 26, 0, 8 }, }, + { { 34, 76, 566 },{ 34, 76, 560 },{ 34, 0, 9 },{ 34, 0, 8 }, }, { { 5, 104, 2758 },{ 98, 5, 1352 },{ 42, 0, 57 },{ 42, 6, 8 }, }, + { { 92, 0, 313 },{ 93, 1, 312 },{ 15, 51, 70 },{ 51, 15, 8 }, }, { { 3, 101, 790 },{ 3, 101, 784 },{ 0, 59, 88 },{ 59, 23, 8 }, }, + { { 14, 107, 790 },{ 11, 109, 784 },{ 31, 67, 70 },{ 67, 31, 8 }, }, { { 19, 117, 790 },{ 19, 117, 784 },{ 39, 75, 70 },{ 75, 39, 8 }, }, + { { 28, 126, 790 },{ 28, 126, 784 },{ 83, 5, 33 },{ 84, 48, 8 }, }, { { 132, 0, 239 },{ 36, 134, 784 },{ 91, 13, 33 },{ 92, 56, 8 }, }, + { { 142, 4, 239 },{ 44, 142, 784 },{ 99, 21, 33 },{ 100, 64, 8 }, }, { { 150, 12, 239 },{ 52, 150, 784 },{ 107, 29, 33 },{ 108, 72, 8 }, }, + { { 159, 21, 239 },{ 61, 159, 784 },{ 116, 38, 33 },{ 117, 81, 8 }, }, { { 167, 29, 239 },{ 69, 167, 784 },{ 124, 46, 33 },{ 125, 89, 8 }, }, + { { 175, 37, 239 },{ 77, 175, 784 },{ 132, 54, 33 },{ 133, 97, 8 }, }, { { 183, 45, 239 },{ 85, 183, 784 },{ 140, 62, 33 },{ 141, 105, 8 }, }, + { { 192, 54, 239 },{ 94, 192, 784 },{ 149, 71, 33 },{ 150, 114, 8 }, }, { { 200, 62, 239 },{ 102, 200, 784 },{ 157, 79, 33 },{ 158, 122, 8 }, }, + { { 208, 70, 239 },{ 110, 208, 784 },{ 165, 87, 33 },{ 166, 130, 8 }, }, { { 216, 78, 239 },{ 118, 216, 784 },{ 173, 95, 33 },{ 174, 138, 8 }, }, + { { 225, 87, 239 },{ 127, 225, 784 },{ 182, 104, 33 },{ 183, 147, 8 }, }, { { 233, 95, 239 },{ 135, 233, 784 },{ 190, 112, 33 },{ 191, 155, 8 }, }, + { { 241, 103, 239 },{ 143, 241, 784 },{ 198, 120, 33 },{ 199, 163, 8 }, }, { { 111, 208, 3682 },{ 151, 249, 784 },{ 206, 128, 33 },{ 207, 171, 8 }, }, + { { 120, 217, 3682 },{ 180, 216, 3648 },{ 215, 137, 33 },{ 216, 180, 8 }, }, { { 128, 225, 3682 },{ 188, 224, 3648 },{ 223, 145, 33 },{ 224, 188, 8 }, }, + { { 155, 253, 3928 },{ 196, 232, 3648 },{ 231, 153, 33 },{ 232, 196, 8 }, }, { { 144, 241, 3682 },{ 204, 240, 3648 },{ 239, 161, 33 },{ 240, 204, 8 }, }, + { { 153, 250, 3682 },{ 213, 249, 3648 },{ 248, 170, 33 },{ 249, 213, 8 }, }, { { 179, 221, 4040 },{ 255, 221, 8 },{ 179, 221, 456 },{ 255, 221, 8 }, }, + { { 187, 229, 4040 },{ 255, 229, 8 },{ 187, 229, 456 },{ 255, 229, 8 }, }, { { 195, 237, 4040 },{ 255, 237, 8 },{ 195, 237, 456 },{ 255, 237, 8 }, }, + { { 24, 80, 566 },{ 24, 80, 560 },{ 24, 0, 9 },{ 24, 0, 8 }, }, { { 32, 88, 566 },{ 32, 88, 560 },{ 32, 0, 9 },{ 32, 0, 8 }, }, + { { 40, 96, 566 },{ 40, 96, 560 },{ 40, 0, 9 },{ 40, 0, 8 }, }, { { 48, 104, 566 },{ 48, 104, 560 },{ 48, 0, 9 },{ 48, 0, 8 }, }, + { { 9, 138, 2758 },{ 130, 7, 1352 },{ 9, 57, 70 },{ 57, 9, 8 }, }, { { 119, 0, 313 },{ 120, 0, 312 },{ 17, 65, 70 },{ 65, 17, 8 }, }, + { { 0, 128, 784 },{ 128, 6, 312 },{ 25, 73, 70 },{ 73, 25, 8 }, }, { { 6, 137, 790 },{ 5, 136, 784 },{ 33, 81, 70 },{ 81, 33, 8 }, }, + { { 42, 171, 2758 },{ 14, 145, 784 },{ 42, 90, 70 },{ 90, 42, 8 }, }, { { 50, 179, 2758 },{ 22, 153, 784 },{ 50, 98, 70 },{ 98, 50, 8 }, }, + { { 58, 187, 2758 },{ 30, 161, 784 },{ 58, 106, 70 },{ 106, 58, 8 }, }, { { 191, 18, 1329 },{ 38, 169, 784 },{ 112, 9, 33 },{ 114, 66, 8 }, }, + { { 176, 0, 239 },{ 47, 178, 784 },{ 121, 18, 33 },{ 123, 75, 8 }, }, { { 187, 1, 239 },{ 55, 186, 784 },{ 129, 26, 33 },{ 131, 83, 8 }, }, + { { 195, 10, 239 },{ 63, 194, 784 },{ 137, 34, 33 },{ 139, 91, 8 }, }, { { 203, 18, 239 },{ 71, 202, 784 },{ 145, 42, 33 },{ 147, 99, 8 }, }, + { { 212, 27, 239 },{ 80, 211, 784 },{ 154, 51, 33 },{ 156, 108, 8 }, }, { { 220, 35, 239 },{ 88, 219, 784 },{ 162, 59, 33 },{ 164, 116, 8 }, }, + { { 228, 43, 239 },{ 96, 227, 784 },{ 170, 67, 33 },{ 172, 124, 8 }, }, { { 236, 51, 239 },{ 104, 235, 784 },{ 178, 75, 33 },{ 180, 132, 8 }, }, + { { 245, 60, 239 },{ 113, 244, 784 },{ 187, 84, 33 },{ 189, 141, 8 }, }, { { 91, 194, 3680 },{ 149, 197, 3648 },{ 195, 92, 33 },{ 197, 149, 8 }, }, + { { 99, 202, 3680 },{ 157, 205, 3648 },{ 203, 100, 33 },{ 205, 157, 8 }, }, { { 107, 210, 3680 },{ 165, 213, 3648 },{ 211, 108, 33 },{ 213, 165, 8 }, }, + { { 119, 249, 3928 },{ 174, 222, 3648 },{ 220, 117, 33 },{ 222, 174, 8 }, }, { { 127, 255, 856 },{ 182, 230, 3648 },{ 228, 125, 33 },{ 230, 182, 8 }, }, + { { 255, 135, 169 },{ 190, 238, 3648 },{ 236, 133, 33 },{ 238, 190, 8 }, }, { { 140, 243, 3680 },{ 198, 246, 3648 },{ 244, 141, 33 },{ 246, 198, 8 }, }, + { { 151, 207, 4040 },{ 255, 207, 8 },{ 151, 207, 456 },{ 255, 207, 8 }, }, { { 159, 215, 4040 },{ 255, 215, 8 },{ 159, 215, 456 },{ 255, 215, 8 }, }, + { { 167, 223, 4040 },{ 255, 223, 8 },{ 167, 223, 456 },{ 255, 223, 8 }, }, { { 175, 231, 4040 },{ 255, 231, 8 },{ 175, 231, 456 },{ 255, 231, 8 }, }, + { { 33, 106, 566 },{ 33, 106, 560 },{ 33, 0, 9 },{ 33, 0, 8 }, }, { { 41, 114, 566 },{ 41, 114, 560 },{ 41, 0, 9 },{ 41, 0, 8 }, }, + { { 49, 122, 566 },{ 49, 122, 560 },{ 49, 0, 9 },{ 49, 0, 8 }, }, { { 57, 130, 566 },{ 57, 130, 560 },{ 57, 0, 9 },{ 57, 0, 8 }, }, + { { 66, 139, 566 },{ 66, 139, 560 },{ 66, 0, 9 },{ 66, 0, 8 }, }, { { 74, 147, 566 },{ 170, 7, 1352 },{ 8, 74, 70 },{ 74, 8, 8 }, }, + { { 152, 0, 313 },{ 178, 15, 1352 },{ 0, 82, 80 },{ 82, 16, 8 }, }, { { 162, 0, 313 },{ 186, 23, 1352 },{ 24, 90, 70 },{ 90, 24, 8 }, }, + { { 0, 171, 784 },{ 195, 32, 1352 },{ 33, 99, 70 },{ 99, 33, 8 }, }, { { 6, 179, 790 },{ 203, 40, 1352 },{ 41, 107, 70 },{ 107, 41, 8 }, }, + { { 15, 187, 790 },{ 211, 48, 1352 },{ 115, 0, 41 },{ 115, 49, 8 }, }, { { 61, 199, 710 },{ 219, 56, 1352 },{ 57, 123, 70 },{ 123, 57, 8 }, }, + { { 70, 208, 710 },{ 228, 65, 1352 },{ 66, 132, 70 },{ 132, 66, 8 }, }, { { 78, 216, 710 },{ 236, 73, 1352 },{ 74, 140, 70 },{ 140, 74, 8 }, }, + { { 86, 224, 710 },{ 244, 81, 1352 },{ 145, 7, 33 },{ 148, 82, 8 }, }, { { 222, 8, 233 },{ 252, 89, 1352 },{ 153, 15, 33 },{ 156, 90, 8 }, }, + { { 235, 0, 239 },{ 241, 101, 328 },{ 166, 6, 39 },{ 165, 99, 8 }, }, { { 32, 170, 3680 },{ 249, 109, 328 },{ 0, 175, 98 },{ 173, 107, 8 }, }, + { { 40, 178, 3680 },{ 115, 181, 3648 },{ 8, 183, 98 },{ 181, 115, 8 }, }, { { 48, 186, 3680 },{ 123, 189, 3648 },{ 16, 191, 98 },{ 189, 123, 8 }, }, + { { 57, 195, 3680 },{ 132, 198, 3648 },{ 25, 200, 98 },{ 198, 132, 8 }, }, { { 67, 243, 3928 },{ 140, 206, 3648 },{ 33, 208, 98 },{ 206, 140, 8 }, }, + { { 76, 251, 3928 },{ 148, 214, 3648 },{ 41, 216, 98 },{ 214, 148, 8 }, }, { { 86, 255, 856 },{ 156, 222, 3648 },{ 49, 224, 98 },{ 222, 156, 8 }, }, + { { 255, 93, 169 },{ 165, 231, 3648 },{ 58, 233, 98 },{ 231, 165, 8 }, }, { { 98, 236, 3680 },{ 173, 239, 3648 },{ 66, 241, 98 },{ 239, 173, 8 }, }, + { { 108, 181, 4040 },{ 181, 247, 3648 },{ 74, 249, 98 },{ 247, 181, 8 }, }, { { 116, 189, 4040 },{ 255, 189, 8 },{ 116, 189, 456 },{ 255, 189, 8 }, }, + { { 125, 198, 4040 },{ 255, 198, 8 },{ 125, 198, 456 },{ 255, 198, 8 }, }, { { 133, 206, 4040 },{ 255, 206, 8 },{ 133, 206, 456 },{ 255, 206, 8 }, }, + { { 141, 214, 4040 },{ 255, 214, 8 },{ 141, 214, 456 },{ 255, 214, 8 }, }, { { 149, 222, 4040 },{ 255, 222, 8 },{ 149, 222, 456 },{ 255, 222, 8 }, }, + { { 47, 183, 566 },{ 47, 183, 560 },{ 47, 0, 9 },{ 47, 0, 8 }, }, { { 55, 191, 566 },{ 55, 191, 560 },{ 55, 0, 9 },{ 55, 0, 8 }, }, + { { 63, 199, 566 },{ 63, 199, 560 },{ 63, 0, 9 },{ 63, 0, 8 }, }, { { 71, 207, 566 },{ 71, 207, 560 },{ 71, 0, 9 },{ 71, 0, 8 }, }, + { { 80, 216, 566 },{ 80, 216, 560 },{ 80, 0, 9 },{ 80, 0, 8 }, }, { { 88, 224, 566 },{ 88, 224, 560 },{ 88, 0, 9 },{ 88, 0, 8 }, }, + { { 3, 233, 710 },{ 3, 233, 704 },{ 2, 96, 70 },{ 96, 2, 8 }, }, { { 11, 241, 710 },{ 11, 241, 704 },{ 10, 104, 70 },{ 104, 10, 8 }, }, + { { 20, 250, 710 },{ 20, 250, 704 },{ 19, 113, 70 },{ 113, 19, 8 }, }, { { 27, 121, 3654 },{ 27, 121, 3648 },{ 27, 121, 70 },{ 121, 27, 8 }, }, + { { 35, 129, 3654 },{ 35, 129, 3648 },{ 35, 129, 70 },{ 129, 35, 8 }, }, { { 43, 137, 3654 },{ 43, 137, 3648 },{ 43, 137, 70 },{ 137, 43, 8 }, }, + { { 52, 146, 3654 },{ 52, 146, 3648 },{ 52, 146, 70 },{ 146, 52, 8 }, }, { { 60, 154, 3654 },{ 60, 154, 3648 },{ 60, 154, 70 },{ 154, 60, 8 }, }, + { { 68, 162, 3654 },{ 68, 162, 3648 },{ 68, 162, 70 },{ 162, 68, 8 }, }, { { 76, 170, 3654 },{ 76, 170, 3648 },{ 76, 170, 70 },{ 170, 76, 8 }, }, + { { 85, 179, 3654 },{ 85, 179, 3648 },{ 85, 179, 70 },{ 179, 85, 8 }, }, { { 93, 187, 3654 },{ 93, 187, 3648 },{ 93, 187, 70 },{ 187, 93, 8 }, }, + { { 101, 195, 3654 },{ 101, 195, 3648 },{ 101, 195, 70 },{ 195, 101, 8 }, }, { { 109, 203, 3654 },{ 109, 203, 3648 },{ 109, 203, 70 },{ 203, 109, 8 }, }, + { { 118, 212, 3654 },{ 118, 212, 3648 },{ 118, 212, 70 },{ 212, 118, 8 }, }, { { 126, 220, 3654 },{ 126, 220, 3648 },{ 126, 220, 70 },{ 220, 126, 8 }, }, + { { 134, 228, 3654 },{ 134, 228, 3648 },{ 134, 228, 70 },{ 228, 134, 8 }, }, { { 5, 236, 3680 },{ 142, 236, 3648 },{ 5, 236, 96 },{ 236, 142, 8 }, }, + { { 14, 245, 3680 },{ 151, 245, 3648 },{ 14, 245, 96 },{ 245, 151, 8 }, }, { { 23, 159, 4040 },{ 159, 253, 3648 },{ 23, 159, 456 },{ 253, 159, 8 }, }, + { { 31, 167, 4040 },{ 255, 167, 8 },{ 31, 167, 456 },{ 255, 167, 8 }, }, { { 39, 175, 4040 },{ 255, 175, 8 },{ 39, 175, 456 },{ 255, 175, 8 }, }, + { { 48, 184, 4040 },{ 255, 184, 8 },{ 48, 184, 456 },{ 255, 184, 8 }, }, { { 56, 192, 4040 },{ 255, 192, 8 },{ 56, 192, 456 },{ 255, 192, 8 }, }, + { { 64, 200, 4040 },{ 255, 200, 8 },{ 64, 200, 456 },{ 255, 200, 8 }, },{ { 72, 208, 4040 },{ 255, 208, 8 },{ 72, 208, 456 },{ 255, 208, 8 }, }, + + }; + + struct dxt5a_block + { + uint8_t m_endpoints[2]; + + enum { cTotalSelectorBytes = 6 }; + uint8_t m_selectors[cTotalSelectorBytes]; + + inline void clear() + { + basisu::clear_obj(*this); + } + + inline uint32_t get_low_alpha() const + { + return m_endpoints[0]; + } + + inline uint32_t get_high_alpha() const + { + return m_endpoints[1]; + } + + inline void set_low_alpha(uint32_t i) + { + assert(i <= UINT8_MAX); + m_endpoints[0] = static_cast(i); + } + + inline void set_high_alpha(uint32_t i) + { + assert(i <= UINT8_MAX); + m_endpoints[1] = static_cast(i); + } + + inline bool is_alpha6_block() const { return get_low_alpha() <= get_high_alpha(); } + + uint32_t get_endpoints_as_word() const { return m_endpoints[0] | (m_endpoints[1] << 8); } + uint32_t get_selectors_as_word(uint32_t index) { assert(index < 3); return m_selectors[index * 2] | (m_selectors[index * 2 + 1] << 8); } + + inline uint32_t get_selector(uint32_t x, uint32_t y) const + { + assert((x < 4U) && (y < 4U)); + + uint32_t selector_index = (y * 4) + x; + uint32_t bit_index = selector_index * cDXT5SelectorBits; + + uint32_t byte_index = bit_index >> 3; + uint32_t bit_ofs = bit_index & 7; + + uint32_t v = m_selectors[byte_index]; + if (byte_index < (cTotalSelectorBytes - 1)) + v |= (m_selectors[byte_index + 1] << 8); + + return (v >> bit_ofs) & 7; + } + + inline void set_selector(uint32_t x, uint32_t y, uint32_t val) + { + assert((x < 4U) && (y < 4U) && (val < 8U)); + + uint32_t selector_index = (y * 4) + x; + uint32_t bit_index = selector_index * cDXT5SelectorBits; + + uint32_t byte_index = bit_index >> 3; + uint32_t bit_ofs = bit_index & 7; + + uint32_t v = m_selectors[byte_index]; + if (byte_index < (cTotalSelectorBytes - 1)) + v |= (m_selectors[byte_index + 1] << 8); + + v &= (~(7 << bit_ofs)); + v |= (val << bit_ofs); + + m_selectors[byte_index] = static_cast(v); + if (byte_index < (cTotalSelectorBytes - 1)) + m_selectors[byte_index + 1] = static_cast(v >> 8); + } + + enum { cMaxSelectorValues = 8 }; + + static uint32_t get_block_values6(color32* pDst, uint32_t l, uint32_t h) + { + pDst[0].a = static_cast(l); + pDst[1].a = static_cast(h); + pDst[2].a = static_cast((l * 4 + h) / 5); + pDst[3].a = static_cast((l * 3 + h * 2) / 5); + pDst[4].a = static_cast((l * 2 + h * 3) / 5); + pDst[5].a = static_cast((l + h * 4) / 5); + pDst[6].a = 0; + pDst[7].a = 255; + return 6; + } + + static uint32_t get_block_values8(color32* pDst, uint32_t l, uint32_t h) + { + pDst[0].a = static_cast(l); + pDst[1].a = static_cast(h); + pDst[2].a = static_cast((l * 6 + h) / 7); + pDst[3].a = static_cast((l * 5 + h * 2) / 7); + pDst[4].a = static_cast((l * 4 + h * 3) / 7); + pDst[5].a = static_cast((l * 3 + h * 4) / 7); + pDst[6].a = static_cast((l * 2 + h * 5) / 7); + pDst[7].a = static_cast((l + h * 6) / 7); + return 8; + } + + static uint32_t get_block_values(color32* pDst, uint32_t l, uint32_t h) + { + if (l > h) + return get_block_values8(pDst, l, h); + else + return get_block_values6(pDst, l, h); + } + }; + + static void convert_etc1s_to_dxt5a(dxt5a_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector) + { + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (low_selector == high_selector) + { + uint32_t r; + decoder_etc_block::get_block_color5_r(base_color, inten_table, low_selector, r); + + pDst_block->set_low_alpha(r); + pDst_block->set_high_alpha(r); + pDst_block->m_selectors[0] = 0; + pDst_block->m_selectors[1] = 0; + pDst_block->m_selectors[2] = 0; + pDst_block->m_selectors[3] = 0; + pDst_block->m_selectors[4] = 0; + pDst_block->m_selectors[5] = 0; + return; + } + else if (pSelector->m_num_unique_selectors == 2) + { + color32 block_colors[4]; + + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + const uint32_t r0 = block_colors[low_selector].r; + const uint32_t r1 = block_colors[high_selector].r; + + pDst_block->set_low_alpha(r0); + pDst_block->set_high_alpha(r1); + + // TODO: Optimize this + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + pDst_block->set_selector(x, y, (s == high_selector) ? 1 : 0); + } + } + + return; + } + + uint32_t selector_range_table = 0; + for (selector_range_table = 0; selector_range_table < NUM_DXT5A_SELECTOR_RANGES; selector_range_table++) + if ((low_selector == s_dxt5a_selector_ranges[selector_range_table].m_low) && (high_selector == s_dxt5a_selector_ranges[selector_range_table].m_high)) + break; + if (selector_range_table >= NUM_DXT5A_SELECTOR_RANGES) + selector_range_table = 0; + + const etc1_g_to_dxt5a_conversion* pTable_entry = &g_etc1_g_to_dxt5a[base_color.r + inten_table * 32][selector_range_table]; + + pDst_block->set_low_alpha(pTable_entry->m_lo); + pDst_block->set_high_alpha(pTable_entry->m_hi); + + // TODO: Optimize this (like ETC1->BC1) + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + + uint32_t ds = (pTable_entry->m_trans >> (s * 3)) & 7; + + pDst_block->set_selector(x, y, ds); + } + } + } +#endif //BASISD_SUPPORT_DXT5A + + // PVRTC + +#if BASISD_SUPPORT_PVRTC1 || BASISD_SUPPORT_UASTC + static const uint16_t g_pvrtc_swizzle_table[256] = + { + 0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015, 0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055, 0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115, 0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155, + 0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415, 0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455, 0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515, 0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555, + 0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015, 0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055, 0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115, 0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155, + 0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415, 0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455, 0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515, 0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555, + 0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015, 0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055, 0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115, 0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155, + 0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415, 0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455, 0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515, 0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555, + 0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015, 0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055, 0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115, 0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155, + 0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415, 0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455, 0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515, 0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555 + }; + + // Note we can't use simple calculations to convert PVRTC1 encoded endpoint components to/from 8-bits, due to hardware approximations. + static const uint8_t g_pvrtc_5[32] = { 0,8,16,24,33,41,49,57,66,74,82,90,99,107,115,123,132,140,148,156,165,173,181,189,198,206,214,222,231,239,247,255 }; + static const uint8_t g_pvrtc_4[16] = { 0,16,33,49,66,82,99,115,140,156,173,189,206,222,239,255 }; + static const uint8_t g_pvrtc_3[8] = { 0,33,74,107,148,181,222,255 }; + static const uint8_t g_pvrtc_alpha[9] = { 0,34,68,102,136,170,204,238,255 }; + + static const uint8_t g_pvrtc_5_floor[256] = + { + 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3, + 3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7, + 7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11, + 11,11,11,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15, + 15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19, + 19,19,19,19,19,20,20,20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23, + 23,23,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27, + 27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31 + }; + + static const uint8_t g_pvrtc_5_ceil[256] = + { + 0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4, + 4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,8,8,8,8,8,8, + 8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,12,12,12,12,12, + 12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16, + 16,16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,18,18,18,19,19,19,19,19,19,19,19,20,20,20, + 20,20,20,20,20,20,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,24,24, + 24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,28, + 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31 + }; + + static const uint8_t g_pvrtc_4_floor[256] = + { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15 + }; + + static const uint8_t g_pvrtc_4_ceil[256] = + { + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14, + 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15 + }; + + static const uint8_t g_pvrtc_3_floor[256] = + { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7 + }; + + static const uint8_t g_pvrtc_3_ceil[256] = + { + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 + }; + + static const uint8_t g_pvrtc_alpha_floor[256] = + { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8 + }; + + static const uint8_t g_pvrtc_alpha_ceil[256] = + { + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, + 3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + + struct pvrtc4_block + { + uint32_t m_modulation; + uint32_t m_endpoints; + + pvrtc4_block() : m_modulation(0), m_endpoints(0) { } + + inline bool operator== (const pvrtc4_block& rhs) const + { + return (m_modulation == rhs.m_modulation) && (m_endpoints == rhs.m_endpoints); + } + + inline void clear() + { + m_modulation = 0; + m_endpoints = 0; + } + + inline bool get_block_uses_transparent_modulation() const + { + return (m_endpoints & 1) != 0; + } + + inline void set_block_uses_transparent_modulation(bool m) + { + m_endpoints = (m_endpoints & ~1U) | static_cast(m); + } + + inline bool is_endpoint_opaque(uint32_t endpoint_index) const + { + static const uint32_t s_bitmasks[2] = { 0x8000U, 0x80000000U }; + return (m_endpoints & s_bitmasks[basisu::open_range_check(endpoint_index, 2U)]) != 0; + } + + inline void set_endpoint_opaque(uint32_t endpoint_index, bool opaque) + { + assert(endpoint_index < 2); + static const uint32_t s_bitmasks[2] = { 0x8000U, 0x80000000U }; + if (opaque) + m_endpoints |= s_bitmasks[endpoint_index]; + else + m_endpoints &= ~s_bitmasks[endpoint_index]; + } + + inline color32 get_endpoint_5554(uint32_t endpoint_index) const + { + assert(endpoint_index < 2); + static const uint32_t s_endpoint_mask[2] = { 0xFFFE, 0xFFFF }; + uint32_t packed = (m_endpoints >> (basisu::open_range_check(endpoint_index, 2U) ? 16 : 0)) & s_endpoint_mask[endpoint_index]; + + uint32_t r, g, b, a; + if (packed & 0x8000) + { + // opaque 554 or 555 + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 31; + + if (!endpoint_index) + b |= (b >> 4); + + a = 0xF; + } + else + { + // translucent 4433 or 4443 + r = (packed >> 7) & 0x1E; + g = (packed >> 3) & 0x1E; + b = (packed & 0xF) << 1; + + r |= (r >> 4); + g |= (g >> 4); + + if (!endpoint_index) + b |= (b >> 3); + else + b |= (b >> 4); + + a = (packed >> 11) & 0xE; + } + + assert((r < 32) && (g < 32) && (b < 32) && (a < 16)); + + return color32(r, g, b, a); + } + + inline color32 get_endpoint_8888(uint32_t endpoint_index) const + { + assert(endpoint_index < 2); + static const uint32_t s_endpoint_mask[2] = { 0xFFFE, 0xFFFF }; + uint32_t packed = (m_endpoints >> (basisu::open_range_check(endpoint_index, 2U) ? 16 : 0)) & s_endpoint_mask[endpoint_index]; + + uint32_t r, g, b, a; + if (packed & 0x8000) + { + // opaque 554 or 555 + // 1RRRRRGGGGGBBBBM + // 1RRRRRGGGGGBBBBB + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 31; + + r = g_pvrtc_5[r]; + g = g_pvrtc_5[g]; + + if (!endpoint_index) + b = g_pvrtc_4[b >> 1]; + else + b = g_pvrtc_5[b]; + + a = 255; + } + else + { + // translucent 4433 or 4443 + // 0AAA RRRR GGGG BBBM + // 0AAA RRRR GGGG BBBB + r = (packed >> 8) & 0xF; + g = (packed >> 4) & 0xF; + b = packed & 0xF; + a = (packed >> 12) & 7; + + r = g_pvrtc_4[r]; + g = g_pvrtc_4[g]; + + if (!endpoint_index) + b = g_pvrtc_3[b >> 1]; + else + b = g_pvrtc_4[b]; + + a = g_pvrtc_alpha[a]; + } + + return color32(r, g, b, a); + } + + inline uint32_t get_endpoint_l8(uint32_t endpoint_index) const + { + color32 c(get_endpoint_8888(endpoint_index)); + return c.r + c.g + c.b + c.a; + } + + inline uint32_t get_opaque_endpoint_l0() const + { + uint32_t packed = m_endpoints & 0xFFFE; + + uint32_t r, g, b; + assert(packed & 0x8000); + + // opaque 554 or 555 + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 31; + b |= (b >> 4); + + return r + g + b; + } + + inline uint32_t get_opaque_endpoint_l1() const + { + uint32_t packed = m_endpoints >> 16; + + uint32_t r, g, b; + assert(packed & 0x8000); + + // opaque 554 or 555 + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 31; + + return r + g + b; + } + + static uint32_t get_component_precision_in_bits(uint32_t c, uint32_t endpoint_index, bool opaque_endpoint) + { + static const uint32_t s_comp_prec[4][4] = + { + // R0 G0 B0 A0 R1 G1 B1 A1 + { 4, 4, 3, 3 },{ 4, 4, 4, 3 }, // transparent endpoint + + { 5, 5, 4, 0 },{ 5, 5, 5, 0 } // opaque endpoint + }; + return s_comp_prec[basisu::open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)][basisu::open_range_check(c, 4U)]; + } + + static color32 get_color_precision_in_bits(uint32_t endpoint_index, bool opaque_endpoint) + { + static const color32 s_color_prec[4] = + { + color32(4, 4, 3, 3), color32(4, 4, 4, 3), // transparent endpoint + color32(5, 5, 4, 0), color32(5, 5, 5, 0) // opaque endpoint + }; + return s_color_prec[basisu::open_range_check(endpoint_index, 2U) + (opaque_endpoint * 2)]; + } + + inline void set_opaque_endpoint_floor(uint32_t endpoint_index, const color32& c) + { + assert(endpoint_index < 2); + const uint32_t m = m_endpoints & 1; + + uint32_t r = g_pvrtc_5_floor[c[0]], g = g_pvrtc_5_floor[c[1]], b = c[2]; + + if (!endpoint_index) + b = g_pvrtc_4_floor[b] << 1; + else + b = g_pvrtc_5_floor[b]; + + // rgba=555 here + assert((r < 32) && (g < 32) && (b < 32)); + + // 1RRRRRGGGGGBBBBM + // 1RRRRRGGGGGBBBBB + + // opaque 554 or 555 + uint32_t packed = 0x8000 | (r << 10) | (g << 5) | b; + if (!endpoint_index) + packed = (packed & ~1) | m; + + assert(packed <= 0xFFFF); + + if (endpoint_index) + m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16); + else + m_endpoints = (m_endpoints & 0xFFFF0000U) | packed; + } + + inline void set_opaque_endpoint_ceil(uint32_t endpoint_index, const color32& c) + { + assert(endpoint_index < 2); + const uint32_t m = m_endpoints & 1; + + uint32_t r = g_pvrtc_5_ceil[c[0]], g = g_pvrtc_5_ceil[c[1]], b = c[2]; + + if (!endpoint_index) + b = g_pvrtc_4_ceil[b] << 1; + else + b = g_pvrtc_5_ceil[b]; + + // rgba=555 here + assert((r < 32) && (g < 32) && (b < 32)); + + // 1RRRRRGGGGGBBBBM + // 1RRRRRGGGGGBBBBB + + // opaque 554 or 555 + uint32_t packed = 0x8000 | (r << 10) | (g << 5) | b; + if (!endpoint_index) + packed |= m; + + assert(packed <= 0xFFFF); + + if (endpoint_index) + m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16); + else + m_endpoints = (m_endpoints & 0xFFFF0000U) | packed; + } + + // opaque endpoints: 554 or 555 + // transparent endpoints: 3443 or 3444 + inline void set_endpoint_raw(uint32_t endpoint_index, const color32& c, bool opaque_endpoint) + { + assert(endpoint_index < 2); + const uint32_t m = m_endpoints & 1; + uint32_t r = c[0], g = c[1], b = c[2], a = c[3]; + + uint32_t packed; + + if (opaque_endpoint) + { + if (!endpoint_index) + { + // 554 + // 1RRRRRGGGGGBBBBM + assert((r < 32) && (g < 32) && (b < 16)); + packed = 0x8000 | (r << 10) | (g << 5) | (b << 1) | m; + } + else + { + // 555 + // 1RRRRRGGGGGBBBBB + assert((r < 32) && (g < 32) && (b < 32)); + packed = 0x8000 | (r << 10) | (g << 5) | b; + } + } + else + { + if (!endpoint_index) + { + // 3443 + // 0AAA RRRR GGGG BBBM + assert((r < 16) && (g < 16) && (b < 8) && (a < 8)); + packed = (a << 12) | (r << 8) | (g << 4) | (b << 1) | m; + } + else + { + // 3444 + // 0AAA RRRR GGGG BBBB + assert((r < 16) && (g < 16) && (b < 16) && (a < 8)); + packed = (a << 12) | (r << 8) | (g << 4) | b; + } + } + + assert(packed <= 0xFFFF); + + if (endpoint_index) + m_endpoints = (m_endpoints & 0xFFFFU) | (packed << 16); + else + m_endpoints = (m_endpoints & 0xFFFF0000U) | packed; + } + + inline void set_endpoint_floor(uint32_t endpoint_index, const color32& c) + { + assert(endpoint_index < 2); + + int a = g_pvrtc_alpha_floor[c.a]; + if (a == 8) + { + // 554 or 555 + uint32_t r = g_pvrtc_5_floor[c[0]], g = g_pvrtc_5_floor[c[1]], b = c[2]; + + if (!endpoint_index) + b = g_pvrtc_4_floor[b]; + else + b = g_pvrtc_5_floor[b]; + + set_endpoint_raw(endpoint_index, color32(r, g, b, a), true); + } + else + { + // 4433 or 4443 + uint32_t r = g_pvrtc_4_floor[c[0]], g = g_pvrtc_4_floor[c[1]], b = c[2]; + + if (!endpoint_index) + b = g_pvrtc_3_floor[b]; + else + b = g_pvrtc_4_floor[b]; + + set_endpoint_raw(endpoint_index, color32(r, g, b, a), false); + } + } + + inline void set_endpoint_ceil(uint32_t endpoint_index, const color32& c) + { + assert(endpoint_index < 2); + + int a = g_pvrtc_alpha_ceil[c.a]; + if (a == 8) + { + // 554 or 555 + uint32_t r = g_pvrtc_5_ceil[c[0]], g = g_pvrtc_5_ceil[c[1]], b = c[2]; + + if (!endpoint_index) + b = g_pvrtc_4_ceil[b]; + else + b = g_pvrtc_5_ceil[b]; + + set_endpoint_raw(endpoint_index, color32(r, g, b, a), true); + } + else + { + // 4433 or 4443 + uint32_t r = g_pvrtc_4_ceil[c[0]], g = g_pvrtc_4_ceil[c[1]], b = c[2]; + + if (!endpoint_index) + b = g_pvrtc_3_ceil[b]; + else + b = g_pvrtc_4_ceil[b]; + + set_endpoint_raw(endpoint_index, color32(r, g, b, a), false); + } + } + + inline uint32_t get_modulation(uint32_t x, uint32_t y) const + { + assert((x < 4) && (y < 4)); + return (m_modulation >> ((y * 4 + x) * 2)) & 3; + } + + // Scaled by 8 + inline const uint32_t* get_scaled_modulation_values(bool block_uses_transparent_modulation) const + { + static const uint32_t s_block_scales[2][4] = { { 0, 3, 5, 8 },{ 0, 4, 4, 8 } }; + return s_block_scales[block_uses_transparent_modulation]; + } + + // Scaled by 8 + inline uint32_t get_scaled_modulation(uint32_t x, uint32_t y) const + { + return get_scaled_modulation_values(get_block_uses_transparent_modulation())[get_modulation(x, y)]; + } + + inline void set_modulation(uint32_t x, uint32_t y, uint32_t s) + { + assert((x < 4) && (y < 4) && (s < 4)); + uint32_t n = (y * 4 + x) * 2; + m_modulation = (m_modulation & (~(3 << n))) | (s << n); + assert(get_modulation(x, y) == s); + } + + // Assumes modulation was initialized to 0 + inline void set_modulation_fast(uint32_t x, uint32_t y, uint32_t s) + { + assert((x < 4) && (y < 4) && (s < 4)); + uint32_t n = (y * 4 + x) * 2; + m_modulation |= (s << n); + assert(get_modulation(x, y) == s); + } + }; + +#if 0 + static const uint8_t g_pvrtc_bilinear_weights[16][4] = + { + { 4, 4, 4, 4 }, { 2, 6, 2, 6 }, { 8, 0, 8, 0 }, { 6, 2, 6, 2 }, + { 2, 2, 6, 6 }, { 1, 3, 3, 9 }, { 4, 0, 12, 0 }, { 3, 1, 9, 3 }, + { 8, 8, 0, 0 }, { 4, 12, 0, 0 }, { 16, 0, 0, 0 }, { 12, 4, 0, 0 }, + { 6, 6, 2, 2 }, { 3, 9, 1, 3 }, { 12, 0, 4, 0 }, { 9, 3, 3, 1 }, + }; +#endif + + struct pvrtc1_temp_block + { + decoder_etc_block m_etc1_block; + uint32_t m_pvrtc_endpoints; + }; + + static inline uint32_t get_opaque_endpoint_l0(uint32_t endpoints) + { + uint32_t packed = endpoints; + + uint32_t r, g, b; + assert(packed & 0x8000); + + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 30; + b |= (b >> 4); + + return r + g + b; + } + + static inline uint32_t get_opaque_endpoint_l1(uint32_t endpoints) + { + uint32_t packed = endpoints >> 16; + + uint32_t r, g, b; + assert(packed & 0x8000); + + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 31; + + return r + g + b; + } + + static color32 get_endpoint_8888(uint32_t endpoints, uint32_t endpoint_index) + { + assert(endpoint_index < 2); + static const uint32_t s_endpoint_mask[2] = { 0xFFFE, 0xFFFF }; + uint32_t packed = (endpoints >> (basisu::open_range_check(endpoint_index, 2U) ? 16 : 0)) & s_endpoint_mask[endpoint_index]; + + uint32_t r, g, b, a; + if (packed & 0x8000) + { + // opaque 554 or 555 + // 1RRRRRGGGGGBBBBM + // 1RRRRRGGGGGBBBBB + r = (packed >> 10) & 31; + g = (packed >> 5) & 31; + b = packed & 31; + + r = g_pvrtc_5[r]; + g = g_pvrtc_5[g]; + + if (!endpoint_index) + b = g_pvrtc_4[b >> 1]; + else + b = g_pvrtc_5[b]; + + a = 255; + } + else + { + // translucent 4433 or 4443 + // 0AAA RRRR GGGG BBBM + // 0AAA RRRR GGGG BBBB + r = (packed >> 8) & 0xF; + g = (packed >> 4) & 0xF; + b = packed & 0xF; + a = (packed >> 12) & 7; + + r = g_pvrtc_4[r]; + g = g_pvrtc_4[g]; + + if (!endpoint_index) + b = g_pvrtc_3[b >> 1]; + else + b = g_pvrtc_4[b]; + + a = g_pvrtc_alpha[a]; + } + + return color32(r, g, b, a); + } + + static uint32_t get_endpoint_l8(uint32_t endpoints, uint32_t endpoint_index) + { + color32 c(get_endpoint_8888(endpoints, endpoint_index)); + return c.r + c.g + c.b + c.a; + } +#endif + +#if BASISD_SUPPORT_PVRTC1 + // TODO: Support decoding a non-pow2 ETC1S texture into the next larger pow2 PVRTC texture. + static void fixup_pvrtc1_4_modulation_rgb(const decoder_etc_block* pETC_Blocks, const uint32_t* pPVRTC_endpoints, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y) + { + const uint32_t x_mask = num_blocks_x - 1; + const uint32_t y_mask = num_blocks_y - 1; + const uint32_t x_bits = basisu::total_bits(x_mask); + const uint32_t y_bits = basisu::total_bits(y_mask); + const uint32_t min_bits = basisu::minimum(x_bits, y_bits); + //const uint32_t max_bits = basisu::maximum(x_bits, y_bits); + const uint32_t swizzle_mask = (1 << (min_bits * 2)) - 1; + + uint32_t block_index = 0; + + // really 3x3 + int e0[4][4], e1[4][4]; + + for (int y = 0; y < static_cast(num_blocks_y); y++) + { + const uint32_t* pE_rows[3]; + + for (int ey = 0; ey < 3; ey++) + { + int by = y + ey - 1; + + const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x]; + + pE_rows[ey] = pE; + + for (int ex = 0; ex < 3; ex++) + { + int bx = 0 + ex - 1; + + const uint32_t e = pE[bx & x_mask]; + + e0[ex][ey] = (get_opaque_endpoint_l0(e) * 255) / 31; + e1[ex][ey] = (get_opaque_endpoint_l1(e) * 255) / 31; + } + } + + const uint32_t y_swizzle = (g_pvrtc_swizzle_table[y >> 8] << 16) | g_pvrtc_swizzle_table[y & 0xFF]; + + for (int x = 0; x < static_cast(num_blocks_x); x++, block_index++) + { + const decoder_etc_block& src_block = pETC_Blocks[block_index]; + + const uint32_t x_swizzle = (g_pvrtc_swizzle_table[x >> 8] << 17) | (g_pvrtc_swizzle_table[x & 0xFF] << 1); + + uint32_t swizzled = x_swizzle | y_swizzle; + if (num_blocks_x != num_blocks_y) + { + swizzled &= swizzle_mask; + + if (num_blocks_x > num_blocks_y) + swizzled |= ((x >> min_bits) << (min_bits * 2)); + else + swizzled |= ((y >> min_bits) << (min_bits * 2)); + } + + pvrtc4_block* pDst_block = static_cast(pDst_blocks) + swizzled; + pDst_block->m_endpoints = pPVRTC_endpoints[block_index]; + + uint32_t base_r = g_etc_5_to_8[src_block.m_differential.m_red1]; + uint32_t base_g = g_etc_5_to_8[src_block.m_differential.m_green1]; + uint32_t base_b = g_etc_5_to_8[src_block.m_differential.m_blue1]; + + const int* pInten_table48 = g_etc1_inten_tables48[src_block.m_differential.m_cw1]; + int by = (base_r + base_g + base_b) * 16; + int block_colors_y_x16[4]; + block_colors_y_x16[0] = by + pInten_table48[2]; + block_colors_y_x16[1] = by + pInten_table48[3]; + block_colors_y_x16[2] = by + pInten_table48[1]; + block_colors_y_x16[3] = by + pInten_table48[0]; + + { + const uint32_t ex = 2; + int bx = x + ex - 1; + bx &= x_mask; + +#define DO_ROW(ey) \ + { \ + const uint32_t e = pE_rows[ey][bx]; \ + e0[ex][ey] = (get_opaque_endpoint_l0(e) * 255) / 31; \ + e1[ex][ey] = (get_opaque_endpoint_l1(e) * 255) / 31; \ + } + + DO_ROW(0); + DO_ROW(1); + DO_ROW(2); +#undef DO_ROW + } + + uint32_t mod = 0; + + uint32_t lookup_x[4]; + +#define DO_LOOKUP(lx) { \ + const uint32_t byte_ofs = 7 - (((lx) * 4) >> 3); \ + const uint32_t lsb_bits = src_block.m_bytes[byte_ofs] >> (((lx) & 1) * 4); \ + const uint32_t msb_bits = src_block.m_bytes[byte_ofs - 2] >> (((lx) & 1) * 4); \ + lookup_x[lx] = (lsb_bits & 0xF) | ((msb_bits & 0xF) << 4); } + + DO_LOOKUP(0); + DO_LOOKUP(1); + DO_LOOKUP(2); + DO_LOOKUP(3); +#undef DO_LOOKUP + +#define DO_PIX(lx, ly, w0, w1, w2, w3) \ + { \ + int ca_l = a0 * w0 + a1 * w1 + a2 * w2 + a3 * w3; \ + int cb_l = b0 * w0 + b1 * w1 + b2 * w2 + b3 * w3; \ + int cl = block_colors_y_x16[g_etc1_x_selector_unpack[ly][lookup_x[lx]]]; \ + int dl = cb_l - ca_l; \ + int vl = cl - ca_l; \ + int p = vl * 16; \ + if (ca_l > cb_l) { p = -p; dl = -dl; } \ + uint32_t m = 0; \ + if (p > 3 * dl) m = (uint32_t)(1 << ((ly) * 8 + (lx) * 2)); \ + if (p > 8 * dl) m = (uint32_t)(2 << ((ly) * 8 + (lx) * 2)); \ + if (p > 13 * dl) m = (uint32_t)(3 << ((ly) * 8 + (lx) * 2)); \ + mod |= m; \ + } + + { + const uint32_t ex = 0, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 0, 4, 4, 4, 4); + DO_PIX(1, 0, 2, 6, 2, 6); + DO_PIX(0, 1, 2, 2, 6, 6); + DO_PIX(1, 1, 1, 3, 3, 9); + } + + { + const uint32_t ex = 1, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 0, 8, 0, 8, 0); + DO_PIX(3, 0, 6, 2, 6, 2); + DO_PIX(2, 1, 4, 0, 12, 0); + DO_PIX(3, 1, 3, 1, 9, 3); + } + + { + const uint32_t ex = 0, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 2, 8, 8, 0, 0); + DO_PIX(1, 2, 4, 12, 0, 0); + DO_PIX(0, 3, 6, 6, 2, 2); + DO_PIX(1, 3, 3, 9, 1, 3); + } + + { + const uint32_t ex = 1, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 2, 16, 0, 0, 0); + DO_PIX(3, 2, 12, 4, 0, 0); + DO_PIX(2, 3, 12, 0, 4, 0); + DO_PIX(3, 3, 9, 3, 3, 1); + } +#undef DO_PIX + + pDst_block->m_modulation = mod; + + e0[0][0] = e0[1][0]; e0[1][0] = e0[2][0]; + e0[0][1] = e0[1][1]; e0[1][1] = e0[2][1]; + e0[0][2] = e0[1][2]; e0[1][2] = e0[2][2]; + + e1[0][0] = e1[1][0]; e1[1][0] = e1[2][0]; + e1[0][1] = e1[1][1]; e1[1][1] = e1[2][1]; + e1[0][2] = e1[1][2]; e1[1][2] = e1[2][2]; + + } // x + } // y + } + + static void fixup_pvrtc1_4_modulation_rgba( + const decoder_etc_block* pETC_Blocks, + const uint32_t* pPVRTC_endpoints, + void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, void *pAlpha_blocks, + const endpoint* pEndpoints, const selector* pSelectors) + { + const uint32_t x_mask = num_blocks_x - 1; + const uint32_t y_mask = num_blocks_y - 1; + const uint32_t x_bits = basisu::total_bits(x_mask); + const uint32_t y_bits = basisu::total_bits(y_mask); + const uint32_t min_bits = basisu::minimum(x_bits, y_bits); + //const uint32_t max_bits = basisu::maximum(x_bits, y_bits); + const uint32_t swizzle_mask = (1 << (min_bits * 2)) - 1; + + uint32_t block_index = 0; + + // really 3x3 + int e0[4][4], e1[4][4]; + + for (int y = 0; y < static_cast(num_blocks_y); y++) + { + const uint32_t* pE_rows[3]; + + for (int ey = 0; ey < 3; ey++) + { + int by = y + ey - 1; + + const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x]; + + pE_rows[ey] = pE; + + for (int ex = 0; ex < 3; ex++) + { + int bx = 0 + ex - 1; + + const uint32_t e = pE[bx & x_mask]; + + e0[ex][ey] = get_endpoint_l8(e, 0); + e1[ex][ey] = get_endpoint_l8(e, 1); + } + } + + const uint32_t y_swizzle = (g_pvrtc_swizzle_table[y >> 8] << 16) | g_pvrtc_swizzle_table[y & 0xFF]; + + for (int x = 0; x < static_cast(num_blocks_x); x++, block_index++) + { + const decoder_etc_block& src_block = pETC_Blocks[block_index]; + + const uint16_t* pSrc_alpha_block = reinterpret_cast(static_cast(pAlpha_blocks) + x + (y * num_blocks_x)); + const endpoint* pAlpha_endpoints = &pEndpoints[pSrc_alpha_block[0]]; + const selector* pAlpha_selectors = &pSelectors[pSrc_alpha_block[1]]; + + const uint32_t x_swizzle = (g_pvrtc_swizzle_table[x >> 8] << 17) | (g_pvrtc_swizzle_table[x & 0xFF] << 1); + + uint32_t swizzled = x_swizzle | y_swizzle; + if (num_blocks_x != num_blocks_y) + { + swizzled &= swizzle_mask; + + if (num_blocks_x > num_blocks_y) + swizzled |= ((x >> min_bits) << (min_bits * 2)); + else + swizzled |= ((y >> min_bits) << (min_bits * 2)); + } + + pvrtc4_block* pDst_block = static_cast(pDst_blocks) + swizzled; + pDst_block->m_endpoints = pPVRTC_endpoints[block_index]; + + uint32_t base_r = g_etc_5_to_8[src_block.m_differential.m_red1]; + uint32_t base_g = g_etc_5_to_8[src_block.m_differential.m_green1]; + uint32_t base_b = g_etc_5_to_8[src_block.m_differential.m_blue1]; + + const int* pInten_table48 = g_etc1_inten_tables48[src_block.m_differential.m_cw1]; + int by = (base_r + base_g + base_b) * 16; + int block_colors_y_x16[4]; + block_colors_y_x16[0] = basisu::clamp(by + pInten_table48[0], 0, 48 * 255); + block_colors_y_x16[1] = basisu::clamp(by + pInten_table48[1], 0, 48 * 255); + block_colors_y_x16[2] = basisu::clamp(by + pInten_table48[2], 0, 48 * 255); + block_colors_y_x16[3] = basisu::clamp(by + pInten_table48[3], 0, 48 * 255); + + uint32_t alpha_base_g = g_etc_5_to_8[pAlpha_endpoints->m_color5.g] * 16; + const int* pInten_table16 = g_etc1_inten_tables16[pAlpha_endpoints->m_inten5]; + int alpha_block_colors_x16[4]; + alpha_block_colors_x16[0] = basisu::clamp(alpha_base_g + pInten_table16[0], 0, 16 * 255); + alpha_block_colors_x16[1] = basisu::clamp(alpha_base_g + pInten_table16[1], 0, 16 * 255); + alpha_block_colors_x16[2] = basisu::clamp(alpha_base_g + pInten_table16[2], 0, 16 * 255); + alpha_block_colors_x16[3] = basisu::clamp(alpha_base_g + pInten_table16[3], 0, 16 * 255); + + // clamp((base_r + base_g + base_b) * 16 + color_inten[s] * 48) + clamp(alpha_base_g * 16 + alpha_inten[as] * 16) + + { + const uint32_t ex = 2; + int bx = x + ex - 1; + bx &= x_mask; + +#define DO_ROW(ey) \ + { \ + const uint32_t e = pE_rows[ey][bx]; \ + e0[ex][ey] = get_endpoint_l8(e, 0); \ + e1[ex][ey] = get_endpoint_l8(e, 1); \ + } + + DO_ROW(0); + DO_ROW(1); + DO_ROW(2); +#undef DO_ROW + } + + uint32_t mod = 0; + +#define DO_PIX(lx, ly, w0, w1, w2, w3) \ + { \ + int ca_l = a0 * w0 + a1 * w1 + a2 * w2 + a3 * w3; \ + int cb_l = b0 * w0 + b1 * w1 + b2 * w2 + b3 * w3; \ + int cl = block_colors_y_x16[(src_block.m_bytes[4 + ly] >> (lx * 2)) & 3] + alpha_block_colors_x16[(pAlpha_selectors->m_selectors[ly] >> (lx * 2)) & 3]; \ + int dl = cb_l - ca_l; \ + int vl = cl - ca_l; \ + int p = vl * 16; \ + if (ca_l > cb_l) { p = -p; dl = -dl; } \ + uint32_t m = 0; \ + if (p > 3 * dl) m = (uint32_t)(1 << ((ly) * 8 + (lx) * 2)); \ + if (p > 8 * dl) m = (uint32_t)(2 << ((ly) * 8 + (lx) * 2)); \ + if (p > 13 * dl) m = (uint32_t)(3 << ((ly) * 8 + (lx) * 2)); \ + mod |= m; \ + } + + { + const uint32_t ex = 0, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 0, 4, 4, 4, 4); + DO_PIX(1, 0, 2, 6, 2, 6); + DO_PIX(0, 1, 2, 2, 6, 6); + DO_PIX(1, 1, 1, 3, 3, 9); + } + + { + const uint32_t ex = 1, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 0, 8, 0, 8, 0); + DO_PIX(3, 0, 6, 2, 6, 2); + DO_PIX(2, 1, 4, 0, 12, 0); + DO_PIX(3, 1, 3, 1, 9, 3); + } + + { + const uint32_t ex = 0, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 2, 8, 8, 0, 0); + DO_PIX(1, 2, 4, 12, 0, 0); + DO_PIX(0, 3, 6, 6, 2, 2); + DO_PIX(1, 3, 3, 9, 1, 3); + } + + { + const uint32_t ex = 1, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 2, 16, 0, 0, 0); + DO_PIX(3, 2, 12, 4, 0, 0); + DO_PIX(2, 3, 12, 0, 4, 0); + DO_PIX(3, 3, 9, 3, 3, 1); + } +#undef DO_PIX + + pDst_block->m_modulation = mod; + + e0[0][0] = e0[1][0]; e0[1][0] = e0[2][0]; + e0[0][1] = e0[1][1]; e0[1][1] = e0[2][1]; + e0[0][2] = e0[1][2]; e0[1][2] = e0[2][2]; + + e1[0][0] = e1[1][0]; e1[1][0] = e1[2][0]; + e1[0][1] = e1[1][1]; e1[1][1] = e1[2][1]; + e1[0][2] = e1[1][2]; e1[1][2] = e1[2][2]; + + } // x + } // y + } +#endif // BASISD_SUPPORT_PVRTC1 + +#if BASISD_SUPPORT_BC7_MODE5 + static dxt_selector_range g_etc1_to_bc7_m5_selector_ranges[] = + { + { 0, 3 }, + { 1, 3 }, + { 0, 2 }, + { 1, 2 }, + { 2, 3 }, + { 0, 1 }, + }; + + const uint32_t NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES = sizeof(g_etc1_to_bc7_m5_selector_ranges) / sizeof(g_etc1_to_bc7_m5_selector_ranges[0]); + + static uint32_t g_etc1_to_bc7_m5_selector_range_index[4][4]; + + const uint32_t NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS = 10; + static const uint8_t g_etc1_to_bc7_m5_selector_mappings[NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS][4] = + { + { 0, 0, 1, 1 }, + { 0, 0, 1, 2 }, + { 0, 0, 1, 3 }, + { 0, 0, 2, 3 }, + { 0, 1, 1, 1 }, + { 0, 1, 2, 2 }, + { 0, 1, 2, 3 }, + { 0, 2, 3, 3 }, + { 1, 2, 2, 2 }, + { 1, 2, 3, 3 }, + }; + + struct etc1_to_bc7_m5_solution + { + uint8_t m_lo; + uint8_t m_hi; + uint16_t m_err; + }; + + static const etc1_to_bc7_m5_solution g_etc1_to_bc7_m5_color[32 * 8 * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS * NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_bc7_m5_color.inc" + }; + + static dxt_selector_range g_etc1_to_bc7_m5a_selector_ranges[] = + { + { 0, 3 }, + { 1, 3 }, + { 0, 2 }, + { 1, 2 }, + { 2, 3 }, + { 0, 1 } + }; + + const uint32_t NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES = sizeof(g_etc1_to_bc7_m5a_selector_ranges) / sizeof(g_etc1_to_bc7_m5a_selector_ranges[0]); + + static uint32_t g_etc1_to_bc7_m5a_selector_range_index[4][4]; + + struct etc1_g_to_bc7_m5a_conversion + { + uint8_t m_lo, m_hi; + uint8_t m_trans; + }; + + static etc1_g_to_bc7_m5a_conversion g_etc1_g_to_bc7_m5a[8 * 32 * NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES] = + { + #include "basisu_transcoder_tables_bc7_m5_alpha.inc" + }; + + static inline uint32_t set_block_bits(uint8_t* pBytes, uint32_t val, uint32_t num_bits, uint32_t cur_ofs) + { + assert(num_bits < 32); + assert(val < (1ULL << num_bits)); + + uint32_t mask = static_cast((1ULL << num_bits) - 1); + + while (num_bits) + { + const uint32_t n = basisu::minimum(8 - (cur_ofs & 7), num_bits); + + pBytes[cur_ofs >> 3] &= ~static_cast(mask << (cur_ofs & 7)); + pBytes[cur_ofs >> 3] |= static_cast(val << (cur_ofs & 7)); + + val >>= n; + mask >>= n; + + num_bits -= n; + cur_ofs += n; + } + + return cur_ofs; + } + + struct bc7_mode_5 + { + union + { + struct + { + uint64_t m_mode : 6; + uint64_t m_rot : 2; + + uint64_t m_r0 : 7; + uint64_t m_r1 : 7; + uint64_t m_g0 : 7; + uint64_t m_g1 : 7; + uint64_t m_b0 : 7; + uint64_t m_b1 : 7; + uint64_t m_a0 : 8; + uint64_t m_a1_0 : 6; + + } m_lo; + + uint64_t m_lo_bits; + }; + + union + { + struct + { + uint64_t m_a1_1 : 2; + + // bit 2 + uint64_t m_c00 : 1; + uint64_t m_c10 : 2; + uint64_t m_c20 : 2; + uint64_t m_c30 : 2; + + uint64_t m_c01 : 2; + uint64_t m_c11 : 2; + uint64_t m_c21 : 2; + uint64_t m_c31 : 2; + + uint64_t m_c02 : 2; + uint64_t m_c12 : 2; + uint64_t m_c22 : 2; + uint64_t m_c32 : 2; + + uint64_t m_c03 : 2; + uint64_t m_c13 : 2; + uint64_t m_c23 : 2; + uint64_t m_c33 : 2; + + // bit 33 + uint64_t m_a00 : 1; + uint64_t m_a10 : 2; + uint64_t m_a20 : 2; + uint64_t m_a30 : 2; + + uint64_t m_a01 : 2; + uint64_t m_a11 : 2; + uint64_t m_a21 : 2; + uint64_t m_a31 : 2; + + uint64_t m_a02 : 2; + uint64_t m_a12 : 2; + uint64_t m_a22 : 2; + uint64_t m_a32 : 2; + + uint64_t m_a03 : 2; + uint64_t m_a13 : 2; + uint64_t m_a23 : 2; + uint64_t m_a33 : 2; + + } m_hi; + + uint64_t m_hi_bits; + }; + }; + +#if BASISD_WRITE_NEW_BC7_MODE5_TABLES + static void create_etc1_to_bc7_m5_color_conversion_table() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_bc7_m5_color.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1_to_bc7_m5_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1_to_bc7_m5_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 127; hi++) + { + for (uint32_t lo = 0; lo <= 127; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 1) | (lo >> 6); + colors[3] = (hi << 1) | (hi >> 6); + + colors[1] = (colors[0] * (64 - 21) + colors[3] * 21 + 32) / 64; + colors[2] = (colors[0] * (64 - 43) + colors[3] * 43 + 32) / 64; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1_to_bc7_m5_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); + } + + static void create_etc1_to_bc7_m5_alpha_conversion_table() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_bc7_m5_alpha.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1_to_bc7_m5a_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1_to_bc7_m5a_selector_ranges[sr].m_high; + + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + uint32_t best_output_selectors = 0; + + for (uint32_t hi = 0; hi <= 255; hi++) + { + for (uint32_t lo = 0; lo <= 255; lo++) + { + uint32_t colors[4]; + + colors[0] = lo; + colors[3] = hi; + + colors[1] = (colors[0] * (64 - 21) + colors[3] * 21 + 32) / 64; + colors[2] = (colors[0] * (64 - 43) + colors[3] * 43 + 32) / 64; + + uint64_t total_err = 0; + uint32_t output_selectors = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int best_mapping_err = INT_MAX; + int best_k = 0; + for (int k = 0; k < 4; k++) + { + int mapping_err = block_colors[s].g - colors[k]; + mapping_err *= mapping_err; + + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + mapping_err *= 5; + + if (mapping_err < best_mapping_err) + { + best_mapping_err = mapping_err; + best_k = k; + } + } // k + + total_err += best_mapping_err; + output_selectors |= (best_k << (s * 2)); + } // s + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + best_output_selectors = output_selectors; + } + + } // lo + } // hi + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, best_output_selectors); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + + } // sr + } // g + } // inten + + fclose(pFile); + } +#endif // BASISD_WRITE_NEW_BC7_MODE5_TABLES + + struct bc7_m5_match_entry + { + uint8_t m_hi; + uint8_t m_lo; + }; + + static bc7_m5_match_entry g_bc7_m5_equals_1[256] = + { + {0,0},{1,0},{3,0},{4,0},{6,0},{7,0},{9,0},{10,0},{12,0},{13,0},{15,0},{16,0},{18,0},{20,0},{21,0},{23,0}, + {24,0},{26,0},{27,0},{29,0},{30,0},{32,0},{33,0},{35,0},{36,0},{38,0},{39,0},{41,0},{42,0},{44,0},{45,0},{47,0}, + {48,0},{50,0},{52,0},{53,0},{55,0},{56,0},{58,0},{59,0},{61,0},{62,0},{64,0},{65,0},{66,0},{68,0},{69,0},{71,0}, + {72,0},{74,0},{75,0},{77,0},{78,0},{80,0},{82,0},{83,0},{85,0},{86,0},{88,0},{89,0},{91,0},{92,0},{94,0},{95,0}, + {97,0},{98,0},{100,0},{101,0},{103,0},{104,0},{106,0},{107,0},{109,0},{110,0},{112,0},{114,0},{115,0},{117,0},{118,0},{120,0}, + {121,0},{123,0},{124,0},{126,0},{127,0},{127,1},{126,2},{126,3},{127,3},{127,4},{126,5},{126,6},{127,6},{127,7},{126,8},{126,9}, + {127,9},{127,10},{126,11},{126,12},{127,12},{127,13},{126,14},{125,15},{127,15},{126,16},{126,17},{127,17},{127,18},{126,19},{126,20},{127,20}, + {127,21},{126,22},{126,23},{127,23},{127,24},{126,25},{126,26},{127,26},{127,27},{126,28},{126,29},{127,29},{127,30},{126,31},{126,32},{127,32}, + {127,33},{126,34},{126,35},{127,35},{127,36},{126,37},{126,38},{127,38},{127,39},{126,40},{126,41},{127,41},{127,42},{126,43},{126,44},{127,44}, + {127,45},{126,46},{125,47},{127,47},{126,48},{126,49},{127,49},{127,50},{126,51},{126,52},{127,52},{127,53},{126,54},{126,55},{127,55},{127,56}, + {126,57},{126,58},{127,58},{127,59},{126,60},{126,61},{127,61},{127,62},{126,63},{125,64},{126,64},{126,65},{127,65},{127,66},{126,67},{126,68}, + {127,68},{127,69},{126,70},{126,71},{127,71},{127,72},{126,73},{126,74},{127,74},{127,75},{126,76},{125,77},{127,77},{126,78},{126,79},{127,79}, + {127,80},{126,81},{126,82},{127,82},{127,83},{126,84},{126,85},{127,85},{127,86},{126,87},{126,88},{127,88},{127,89},{126,90},{126,91},{127,91}, + {127,92},{126,93},{126,94},{127,94},{127,95},{126,96},{126,97},{127,97},{127,98},{126,99},{126,100},{127,100},{127,101},{126,102},{126,103},{127,103}, + {127,104},{126,105},{126,106},{127,106},{127,107},{126,108},{125,109},{127,109},{126,110},{126,111},{127,111},{127,112},{126,113},{126,114},{127,114},{127,115}, + {126,116},{126,117},{127,117},{127,118},{126,119},{126,120},{127,120},{127,121},{126,122},{126,123},{127,123},{127,124},{126,125},{126,126},{127,126},{127,127} + }; + + static void transcoder_init_bc7_mode5() + { +#if 0 + // This is a little too much work to do at init time, so precompute it. + for (int i = 0; i < 256; i++) + { + int lowest_e = 256; + for (int lo = 0; lo < 128; lo++) + { + for (int hi = 0; hi < 128; hi++) + { + const int lo_e = (lo << 1) | (lo >> 6); + const int hi_e = (hi << 1) | (hi >> 6); + + // Selector 1 + int v = (lo_e * (64 - 21) + hi_e * 21 + 32) >> 6; + int e = abs(v - i); + + if (e < lowest_e) + { + g_bc7_m5_equals_1[i].m_hi = static_cast(hi); + g_bc7_m5_equals_1[i].m_lo = static_cast(lo); + + lowest_e = e; + } + + } // hi + + } // lo + + printf("{%u,%u},", g_bc7_m5_equals_1[i].m_hi, g_bc7_m5_equals_1[i].m_lo); + if ((i & 15) == 15) printf("\n"); + } +#endif + + for (uint32_t i = 0; i < NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES; i++) + { + uint32_t l = g_etc1_to_bc7_m5_selector_ranges[i].m_low; + uint32_t h = g_etc1_to_bc7_m5_selector_ranges[i].m_high; + g_etc1_to_bc7_m5_selector_range_index[l][h] = i; + } + + for (uint32_t i = 0; i < NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES; i++) + { + uint32_t l = g_etc1_to_bc7_m5a_selector_ranges[i].m_low; + uint32_t h = g_etc1_to_bc7_m5a_selector_ranges[i].m_high; + g_etc1_to_bc7_m5a_selector_range_index[l][h] = i; + } + } + + static void convert_etc1s_to_bc7_m5_color(void* pDst, const endpoint* pEndpoints, const selector* pSelector) + { + bc7_mode_5* pDst_block = static_cast(pDst); + + // First ensure the block is cleared to all 0's + static_cast(pDst)[0] = 0; + static_cast(pDst)[1] = 0; + + // Set alpha to 255 + pDst_block->m_lo.m_mode = 1 << 5; + pDst_block->m_lo.m_a0 = 255; + pDst_block->m_lo.m_a1_0 = 63; + pDst_block->m_hi.m_a1_1 = 3; + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const uint32_t base_color_r = pEndpoints->m_color5.r; + const uint32_t base_color_g = pEndpoints->m_color5.g; + const uint32_t base_color_b = pEndpoints->m_color5.b; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (pSelector->m_num_unique_selectors == 1) + { + // Solid color block - use precomputed tables and set selectors to 1. + uint32_t r, g, b; + decoder_etc_block::get_block_color5(pEndpoints->m_color5, inten_table, low_selector, r, g, b); + + pDst_block->m_lo.m_r0 = g_bc7_m5_equals_1[r].m_lo; + pDst_block->m_lo.m_g0 = g_bc7_m5_equals_1[g].m_lo; + pDst_block->m_lo.m_b0 = g_bc7_m5_equals_1[b].m_lo; + + pDst_block->m_lo.m_r1 = g_bc7_m5_equals_1[r].m_hi; + pDst_block->m_lo.m_g1 = g_bc7_m5_equals_1[g].m_hi; + pDst_block->m_lo.m_b1 = g_bc7_m5_equals_1[b].m_hi; + + set_block_bits((uint8_t*)pDst, 0x2aaaaaab, 31, 66); + return; + } + else if (pSelector->m_num_unique_selectors == 2) + { + // Only one or two unique selectors, so just switch to block truncation coding (BTC) to avoid quality issues on extreme blocks. + color32 block_colors[4]; + + decoder_etc_block::get_block_colors5(block_colors, color32(base_color_r, base_color_g, base_color_b, 255), inten_table); + + const uint32_t r0 = block_colors[low_selector].r; + const uint32_t g0 = block_colors[low_selector].g; + const uint32_t b0 = block_colors[low_selector].b; + + const uint32_t r1 = block_colors[high_selector].r; + const uint32_t g1 = block_colors[high_selector].g; + const uint32_t b1 = block_colors[high_selector].b; + + pDst_block->m_lo.m_r0 = r0 >> 1; + pDst_block->m_lo.m_g0 = g0 >> 1; + pDst_block->m_lo.m_b0 = b0 >> 1; + + pDst_block->m_lo.m_r1 = r1 >> 1; + pDst_block->m_lo.m_g1 = g1 >> 1; + pDst_block->m_lo.m_b1 = b1 >> 1; + + uint32_t output_low_selector = 0, output_bit_offset = 0, output_bits = 0; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + uint32_t os = (s == low_selector) ? output_low_selector : (3 ^ output_low_selector); + + uint32_t num_bits = 2; + + if ((x | y) == 0) + { + if (os & 2) + { + pDst_block->m_lo.m_r0 = r1 >> 1; + pDst_block->m_lo.m_g0 = g1 >> 1; + pDst_block->m_lo.m_b0 = b1 >> 1; + + pDst_block->m_lo.m_r1 = r0 >> 1; + pDst_block->m_lo.m_g1 = g0 >> 1; + pDst_block->m_lo.m_b1 = b0 >> 1; + + output_low_selector = 3; + os = 0; + } + + num_bits = 1; + } + + output_bits |= (os << output_bit_offset); + output_bit_offset += num_bits; + } + } + + set_block_bits((uint8_t*)pDst, output_bits, 31, 66); + return; + } + + const uint32_t selector_range_table = g_etc1_to_bc7_m5_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_bc7_m5_solution* pTable_r = &g_etc1_to_bc7_m5_color[(inten_table * 32 + base_color_r) * (NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS]; + const etc1_to_bc7_m5_solution* pTable_g = &g_etc1_to_bc7_m5_color[(inten_table * 32 + base_color_g) * (NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS]; + const etc1_to_bc7_m5_solution* pTable_b = &g_etc1_to_bc7_m5_color[(inten_table * 32 + base_color_b) * (NUM_ETC1_TO_BC7_M5_SELECTOR_RANGES * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS]; + + uint32_t best_err = UINT_MAX; + uint32_t best_mapping = 0; + + assert(NUM_ETC1_TO_BC7_M5_SELECTOR_MAPPINGS == 10); +#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } } + DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4); + DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9); +#undef DO_ITER + + const uint8_t* pSelectors_xlat = &g_etc1_to_bc7_m5_selector_mappings[best_mapping][0]; + + uint32_t s_inv = 0; + if (pSelectors_xlat[pSelector->get_selector(0, 0)] & 2) + { + pDst_block->m_lo.m_r0 = pTable_r[best_mapping].m_hi; + pDst_block->m_lo.m_g0 = pTable_g[best_mapping].m_hi; + pDst_block->m_lo.m_b0 = pTable_b[best_mapping].m_hi; + + pDst_block->m_lo.m_r1 = pTable_r[best_mapping].m_lo; + pDst_block->m_lo.m_g1 = pTable_g[best_mapping].m_lo; + pDst_block->m_lo.m_b1 = pTable_b[best_mapping].m_lo; + + s_inv = 3; + } + else + { + pDst_block->m_lo.m_r0 = pTable_r[best_mapping].m_lo; + pDst_block->m_lo.m_g0 = pTable_g[best_mapping].m_lo; + pDst_block->m_lo.m_b0 = pTable_b[best_mapping].m_lo; + + pDst_block->m_lo.m_r1 = pTable_r[best_mapping].m_hi; + pDst_block->m_lo.m_g1 = pTable_g[best_mapping].m_hi; + pDst_block->m_lo.m_b1 = pTable_b[best_mapping].m_hi; + } + + uint32_t output_bits = 0, output_bit_ofs = 0; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const uint32_t s = pSelector->get_selector(x, y); + + const uint32_t os = pSelectors_xlat[s] ^ s_inv; + + output_bits |= (os << output_bit_ofs); + + output_bit_ofs += (((x | y) == 0) ? 1 : 2); + } + } + + set_block_bits((uint8_t*)pDst, output_bits, 31, 66); + } + + static void convert_etc1s_to_bc7_m5_alpha(void* pDst, const endpoint* pEndpoints, const selector* pSelector) + { + bc7_mode_5* pDst_block = static_cast(pDst); + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const uint32_t base_color_r = pEndpoints->m_color5.r; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (pSelector->m_num_unique_selectors == 1) + { + uint32_t r; + decoder_etc_block::get_block_color5_r(pEndpoints->m_color5, inten_table, low_selector, r); + + pDst_block->m_lo.m_a0 = r; + pDst_block->m_lo.m_a1_0 = r & 63; + pDst_block->m_hi.m_a1_1 = r >> 6; + + return; + } + else if (pSelector->m_num_unique_selectors == 2) + { + // Only one or two unique selectors, so just switch to block truncation coding (BTC) to avoid quality issues on extreme blocks. + int block_colors[4]; + + decoder_etc_block::get_block_colors5_g(block_colors, pEndpoints->m_color5, inten_table); + + pDst_block->m_lo.m_a0 = block_colors[low_selector]; + pDst_block->m_lo.m_a1_0 = block_colors[high_selector] & 63; + pDst_block->m_hi.m_a1_1 = block_colors[high_selector] >> 6; + + uint32_t output_low_selector = 0, output_bit_offset = 0, output_bits = 0; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const uint32_t s = pSelector->get_selector(x, y); + uint32_t os = (s == low_selector) ? output_low_selector : (3 ^ output_low_selector); + + uint32_t num_bits = 2; + + if ((x | y) == 0) + { + if (os & 2) + { + pDst_block->m_lo.m_a0 = block_colors[high_selector]; + pDst_block->m_lo.m_a1_0 = block_colors[low_selector] & 63; + pDst_block->m_hi.m_a1_1 = block_colors[low_selector] >> 6; + + output_low_selector = 3; + os = 0; + } + + num_bits = 1; + } + + output_bits |= (os << output_bit_offset); + output_bit_offset += num_bits; + } + } + + set_block_bits((uint8_t*)pDst, output_bits, 31, 97); + return; + } + + const uint32_t selector_range_table = g_etc1_to_bc7_m5a_selector_range_index[low_selector][high_selector]; + + const etc1_g_to_bc7_m5a_conversion* pTable = &g_etc1_g_to_bc7_m5a[inten_table * (32 * NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES) + base_color_r * NUM_ETC1_TO_BC7_M5A_SELECTOR_RANGES + selector_range_table]; + + pDst_block->m_lo.m_a0 = pTable->m_lo; + pDst_block->m_lo.m_a1_0 = pTable->m_hi & 63; + pDst_block->m_hi.m_a1_1 = pTable->m_hi >> 6; + + uint32_t output_bit_offset = 0, output_bits = 0, selector_trans = pTable->m_trans; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const uint32_t s = pSelector->get_selector(x, y); + uint32_t os = (selector_trans >> (s * 2)) & 3; + + uint32_t num_bits = 2; + + if ((x | y) == 0) + { + if (os & 2) + { + pDst_block->m_lo.m_a0 = pTable->m_hi; + pDst_block->m_lo.m_a1_0 = pTable->m_lo & 63; + pDst_block->m_hi.m_a1_1 = pTable->m_lo >> 6; + + selector_trans ^= 0xFF; + os ^= 3; + } + + num_bits = 1; + } + + output_bits |= (os << output_bit_offset); + output_bit_offset += num_bits; + } + } + + set_block_bits((uint8_t*)pDst, output_bits, 31, 97); + } +#endif // BASISD_SUPPORT_BC7_MODE5 + +#if BASISD_SUPPORT_ETC2_EAC_A8 || BASISD_SUPPORT_UASTC + static const uint8_t g_etc2_eac_a8_sel4[6] = { 0x92, 0x49, 0x24, 0x92, 0x49, 0x24 }; +#endif + +#if BASISD_SUPPORT_ETC2_EAC_A8 + static void convert_etc1s_to_etc2_eac_a8(eac_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector) + { + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (low_selector == high_selector) + { + uint32_t r; + decoder_etc_block::get_block_color5_r(base_color, inten_table, low_selector, r); + + // Constant alpha block + // Select table 13, use selector 4 (0), set multiplier to 1 and base color g + pDst_block->m_base = r; + pDst_block->m_table = 13; + pDst_block->m_multiplier = 1; + + // selectors are all 4's + memcpy(pDst_block->m_selectors, g_etc2_eac_a8_sel4, sizeof(g_etc2_eac_a8_sel4)); + + return; + } + + uint32_t selector_range_table = 0; + for (selector_range_table = 0; selector_range_table < NUM_ETC2_EAC_SELECTOR_RANGES; selector_range_table++) + if ((low_selector == s_etc2_eac_selector_ranges[selector_range_table].m_low) && (high_selector == s_etc2_eac_selector_ranges[selector_range_table].m_high)) + break; + if (selector_range_table >= NUM_ETC2_EAC_SELECTOR_RANGES) + selector_range_table = 0; + + const etc1_g_to_eac_conversion* pTable_entry = &s_etc1_g_to_etc2_a8[base_color.r + inten_table * 32][selector_range_table]; + + pDst_block->m_base = pTable_entry->m_base; + pDst_block->m_table = pTable_entry->m_table_mul >> 4; + pDst_block->m_multiplier = pTable_entry->m_table_mul & 15; + + uint64_t selector_bits = 0; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + + uint32_t ds = (pTable_entry->m_trans >> (s * 3)) & 7; + + const uint32_t dst_ofs = 45 - (y + x * 4) * 3; + selector_bits |= (static_cast(ds) << dst_ofs); + } + } + + pDst_block->set_selector_bits(selector_bits); + } +#endif // BASISD_SUPPORT_ETC2_EAC_A8 + +#if BASISD_SUPPORT_ETC2_EAC_RG11 + static const etc1_g_to_eac_conversion s_etc1_g_to_etc2_r11[32 * 8][NUM_ETC2_EAC_SELECTOR_RANGES] = + { + {{0,1,3328},{0,1,3328},{0,16,457},{0,16,456}}, + {{0,226,3936},{0,226,3936},{0,17,424},{8,0,472}}, + {{6,178,4012},{6,178,4008},{0,146,501},{16,0,472}}, + {{14,178,4012},{14,178,4008},{8,146,501},{24,0,472}}, + {{23,178,4012},{23,178,4008},{17,146,501},{33,0,472}}, + {{31,178,4012},{31,178,4008},{25,146,501},{41,0,472}}, + {{39,178,4012},{39,178,4008},{33,146,501},{49,0,472}}, + {{47,178,4012},{47,178,4008},{41,146,501},{27,228,496}}, + {{56,178,4012},{56,178,4008},{50,146,501},{36,228,496}}, + {{64,178,4012},{64,178,4008},{58,146,501},{44,228,496}}, + {{72,178,4012},{72,178,4008},{66,146,501},{52,228,496}}, + {{80,178,4012},{80,178,4008},{74,146,501},{60,228,496}}, + {{89,178,4012},{89,178,4008},{83,146,501},{69,228,496}}, + {{97,178,4012},{97,178,4008},{91,146,501},{77,228,496}}, + {{105,178,4012},{105,178,4008},{99,146,501},{85,228,496}}, + {{113,178,4012},{113,178,4008},{107,146,501},{93,228,496}}, + {{122,178,4012},{122,178,4008},{116,146,501},{102,228,496}}, + {{130,178,4012},{130,178,4008},{124,146,501},{110,228,496}}, + {{138,178,4012},{138,178,4008},{132,146,501},{118,228,496}}, + {{146,178,4012},{146,178,4008},{140,146,501},{126,228,496}}, + {{155,178,4012},{155,178,4008},{149,146,501},{135,228,496}}, + {{163,178,4012},{163,178,4008},{157,146,501},{143,228,496}}, + {{171,178,4012},{171,178,4008},{165,146,501},{151,228,496}}, + {{179,178,4012},{179,178,4008},{173,146,501},{159,228,496}}, + {{188,178,4012},{188,178,4008},{182,146,501},{168,228,496}}, + {{196,178,4012},{196,178,4008},{190,146,501},{176,228,496}}, + {{204,178,4012},{204,178,4008},{198,146,501},{184,228,496}}, + {{212,178,4012},{212,178,4008},{206,146,501},{192,228,496}}, + {{221,178,4012},{221,178,4008},{215,146,501},{201,228,496}}, + {{229,178,4012},{229,178,4008},{223,146,501},{209,228,496}}, + {{235,66,4012},{221,100,4008},{231,146,501},{217,228,496}}, + {{211,102,4085},{254,32,4040},{211,102,501},{254,32,456}}, + {{0,2,3328},{0,2,3328},{0,1,320},{0,1,320}}, + {{7,162,3905},{7,162,3904},{0,17,480},{0,17,480}}, + {{15,162,3906},{15,162,3904},{1,117,352},{1,117,352}}, + {{23,162,3906},{23,162,3904},{5,34,500},{4,53,424}}, + {{32,162,3906},{32,162,3904},{14,34,500},{3,69,424}}, + {{40,162,3906},{40,162,3904},{22,34,500},{1,133,496}}, + {{48,162,3906},{48,162,3904},{30,34,500},{4,85,496}}, + {{56,162,3906},{56,162,3904},{38,34,500},{12,85,496}}, + {{65,162,3906},{65,162,3904},{47,34,500},{1,106,424}}, + {{73,162,3906},{73,162,3904},{55,34,500},{9,106,424}}, + {{81,162,3906},{81,162,3904},{63,34,500},{7,234,496}}, + {{89,162,3906},{89,162,3904},{71,34,500},{15,234,496}}, + {{98,162,3906},{98,162,3904},{80,34,500},{24,234,496}}, + {{106,162,3906},{106,162,3904},{88,34,500},{32,234,496}}, + {{114,162,3906},{114,162,3904},{96,34,500},{40,234,496}}, + {{122,162,3906},{122,162,3904},{104,34,500},{48,234,496}}, + {{131,162,3906},{131,162,3904},{113,34,500},{57,234,496}}, + {{139,162,3906},{139,162,3904},{121,34,500},{65,234,496}}, + {{147,162,3906},{147,162,3904},{129,34,500},{73,234,496}}, + {{155,162,3906},{155,162,3904},{137,34,500},{81,234,496}}, + {{164,162,3906},{164,162,3904},{146,34,500},{90,234,496}}, + {{172,162,3906},{172,162,3904},{154,34,500},{98,234,496}}, + {{180,162,3906},{180,162,3904},{162,34,500},{106,234,496}}, + {{188,162,3906},{188,162,3904},{170,34,500},{114,234,496}}, + {{197,162,3906},{197,162,3904},{179,34,500},{123,234,496}}, + {{205,162,3906},{205,162,3904},{187,34,500},{131,234,496}}, + {{213,162,3906},{213,162,3904},{195,34,500},{139,234,496}}, + {{221,162,3906},{221,162,3904},{203,34,500},{147,234,496}}, + {{230,162,3906},{230,162,3904},{212,34,500},{156,234,496}}, + {{238,162,3906},{174,106,4008},{220,34,500},{164,234,496}}, + {{240,178,4001},{182,106,4008},{228,34,500},{172,234,496}}, + {{166,108,4085},{115,31,4080},{166,108,501},{115,31,496}}, + {{1,68,3328},{1,68,3328},{0,1,384},{0,1,384}}, + {{1,51,3968},{1,51,3968},{0,2,384},{0,2,384}}, + {{21,18,3851},{21,18,3848},{1,50,488},{1,50,488}}, + {{26,195,3851},{29,18,3848},{0,67,488},{0,67,488}}, + {{35,195,3851},{38,18,3848},{12,115,488},{0,3,496}}, + {{43,195,3851},{46,18,3848},{20,115,488},{2,6,424}}, + {{51,195,3851},{54,18,3848},{36,66,482},{4,22,424}}, + {{59,195,3851},{62,18,3848},{44,66,482},{3,73,424}}, + {{68,195,3851},{71,18,3848},{53,66,482},{3,22,496}}, + {{76,195,3851},{79,18,3848},{61,66,482},{2,137,496}}, + {{84,195,3851},{87,18,3848},{69,66,482},{1,89,496}}, + {{92,195,3851},{95,18,3848},{77,66,482},{9,89,496}}, + {{101,195,3851},{104,18,3848},{86,66,482},{18,89,496}}, + {{109,195,3851},{112,18,3848},{94,66,482},{26,89,496}}, + {{117,195,3851},{120,18,3848},{102,66,482},{34,89,496}}, + {{125,195,3851},{128,18,3848},{110,66,482},{42,89,496}}, + {{134,195,3851},{137,18,3848},{119,66,482},{51,89,496}}, + {{141,195,3907},{145,18,3848},{127,66,482},{59,89,496}}, + {{149,195,3907},{153,18,3848},{135,66,482},{67,89,496}}, + {{157,195,3907},{161,18,3848},{143,66,482},{75,89,496}}, + {{166,195,3907},{170,18,3848},{152,66,482},{84,89,496}}, + {{174,195,3907},{178,18,3848},{160,66,482},{92,89,496}}, + {{182,195,3907},{186,18,3848},{168,66,482},{100,89,496}}, + {{190,195,3907},{194,18,3848},{176,66,482},{108,89,496}}, + {{199,195,3907},{203,18,3848},{185,66,482},{117,89,496}}, + {{207,195,3907},{211,18,3848},{193,66,482},{125,89,496}}, + {{215,195,3907},{219,18,3848},{201,66,482},{133,89,496}}, + {{223,195,3907},{227,18,3848},{209,66,482},{141,89,496}}, + {{232,195,3907},{168,89,4008},{218,66,482},{150,89,496}}, + {{236,18,3907},{176,89,4008},{226,66,482},{158,89,496}}, + {{158,90,4085},{103,31,4080},{158,90,501},{103,31,496}}, + {{166,90,4085},{111,31,4080},{166,90,501},{111,31,496}}, + {{0,70,3328},{0,70,3328},{0,17,448},{0,17,448}}, + {{0,117,3904},{0,117,3904},{0,35,384},{0,35,384}}, + {{13,165,3905},{13,165,3904},{2,211,480},{2,211,480}}, + {{21,165,3906},{21,165,3904},{1,51,488},{1,51,488}}, + {{30,165,3906},{30,165,3904},{7,61,352},{7,61,352}}, + {{38,165,3906},{38,165,3904},{2,125,352},{2,125,352}}, + {{46,165,3906},{46,165,3904},{1,37,500},{10,125,352}}, + {{54,165,3906},{54,165,3904},{9,37,500},{5,61,424}}, + {{63,165,3906},{63,165,3904},{18,37,500},{1,189,424}}, + {{71,165,3906},{71,165,3904},{26,37,500},{9,189,424}}, + {{79,165,3906},{79,165,3904},{34,37,500},{4,77,424}}, + {{87,165,3906},{87,165,3904},{42,37,500},{12,77,424}}, + {{96,165,3906},{96,165,3904},{51,37,500},{8,93,424}}, + {{104,165,3906},{104,165,3904},{59,37,500},{3,141,496}}, + {{112,165,3906},{112,165,3904},{68,37,500},{11,141,496}}, + {{120,165,3906},{120,165,3904},{76,37,500},{6,93,496}}, + {{129,165,3906},{129,165,3904},{85,37,500},{15,93,496}}, + {{70,254,4012},{137,165,3904},{93,37,500},{23,93,496}}, + {{145,165,3906},{145,165,3904},{101,37,500},{31,93,496}}, + {{86,254,4012},{153,165,3904},{109,37,500},{39,93,496}}, + {{163,165,3906},{162,165,3904},{118,37,500},{48,93,496}}, + {{171,165,3906},{170,165,3904},{126,37,500},{56,93,496}}, + {{179,165,3906},{178,165,3904},{134,37,500},{64,93,496}}, + {{187,165,3906},{187,165,3904},{142,37,500},{72,93,496}}, + {{196,165,3906},{196,165,3904},{151,37,500},{81,93,496}}, + {{204,165,3906},{204,165,3904},{159,37,500},{89,93,496}}, + {{212,165,3906},{136,77,4008},{167,37,500},{97,93,496}}, + {{220,165,3906},{131,93,4008},{175,37,500},{105,93,496}}, + {{214,181,4001},{140,93,4008},{184,37,500},{114,93,496}}, + {{222,181,4001},{148,93,4008},{192,37,500},{122,93,496}}, + {{115,95,4085},{99,31,4080},{115,95,501},{99,31,496}}, + {{123,95,4085},{107,31,4080},{123,95,501},{107,31,496}}, + {{0,102,3840},{0,102,3840},{0,18,384},{0,18,384}}, + {{5,167,3904},{5,167,3904},{0,13,256},{0,13,256}}, + {{4,54,3968},{4,54,3968},{1,67,448},{1,67,448}}, + {{30,198,3850},{30,198,3848},{0,3,480},{0,3,480}}, + {{39,198,3850},{39,198,3848},{3,52,488},{3,52,488}}, + {{47,198,3851},{47,198,3848},{3,4,488},{3,4,488}}, + {{55,198,3851},{55,198,3848},{1,70,488},{1,70,488}}, + {{53,167,3906},{63,198,3848},{3,22,488},{3,22,488}}, + {{62,167,3906},{72,198,3848},{24,118,488},{0,6,496}}, + {{70,167,3906},{80,198,3848},{32,118,488},{2,89,488}}, + {{78,167,3906},{88,198,3848},{40,118,488},{1,73,496}}, + {{86,167,3906},{96,198,3848},{48,118,488},{0,28,424}}, + {{95,167,3906},{105,198,3848},{57,118,488},{9,28,424}}, + {{103,167,3906},{113,198,3848},{65,118,488},{5,108,496}}, + {{111,167,3906},{121,198,3848},{73,118,488},{13,108,496}}, + {{119,167,3906},{129,198,3848},{81,118,488},{21,108,496}}, + {{128,167,3906},{138,198,3848},{90,118,488},{6,28,496}}, + {{136,167,3906},{146,198,3848},{98,118,488},{14,28,496}}, + {{145,167,3906},{154,198,3848},{106,118,488},{22,28,496}}, + {{153,167,3906},{162,198,3848},{114,118,488},{30,28,496}}, + {{162,167,3906},{171,198,3848},{123,118,488},{39,28,496}}, + {{170,167,3906},{179,198,3848},{131,118,488},{47,28,496}}, + {{178,167,3906},{187,198,3848},{139,118,488},{55,28,496}}, + {{186,167,3906},{195,198,3848},{147,118,488},{63,28,496}}, + {{194,167,3906},{120,12,4008},{156,118,488},{72,28,496}}, + {{206,198,3907},{116,28,4008},{164,118,488},{80,28,496}}, + {{214,198,3907},{124,28,4008},{172,118,488},{88,28,496}}, + {{222,198,3395},{132,28,4008},{180,118,488},{96,28,496}}, + {{207,134,4001},{141,28,4008},{189,118,488},{105,28,496}}, + {{95,30,4085},{86,31,4080},{95,30,501},{86,31,496}}, + {{103,30,4085},{94,31,4080},{103,30,501},{94,31,496}}, + {{111,30,4085},{102,31,4080},{111,30,501},{102,31,496}}, + {{0,104,3840},{0,104,3840},{0,18,448},{0,18,448}}, + {{4,39,3904},{4,39,3904},{0,4,384},{0,4,384}}, + {{0,56,3968},{0,56,3968},{0,84,448},{0,84,448}}, + {{6,110,3328},{6,110,3328},{0,20,448},{0,20,448}}, + {{41,200,3850},{41,200,3848},{1,4,480},{1,4,480}}, + {{49,200,3850},{49,200,3848},{1,8,416},{1,8,416}}, + {{57,200,3851},{57,200,3848},{1,38,488},{1,38,488}}, + {{65,200,3851},{65,200,3848},{1,120,488},{1,120,488}}, + {{74,200,3851},{74,200,3848},{2,72,488},{2,72,488}}, + {{68,6,3907},{82,200,3848},{2,24,488},{2,24,488}}, + {{77,6,3907},{90,200,3848},{26,120,488},{10,24,488}}, + {{97,63,3330},{98,200,3848},{34,120,488},{2,8,496}}, + {{106,63,3330},{107,200,3848},{43,120,488},{3,92,488}}, + {{114,63,3330},{115,200,3848},{51,120,488},{11,92,488}}, + {{122,63,3330},{123,200,3848},{59,120,488},{7,76,496}}, + {{130,63,3330},{131,200,3848},{67,120,488},{15,76,496}}, + {{139,63,3330},{140,200,3848},{76,120,488},{24,76,496}}, + {{147,63,3330},{148,200,3848},{84,120,488},{32,76,496}}, + {{155,63,3330},{156,200,3848},{92,120,488},{40,76,496}}, + {{164,63,3330},{164,200,3848},{100,120,488},{48,76,496}}, + {{173,63,3330},{173,200,3848},{109,120,488},{57,76,496}}, + {{184,6,3851},{181,200,3848},{117,120,488},{65,76,496}}, + {{192,6,3851},{133,28,3936},{125,120,488},{73,76,496}}, + {{189,200,3907},{141,28,3936},{133,120,488},{81,76,496}}, + {{198,200,3907},{138,108,4000},{142,120,488},{90,76,496}}, + {{206,200,3907},{146,108,4000},{150,120,488},{98,76,496}}, + {{214,200,3395},{154,108,4000},{158,120,488},{106,76,496}}, + {{190,136,4001},{162,108,4000},{166,120,488},{114,76,496}}, + {{123,30,4076},{87,15,4080},{123,30,492},{87,15,496}}, + {{117,110,4084},{80,31,4080},{117,110,500},{80,31,496}}, + {{125,110,4084},{88,31,4080},{125,110,500},{88,31,496}}, + {{133,110,4084},{96,31,4080},{133,110,500},{96,31,496}}, + {{9,56,3904},{9,56,3904},{0,67,448},{0,67,448}}, + {{1,8,3904},{1,8,3904},{1,84,448},{1,84,448}}, + {{1,124,3904},{1,124,3904},{0,39,384},{0,39,384}}, + {{9,124,3904},{9,124,3904},{1,4,448},{1,4,448}}, + {{6,76,3904},{6,76,3904},{0,70,448},{0,70,448}}, + {{62,6,3859},{62,6,3856},{2,38,480},{2,38,480}}, + {{70,6,3859},{70,6,3856},{5,43,416},{5,43,416}}, + {{78,6,3859},{78,6,3856},{2,11,416},{2,11,416}}, + {{87,6,3859},{87,6,3856},{0,171,488},{0,171,488}}, + {{67,8,3906},{95,6,3856},{8,171,488},{8,171,488}}, + {{75,8,3907},{103,6,3856},{5,123,488},{5,123,488}}, + {{83,8,3907},{111,6,3856},{2,75,488},{2,75,488}}, + {{92,8,3907},{120,6,3856},{0,27,488},{0,27,488}}, + {{100,8,3907},{128,6,3856},{8,27,488},{8,27,488}}, + {{120,106,3843},{136,6,3856},{99,6,387},{16,27,488}}, + {{128,106,3843},{144,6,3856},{107,6,387},{2,11,496}}, + {{137,106,3843},{153,6,3856},{117,6,387},{11,11,496}}, + {{145,106,3843},{161,6,3856},{125,6,387},{19,11,496}}, + {{163,8,3851},{137,43,3904},{133,6,387},{27,11,496}}, + {{171,8,3851},{145,43,3904},{141,6,387},{35,11,496}}, + {{180,8,3851},{110,11,4000},{150,6,387},{44,11,496}}, + {{188,8,3851},{118,11,4000},{158,6,387},{52,11,496}}, + {{172,72,3907},{126,11,4000},{166,6,387},{60,11,496}}, + {{174,6,3971},{134,11,4000},{174,6,387},{68,11,496}}, + {{183,6,3971},{143,11,4000},{183,6,387},{77,11,496}}, + {{191,6,3971},{151,11,4000},{191,6,387},{85,11,496}}, + {{199,6,3971},{159,11,4000},{199,6,387},{93,11,496}}, + {{92,12,4084},{69,15,4080},{92,12,500},{69,15,496}}, + {{101,12,4084},{78,15,4080},{101,12,500},{78,15,496}}, + {{110,12,4084},{86,15,4080},{110,12,500},{86,15,496}}, + {{118,12,4084},{79,31,4080},{118,12,500},{79,31,496}}, + {{126,12,4084},{87,31,4080},{126,12,500},{87,31,496}}, + {{71,8,3602},{71,8,3600},{2,21,384},{2,21,384}}, + {{79,8,3611},{79,8,3608},{0,69,448},{0,69,448}}, + {{87,8,3611},{87,8,3608},{0,23,384},{0,23,384}}, + {{95,8,3611},{95,8,3608},{1,5,448},{1,5,448}}, + {{104,8,3611},{104,8,3608},{0,88,448},{0,88,448}}, + {{112,8,3611},{112,8,3608},{0,72,448},{0,72,448}}, + {{120,8,3611},{121,8,3608},{36,21,458},{36,21,456}}, + {{133,47,3091},{129,8,3608},{44,21,458},{44,21,456}}, + {{142,47,3091},{138,8,3608},{53,21,459},{53,21,456}}, + {{98,12,3850},{98,12,3848},{61,21,459},{61,21,456}}, + {{106,12,3850},{106,12,3848},{10,92,480},{69,21,456}}, + {{114,12,3851},{114,12,3848},{18,92,480},{77,21,456}}, + {{123,12,3851},{123,12,3848},{3,44,488},{86,21,456}}, + {{95,12,3906},{95,12,3904},{11,44,488},{94,21,456}}, + {{103,12,3906},{103,12,3904},{19,44,488},{102,21,456}}, + {{111,12,3907},{111,12,3904},{27,44,489},{110,21,456}}, + {{120,12,3907},{120,12,3904},{36,44,489},{119,21,456}}, + {{128,12,3907},{128,12,3904},{44,44,489},{127,21,456}}, + {{136,12,3907},{136,12,3904},{52,44,489},{135,21,456}}, + {{144,12,3907},{144,12,3904},{60,44,490},{144,21,456}}, + {{153,12,3907},{153,12,3904},{69,44,490},{153,21,456}}, + {{161,12,3395},{149,188,3968},{77,44,490},{161,21,456}}, + {{169,12,3395},{199,21,3928},{85,44,490},{169,21,456}}, + {{113,95,4001},{202,69,3992},{125,8,483},{177,21,456}}, + {{122,95,4001},{201,21,3984},{134,8,483},{186,21,456}}, + {{143,8,4067},{209,21,3984},{142,8,483},{194,21,456}}, + {{151,8,4067},{47,15,4080},{151,8,483},{47,15,496}}, + {{159,8,4067},{55,15,4080},{159,8,483},{55,15,496}}, + {{168,8,4067},{64,15,4080},{168,8,483},{64,15,496}}, + {{160,40,4075},{72,15,4080},{160,40,491},{72,15,496}}, + {{168,40,4075},{80,15,4080},{168,40,491},{80,15,496}}, + {{144,8,4082},{88,15,4080},{144,8,498},{88,15,496}}, + }; + + static void convert_etc1s_to_etc2_eac_r11(eac_block* pDst_block, const endpoint* pEndpoints, const selector* pSelector) + { + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (low_selector == high_selector) + { + uint32_t r; + decoder_etc_block::get_block_color5_r(base_color, inten_table, low_selector, r); + + // Constant alpha block + // Select table 13, use selector 4 (0), set multiplier to 1 and base color r + pDst_block->m_base = r; + pDst_block->m_table = 13; + pDst_block->m_multiplier = 1; + + // selectors are all 4's + static const uint8_t s_etc2_eac_r11_sel4[6] = { 0x92, 0x49, 0x24, 0x92, 0x49, 0x24 }; + memcpy(pDst_block->m_selectors, s_etc2_eac_r11_sel4, sizeof(s_etc2_eac_r11_sel4)); + + return; + } + + uint32_t selector_range_table = 0; + for (selector_range_table = 0; selector_range_table < NUM_ETC2_EAC_SELECTOR_RANGES; selector_range_table++) + if ((low_selector == s_etc2_eac_selector_ranges[selector_range_table].m_low) && (high_selector == s_etc2_eac_selector_ranges[selector_range_table].m_high)) + break; + if (selector_range_table >= NUM_ETC2_EAC_SELECTOR_RANGES) + selector_range_table = 0; + + const etc1_g_to_eac_conversion* pTable_entry = &s_etc1_g_to_etc2_r11[base_color.r + inten_table * 32][selector_range_table]; + + pDst_block->m_base = pTable_entry->m_base; + pDst_block->m_table = pTable_entry->m_table_mul >> 4; + pDst_block->m_multiplier = pTable_entry->m_table_mul & 15; + + uint64_t selector_bits = 0; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + + uint32_t ds = (pTable_entry->m_trans >> (s * 3)) & 7; + + const uint32_t dst_ofs = 45 - (y + x * 4) * 3; + selector_bits |= (static_cast(ds) << dst_ofs); + } + } + + pDst_block->set_selector_bits(selector_bits); + } +#endif // BASISD_SUPPORT_ETC2_EAC_RG11 + +// ASTC + struct etc1_to_astc_solution + { + uint8_t m_lo; + uint8_t m_hi; + uint16_t m_err; + }; + +#if BASISD_SUPPORT_ASTC + static dxt_selector_range g_etc1_to_astc_selector_ranges[] = + { + { 0, 3 }, + + { 1, 3 }, + { 0, 2 }, + + { 1, 2 }, + + { 2, 3 }, + { 0, 1 }, + }; + + const uint32_t NUM_ETC1_TO_ASTC_SELECTOR_RANGES = sizeof(g_etc1_to_astc_selector_ranges) / sizeof(g_etc1_to_astc_selector_ranges[0]); + + static uint32_t g_etc1_to_astc_selector_range_index[4][4]; + + const uint32_t NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS = 10; + static const uint8_t g_etc1_to_astc_selector_mappings[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS][4] = + { + { 0, 0, 1, 1 }, + { 0, 0, 1, 2 }, + { 0, 0, 1, 3 }, + { 0, 0, 2, 3 }, + { 0, 1, 1, 1 }, + { 0, 1, 2, 2 }, + { 0, 1, 2, 3 }, + { 0, 2, 3, 3 }, + { 1, 2, 2, 2 }, + { 1, 2, 3, 3 }, + }; + + static const etc1_to_astc_solution g_etc1_to_astc[32 * 8 * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS * NUM_ETC1_TO_ASTC_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_astc.inc" + }; + + // The best selector mapping to use given a base base+inten table and used selector range for converting grayscale data. + static uint8_t g_etc1_to_astc_best_grayscale_mapping[32][8][NUM_ETC1_TO_ASTC_SELECTOR_RANGES]; + +#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY + static const etc1_to_astc_solution g_etc1_to_astc_0_255[32 * 8 * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS * NUM_ETC1_TO_ASTC_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_astc_0_255.inc" + }; + static uint8_t g_etc1_to_astc_best_grayscale_mapping_0_255[32][8][NUM_ETC1_TO_ASTC_SELECTOR_RANGES]; +#endif + + static uint32_t g_ise_to_unquant[48]; + +#if BASISD_WRITE_NEW_ASTC_TABLES + static void create_etc1_to_astc_conversion_table_0_47() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_astc.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1_to_astc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1_to_astc_selector_ranges[sr].m_high; + + uint32_t mapping_best_low[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + uint32_t mapping_best_high[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + uint64_t mapping_best_err[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + uint64_t highest_best_err = 0; + + for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 47; hi++) + { + for (uint32_t lo = 0; lo <= 47; lo++) + { + uint32_t colors[4]; + + for (uint32_t s = 0; s < 4; s++) + { + uint32_t s_scaled = s | (s << 2) | (s << 4); + if (s_scaled > 32) + s_scaled++; + + uint32_t c0 = g_ise_to_unquant[lo] | (g_ise_to_unquant[lo] << 8); + uint32_t c1 = g_ise_to_unquant[hi] | (g_ise_to_unquant[hi] << 8); + colors[s] = ((c0 * (64 - s_scaled) + c1 * s_scaled + 32) / 64) >> 8; + } + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1_to_astc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 8; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + mapping_best_low[m] = best_lo; + mapping_best_high[m] = best_hi; + mapping_best_err[m] = best_err; + highest_best_err = basisu::maximum(highest_best_err, best_err); + + } // m + + for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++) + { + uint64_t err = mapping_best_err[m]; + + err = basisu::minimum(err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", mapping_best_low[m], mapping_best_high[m], (uint32_t)err); + + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + + } // sr + } // g + } // inten + + fclose(pFile); + } + + static void create_etc1_to_astc_conversion_table_0_255() + { + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_astc_0_255.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1_to_astc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1_to_astc_selector_ranges[sr].m_high; + + uint32_t mapping_best_low[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + uint32_t mapping_best_high[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + uint64_t mapping_best_err[NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + uint64_t highest_best_err = 0; + + for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 255; hi++) + { + for (uint32_t lo = 0; lo <= 255; lo++) + { + uint32_t colors[4]; + + for (uint32_t s = 0; s < 4; s++) + { + uint32_t s_scaled = s | (s << 2) | (s << 4); + if (s_scaled > 32) + s_scaled++; + + uint32_t c0 = lo | (lo << 8); + uint32_t c1 = hi | (hi << 8); + colors[s] = ((c0 * (64 - s_scaled) + c1 * s_scaled + 32) / 64) >> 8; + } + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1_to_astc_selector_mappings[m][s]]; + + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + int err_scale = 1; + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 8; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + mapping_best_low[m] = best_lo; + mapping_best_high[m] = best_hi; + mapping_best_err[m] = best_err; + highest_best_err = basisu::maximum(highest_best_err, best_err); + } // m + + for (uint32_t m = 0; m < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; m++) + { + uint64_t err = mapping_best_err[m]; + + err = basisu::minimum(err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", mapping_best_low[m], mapping_best_high[m], (uint32_t)err); + + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + + } // sr + } // g + } // inten + + fclose(pFile); + } +#endif + +#endif + +#if BASISD_SUPPORT_UASTC || BASISD_SUPPORT_ASTC + // Table encodes 5 trits to 8 output bits. 3^5 entries. + // Inverse of the trit bit manipulation process in https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-integer-sequence-encoding + static const uint8_t g_astc_trit_encode[243] = { 0, 1, 2, 4, 5, 6, 8, 9, 10, 16, 17, 18, 20, 21, 22, 24, 25, 26, 3, 7, 11, 19, 23, 27, 12, 13, 14, 32, 33, 34, 36, 37, 38, 40, 41, 42, 48, 49, 50, 52, 53, 54, 56, 57, 58, 35, 39, + 43, 51, 55, 59, 44, 45, 46, 64, 65, 66, 68, 69, 70, 72, 73, 74, 80, 81, 82, 84, 85, 86, 88, 89, 90, 67, 71, 75, 83, 87, 91, 76, 77, 78, 128, 129, 130, 132, 133, 134, 136, 137, 138, 144, 145, 146, 148, 149, 150, 152, 153, 154, + 131, 135, 139, 147, 151, 155, 140, 141, 142, 160, 161, 162, 164, 165, 166, 168, 169, 170, 176, 177, 178, 180, 181, 182, 184, 185, 186, 163, 167, 171, 179, 183, 187, 172, 173, 174, 192, 193, 194, 196, 197, 198, 200, 201, 202, + 208, 209, 210, 212, 213, 214, 216, 217, 218, 195, 199, 203, 211, 215, 219, 204, 205, 206, 96, 97, 98, 100, 101, 102, 104, 105, 106, 112, 113, 114, 116, 117, 118, 120, 121, 122, 99, 103, 107, 115, 119, 123, 108, 109, 110, 224, + 225, 226, 228, 229, 230, 232, 233, 234, 240, 241, 242, 244, 245, 246, 248, 249, 250, 227, 231, 235, 243, 247, 251, 236, 237, 238, 28, 29, 30, 60, 61, 62, 92, 93, 94, 156, 157, 158, 188, 189, 190, 220, 221, 222, 31, 63, 95, 159, + 191, 223, 124, 125, 126 }; + + // Extracts bits [low,high] + static inline uint32_t astc_extract_bits(uint32_t bits, int low, int high) + { + return (bits >> low) & ((1 << (high - low + 1)) - 1); + } + + // Writes bits to output in an endian safe way + static inline void astc_set_bits(uint32_t* pOutput, int& bit_pos, uint32_t value, uint32_t total_bits) + { + uint8_t* pBytes = reinterpret_cast(pOutput); + + while (total_bits) + { + const uint32_t bits_to_write = basisu::minimum(total_bits, 8 - (bit_pos & 7)); + + pBytes[bit_pos >> 3] |= static_cast(value << (bit_pos & 7)); + + bit_pos += bits_to_write; + total_bits -= bits_to_write; + value >>= bits_to_write; + } + } + + // Encodes 5 values to output, usable for any range that uses trits and bits + static void astc_encode_trits(uint32_t* pOutput, const uint8_t* pValues, int& bit_pos, int n) + { + // First extract the trits and the bits from the 5 input values + int trits = 0, bits[5]; + const uint32_t bit_mask = (1 << n) - 1; + for (int i = 0; i < 5; i++) + { + static const int s_muls[5] = { 1, 3, 9, 27, 81 }; + + const int t = pValues[i] >> n; + + trits += t * s_muls[i]; + bits[i] = pValues[i] & bit_mask; + } + + // Encode the trits, by inverting the bit manipulations done by the decoder, converting 5 trits into 8-bits. + // See https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-integer-sequence-encoding + + assert(trits < 243); + const int T = g_astc_trit_encode[trits]; + + // Now interleave the 8 encoded trit bits with the bits to form the encoded output. See table 94. + astc_set_bits(pOutput, bit_pos, bits[0] | (astc_extract_bits(T, 0, 1) << n) | (bits[1] << (2 + n)), n * 2 + 2); + + astc_set_bits(pOutput, bit_pos, astc_extract_bits(T, 2, 3) | (bits[2] << 2) | (astc_extract_bits(T, 4, 4) << (2 + n)) | (bits[3] << (3 + n)) | (astc_extract_bits(T, 5, 6) << (3 + n * 2)) | + (bits[4] << (5 + n * 2)) | (astc_extract_bits(T, 7, 7) << (5 + n * 3)), n * 3 + 6); + } +#endif // #if BASISD_SUPPORT_UASTC || BASISD_SUPPORT_ASTC + +#if BASISD_SUPPORT_ASTC + struct astc_block_params + { + // 2 groups of 5, but only a max of 8 are used (RRGGBBAA00) + uint8_t m_endpoints[10]; + uint8_t m_weights[32]; + }; + + // Packs a single format ASTC block using Color Endpoint Mode 12 (LDR RGBA direct), endpoint BISE range 13, 2-bit weights (range 2). + // We're always going to output blocks containing alpha, even if the input doesn't have alpha, for simplicity. + // Each block always has 4x4 weights, uses range 13 BISE encoding on the endpoints (0-47), and each weight ranges from 0-3. This encoding should be roughly equal in quality vs. BC1 for color. + // 8 total endpoints, stored as RGBA LH LH LH LH order, each ranging from 0-47. + // Note the input [0,47] endpoint values are not linear - they are encoded as outlined in the ASTC spec: + // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-endpoint-unquantization + // 32 total weights, stored as 16 CA CA, each ranging from 0-3. + static void astc_pack_block_cem_12_weight_range2(uint32_t *pOutput, const astc_block_params* pBlock) + { + uint8_t* pBytes = reinterpret_cast(pOutput); + + // Write constant block mode, color component selector, number of partitions, color endpoint mode + // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode + pBytes[0] = 0x42; pBytes[1] = 0x84; pBytes[2] = 0x01; pBytes[3] = 0x00; + pBytes[4] = 0x00; pBytes[5] = 0x00; pBytes[6] = 0x00; pBytes[7] = 0xc0; + + pOutput[2] = 0; + pOutput[3] = 0; + + // Pack 8 endpoints (each ranging between [0,47]) using BISE starting at bit 17 + int bit_pos = 17; + astc_encode_trits(pOutput, pBlock->m_endpoints, bit_pos, 4); + astc_encode_trits(pOutput, pBlock->m_endpoints + 5, bit_pos, 4); + + // Pack 32 2-bit weights, which are stored from the top down into the block in opposite bit order. + + for (uint32_t i = 0; i < 32; i++) + { + static const uint8_t s_reverse_bits[4] = { 0, 2, 1, 3 }; + const uint32_t ofs = 126 - (i * 2); + pBytes[ofs >> 3] |= (s_reverse_bits[pBlock->m_weights[i]] << (ofs & 7)); + } + } + + // CEM mode 12 (LDR RGBA Direct), 8-bit endpoints, 1-bit weights + // This ASTC mode is basically block truncation coding (BTC) using 1-bit weights and 8-bit/component endpoints - very convenient. + static void astc_pack_block_cem_12_weight_range0(uint32_t* pOutput, const astc_block_params* pBlock) + { + uint8_t* pBytes = reinterpret_cast(pOutput); + + // Write constant block mode, color component selector, number of partitions, color endpoint mode + // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode + pBytes[0] = 0x41; pBytes[1] = 0x84; pBytes[2] = 0x01; pBytes[3] = 0x00; + pOutput[1] = 0; + pBytes[8] = 0x00; pBytes[9] = 0x00; pBytes[10] = 0x00; pBytes[11] = 0xc0; + pOutput[3] = 0; + + // Pack 8 endpoints (each ranging between [0,255]) as 8-bits starting at bit 17 + int bit_pos = 17; + for (uint32_t i = 0; i < 8; i++) + astc_set_bits(pOutput, bit_pos, pBlock->m_endpoints[i], 8); + + // Pack 32 1-bit weights, which are stored from the top down into the block in opposite bit order. + for (uint32_t i = 0; i < 32; i++) + { + const uint32_t ofs = 127 - i; + pBytes[ofs >> 3] |= (pBlock->m_weights[i] << (ofs & 7)); + } + } + +#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY + // Optional 8-bit endpoint packing functions. + + // CEM mode 4 (LDR Luminance+Alpha Direct), 8-bit endpoints, 2 bit weights + static void astc_pack_block_cem_4_weight_range2(uint32_t* pOutput, const astc_block_params* pBlock) + { + uint8_t* pBytes = reinterpret_cast(pOutput); + + // Write constant block mode, color component selector, number of partitions, color endpoint mode + // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode + pBytes[0] = 0x42; pBytes[1] = 0x84; pBytes[2] = 0x00; pBytes[3] = 0x00; + pBytes[4] = 0x00; pBytes[5] = 0x00; pBytes[6] = 0x00; pBytes[7] = 0xc0; + + pOutput[2] = 0; + pOutput[3] = 0; + + // Pack 4 endpoints (each ranging between [0,255]) as 8-bits starting at bit 17 + int bit_pos = 17; + for (uint32_t i = 0; i < 4; i++) + astc_set_bits(pOutput, bit_pos, pBlock->m_endpoints[i], 8); + + // Pack 32 2-bit weights, which are stored from the top down into the block in opposite bit order. + for (uint32_t i = 0; i < 32; i++) + { + static const uint8_t s_reverse_bits[4] = { 0, 2, 1, 3 }; + const uint32_t ofs = 126 - (i * 2); + pBytes[ofs >> 3] |= (s_reverse_bits[pBlock->m_weights[i]] << (ofs & 7)); + } + } + + // CEM mode 8 (LDR RGB Direct), 8-bit endpoints, 2 bit weights + static void astc_pack_block_cem_8_weight_range2(uint32_t* pOutput, const astc_block_params* pBlock) + { + uint8_t* pBytes = reinterpret_cast(pOutput); + + // Write constant block mode, color component selector, number of partitions, color endpoint mode + // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#_block_mode + pBytes[0] = 0x42; pBytes[1] = 0x00; pBytes[2] = 0x01; pBytes[3] = 0x00; + + pOutput[1] = 0; + pOutput[2] = 0; + pOutput[3] = 0; + + // Pack 6 endpoints (each ranging between [0,255]) as 8-bits starting at bit 17 + int bit_pos = 17; + for (uint32_t i = 0; i < 6; i++) + astc_set_bits(pOutput, bit_pos, pBlock->m_endpoints[i], 8); + + // Pack 16 2-bit weights, which are stored from the top down into the block in opposite bit order. + for (uint32_t i = 0; i < 16; i++) + { + static const uint8_t s_reverse_bits[4] = { 0, 2, 1, 3 }; + const uint32_t ofs = 126 - (i * 2); + pBytes[ofs >> 3] |= (s_reverse_bits[pBlock->m_weights[i]] << (ofs & 7)); + } + } +#endif + + // Optimal quantized [0,47] entry to use given [0,255] input + static uint8_t g_astc_single_color_encoding_0[256]; + + // Optimal quantized [0,47] low/high values given [0,255] input assuming a selector of 1 + static struct + { + uint8_t m_lo, m_hi; + } g_astc_single_color_encoding_1[256]; + + static void transcoder_init_astc() + { + for (uint32_t base_color = 0; base_color < 32; base_color++) + { + for (uint32_t inten_table = 0; inten_table < 8; inten_table++) + { + for (uint32_t range_index = 0; range_index < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; range_index++) + { + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc[(inten_table * 32 + base_color) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + range_index * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + uint32_t best_mapping = 0; + uint32_t best_err = UINT32_MAX; + for (uint32_t mapping_index = 0; mapping_index < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; mapping_index++) + { + if (pTable_g[mapping_index].m_err < best_err) + { + best_err = pTable_g[mapping_index].m_err; + best_mapping = mapping_index; + } + } + + g_etc1_to_astc_best_grayscale_mapping[base_color][inten_table][range_index] = static_cast(best_mapping); + } + } + } + +#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY + for (uint32_t base_color = 0; base_color < 32; base_color++) + { + for (uint32_t inten_table = 0; inten_table < 8; inten_table++) + { + for (uint32_t range_index = 0; range_index < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; range_index++) + { + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + range_index * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + uint32_t best_mapping = 0; + uint32_t best_err = UINT32_MAX; + for (uint32_t mapping_index = 0; mapping_index < NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS; mapping_index++) + { + if (pTable_g[mapping_index].m_err < best_err) + { + best_err = pTable_g[mapping_index].m_err; + best_mapping = mapping_index; + } + } + + g_etc1_to_astc_best_grayscale_mapping_0_255[base_color][inten_table][range_index] = static_cast(best_mapping); + } + } + } +#endif + + for (uint32_t i = 0; i < NUM_ETC1_TO_ASTC_SELECTOR_RANGES; i++) + { + uint32_t l = g_etc1_to_astc_selector_ranges[i].m_low; + uint32_t h = g_etc1_to_astc_selector_ranges[i].m_high; + g_etc1_to_astc_selector_range_index[l][h] = i; + } + + // Endpoint dequantization, see: + // https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-endpoint-unquantization + for (uint32_t trit = 0; trit < 3; trit++) + { + for (uint32_t bit = 0; bit < 16; bit++) + { + const uint32_t A = (bit & 1) ? 511 : 0; + const uint32_t B = (bit >> 1) | ((bit >> 1) << 6); + const uint32_t C = 22; + const uint32_t D = trit; + + uint32_t unq = D * C + B; + unq = unq ^ A; + unq = (A & 0x80) | (unq >> 2); + + g_ise_to_unquant[bit | (trit << 4)] = unq; + } + } + + // Compute table used for optimal single color encoding. + for (int i = 0; i < 256; i++) + { + int lowest_e = INT_MAX; + + for (int lo = 0; lo < 48; lo++) + { + for (int hi = 0; hi < 48; hi++) + { + const int lo_v = g_ise_to_unquant[lo]; + const int hi_v = g_ise_to_unquant[hi]; + + int l = lo_v | (lo_v << 8); + int h = hi_v | (hi_v << 8); + + int v = ((l * (64 - 21) + (h * 21) + 32) / 64) >> 8; + + int e = abs(v - i); + + if (e < lowest_e) + { + g_astc_single_color_encoding_1[i].m_hi = static_cast(hi); + g_astc_single_color_encoding_1[i].m_lo = static_cast(lo); + + lowest_e = e; + } + + } // hi + } // lo + } + + for (int i = 0; i < 256; i++) + { + int lowest_e = INT_MAX; + + for (int lo = 0; lo < 48; lo++) + { + const int lo_v = g_ise_to_unquant[lo]; + + int e = abs(lo_v - i); + + if (e < lowest_e) + { + g_astc_single_color_encoding_0[i] = static_cast(lo); + + lowest_e = e; + } + } // lo + } + } + + // Converts opaque or color+alpha ETC1S block to ASTC 4x4. + // This function tries to use the best ASTC mode given the block's actual contents. + static void convert_etc1s_to_astc_4x4(void* pDst_block, const endpoint* pEndpoints, const selector* pSelector, + bool transcode_alpha, const endpoint *pEndpoint_codebook, const selector *pSelector_codebook) + { + astc_block_params blk; + + blk.m_endpoints[8] = 0; + blk.m_endpoints[9] = 0; + + int constant_alpha_val = 255; + int num_unique_alpha_selectors = 1; + + if (transcode_alpha) + { + const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]]; + + num_unique_alpha_selectors = alpha_selectors.m_num_unique_selectors; + + if (num_unique_alpha_selectors == 1) + { + const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]]; + + const color32& alpha_base_color = alpha_endpoint.m_color5; + const uint32_t alpha_inten_table = alpha_endpoint.m_inten5; + + int alpha_block_colors[4]; + decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table); + + constant_alpha_val = alpha_block_colors[alpha_selectors.m_lo_selector]; + } + } + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + // Handle solid color or BTC blocks, which can always be encoded from ETC1S to ASTC losslessly. + if ((pSelector->m_num_unique_selectors == 1) && (num_unique_alpha_selectors == 1)) + { + // Both color and alpha are constant, write a solid color block and exit. + // See https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-void-extent-blocks + uint32_t r, g, b; + decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b); + + uint32_t* pOutput = static_cast(pDst_block); + uint8_t* pBytes = reinterpret_cast(pDst_block); + + pBytes[0] = 0xfc; pBytes[1] = 0xfd; pBytes[2] = 0xff; pBytes[3] = 0xff; + + pOutput[1] = 0xffffffff; + pOutput[2] = 0; + pOutput[3] = 0; + + int bit_pos = 64; + astc_set_bits(pOutput, bit_pos, r | (r << 8), 16); + astc_set_bits(pOutput, bit_pos, g | (g << 8), 16); + astc_set_bits(pOutput, bit_pos, b | (b << 8), 16); + astc_set_bits(pOutput, bit_pos, constant_alpha_val | (constant_alpha_val << 8), 16); + + return; + } + else if ((pSelector->m_num_unique_selectors <= 2) && (num_unique_alpha_selectors <= 2)) + { + // Both color and alpha use <= 2 unique selectors each. + // Use block truncation coding, which is lossless with ASTC (8-bit endpoints, 1-bit weights). + color32 block_colors[4]; + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + blk.m_endpoints[0] = block_colors[low_selector].r; + blk.m_endpoints[2] = block_colors[low_selector].g; + blk.m_endpoints[4] = block_colors[low_selector].b; + + blk.m_endpoints[1] = block_colors[high_selector].r; + blk.m_endpoints[3] = block_colors[high_selector].g; + blk.m_endpoints[5] = block_colors[high_selector].b; + + int s0 = blk.m_endpoints[0] + blk.m_endpoints[2] + blk.m_endpoints[4]; + int s1 = blk.m_endpoints[1] + blk.m_endpoints[3] + blk.m_endpoints[5]; + bool invert = false; + if (s1 < s0) + { + std::swap(blk.m_endpoints[0], blk.m_endpoints[1]); + std::swap(blk.m_endpoints[2], blk.m_endpoints[3]); + std::swap(blk.m_endpoints[4], blk.m_endpoints[5]); + invert = true; + } + + if (transcode_alpha) + { + const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]]; + const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]]; + + const color32& alpha_base_color = alpha_endpoint.m_color5; + const uint32_t alpha_inten_table = alpha_endpoint.m_inten5; + + const uint32_t alpha_low_selector = alpha_selectors.m_lo_selector; + const uint32_t alpha_high_selector = alpha_selectors.m_hi_selector; + + int alpha_block_colors[4]; + decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table); + + blk.m_endpoints[6] = static_cast(alpha_block_colors[alpha_low_selector]); + blk.m_endpoints[7] = static_cast(alpha_block_colors[alpha_high_selector]); + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = alpha_selectors.get_selector(x, y); + s = (s == alpha_high_selector) ? 1 : 0; + + blk.m_weights[(x + y * 4) * 2 + 1] = static_cast(s); + } // x + } // y + } + else + { + blk.m_endpoints[6] = 255; + blk.m_endpoints[7] = 255; + + for (uint32_t i = 0; i < 16; i++) + blk.m_weights[i * 2 + 1] = 0; + } + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + + s = (s == high_selector) ? 1 : 0; + + if (invert) + s = 1 - s; + + blk.m_weights[(x + y * 4) * 2] = static_cast(s); + } // x + } // y + + astc_pack_block_cem_12_weight_range0(reinterpret_cast(pDst_block), &blk); + + return; + } + + // Either alpha and/or color use > 2 unique selectors each, so we must do something more complex. + +#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY + // The optional higher quality modes use 8-bits endpoints vs. [0,47] endpoints. + + // If the block's base color is grayscale, all pixels are grayscale, so encode the block as Luminance+Alpha. + if ((base_color.r == base_color.g) && (base_color.r == base_color.b)) + { + if (transcode_alpha) + { + const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]]; + const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]]; + + const color32& alpha_base_color = alpha_endpoint.m_color5; + const uint32_t alpha_inten_table = alpha_endpoint.m_inten5; + + const uint32_t alpha_low_selector = alpha_selectors.m_lo_selector; + const uint32_t alpha_high_selector = alpha_selectors.m_hi_selector; + + if (num_unique_alpha_selectors <= 2) + { + // Simple alpha block with only 1 or 2 unique values, so use BTC. This is lossless. + int alpha_block_colors[4]; + decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table); + + blk.m_endpoints[2] = static_cast(alpha_block_colors[alpha_low_selector]); + blk.m_endpoints[3] = static_cast(alpha_block_colors[alpha_high_selector]); + + for (uint32_t i = 0; i < 16; i++) + { + uint32_t s = alpha_selectors.get_selector(i & 3, i >> 2); + blk.m_weights[i * 2 + 1] = (s == alpha_high_selector) ? 3 : 0; + } + } + else + { + // Convert ETC1S alpha + const uint32_t alpha_selector_range_table = g_etc1_to_astc_selector_range_index[alpha_low_selector][alpha_high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(alpha_inten_table * 32 + alpha_base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + alpha_selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + const uint32_t best_mapping = g_etc1_to_astc_best_grayscale_mapping_0_255[alpha_base_color.g][alpha_inten_table][alpha_selector_range_table]; + + blk.m_endpoints[2] = pTable_g[best_mapping].m_lo; + blk.m_endpoints[3] = pTable_g[best_mapping].m_hi; + + const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0]; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = alpha_selectors.get_selector(x, y); + uint32_t as = pSelectors_xlat[s]; + + blk.m_weights[(x + y * 4) * 2 + 1] = static_cast(as); + } // x + } // y + } + } + else + { + // No alpha slice - set output alpha to all 255's + blk.m_endpoints[2] = 255; + blk.m_endpoints[3] = 255; + + for (uint32_t i = 0; i < 16; i++) + blk.m_weights[i * 2 + 1] = 0; + } + + if (pSelector->m_num_unique_selectors <= 2) + { + // Simple color block with only 1 or 2 unique values, so use BTC. This is lossless. + int block_colors[4]; + decoder_etc_block::get_block_colors5_g(block_colors, base_color, inten_table); + + blk.m_endpoints[0] = static_cast(block_colors[low_selector]); + blk.m_endpoints[1] = static_cast(block_colors[high_selector]); + + for (uint32_t i = 0; i < 16; i++) + { + uint32_t s = pSelector->get_selector(i & 3, i >> 2); + blk.m_weights[i * 2] = (s == high_selector) ? 3 : 0; + } + } + else + { + // Convert ETC1S alpha + const uint32_t selector_range_table = g_etc1_to_astc_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + const uint32_t best_mapping = g_etc1_to_astc_best_grayscale_mapping_0_255[base_color.g][inten_table][selector_range_table]; + + blk.m_endpoints[0] = pTable_g[best_mapping].m_lo; + blk.m_endpoints[1] = pTable_g[best_mapping].m_hi; + + const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0]; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + uint32_t as = pSelectors_xlat[s]; + + blk.m_weights[(x + y * 4) * 2] = static_cast(as); + } // x + } // y + } + + astc_pack_block_cem_4_weight_range2(reinterpret_cast(pDst_block), &blk); + return; + } + + // The block isn't grayscale and it uses > 2 unique selectors for opaque and/or alpha. + // Check for fully opaque blocks, if so use 8-bit endpoints for slightly higher opaque quality (higher than BC1, but lower than BC7 mode 6 opaque). + if ((num_unique_alpha_selectors == 1) && (constant_alpha_val == 255)) + { + // Convert ETC1S color + const uint32_t selector_range_table = g_etc1_to_astc_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_astc_solution* pTable_r = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.r) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + const etc1_to_astc_solution* pTable_b = &g_etc1_to_astc_0_255[(inten_table * 32 + base_color.b) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + uint32_t best_err = UINT_MAX; + uint32_t best_mapping = 0; + + assert(NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS == 10); +#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } } + DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4); + DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9); +#undef DO_ITER + + blk.m_endpoints[0] = pTable_r[best_mapping].m_lo; + blk.m_endpoints[1] = pTable_r[best_mapping].m_hi; + + blk.m_endpoints[2] = pTable_g[best_mapping].m_lo; + blk.m_endpoints[3] = pTable_g[best_mapping].m_hi; + + blk.m_endpoints[4] = pTable_b[best_mapping].m_lo; + blk.m_endpoints[5] = pTable_b[best_mapping].m_hi; + + int s0 = blk.m_endpoints[0] + blk.m_endpoints[2] + blk.m_endpoints[4]; + int s1 = blk.m_endpoints[1] + blk.m_endpoints[3] + blk.m_endpoints[5]; + bool invert = false; + + if (s1 < s0) + { + std::swap(blk.m_endpoints[0], blk.m_endpoints[1]); + std::swap(blk.m_endpoints[2], blk.m_endpoints[3]); + std::swap(blk.m_endpoints[4], blk.m_endpoints[5]); + invert = true; + } + + const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0]; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + uint32_t as = pSelectors_xlat[s]; + if (invert) + as = 3 - as; + + blk.m_weights[x + y * 4] = static_cast(as); + } // x + } // y + + // Now pack to ASTC + astc_pack_block_cem_8_weight_range2(reinterpret_cast(pDst_block), &blk); + return; + } +#endif //#if BASISD_SUPPORT_ASTC_HIGHER_OPAQUE_QUALITY + + // Nothing else worked, so fall back to CEM Mode 12 (LDR RGBA Direct), [0,47] endpoints, weight range 2 (2-bit weights), dual planes. + // This mode can handle everything, but at slightly less quality than BC1. + if (transcode_alpha) + { + const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pDst_block)[0]]; + const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pDst_block)[1]]; + + const color32& alpha_base_color = alpha_endpoint.m_color5; + const uint32_t alpha_inten_table = alpha_endpoint.m_inten5; + + const uint32_t alpha_low_selector = alpha_selectors.m_lo_selector; + const uint32_t alpha_high_selector = alpha_selectors.m_hi_selector; + + if (alpha_low_selector == alpha_high_selector) + { + // Solid alpha block - use precomputed tables. + int alpha_block_colors[4]; + decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table); + + const uint32_t g = alpha_block_colors[alpha_low_selector]; + + blk.m_endpoints[6] = g_astc_single_color_encoding_1[g].m_lo; + blk.m_endpoints[7] = g_astc_single_color_encoding_1[g].m_hi; + + for (uint32_t i = 0; i < 16; i++) + blk.m_weights[i * 2 + 1] = 1; + } + else if ((alpha_inten_table >= 7) && (alpha_selectors.m_num_unique_selectors == 2) && (alpha_low_selector == 0) && (alpha_high_selector == 3)) + { + // Handle outlier case where only the two outer colors are used with inten table 7. + color32 alpha_block_colors[4]; + + decoder_etc_block::get_block_colors5(alpha_block_colors, alpha_base_color, alpha_inten_table); + + const uint32_t g0 = alpha_block_colors[0].g; + const uint32_t g1 = alpha_block_colors[3].g; + + blk.m_endpoints[6] = g_astc_single_color_encoding_0[g0]; + blk.m_endpoints[7] = g_astc_single_color_encoding_0[g1]; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = alpha_selectors.get_selector(x, y); + uint32_t as = (s == alpha_high_selector) ? 3 : 0; + + blk.m_weights[(x + y * 4) * 2 + 1] = static_cast(as); + } // x + } // y + } + else + { + // Convert ETC1S alpha + const uint32_t alpha_selector_range_table = g_etc1_to_astc_selector_range_index[alpha_low_selector][alpha_high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc[(alpha_inten_table * 32 + alpha_base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + alpha_selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + const uint32_t best_mapping = g_etc1_to_astc_best_grayscale_mapping[alpha_base_color.g][alpha_inten_table][alpha_selector_range_table]; + + blk.m_endpoints[6] = pTable_g[best_mapping].m_lo; + blk.m_endpoints[7] = pTable_g[best_mapping].m_hi; + + const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0]; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = alpha_selectors.get_selector(x, y); + uint32_t as = pSelectors_xlat[s]; + + blk.m_weights[(x + y * 4) * 2 + 1] = static_cast(as); + } // x + } // y + } + } + else + { + // No alpha slice - set output alpha to all 255's + // 1 is 255 when dequantized + blk.m_endpoints[6] = 1; + blk.m_endpoints[7] = 1; + + for (uint32_t i = 0; i < 16; i++) + blk.m_weights[i * 2 + 1] = 0; + } + + if (low_selector == high_selector) + { + // Solid color block - use precomputed tables of optimal endpoints assuming selector weights are all 1. + color32 block_colors[4]; + + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + const uint32_t r = block_colors[low_selector].r; + const uint32_t g = block_colors[low_selector].g; + const uint32_t b = block_colors[low_selector].b; + + blk.m_endpoints[0] = g_astc_single_color_encoding_1[r].m_lo; + blk.m_endpoints[1] = g_astc_single_color_encoding_1[r].m_hi; + + blk.m_endpoints[2] = g_astc_single_color_encoding_1[g].m_lo; + blk.m_endpoints[3] = g_astc_single_color_encoding_1[g].m_hi; + + blk.m_endpoints[4] = g_astc_single_color_encoding_1[b].m_lo; + blk.m_endpoints[5] = g_astc_single_color_encoding_1[b].m_hi; + + int s0 = g_ise_to_unquant[blk.m_endpoints[0]] + g_ise_to_unquant[blk.m_endpoints[2]] + g_ise_to_unquant[blk.m_endpoints[4]]; + int s1 = g_ise_to_unquant[blk.m_endpoints[1]] + g_ise_to_unquant[blk.m_endpoints[3]] + g_ise_to_unquant[blk.m_endpoints[5]]; + bool invert = false; + + if (s1 < s0) + { + std::swap(blk.m_endpoints[0], blk.m_endpoints[1]); + std::swap(blk.m_endpoints[2], blk.m_endpoints[3]); + std::swap(blk.m_endpoints[4], blk.m_endpoints[5]); + invert = true; + } + + for (uint32_t i = 0; i < 16; i++) + blk.m_weights[i * 2] = invert ? 2 : 1; + } + else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3)) + { + // Handle outlier case where only the two outer colors are used with inten table 7. + color32 block_colors[4]; + + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + const uint32_t r0 = block_colors[0].r; + const uint32_t g0 = block_colors[0].g; + const uint32_t b0 = block_colors[0].b; + + const uint32_t r1 = block_colors[3].r; + const uint32_t g1 = block_colors[3].g; + const uint32_t b1 = block_colors[3].b; + + blk.m_endpoints[0] = g_astc_single_color_encoding_0[r0]; + blk.m_endpoints[1] = g_astc_single_color_encoding_0[r1]; + + blk.m_endpoints[2] = g_astc_single_color_encoding_0[g0]; + blk.m_endpoints[3] = g_astc_single_color_encoding_0[g1]; + + blk.m_endpoints[4] = g_astc_single_color_encoding_0[b0]; + blk.m_endpoints[5] = g_astc_single_color_encoding_0[b1]; + + int s0 = g_ise_to_unquant[blk.m_endpoints[0]] + g_ise_to_unquant[blk.m_endpoints[2]] + g_ise_to_unquant[blk.m_endpoints[4]]; + int s1 = g_ise_to_unquant[blk.m_endpoints[1]] + g_ise_to_unquant[blk.m_endpoints[3]] + g_ise_to_unquant[blk.m_endpoints[5]]; + bool invert = false; + + if (s1 < s0) + { + std::swap(blk.m_endpoints[0], blk.m_endpoints[1]); + std::swap(blk.m_endpoints[2], blk.m_endpoints[3]); + std::swap(blk.m_endpoints[4], blk.m_endpoints[5]); + invert = true; + } + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + uint32_t as = (s == low_selector) ? 0 : 3; + + if (invert) + as = 3 - as; + + blk.m_weights[(x + y * 4) * 2] = static_cast(as); + } // x + } // y + } + else + { + // Convert ETC1S color + const uint32_t selector_range_table = g_etc1_to_astc_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1_to_astc_solution* pTable_r = &g_etc1_to_astc[(inten_table * 32 + base_color.r) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + const etc1_to_astc_solution* pTable_g = &g_etc1_to_astc[(inten_table * 32 + base_color.g) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + const etc1_to_astc_solution* pTable_b = &g_etc1_to_astc[(inten_table * 32 + base_color.b) * (NUM_ETC1_TO_ASTC_SELECTOR_RANGES * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS]; + + uint32_t best_err = UINT_MAX; + uint32_t best_mapping = 0; + + assert(NUM_ETC1_TO_ASTC_SELECTOR_MAPPINGS == 10); +#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } } + DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4); + DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9); +#undef DO_ITER + + blk.m_endpoints[0] = pTable_r[best_mapping].m_lo; + blk.m_endpoints[1] = pTable_r[best_mapping].m_hi; + + blk.m_endpoints[2] = pTable_g[best_mapping].m_lo; + blk.m_endpoints[3] = pTable_g[best_mapping].m_hi; + + blk.m_endpoints[4] = pTable_b[best_mapping].m_lo; + blk.m_endpoints[5] = pTable_b[best_mapping].m_hi; + + int s0 = g_ise_to_unquant[blk.m_endpoints[0]] + g_ise_to_unquant[blk.m_endpoints[2]] + g_ise_to_unquant[blk.m_endpoints[4]]; + int s1 = g_ise_to_unquant[blk.m_endpoints[1]] + g_ise_to_unquant[blk.m_endpoints[3]] + g_ise_to_unquant[blk.m_endpoints[5]]; + bool invert = false; + + if (s1 < s0) + { + std::swap(blk.m_endpoints[0], blk.m_endpoints[1]); + std::swap(blk.m_endpoints[2], blk.m_endpoints[3]); + std::swap(blk.m_endpoints[4], blk.m_endpoints[5]); + invert = true; + } + + const uint8_t* pSelectors_xlat = &g_etc1_to_astc_selector_mappings[best_mapping][0]; + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = pSelector->get_selector(x, y); + uint32_t as = pSelectors_xlat[s]; + if (invert) + as = 3 - as; + + blk.m_weights[(x + y * 4) * 2] = static_cast(as); + } // x + } // y + } + + // Now pack to ASTC + astc_pack_block_cem_12_weight_range2(reinterpret_cast(pDst_block), &blk); + } +#endif + +#if BASISD_SUPPORT_ATC + // ATC and PVRTC2 both use these tables. + struct etc1s_to_atc_solution + { + uint8_t m_lo; + uint8_t m_hi; + uint16_t m_err; + }; + + static dxt_selector_range g_etc1s_to_atc_selector_ranges[] = + { + { 0, 3 }, + { 1, 3 }, + { 0, 2 }, + { 1, 2 }, + { 2, 3 }, + { 0, 1 }, + }; + + const uint32_t NUM_ETC1S_TO_ATC_SELECTOR_RANGES = sizeof(g_etc1s_to_atc_selector_ranges) / sizeof(g_etc1s_to_atc_selector_ranges[0]); + + static uint32_t g_etc1s_to_atc_selector_range_index[4][4]; + + const uint32_t NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS = 10; + static const uint8_t g_etc1s_to_atc_selector_mappings[NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS][4] = + { + { 0, 0, 1, 1 }, + { 0, 0, 1, 2 }, + { 0, 0, 1, 3 }, + { 0, 0, 2, 3 }, + { 0, 1, 1, 1 }, + { 0, 1, 2, 2 }, + { 0, 1, 2, 3 }, //6 - identity + { 0, 2, 3, 3 }, + { 1, 2, 2, 2 }, + { 1, 2, 3, 3 }, + }; + const uint32_t ATC_IDENTITY_SELECTOR_MAPPING_INDEX = 6; + +#if BASISD_SUPPORT_PVRTC2 + static const etc1s_to_atc_solution g_etc1s_to_pvrtc2_45[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_pvrtc2_45.inc" + }; + +#if 0 + static const etc1s_to_atc_solution g_etc1s_to_pvrtc2_alpha_33[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_pvrtc2_alpha_33.inc" + }; +#endif + +#endif + + static const etc1s_to_atc_solution g_etc1s_to_atc_55[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_atc_55.inc" + }; + + static const etc1s_to_atc_solution g_etc1s_to_atc_56[32 * 8 * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS * NUM_ETC1S_TO_ATC_SELECTOR_RANGES] = { +#include "basisu_transcoder_tables_atc_56.inc" + }; + + struct atc_match_entry + { + uint8_t m_lo; + uint8_t m_hi; + }; + static atc_match_entry g_pvrtc2_match45_equals_1[256], g_atc_match55_equals_1[256], g_atc_match56_equals_1[256]; // selector 1 + static atc_match_entry g_pvrtc2_match4[256], g_atc_match5[256], g_atc_match6[256]; + + static void prepare_atc_single_color_table(atc_match_entry* pTable, int size0, int size1, int sel) + { + for (int i = 0; i < 256; i++) + { + int lowest_e = 256; + for (int lo = 0; lo < size0; lo++) + { + int lo_e = lo; + if (size0 == 16) + { + lo_e = (lo_e << 1) | (lo_e >> 3); + lo_e = (lo_e << 3) | (lo_e >> 2); + } + else if (size0 == 32) + lo_e = (lo_e << 3) | (lo_e >> 2); + else + lo_e = (lo_e << 2) | (lo_e >> 4); + + for (int hi = 0; hi < size1; hi++) + { + int hi_e = hi; + if (size1 == 16) + { + // This is only for PVRTC2 - expand to 5 then 8 + hi_e = (hi_e << 1) | (hi_e >> 3); + hi_e = (hi_e << 3) | (hi_e >> 2); + } + else if (size1 == 32) + hi_e = (hi_e << 3) | (hi_e >> 2); + else + hi_e = (hi_e << 2) | (hi_e >> 4); + + int e; + + if (sel == 1) + { + // Selector 1 + e = abs(((lo_e * 5 + hi_e * 3) / 8) - i); + } + else + { + assert(sel == 3); + + // Selector 3 + e = abs(hi_e - i); + } + + if (e < lowest_e) + { + pTable[i].m_lo = static_cast(lo); + pTable[i].m_hi = static_cast(hi); + + lowest_e = e; + } + + } // hi + } // lo + } // i + } + + static void transcoder_init_atc() + { + prepare_atc_single_color_table(g_pvrtc2_match45_equals_1, 16, 32, 1); + prepare_atc_single_color_table(g_atc_match55_equals_1, 32, 32, 1); + prepare_atc_single_color_table(g_atc_match56_equals_1, 32, 64, 1); + + prepare_atc_single_color_table(g_pvrtc2_match4, 1, 16, 3); + prepare_atc_single_color_table(g_atc_match5, 1, 32, 3); + prepare_atc_single_color_table(g_atc_match6, 1, 64, 3); + + for (uint32_t i = 0; i < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; i++) + { + uint32_t l = g_etc1s_to_atc_selector_ranges[i].m_low; + uint32_t h = g_etc1s_to_atc_selector_ranges[i].m_high; + g_etc1s_to_atc_selector_range_index[l][h] = i; + } + } + + struct atc_block + { + uint8_t m_lo[2]; + uint8_t m_hi[2]; + uint8_t m_sels[4]; + + void set_low_color(uint32_t r, uint32_t g, uint32_t b) + { + assert((r < 32) && (g < 32) && (b < 32)); + uint32_t x = (r << 10) | (g << 5) | b; + m_lo[0] = x & 0xFF; + m_lo[1] = (x >> 8) & 0xFF; + } + + void set_high_color(uint32_t r, uint32_t g, uint32_t b) + { + assert((r < 32) && (g < 64) && (b < 32)); + uint32_t x = (r << 11) | (g << 5) | b; + m_hi[0] = x & 0xFF; + m_hi[1] = (x >> 8) & 0xFF; + } + }; + + static void convert_etc1s_to_atc(void* pDst, const endpoint* pEndpoints, const selector* pSelector) + { + atc_block* pBlock = static_cast(pDst); + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (low_selector == high_selector) + { + uint32_t r, g, b; + decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b); + + pBlock->set_low_color(g_atc_match55_equals_1[r].m_lo, g_atc_match56_equals_1[g].m_lo, g_atc_match55_equals_1[b].m_lo); + pBlock->set_high_color(g_atc_match55_equals_1[r].m_hi, g_atc_match56_equals_1[g].m_hi, g_atc_match55_equals_1[b].m_hi); + + pBlock->m_sels[0] = 0x55; + pBlock->m_sels[1] = 0x55; + pBlock->m_sels[2] = 0x55; + pBlock->m_sels[3] = 0x55; + + return; + } + else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3)) + { + color32 block_colors[4]; + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + const uint32_t r0 = block_colors[0].r; + const uint32_t g0 = block_colors[0].g; + const uint32_t b0 = block_colors[0].b; + + const uint32_t r1 = block_colors[3].r; + const uint32_t g1 = block_colors[3].g; + const uint32_t b1 = block_colors[3].b; + + pBlock->set_low_color(g_atc_match5[r0].m_hi, g_atc_match5[g0].m_hi, g_atc_match5[b0].m_hi); + pBlock->set_high_color(g_atc_match5[r1].m_hi, g_atc_match6[g1].m_hi, g_atc_match5[b1].m_hi); + + pBlock->m_sels[0] = pSelector->m_selectors[0]; + pBlock->m_sels[1] = pSelector->m_selectors[1]; + pBlock->m_sels[2] = pSelector->m_selectors[2]; + pBlock->m_sels[3] = pSelector->m_selectors[3]; + + return; + } + + const uint32_t selector_range_table = g_etc1s_to_atc_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1s_to_atc_solution* pTable_r = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.r) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS]; + const etc1s_to_atc_solution* pTable_g = &g_etc1s_to_atc_56[(inten_table * 32 + base_color.g) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS]; + const etc1s_to_atc_solution* pTable_b = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.b) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS]; + + uint32_t best_err = UINT_MAX; + uint32_t best_mapping = 0; + + assert(NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS == 10); +#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } } + DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4); + DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9); +#undef DO_ITER + + pBlock->set_low_color(pTable_r[best_mapping].m_lo, pTable_g[best_mapping].m_lo, pTable_b[best_mapping].m_lo); + pBlock->set_high_color(pTable_r[best_mapping].m_hi, pTable_g[best_mapping].m_hi, pTable_b[best_mapping].m_hi); + + if (ATC_IDENTITY_SELECTOR_MAPPING_INDEX == best_mapping) + { + pBlock->m_sels[0] = pSelector->m_selectors[0]; + pBlock->m_sels[1] = pSelector->m_selectors[1]; + pBlock->m_sels[2] = pSelector->m_selectors[2]; + pBlock->m_sels[3] = pSelector->m_selectors[3]; + } + else + { + const uint8_t* pSelectors_xlat = &g_etc1s_to_atc_selector_mappings[best_mapping][0]; + + const uint32_t sel_bits0 = pSelector->m_selectors[0]; + const uint32_t sel_bits1 = pSelector->m_selectors[1]; + const uint32_t sel_bits2 = pSelector->m_selectors[2]; + const uint32_t sel_bits3 = pSelector->m_selectors[3]; + + uint32_t atc_sels0 = 0, atc_sels1 = 0, atc_sels2 = 0, atc_sels3 = 0; + +#define DO_X(x) { \ + const uint32_t x_shift = (x) * 2; \ + atc_sels0 |= (pSelectors_xlat[(sel_bits0 >> x_shift) & 3] << x_shift); \ + atc_sels1 |= (pSelectors_xlat[(sel_bits1 >> x_shift) & 3] << x_shift); \ + atc_sels2 |= (pSelectors_xlat[(sel_bits2 >> x_shift) & 3] << x_shift); \ + atc_sels3 |= (pSelectors_xlat[(sel_bits3 >> x_shift) & 3] << x_shift); } + + DO_X(0); + DO_X(1); + DO_X(2); + DO_X(3); +#undef DO_X + + pBlock->m_sels[0] = (uint8_t)atc_sels0; + pBlock->m_sels[1] = (uint8_t)atc_sels1; + pBlock->m_sels[2] = (uint8_t)atc_sels2; + pBlock->m_sels[3] = (uint8_t)atc_sels3; + } + } + +#if BASISD_WRITE_NEW_ATC_TABLES + static void create_etc1s_to_atc_conversion_tables() + { + // ATC 55 + FILE* pFile = nullptr; + fopen_s(&pFile, "basisu_transcoder_tables_atc_55.inc", "w"); + + uint32_t n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 31; hi++) + { + for (uint32_t lo = 0; lo <= 31; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 3) | (lo >> 2); + colors[3] = (hi << 3) | (hi >> 2); + + colors[1] = (colors[0] * 5 + colors[3] * 3) / 8; + colors[2] = (colors[3] * 5 + colors[0] * 3) / 8; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + //assert(best_err <= 0xFFFF); + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); + pFile = nullptr; + + // ATC 56 + fopen_s(&pFile, "basisu_transcoder_tables_atc_56.inc", "w"); + + n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 63; hi++) + { + for (uint32_t lo = 0; lo <= 31; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 3) | (lo >> 2); + colors[3] = (hi << 2) | (hi >> 4); + + colors[1] = (colors[0] * 5 + colors[3] * 3) / 8; + colors[2] = (colors[3] * 5 + colors[0] * 3) / 8; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + //assert(best_err <= 0xFFFF); + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); + + // PVRTC2 45 + fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_45.inc", "w"); + + n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 31; hi++) + { + for (uint32_t lo = 0; lo <= 15; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 1) | (lo >> 3); + colors[0] = (colors[0] << 3) | (colors[0] >> 2); + + colors[3] = (hi << 3) | (hi >> 2); + + colors[1] = (colors[0] * 5 + colors[3] * 3) / 8; + colors[2] = (colors[3] * 5 + colors[0] * 3) / 8; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + //assert(best_err <= 0xFFFF); + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); + +#if 0 + // PVRTC2 34 + fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_34.inc", "w"); + + n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 15; hi++) + { + for (uint32_t lo = 0; lo <= 7; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 2) | (lo >> 1); + colors[0] = (colors[0] << 3) | (colors[0] >> 2); + + colors[3] = (hi << 1) | (hi >> 3); + colors[3] = (colors[3] << 3) | (colors[3] >> 2); + + colors[1] = (colors[0] * 5 + colors[3] * 3) / 8; + colors[2] = (colors[3] * 5 + colors[0] * 3) / 8; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + //assert(best_err <= 0xFFFF); + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); +#endif +#if 0 + // PVRTC2 44 + fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_44.inc", "w"); + + n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 15; hi++) + { + for (uint32_t lo = 0; lo <= 15; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 1) | (lo >> 3); + colors[0] = (colors[0] << 3) | (colors[0] >> 2); + + colors[3] = (hi << 1) | (hi >> 3); + colors[3] = (colors[3] << 3) | (colors[3] >> 2); + + colors[1] = (colors[0] * 5 + colors[3] * 3) / 8; + colors[2] = (colors[3] * 5 + colors[0] * 3) / 8; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + //assert(best_err <= 0xFFFF); + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); +#endif + + // PVRTC2 alpha 33 + fopen_s(&pFile, "basisu_transcoder_tables_pvrtc2_alpha_33.inc", "w"); + + n = 0; + + for (int inten = 0; inten < 8; inten++) + { + for (uint32_t g = 0; g < 32; g++) + { + color32 block_colors[4]; + decoder_etc_block::get_diff_subblock_colors(block_colors, decoder_etc_block::pack_color5(color32(g, g, g, 255), false), inten); + + for (uint32_t sr = 0; sr < NUM_ETC1S_TO_ATC_SELECTOR_RANGES; sr++) + { + const uint32_t low_selector = g_etc1s_to_atc_selector_ranges[sr].m_low; + const uint32_t high_selector = g_etc1s_to_atc_selector_ranges[sr].m_high; + + for (uint32_t m = 0; m < NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS; m++) + { + uint32_t best_lo = 0; + uint32_t best_hi = 0; + uint64_t best_err = UINT64_MAX; + + for (uint32_t hi = 0; hi <= 7; hi++) + { + for (uint32_t lo = 0; lo <= 7; lo++) + { + uint32_t colors[4]; + + colors[0] = (lo << 1); + colors[0] = (colors[0] << 4) | colors[0]; + + colors[3] = (hi << 1) | 1; + colors[3] = (colors[3] << 4) | colors[3]; + + colors[1] = (colors[0] * 5 + colors[3] * 3) / 8; + colors[2] = (colors[3] * 5 + colors[0] * 3) / 8; + + uint64_t total_err = 0; + + for (uint32_t s = low_selector; s <= high_selector; s++) + { + int err = block_colors[s].g - colors[g_etc1s_to_atc_selector_mappings[m][s]]; + + int err_scale = 1; + // Special case when the intensity table is 7, low_selector is 0, and high_selector is 3. In this extreme case, it's likely the encoder is trying to strongly favor + // the low/high selectors which are clamping to either 0 or 255. + if (((inten == 7) && (low_selector == 0) && (high_selector == 3)) && ((s == 0) || (s == 3))) + err_scale = 5; + + total_err += (err * err) * err_scale; + } + + if (total_err < best_err) + { + best_err = total_err; + best_lo = lo; + best_hi = hi; + } + } + } + + //assert(best_err <= 0xFFFF); + best_err = basisu::minimum(best_err, 0xFFFF); + + fprintf(pFile, "{%u,%u,%u},", best_lo, best_hi, (uint32_t)best_err); + n++; + if ((n & 31) == 31) + fprintf(pFile, "\n"); + } // m + } // sr + } // g + } // inten + + fclose(pFile); + } +#endif // BASISD_WRITE_NEW_ATC_TABLES + +#endif // BASISD_SUPPORT_ATC + +#if BASISD_SUPPORT_PVRTC2 + struct pvrtc2_block + { + uint8_t m_modulation[4]; + + union + { + union + { + // Opaque mode: RGB colora=554 and colorb=555 + struct + { + uint32_t m_mod_flag : 1; + uint32_t m_blue_a : 4; + uint32_t m_green_a : 5; + uint32_t m_red_a : 5; + uint32_t m_hard_flag : 1; + uint32_t m_blue_b : 5; + uint32_t m_green_b : 5; + uint32_t m_red_b : 5; + uint32_t m_opaque_flag : 1; + + } m_opaque_color_data; + + // Transparent mode: RGBA colora=4433 and colorb=4443 + struct + { + uint32_t m_mod_flag : 1; + uint32_t m_blue_a : 3; + uint32_t m_green_a : 4; + uint32_t m_red_a : 4; + uint32_t m_alpha_a : 3; + uint32_t m_hard_flag : 1; + uint32_t m_blue_b : 4; + uint32_t m_green_b : 4; + uint32_t m_red_b : 4; + uint32_t m_alpha_b : 3; + uint32_t m_opaque_flag : 1; + + } m_trans_color_data; + }; + + uint32_t m_color_data_bits; + }; + + // 554 + void set_low_color(uint32_t r, uint32_t g, uint32_t b) + { + assert((r < 32) && (g < 32) && (b < 16)); + m_opaque_color_data.m_red_a = r; + m_opaque_color_data.m_green_a = g; + m_opaque_color_data.m_blue_a = b; + } + + // 555 + void set_high_color(uint32_t r, uint32_t g, uint32_t b) + { + assert((r < 32) && (g < 32) && (b < 32)); + m_opaque_color_data.m_red_b = r; + m_opaque_color_data.m_green_b = g; + m_opaque_color_data.m_blue_b = b; + } + + // 4433 + void set_trans_low_color(uint32_t r, uint32_t g, uint32_t b, uint32_t a) + { + assert((r < 16) && (g < 16) && (b < 8) && (a < 8)); + m_trans_color_data.m_red_a = r; + m_trans_color_data.m_green_a = g; + m_trans_color_data.m_blue_a = b; + m_trans_color_data.m_alpha_a = a; + } + + // 4443 + void set_trans_high_color(uint32_t r, uint32_t g, uint32_t b, uint32_t a) + { + assert((r < 16) && (g < 16) && (b < 16) && (a < 8)); + m_trans_color_data.m_red_b = r; + m_trans_color_data.m_green_b = g; + m_trans_color_data.m_blue_b = b; + m_trans_color_data.m_alpha_b = a; + } + }; + + static struct + { + uint8_t m_l, m_h; + } g_pvrtc2_trans_match34[256]; + + static struct + { + uint8_t m_l, m_h; + } g_pvrtc2_trans_match44[256]; + + static struct + { + uint8_t m_l, m_h; + } g_pvrtc2_alpha_match33[256]; + + static struct + { + uint8_t m_l, m_h; + } g_pvrtc2_alpha_match33_0[256]; + + static struct + { + uint8_t m_l, m_h; + } g_pvrtc2_alpha_match33_3[256]; + + // PVRTC2 can be forced to look like a slightly weaker variant of ATC/BC1, so that's what we do here for simplicity. + static void convert_etc1s_to_pvrtc2_rgb(void* pDst, const endpoint* pEndpoints, const selector* pSelector) + { + pvrtc2_block* pBlock = static_cast(pDst); + + pBlock->m_opaque_color_data.m_hard_flag = 1; + pBlock->m_opaque_color_data.m_mod_flag = 0; + pBlock->m_opaque_color_data.m_opaque_flag = 1; + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + if (low_selector == high_selector) + { + uint32_t r, g, b; + decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b); + + pBlock->set_low_color(g_atc_match55_equals_1[r].m_lo, g_atc_match55_equals_1[g].m_lo, g_pvrtc2_match45_equals_1[b].m_lo); + pBlock->set_high_color(g_atc_match55_equals_1[r].m_hi, g_atc_match55_equals_1[g].m_hi, g_pvrtc2_match45_equals_1[b].m_hi); + + pBlock->m_modulation[0] = 0x55; + pBlock->m_modulation[1] = 0x55; + pBlock->m_modulation[2] = 0x55; + pBlock->m_modulation[3] = 0x55; + + return; + } + else if ((inten_table >= 7) && (pSelector->m_num_unique_selectors == 2) && (pSelector->m_lo_selector == 0) && (pSelector->m_hi_selector == 3)) + { + color32 block_colors[4]; + decoder_etc_block::get_block_colors5(block_colors, base_color, inten_table); + + const uint32_t r0 = block_colors[0].r; + const uint32_t g0 = block_colors[0].g; + const uint32_t b0 = block_colors[0].b; + + const uint32_t r1 = block_colors[3].r; + const uint32_t g1 = block_colors[3].g; + const uint32_t b1 = block_colors[3].b; + + pBlock->set_low_color(g_atc_match5[r0].m_hi, g_atc_match5[g0].m_hi, g_pvrtc2_match4[b0].m_hi); + pBlock->set_high_color(g_atc_match5[r1].m_hi, g_atc_match5[g1].m_hi, g_atc_match5[b1].m_hi); + + pBlock->m_modulation[0] = pSelector->m_selectors[0]; + pBlock->m_modulation[1] = pSelector->m_selectors[1]; + pBlock->m_modulation[2] = pSelector->m_selectors[2]; + pBlock->m_modulation[3] = pSelector->m_selectors[3]; + + return; + } + + const uint32_t selector_range_table = g_etc1s_to_atc_selector_range_index[low_selector][high_selector]; + + //[32][8][RANGES][MAPPING] + const etc1s_to_atc_solution* pTable_r = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.r) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS]; + const etc1s_to_atc_solution* pTable_g = &g_etc1s_to_atc_55[(inten_table * 32 + base_color.g) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS]; + const etc1s_to_atc_solution* pTable_b = &g_etc1s_to_pvrtc2_45[(inten_table * 32 + base_color.b) * (NUM_ETC1S_TO_ATC_SELECTOR_RANGES * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS) + selector_range_table * NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS]; + + uint32_t best_err = UINT_MAX; + uint32_t best_mapping = 0; + + assert(NUM_ETC1S_TO_ATC_SELECTOR_MAPPINGS == 10); +#define DO_ITER(m) { uint32_t total_err = pTable_r[m].m_err + pTable_g[m].m_err + pTable_b[m].m_err; if (total_err < best_err) { best_err = total_err; best_mapping = m; } } + DO_ITER(0); DO_ITER(1); DO_ITER(2); DO_ITER(3); DO_ITER(4); + DO_ITER(5); DO_ITER(6); DO_ITER(7); DO_ITER(8); DO_ITER(9); +#undef DO_ITER + + pBlock->set_low_color(pTable_r[best_mapping].m_lo, pTable_g[best_mapping].m_lo, pTable_b[best_mapping].m_lo); + pBlock->set_high_color(pTable_r[best_mapping].m_hi, pTable_g[best_mapping].m_hi, pTable_b[best_mapping].m_hi); + + if (ATC_IDENTITY_SELECTOR_MAPPING_INDEX == best_mapping) + { + pBlock->m_modulation[0] = pSelector->m_selectors[0]; + pBlock->m_modulation[1] = pSelector->m_selectors[1]; + pBlock->m_modulation[2] = pSelector->m_selectors[2]; + pBlock->m_modulation[3] = pSelector->m_selectors[3]; + } + else + { + // TODO: We could make this faster using several precomputed 256 entry tables, like ETC1S->BC1 does. + const uint8_t* pSelectors_xlat = &g_etc1s_to_atc_selector_mappings[best_mapping][0]; + + const uint32_t sel_bits0 = pSelector->m_selectors[0]; + const uint32_t sel_bits1 = pSelector->m_selectors[1]; + const uint32_t sel_bits2 = pSelector->m_selectors[2]; + const uint32_t sel_bits3 = pSelector->m_selectors[3]; + + uint32_t sels0 = 0, sels1 = 0, sels2 = 0, sels3 = 0; + +#define DO_X(x) { \ + const uint32_t x_shift = (x) * 2; \ + sels0 |= (pSelectors_xlat[(sel_bits0 >> x_shift) & 3] << x_shift); \ + sels1 |= (pSelectors_xlat[(sel_bits1 >> x_shift) & 3] << x_shift); \ + sels2 |= (pSelectors_xlat[(sel_bits2 >> x_shift) & 3] << x_shift); \ + sels3 |= (pSelectors_xlat[(sel_bits3 >> x_shift) & 3] << x_shift); } + + DO_X(0); + DO_X(1); + DO_X(2); + DO_X(3); +#undef DO_X + + pBlock->m_modulation[0] = (uint8_t)sels0; + pBlock->m_modulation[1] = (uint8_t)sels1; + pBlock->m_modulation[2] = (uint8_t)sels2; + pBlock->m_modulation[3] = (uint8_t)sels3; + } + } + + typedef struct { float c[4]; } vec4F; + + static inline vec4F* vec4F_set_scalar(vec4F* pV, float x) { pV->c[0] = x; pV->c[1] = x; pV->c[2] = x; pV->c[3] = x; return pV; } + static inline vec4F* vec4F_set(vec4F* pV, float x, float y, float z, float w) { pV->c[0] = x; pV->c[1] = y; pV->c[2] = z; pV->c[3] = w; return pV; } + static inline vec4F* vec4F_saturate_in_place(vec4F* pV) { pV->c[0] = saturate(pV->c[0]); pV->c[1] = saturate(pV->c[1]); pV->c[2] = saturate(pV->c[2]); pV->c[3] = saturate(pV->c[3]); return pV; } + static inline vec4F vec4F_saturate(const vec4F* pV) { vec4F res; res.c[0] = saturate(pV->c[0]); res.c[1] = saturate(pV->c[1]); res.c[2] = saturate(pV->c[2]); res.c[3] = saturate(pV->c[3]); return res; } + static inline vec4F vec4F_from_color(const color32* pC) { vec4F res; vec4F_set(&res, pC->c[0], pC->c[1], pC->c[2], pC->c[3]); return res; } + static inline vec4F vec4F_add(const vec4F* pLHS, const vec4F* pRHS) { vec4F res; vec4F_set(&res, pLHS->c[0] + pRHS->c[0], pLHS->c[1] + pRHS->c[1], pLHS->c[2] + pRHS->c[2], pLHS->c[3] + pRHS->c[3]); return res; } + static inline vec4F vec4F_sub(const vec4F* pLHS, const vec4F* pRHS) { vec4F res; vec4F_set(&res, pLHS->c[0] - pRHS->c[0], pLHS->c[1] - pRHS->c[1], pLHS->c[2] - pRHS->c[2], pLHS->c[3] - pRHS->c[3]); return res; } + static inline float vec4F_dot(const vec4F* pLHS, const vec4F* pRHS) { return pLHS->c[0] * pRHS->c[0] + pLHS->c[1] * pRHS->c[1] + pLHS->c[2] * pRHS->c[2] + pLHS->c[3] * pRHS->c[3]; } + static inline vec4F vec4F_mul(const vec4F* pLHS, float s) { vec4F res; vec4F_set(&res, pLHS->c[0] * s, pLHS->c[1] * s, pLHS->c[2] * s, pLHS->c[3] * s); return res; } + static inline vec4F* vec4F_normalize_in_place(vec4F* pV) { float s = pV->c[0] * pV->c[0] + pV->c[1] * pV->c[1] + pV->c[2] * pV->c[2] + pV->c[3] * pV->c[3]; if (s != 0.0f) { s = 1.0f / sqrtf(s); pV->c[0] *= s; pV->c[1] *= s; pV->c[2] *= s; pV->c[3] *= s; } return pV; } + + static color32 convert_rgba_5554_to_8888(const color32& col) + { + return color32((col[0] << 3) | (col[0] >> 2), (col[1] << 3) | (col[1] >> 2), (col[2] << 3) | (col[2] >> 2), (col[3] << 4) | col[3]); + } + + static inline int sq(int x) { return x * x; } + + // PVRTC2 is a slightly borked format for alpha: In Non-Interpolated mode, the way AlphaB8 is exanded from 4 to 8 bits means it can never be 0. + // This is actually very bad, because on 100% transparent blocks which have non-trivial color pixels, part of the color channel will leak into alpha! + // And there's nothing straightforward we can do because using the other modes is too expensive/complex. I can see why Apple didn't adopt it. + static void convert_etc1s_to_pvrtc2_rgba(void* pDst, const endpoint* pEndpoints, const selector* pSelector, const endpoint* pEndpoint_codebook, const selector* pSelector_codebook) + { + pvrtc2_block* pBlock = static_cast(pDst); + + const endpoint& alpha_endpoint = pEndpoint_codebook[((uint16_t*)pBlock)[0]]; + const selector& alpha_selectors = pSelector_codebook[((uint16_t*)pBlock)[1]]; + + pBlock->m_opaque_color_data.m_hard_flag = 1; + pBlock->m_opaque_color_data.m_mod_flag = 0; + pBlock->m_opaque_color_data.m_opaque_flag = 0; + + const int num_unique_alpha_selectors = alpha_selectors.m_num_unique_selectors; + + const color32& alpha_base_color = alpha_endpoint.m_color5; + const uint32_t alpha_inten_table = alpha_endpoint.m_inten5; + + int constant_alpha_val = -1; + + int alpha_block_colors[4]; + decoder_etc_block::get_block_colors5_g(alpha_block_colors, alpha_base_color, alpha_inten_table); + + if (num_unique_alpha_selectors == 1) + { + constant_alpha_val = alpha_block_colors[alpha_selectors.m_lo_selector]; + } + else + { + constant_alpha_val = alpha_block_colors[alpha_selectors.m_lo_selector]; + + for (uint32_t i = alpha_selectors.m_lo_selector + 1; i <= alpha_selectors.m_hi_selector; i++) + { + if (constant_alpha_val != alpha_block_colors[i]) + { + constant_alpha_val = -1; + break; + } + } + } + + if (constant_alpha_val >= 250) + { + // It's opaque enough, so don't bother trying to encode it as an alpha block. + convert_etc1s_to_pvrtc2_rgb(pDst, pEndpoints, pSelector); + return; + } + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + const int num_unique_color_selectors = pSelector->m_num_unique_selectors; + + // We need to reencode the block at the pixel level, unfortunately, from two ETC1S planes. + // Do 4D incremental PCA, project all pixels to this hyperline, then quantize to packed endpoints and compute the modulation values. + const int br = (base_color.r << 3) | (base_color.r >> 2); + const int bg = (base_color.g << 3) | (base_color.g >> 2); + const int bb = (base_color.b << 3) | (base_color.b >> 2); + + color32 block_cols[4]; + for (uint32_t i = 0; i < 4; i++) + { + const int ci = g_etc1_inten_tables[inten_table][i]; + block_cols[i].set_clamped(br + ci, bg + ci, bb + ci, alpha_block_colors[i]); + } + + bool solid_color_block = true; + if (num_unique_color_selectors > 1) + { + for (uint32_t i = low_selector + 1; i <= high_selector; i++) + { + if ((block_cols[low_selector].r != block_cols[i].r) || (block_cols[low_selector].g != block_cols[i].g) || (block_cols[low_selector].b != block_cols[i].b)) + { + solid_color_block = false; + break; + } + } + } + + if ((solid_color_block) && (constant_alpha_val >= 0)) + { + // Constant color/alpha block. + // This is more complex than it may seem because of the way color and alpha are packed in PVRTC2. We need to evaluate mod0, mod1 and mod3 encodings to find the best one. + uint32_t r, g, b; + decoder_etc_block::get_block_color5(base_color, inten_table, low_selector, r, g, b); + + // Mod 0 + uint32_t lr0 = (r * 15 + 128) / 255, lg0 = (g * 15 + 128) / 255, lb0 = (b * 7 + 128) / 255; + uint32_t la0 = g_pvrtc2_alpha_match33_0[constant_alpha_val].m_l; + + uint32_t cr0 = (lr0 << 1) | (lr0 >> 3); + uint32_t cg0 = (lg0 << 1) | (lg0 >> 3); + uint32_t cb0 = (lb0 << 2) | (lb0 >> 1); + uint32_t ca0 = (la0 << 1); + + cr0 = (cr0 << 3) | (cr0 >> 2); + cg0 = (cg0 << 3) | (cg0 >> 2); + cb0 = (cb0 << 3) | (cb0 >> 2); + ca0 = (ca0 << 4) | ca0; + + uint32_t err0 = sq(cr0 - r) + sq(cg0 - g) + sq(cb0 - b) + sq(ca0 - constant_alpha_val) * 2; + + // If the alpha is < 3 or so we're kinda screwed. It's better to have some RGB error than it is to turn a 100% transparent area slightly opaque. + if ((err0 == 0) || (constant_alpha_val < 3)) + { + pBlock->set_trans_low_color(lr0, lg0, lb0, la0); + pBlock->set_trans_high_color(0, 0, 0, 0); + + pBlock->m_modulation[0] = 0; + pBlock->m_modulation[1] = 0; + pBlock->m_modulation[2] = 0; + pBlock->m_modulation[3] = 0; + return; + } + + // Mod 3 + uint32_t lr3 = (r * 15 + 128) / 255, lg3 = (g * 15 + 128) / 255, lb3 = (b * 15 + 128) / 255; + uint32_t la3 = g_pvrtc2_alpha_match33_3[constant_alpha_val].m_l; + + uint32_t cr3 = (lr3 << 1) | (lr3 >> 3); + uint32_t cg3 = (lg3 << 1) | (lg3 >> 3); + uint32_t cb3 = (lb3 << 1) | (lb3 >> 3); + uint32_t ca3 = (la3 << 1) | 1; + + cr3 = (cr3 << 3) | (cr3 >> 2); + cg3 = (cg3 << 3) | (cg3 >> 2); + cb3 = (cb3 << 3) | (cb3 >> 2); + ca3 = (ca3 << 4) | ca3; + + uint32_t err3 = sq(cr3 - r) + sq(cg3 - g) + sq(cb3 - b) + sq(ca3 - constant_alpha_val) * 2; + + // Mod 1 + uint32_t lr1 = g_pvrtc2_trans_match44[r].m_l, lg1 = g_pvrtc2_trans_match44[g].m_l, lb1 = g_pvrtc2_trans_match34[b].m_l; + uint32_t hr1 = g_pvrtc2_trans_match44[r].m_h, hg1 = g_pvrtc2_trans_match44[g].m_h, hb1 = g_pvrtc2_trans_match34[b].m_h; + uint32_t la1 = g_pvrtc2_alpha_match33[constant_alpha_val].m_l, ha1 = g_pvrtc2_alpha_match33[constant_alpha_val].m_h; + + uint32_t clr1 = (lr1 << 1) | (lr1 >> 3); + uint32_t clg1 = (lg1 << 1) | (lg1 >> 3); + uint32_t clb1 = (lb1 << 2) | (lb1 >> 1); + uint32_t cla1 = (la1 << 1); + + clr1 = (clr1 << 3) | (clr1 >> 2); + clg1 = (clg1 << 3) | (clg1 >> 2); + clb1 = (clb1 << 3) | (clb1 >> 2); + cla1 = (cla1 << 4) | cla1; + + uint32_t chr1 = (hr1 << 1) | (hr1 >> 3); + uint32_t chg1 = (hg1 << 1) | (hg1 >> 3); + uint32_t chb1 = (hb1 << 1) | (hb1 >> 3); + uint32_t cha1 = (ha1 << 1) | 1; + + chr1 = (chr1 << 3) | (chr1 >> 2); + chg1 = (chg1 << 3) | (chg1 >> 2); + chb1 = (chb1 << 3) | (chb1 >> 2); + cha1 = (cha1 << 4) | cha1; + + uint32_t r1 = (clr1 * 5 + chr1 * 3) / 8; + uint32_t g1 = (clg1 * 5 + chg1 * 3) / 8; + uint32_t b1 = (clb1 * 5 + chb1 * 3) / 8; + uint32_t a1 = (cla1 * 5 + cha1 * 3) / 8; + + uint32_t err1 = sq(r1 - r) + sq(g1 - g) + sq(b1 - b) + sq(a1 - constant_alpha_val) * 2; + + if ((err1 < err0) && (err1 < err3)) + { + pBlock->set_trans_low_color(lr1, lg1, lb1, la1); + pBlock->set_trans_high_color(hr1, hg1, hb1, ha1); + + pBlock->m_modulation[0] = 0x55; + pBlock->m_modulation[1] = 0x55; + pBlock->m_modulation[2] = 0x55; + pBlock->m_modulation[3] = 0x55; + } + else if (err0 < err3) + { + pBlock->set_trans_low_color(lr0, lg0, lb0, la0); + pBlock->set_trans_high_color(0, 0, 0, 0); + + pBlock->m_modulation[0] = 0; + pBlock->m_modulation[1] = 0; + pBlock->m_modulation[2] = 0; + pBlock->m_modulation[3] = 0; + } + else + { + pBlock->set_trans_low_color(0, 0, 0, 0); + pBlock->set_trans_high_color(lr3, lg3, lb3, la3); + + pBlock->m_modulation[0] = 0xFF; + pBlock->m_modulation[1] = 0xFF; + pBlock->m_modulation[2] = 0xFF; + pBlock->m_modulation[3] = 0xFF; + } + + return; + } + + // It's a complex block with non-solid color and/or alpha pixels. + vec4F minColor, maxColor; + + if (solid_color_block) + { + // It's a solid color block. + uint32_t low_a = block_cols[alpha_selectors.m_lo_selector].a; + uint32_t high_a = block_cols[alpha_selectors.m_hi_selector].a; + + const float S = 1.0f / 255.0f; + vec4F_set(&minColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, low_a * S); + vec4F_set(&maxColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, high_a * S); + } + else if (constant_alpha_val >= 0) + { + // It's a solid alpha block. + const float S = 1.0f / 255.0f; + vec4F_set(&minColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, constant_alpha_val * S); + vec4F_set(&maxColor, block_cols[high_selector].r * S, block_cols[high_selector].g * S, block_cols[high_selector].b * S, constant_alpha_val * S); + } + // See if any of the block colors got clamped - if so the principle axis got distorted (it's no longer just the ETC1S luma axis). + // To keep quality up we need to use full 4D PCA in this case. + else if ((block_cols[low_selector].c[0] == 0) || (block_cols[high_selector].c[0] == 255) || + (block_cols[low_selector].c[1] == 0) || (block_cols[high_selector].c[1] == 255) || + (block_cols[low_selector].c[2] == 0) || (block_cols[high_selector].c[2] == 255) || + (block_cols[alpha_selectors.m_lo_selector].c[3] == 0) || (block_cols[alpha_selectors.m_hi_selector].c[3] == 255)) + { + // Find principle component of RGBA colors treated as 4D vectors. + color32 pixels[16]; + + uint32_t sum_r = 0, sum_g = 0, sum_b = 0, sum_a = 0; + for (uint32_t i = 0; i < 16; i++) + { + color32 rgb(block_cols[pSelector->get_selector(i & 3, i >> 2)]); + uint32_t a = block_cols[alpha_selectors.get_selector(i & 3, i >> 2)].a; + + pixels[i].set(rgb.r, rgb.g, rgb.b, a); + + sum_r += rgb.r; + sum_g += rgb.g; + sum_b += rgb.b; + sum_a += a; + } + + vec4F meanColor; + vec4F_set(&meanColor, (float)sum_r, (float)sum_g, (float)sum_b, (float)sum_a); + vec4F meanColorScaled = vec4F_mul(&meanColor, 1.0f / 16.0f); + + meanColor = vec4F_mul(&meanColor, 1.0f / (float)(16.0f * 255.0f)); + vec4F_saturate_in_place(&meanColor); + + vec4F axis; + vec4F_set_scalar(&axis, 0.0f); + // Why this incremental method? Because it's stable and predictable. Covar+power method can require a lot of iterations to converge in 4D. + for (uint32_t i = 0; i < 16; i++) + { + vec4F color = vec4F_from_color(&pixels[i]); + color = vec4F_sub(&color, &meanColorScaled); + vec4F a = vec4F_mul(&color, color.c[0]); + vec4F b = vec4F_mul(&color, color.c[1]); + vec4F c = vec4F_mul(&color, color.c[2]); + vec4F d = vec4F_mul(&color, color.c[3]); + vec4F n = i ? axis : color; + vec4F_normalize_in_place(&n); + axis.c[0] += vec4F_dot(&a, &n); + axis.c[1] += vec4F_dot(&b, &n); + axis.c[2] += vec4F_dot(&c, &n); + axis.c[3] += vec4F_dot(&d, &n); + } + + vec4F_normalize_in_place(&axis); + + if (vec4F_dot(&axis, &axis) < .5f) + vec4F_set_scalar(&axis, .5f); + + float l = 1e+9f, h = -1e+9f; + + for (uint32_t i = 0; i < 16; i++) + { + vec4F color = vec4F_from_color(&pixels[i]); + + vec4F q = vec4F_sub(&color, &meanColorScaled); + float d = vec4F_dot(&q, &axis); + + l = basisu::minimum(l, d); + h = basisu::maximum(h, d); + } + + l *= (1.0f / 255.0f); + h *= (1.0f / 255.0f); + + vec4F b0 = vec4F_mul(&axis, l); + vec4F b1 = vec4F_mul(&axis, h); + vec4F c0 = vec4F_add(&meanColor, &b0); + vec4F c1 = vec4F_add(&meanColor, &b1); + minColor = vec4F_saturate(&c0); + maxColor = vec4F_saturate(&c1); + if (minColor.c[3] > maxColor.c[3]) + { + // VS 2019 release Code Generator issue + //std::swap(minColor, maxColor); + + float a = minColor.c[0], b = minColor.c[1], c = minColor.c[2], d = minColor.c[3]; + minColor.c[0] = maxColor.c[0]; minColor.c[1] = maxColor.c[1]; minColor.c[2] = maxColor.c[2]; minColor.c[3] = maxColor.c[3]; + minColor.c[0] = maxColor.c[0]; minColor.c[1] = maxColor.c[1]; minColor.c[2] = maxColor.c[2]; minColor.c[3] = maxColor.c[3]; + maxColor.c[0] = a; maxColor.c[1] = b; maxColor.c[2] = c; maxColor.c[3] = d; + } + } + else + { + // We know the RGB axis is luma, because it's an ETC1S block and none of the block colors got clamped. So we only need to use 2D PCA. + // We project each LA vector onto two 2D lines with axes (1,1) and (1,-1) and find the largest projection to determine if axis A is flipped relative to L. + uint32_t block_cols_l[4], block_cols_a[4]; + for (uint32_t i = 0; i < 4; i++) + { + block_cols_l[i] = block_cols[i].r + block_cols[i].g + block_cols[i].b; + block_cols_a[i] = block_cols[i].a * 3; + } + + int p0_min = INT_MAX, p0_max = INT_MIN; + int p1_min = INT_MAX, p1_max = INT_MIN; + for (uint32_t y = 0; y < 4; y++) + { + const uint32_t cs = pSelector->m_selectors[y]; + const uint32_t as = alpha_selectors.m_selectors[y]; + + { + const int l = block_cols_l[cs & 3]; + const int a = block_cols_a[as & 3]; + const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0); + const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1); + } + { + const int l = block_cols_l[(cs >> 2) & 3]; + const int a = block_cols_a[(as >> 2) & 3]; + const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0); + const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1); + } + { + const int l = block_cols_l[(cs >> 4) & 3]; + const int a = block_cols_a[(as >> 4) & 3]; + const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0); + const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1); + } + { + const int l = block_cols_l[cs >> 6]; + const int a = block_cols_a[as >> 6]; + const int p0 = l + a; p0_min = basisu::minimum(p0_min, p0); p0_max = basisu::maximum(p0_max, p0); + const int p1 = l - a; p1_min = basisu::minimum(p1_min, p1); p1_max = basisu::maximum(p1_max, p1); + } + } + + int dist0 = p0_max - p0_min; + int dist1 = p1_max - p1_min; + + const float S = 1.0f / 255.0f; + + vec4F_set(&minColor, block_cols[low_selector].r * S, block_cols[low_selector].g * S, block_cols[low_selector].b * S, block_cols[alpha_selectors.m_lo_selector].a * S); + vec4F_set(&maxColor, block_cols[high_selector].r * S, block_cols[high_selector].g * S, block_cols[high_selector].b * S, block_cols[alpha_selectors.m_hi_selector].a * S); + + // See if the A component of the principle axis is flipped relative to L. If so, we need to flip either RGB or A bounds. + if (dist1 > dist0) + { + std::swap(minColor.c[0], maxColor.c[0]); + std::swap(minColor.c[1], maxColor.c[1]); + std::swap(minColor.c[2], maxColor.c[2]); + } + } + + // 4433 4443 + color32 trialMinColor, trialMaxColor; + + trialMinColor.set_clamped((int)(minColor.c[0] * 15.0f + .5f), (int)(minColor.c[1] * 15.0f + .5f), (int)(minColor.c[2] * 7.0f + .5f), (int)(minColor.c[3] * 7.0f + .5f)); + trialMaxColor.set_clamped((int)(maxColor.c[0] * 15.0f + .5f), (int)(maxColor.c[1] * 15.0f + .5f), (int)(maxColor.c[2] * 15.0f + .5f), (int)(maxColor.c[3] * 7.0f + .5f)); + + pBlock->set_trans_low_color(trialMinColor.r, trialMinColor.g, trialMinColor.b, trialMinColor.a); + pBlock->set_trans_high_color(trialMaxColor.r, trialMaxColor.g, trialMaxColor.b, trialMaxColor.a); + + color32 color_a((trialMinColor.r << 1) | (trialMinColor.r >> 3), (trialMinColor.g << 1) | (trialMinColor.g >> 3), (trialMinColor.b << 2) | (trialMinColor.b >> 1), trialMinColor.a << 1); + color32 color_b((trialMaxColor.r << 1) | (trialMaxColor.r >> 3), (trialMaxColor.g << 1) | (trialMaxColor.g >> 3), (trialMaxColor.b << 1) | (trialMaxColor.b >> 3), (trialMaxColor.a << 1) | 1); + + color32 color0(convert_rgba_5554_to_8888(color_a)); + color32 color3(convert_rgba_5554_to_8888(color_b)); + + const int lr = color0.r; + const int lg = color0.g; + const int lb = color0.b; + const int la = color0.a; + + const int axis_r = color3.r - lr; + const int axis_g = color3.g - lg; + const int axis_b = color3.b - lb; + const int axis_a = color3.a - la; + const int len_a = (axis_r * axis_r) + (axis_g * axis_g) + (axis_b * axis_b) + (axis_a * axis_a); + + const int thresh01 = (len_a * 3) / 16; + const int thresh12 = len_a >> 1; + const int thresh23 = (len_a * 13) / 16; + + if ((axis_r | axis_g | axis_b) == 0) + { + int ca_sel[4]; + + for (uint32_t i = 0; i < 4; i++) + { + int ca = (block_cols[i].a - la) * axis_a; + ca_sel[i] = (ca >= thresh23) + (ca >= thresh12) + (ca >= thresh01); + } + + for (uint32_t y = 0; y < 4; y++) + { + const uint32_t a_sels = alpha_selectors.m_selectors[y]; + + uint32_t sel = ca_sel[a_sels & 3] | (ca_sel[(a_sels >> 2) & 3] << 2) | (ca_sel[(a_sels >> 4) & 3] << 4) | (ca_sel[a_sels >> 6] << 6); + + pBlock->m_modulation[y] = (uint8_t)sel; + } + } + else + { + int cy[4], ca[4]; + + for (uint32_t i = 0; i < 4; i++) + { + cy[i] = (block_cols[i].r - lr) * axis_r + (block_cols[i].g - lg) * axis_g + (block_cols[i].b - lb) * axis_b; + ca[i] = (block_cols[i].a - la) * axis_a; + } + + for (uint32_t y = 0; y < 4; y++) + { + const uint32_t c_sels = pSelector->m_selectors[y]; + const uint32_t a_sels = alpha_selectors.m_selectors[y]; + + const int d0 = cy[c_sels & 3] + ca[a_sels & 3]; + const int d1 = cy[(c_sels >> 2) & 3] + ca[(a_sels >> 2) & 3]; + const int d2 = cy[(c_sels >> 4) & 3] + ca[(a_sels >> 4) & 3]; + const int d3 = cy[c_sels >> 6] + ca[a_sels >> 6]; + + uint32_t sel = ((d0 >= thresh23) + (d0 >= thresh12) + (d0 >= thresh01)) | + (((d1 >= thresh23) + (d1 >= thresh12) + (d1 >= thresh01)) << 2) | + (((d2 >= thresh23) + (d2 >= thresh12) + (d2 >= thresh01)) << 4) | + (((d3 >= thresh23) + (d3 >= thresh12) + (d3 >= thresh01)) << 6); + + pBlock->m_modulation[y] = (uint8_t)sel; + } + } + } + + static void transcoder_init_pvrtc2() + { + for (uint32_t v = 0; v < 256; v++) + { + int best_l = 0, best_h = 0, lowest_err = INT_MAX; + + for (uint32_t l = 0; l < 8; l++) + { + uint32_t le = (l << 1); + le = (le << 4) | le; + + for (uint32_t h = 0; h < 8; h++) + { + uint32_t he = (h << 1) | 1; + he = (he << 4) | he; + + uint32_t m = (le * 5 + he * 3) / 8; + + int err = (int)labs((int)v - (int)m); + if (err < lowest_err) + { + lowest_err = err; + best_l = l; + best_h = h; + } + } + } + + g_pvrtc2_alpha_match33[v].m_l = (uint8_t)best_l; + g_pvrtc2_alpha_match33[v].m_h = (uint8_t)best_h; + } + + for (uint32_t v = 0; v < 256; v++) + { + int best_l = 0, best_h = 0, lowest_err = INT_MAX; + + for (uint32_t l = 0; l < 8; l++) + { + uint32_t le = (l << 1); + le = (le << 4) | le; + + int err = (int)labs((int)v - (int)le); + if (err < lowest_err) + { + lowest_err = err; + best_l = l; + best_h = l; + } + } + + g_pvrtc2_alpha_match33_0[v].m_l = (uint8_t)best_l; + g_pvrtc2_alpha_match33_0[v].m_h = (uint8_t)best_h; + } + + for (uint32_t v = 0; v < 256; v++) + { + int best_l = 0, best_h = 0, lowest_err = INT_MAX; + + for (uint32_t h = 0; h < 8; h++) + { + uint32_t he = (h << 1) | 1; + he = (he << 4) | he; + + int err = (int)labs((int)v - (int)he); + if (err < lowest_err) + { + lowest_err = err; + best_l = h; + best_h = h; + } + } + + g_pvrtc2_alpha_match33_3[v].m_l = (uint8_t)best_l; + g_pvrtc2_alpha_match33_3[v].m_h = (uint8_t)best_h; + } + + for (uint32_t v = 0; v < 256; v++) + { + int best_l = 0, best_h = 0, lowest_err = INT_MAX; + + for (uint32_t l = 0; l < 8; l++) + { + uint32_t le = (l << 2) | (l >> 1); + le = (le << 3) | (le >> 2); + + for (uint32_t h = 0; h < 16; h++) + { + uint32_t he = (h << 1) | (h >> 3); + he = (he << 3) | (he >> 2); + + uint32_t m = (le * 5 + he * 3) / 8; + + int err = (int)labs((int)v - (int)m); + if (err < lowest_err) + { + lowest_err = err; + best_l = l; + best_h = h; + } + } + } + + g_pvrtc2_trans_match34[v].m_l = (uint8_t)best_l; + g_pvrtc2_trans_match34[v].m_h = (uint8_t)best_h; + } + + for (uint32_t v = 0; v < 256; v++) + { + int best_l = 0, best_h = 0, lowest_err = INT_MAX; + + for (uint32_t l = 0; l < 16; l++) + { + uint32_t le = (l << 1) | (l >> 3); + le = (le << 3) | (le >> 2); + + for (uint32_t h = 0; h < 16; h++) + { + uint32_t he = (h << 1) | (h >> 3); + he = (he << 3) | (he >> 2); + + uint32_t m = (le * 5 + he * 3) / 8; + + int err = (int)labs((int)v - (int)m); + if (err < lowest_err) + { + lowest_err = err; + best_l = l; + best_h = h; + } + } + } + + g_pvrtc2_trans_match44[v].m_l = (uint8_t)best_l; + g_pvrtc2_trans_match44[v].m_h = (uint8_t)best_h; + } + } +#endif // BASISD_SUPPORT_PVRTC2 + + basisu_lowlevel_etc1s_transcoder::basisu_lowlevel_etc1s_transcoder() : + m_pGlobal_codebook(nullptr), + m_selector_history_buf_size(0) + { + } + + bool basisu_lowlevel_etc1s_transcoder::decode_palettes( + uint32_t num_endpoints, const uint8_t* pEndpoints_data, uint32_t endpoints_data_size, + uint32_t num_selectors, const uint8_t* pSelectors_data, uint32_t selectors_data_size) + { + if (m_pGlobal_codebook) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 11\n"); + return false; + } + bitwise_decoder sym_codec; + + huffman_decoding_table color5_delta_model0, color5_delta_model1, color5_delta_model2, inten_delta_model; + + if (!sym_codec.init(pEndpoints_data, endpoints_data_size)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 0\n"); + return false; + } + + if (!sym_codec.read_huffman_table(color5_delta_model0)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 1\n"); + return false; + } + + if (!sym_codec.read_huffman_table(color5_delta_model1)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 1a\n"); + return false; + } + + if (!sym_codec.read_huffman_table(color5_delta_model2)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 2a\n"); + return false; + } + + if (!sym_codec.read_huffman_table(inten_delta_model)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 2b\n"); + return false; + } + + if (!color5_delta_model0.is_valid() || !color5_delta_model1.is_valid() || !color5_delta_model2.is_valid() || !inten_delta_model.is_valid()) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 2b\n"); + return false; + } + + const bool endpoints_are_grayscale = sym_codec.get_bits(1) != 0; + + m_local_endpoints.resize(num_endpoints); + + color32 prev_color5(16, 16, 16, 0); + uint32_t prev_inten = 0; + + for (uint32_t i = 0; i < num_endpoints; i++) + { + uint32_t inten_delta = sym_codec.decode_huffman(inten_delta_model); + m_local_endpoints[i].m_inten5 = static_cast((inten_delta + prev_inten) & 7); + prev_inten = m_local_endpoints[i].m_inten5; + + for (uint32_t c = 0; c < (endpoints_are_grayscale ? 1U : 3U); c++) + { + int delta; + if (prev_color5[c] <= basist::COLOR5_PAL0_PREV_HI) + delta = sym_codec.decode_huffman(color5_delta_model0); + else if (prev_color5[c] <= basist::COLOR5_PAL1_PREV_HI) + delta = sym_codec.decode_huffman(color5_delta_model1); + else + delta = sym_codec.decode_huffman(color5_delta_model2); + + int v = (prev_color5[c] + delta) & 31; + + m_local_endpoints[i].m_color5[c] = static_cast(v); + + prev_color5[c] = static_cast(v); + } + + if (endpoints_are_grayscale) + { + m_local_endpoints[i].m_color5[1] = m_local_endpoints[i].m_color5[0]; + m_local_endpoints[i].m_color5[2] = m_local_endpoints[i].m_color5[0]; + } + } + + sym_codec.stop(); + + m_local_selectors.resize(num_selectors); + + if (!sym_codec.init(pSelectors_data, selectors_data_size)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 5\n"); + return false; + } + + basist::huffman_decoding_table delta_selector_pal_model; + + const bool used_global_selector_cb = (sym_codec.get_bits(1) == 1); + + if (used_global_selector_cb) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: global selector codebooks are unsupported\n"); + return false; + } + else + { + const bool used_hybrid_selector_cb = (sym_codec.get_bits(1) == 1); + + if (used_hybrid_selector_cb) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: hybrid global selector codebooks are unsupported\n"); + return false; + } + + const bool used_raw_encoding = (sym_codec.get_bits(1) == 1); + + if (used_raw_encoding) + { + for (uint32_t i = 0; i < num_selectors; i++) + { + for (uint32_t j = 0; j < 4; j++) + { + uint32_t cur_byte = sym_codec.get_bits(8); + + for (uint32_t k = 0; k < 4; k++) + m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3); + } + + m_local_selectors[i].init_flags(); + } + } + else + { + if (!sym_codec.read_huffman_table(delta_selector_pal_model)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 10\n"); + return false; + } + + if ((num_selectors > 1) && (!delta_selector_pal_model.is_valid())) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_palettes: fail 10a\n"); + return false; + } + + uint8_t prev_bytes[4] = { 0, 0, 0, 0 }; + + for (uint32_t i = 0; i < num_selectors; i++) + { + if (!i) + { + for (uint32_t j = 0; j < 4; j++) + { + uint32_t cur_byte = sym_codec.get_bits(8); + prev_bytes[j] = static_cast(cur_byte); + + for (uint32_t k = 0; k < 4; k++) + m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3); + } + m_local_selectors[i].init_flags(); + continue; + } + + for (uint32_t j = 0; j < 4; j++) + { + int delta_byte = sym_codec.decode_huffman(delta_selector_pal_model); + + uint32_t cur_byte = delta_byte ^ prev_bytes[j]; + prev_bytes[j] = static_cast(cur_byte); + + for (uint32_t k = 0; k < 4; k++) + m_local_selectors[i].set_selector(k, j, (cur_byte >> (k * 2)) & 3); + } + m_local_selectors[i].init_flags(); + } + } + } + + sym_codec.stop(); + + return true; + } + + bool basisu_lowlevel_etc1s_transcoder::decode_tables(const uint8_t* pTable_data, uint32_t table_data_size) + { + basist::bitwise_decoder sym_codec; + if (!sym_codec.init(pTable_data, table_data_size)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 0\n"); + return false; + } + + if (!sym_codec.read_huffman_table(m_endpoint_pred_model)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 1\n"); + return false; + } + + if (m_endpoint_pred_model.get_code_sizes().size() == 0) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 1a\n"); + return false; + } + + if (!sym_codec.read_huffman_table(m_delta_endpoint_model)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 2\n"); + return false; + } + + if (m_delta_endpoint_model.get_code_sizes().size() == 0) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 2a\n"); + return false; + } + + if (!sym_codec.read_huffman_table(m_selector_model)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 3\n"); + return false; + } + + if (m_selector_model.get_code_sizes().size() == 0) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 3a\n"); + return false; + } + + if (!sym_codec.read_huffman_table(m_selector_history_buf_rle_model)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 4\n"); + return false; + } + + if (m_selector_history_buf_rle_model.get_code_sizes().size() == 0) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 4a\n"); + return false; + } + + m_selector_history_buf_size = sym_codec.get_bits(13); + // Check for bogus values. + if (!m_selector_history_buf_size) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::decode_tables: fail 5\n"); + return false; + } + + sym_codec.stop(); + + return true; + } + + bool basisu_lowlevel_etc1s_transcoder::transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const bool is_video, const bool is_alpha_slice, const uint32_t level_index, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels, + basisu_transcoder_state* pState, bool transcode_alpha, void *pAlpha_blocks, uint32_t output_rows_in_pixels) + { + // 'pDst_blocks' unused when disabling *all* hardware transcode options + // (and 'bc1_allow_threecolor_blocks' when disabling DXT) + BASISU_NOTE_UNUSED(pDst_blocks); + BASISU_NOTE_UNUSED(bc1_allow_threecolor_blocks); + BASISU_NOTE_UNUSED(transcode_alpha); + BASISU_NOTE_UNUSED(pAlpha_blocks); + + assert(g_transcoder_initialized); + if (!g_transcoder_initialized) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: Transcoder not globally initialized.\n"); + return false; + } + + if (!pState) + pState = &m_def_state; + + const uint32_t total_blocks = num_blocks_x * num_blocks_y; + + if (!output_row_pitch_in_blocks_or_pixels) + { + if (basis_block_format_is_uncompressed(fmt)) + output_row_pitch_in_blocks_or_pixels = orig_width; + else + { + if (fmt == block_format::cFXT1_RGB) + output_row_pitch_in_blocks_or_pixels = (orig_width + 7) / 8; + else + output_row_pitch_in_blocks_or_pixels = num_blocks_x; + } + } + + if (basis_block_format_is_uncompressed(fmt)) + { + if (!output_rows_in_pixels) + output_rows_in_pixels = orig_height; + } + + basisu::vector* pPrev_frame_indices = nullptr; + if (is_video) + { + // TODO: Add check to make sure the caller hasn't tried skipping past p-frames + //const bool alpha_flag = (slice_desc.m_flags & cSliceDescFlagsHasAlpha) != 0; + //const uint32_t level_index = slice_desc.m_level_index; + + if (level_index >= basisu_transcoder_state::cMaxPrevFrameLevels) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: unsupported level_index\n"); + return false; + } + + pPrev_frame_indices = &pState->m_prev_frame_indices[is_alpha_slice][level_index]; + if (pPrev_frame_indices->size() < total_blocks) + pPrev_frame_indices->resize(total_blocks); + } + + basist::bitwise_decoder sym_codec; + + if (!sym_codec.init(pImage_data, image_data_size)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: sym_codec.init failed\n"); + return false; + } + + approx_move_to_front selector_history_buf(m_selector_history_buf_size); + + uint32_t cur_selector_rle_count = 0; + + decoder_etc_block block; + memset(&block, 0, sizeof(block)); + + //block.set_flip_bit(true); + // Setting the flip bit to false to be compatible with the Khronos KDFS. + block.set_flip_bit(false); + + block.set_diff_bit(true); + + void* pPVRTC_work_mem = nullptr; + uint32_t* pPVRTC_endpoints = nullptr; + if ((fmt == block_format::cPVRTC1_4_RGB) || (fmt == block_format::cPVRTC1_4_RGBA)) + { + pPVRTC_work_mem = malloc(num_blocks_x * num_blocks_y * (sizeof(decoder_etc_block) + sizeof(uint32_t))); + if (!pPVRTC_work_mem) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: malloc failed\n"); + return false; + } + pPVRTC_endpoints = (uint32_t*) & ((decoder_etc_block*)pPVRTC_work_mem)[num_blocks_x * num_blocks_y]; + } + + if (pState->m_block_endpoint_preds[0].size() < num_blocks_x) + { + pState->m_block_endpoint_preds[0].resize(num_blocks_x); + pState->m_block_endpoint_preds[1].resize(num_blocks_x); + } + + uint32_t cur_pred_bits = 0; + int prev_endpoint_pred_sym = 0; + int endpoint_pred_repeat_count = 0; + uint32_t prev_endpoint_index = 0; + const endpoint_vec& endpoints = m_pGlobal_codebook ? m_pGlobal_codebook->m_local_endpoints : m_local_endpoints; + const selector_vec& selectors = m_pGlobal_codebook ? m_pGlobal_codebook->m_local_selectors : m_local_selectors; + if (!endpoints.size() || !selectors.size()) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: global codebooks must be unpacked first\n"); + return false; + } + + const uint32_t SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX = (uint32_t)selectors.size(); + const uint32_t SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX = m_selector_history_buf_size + SELECTOR_HISTORY_BUF_FIRST_SYMBOL_INDEX; + + for (uint32_t block_y = 0; block_y < num_blocks_y; block_y++) + { + const uint32_t cur_block_endpoint_pred_array = block_y & 1; + + for (uint32_t block_x = 0; block_x < num_blocks_x; block_x++) + { + // Decode endpoint index predictor symbols + if ((block_x & 1) == 0) + { + if ((block_y & 1) == 0) + { + if (endpoint_pred_repeat_count) + { + endpoint_pred_repeat_count--; + cur_pred_bits = prev_endpoint_pred_sym; + } + else + { + cur_pred_bits = sym_codec.decode_huffman(m_endpoint_pred_model); + if (cur_pred_bits == ENDPOINT_PRED_REPEAT_LAST_SYMBOL) + { + endpoint_pred_repeat_count = sym_codec.decode_vlc(ENDPOINT_PRED_COUNT_VLC_BITS) + ENDPOINT_PRED_MIN_REPEAT_COUNT - 1; + + cur_pred_bits = prev_endpoint_pred_sym; + } + else + { + prev_endpoint_pred_sym = cur_pred_bits; + } + } + + pState->m_block_endpoint_preds[cur_block_endpoint_pred_array ^ 1][block_x].m_pred_bits = (uint8_t)(cur_pred_bits >> 4); + } + else + { + cur_pred_bits = pState->m_block_endpoint_preds[cur_block_endpoint_pred_array][block_x].m_pred_bits; + } + } + + // Decode endpoint index + uint32_t endpoint_index, selector_index = 0; + + const uint32_t pred = cur_pred_bits & 3; + cur_pred_bits >>= 2; + + if (pred == 0) + { + // Left + if (!block_x) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: invalid datastream (0)\n"); + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + return false; + } + + endpoint_index = prev_endpoint_index; + } + else if (pred == 1) + { + // Upper + if (!block_y) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: invalid datastream (1)\n"); + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + return false; + } + + endpoint_index = pState->m_block_endpoint_preds[cur_block_endpoint_pred_array ^ 1][block_x].m_endpoint_index; + } + else if (pred == 2) + { + if (is_video) + { + assert(pred == CR_ENDPOINT_PRED_INDEX); + endpoint_index = (*pPrev_frame_indices)[block_x + block_y * num_blocks_x]; + selector_index = endpoint_index >> 16; + endpoint_index &= 0xFFFFU; + } + else + { + // Upper left + if ((!block_x) || (!block_y)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: invalid datastream (2)\n"); + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + return false; + } + + endpoint_index = pState->m_block_endpoint_preds[cur_block_endpoint_pred_array ^ 1][block_x - 1].m_endpoint_index; + } + } + else + { + // Decode and apply delta + const uint32_t delta_sym = sym_codec.decode_huffman(m_delta_endpoint_model); + + endpoint_index = delta_sym + prev_endpoint_index; + if (endpoint_index >= endpoints.size()) + endpoint_index -= (int)endpoints.size(); + } + + pState->m_block_endpoint_preds[cur_block_endpoint_pred_array][block_x].m_endpoint_index = (uint16_t)endpoint_index; + + prev_endpoint_index = endpoint_index; + + // Decode selector index + if ((!is_video) || (pred != CR_ENDPOINT_PRED_INDEX)) + { + int selector_sym; + if (cur_selector_rle_count > 0) + { + cur_selector_rle_count--; + + selector_sym = (int)selectors.size(); + } + else + { + selector_sym = sym_codec.decode_huffman(m_selector_model); + + if (selector_sym == static_cast(SELECTOR_HISTORY_BUF_RLE_SYMBOL_INDEX)) + { + int run_sym = sym_codec.decode_huffman(m_selector_history_buf_rle_model); + + if (run_sym == (SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL - 1)) + cur_selector_rle_count = sym_codec.decode_vlc(7) + SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH; + else + cur_selector_rle_count = run_sym + SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH; + + if (cur_selector_rle_count > total_blocks) + { + // The file is corrupted or we've got a bug. + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: invalid datastream (3)\n"); + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + return false; + } + + selector_sym = (int)selectors.size(); + + cur_selector_rle_count--; + } + } + + if (selector_sym >= (int)selectors.size()) + { + assert(m_selector_history_buf_size > 0); + + int history_buf_index = selector_sym - (int)selectors.size(); + + if (history_buf_index >= (int)selector_history_buf.size()) + { + // The file is corrupted or we've got a bug. + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: invalid datastream (4)\n"); + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + return false; + } + + selector_index = selector_history_buf[history_buf_index]; + + if (history_buf_index != 0) + selector_history_buf.use(history_buf_index); + } + else + { + selector_index = selector_sym; + + if (m_selector_history_buf_size) + selector_history_buf.add(selector_index); + } + } + + if ((endpoint_index >= endpoints.size()) || (selector_index >= selectors.size())) + { + // The file is corrupted or we've got a bug. + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: invalid datastream (5)\n"); + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + return false; + } + + if (is_video) + (*pPrev_frame_indices)[block_x + block_y * num_blocks_x] = endpoint_index | (selector_index << 16); + +#if BASISD_ENABLE_DEBUG_FLAGS + if ((g_debug_flags & cDebugFlagVisCRs) && ((fmt == block_format::cETC1) || (fmt == block_format::cBC1))) + { + if ((is_video) && (pred == 2)) + { + decoder_etc_block* pDst_block = reinterpret_cast(static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes); + memset(pDst_block, 0xFF, 8); + continue; + } + } +#endif + + const endpoint* pEndpoints = &endpoints[endpoint_index]; + const selector* pSelector = &selectors[selector_index]; + + switch (fmt) + { + case block_format::cETC1: + { + decoder_etc_block* pDst_block = reinterpret_cast(static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes); + + block.set_base5_color(decoder_etc_block::pack_color5(pEndpoints->m_color5, false)); + block.set_inten_table(0, pEndpoints->m_inten5); + block.set_inten_table(1, pEndpoints->m_inten5); + + pDst_block->m_uint32[0] = block.m_uint32[0]; + pDst_block->set_raw_selector_bits(pSelector->m_bytes[0], pSelector->m_bytes[1], pSelector->m_bytes[2], pSelector->m_bytes[3]); + + break; + } + case block_format::cBC1: + { +#if BASISD_SUPPORT_DXT1 + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; +#if BASISD_ENABLE_DEBUG_FLAGS + if (g_debug_flags & (cDebugFlagVisBC1Sels | cDebugFlagVisBC1Endpoints)) + convert_etc1s_to_dxt1_vis(static_cast(pDst_block), pEndpoints, pSelector, bc1_allow_threecolor_blocks); + else +#endif + convert_etc1s_to_dxt1(static_cast(pDst_block), pEndpoints, pSelector, bc1_allow_threecolor_blocks); +#else + assert(0); +#endif + break; + } + case block_format::cBC4: + { +#if BASISD_SUPPORT_DXT5A + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_dxt5a(static_cast(pDst_block), pEndpoints, pSelector); +#else + assert(0); +#endif + break; + } + case block_format::cPVRTC1_4_RGB: + { +#if BASISD_SUPPORT_PVRTC1 + block.set_base5_color(decoder_etc_block::pack_color5(pEndpoints->m_color5, false)); + block.set_inten_table(0, pEndpoints->m_inten5); + block.set_inten_table(1, pEndpoints->m_inten5); + block.set_raw_selector_bits(pSelector->m_bytes[0], pSelector->m_bytes[1], pSelector->m_bytes[2], pSelector->m_bytes[3]); + + ((decoder_etc_block*)pPVRTC_work_mem)[block_x + block_y * num_blocks_x] = block; + + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + + // Get block's RGB bounding box + color32 block_colors[2]; + decoder_etc_block::get_block_colors5_bounds(block_colors, base_color, inten_table, low_selector, high_selector); + + assert(block_colors[0][0] <= block_colors[1][0]); + assert(block_colors[0][1] <= block_colors[1][1]); + assert(block_colors[0][2] <= block_colors[1][2]); + + // Set PVRTC1 endpoints to floor/ceil of bounding box's coordinates. + pvrtc4_block temp; + temp.set_opaque_endpoint_floor(0, block_colors[0]); + temp.set_opaque_endpoint_ceil(1, block_colors[1]); + + pPVRTC_endpoints[block_x + block_y * num_blocks_x] = temp.m_endpoints; +#else + assert(0); +#endif + + break; + } + case block_format::cPVRTC1_4_RGBA: + { +#if BASISD_SUPPORT_PVRTC1 + assert(pAlpha_blocks); + + block.set_base5_color(decoder_etc_block::pack_color5(pEndpoints->m_color5, false)); + block.set_inten_table(0, pEndpoints->m_inten5); + block.set_inten_table(1, pEndpoints->m_inten5); + block.set_raw_selector_bits(pSelector->m_selectors[0], pSelector->m_selectors[1], pSelector->m_selectors[2], pSelector->m_selectors[3]); + + ((decoder_etc_block*)pPVRTC_work_mem)[block_x + block_y * num_blocks_x] = block; + + // Get block's RGBA bounding box + const color32& base_color = pEndpoints->m_color5; + const uint32_t inten_table = pEndpoints->m_inten5; + const uint32_t low_selector = pSelector->m_lo_selector; + const uint32_t high_selector = pSelector->m_hi_selector; + color32 block_colors[2]; + decoder_etc_block::get_block_colors5_bounds(block_colors, base_color, inten_table, low_selector, high_selector); + + assert(block_colors[0][0] <= block_colors[1][0]); + assert(block_colors[0][1] <= block_colors[1][1]); + assert(block_colors[0][2] <= block_colors[1][2]); + + const uint16_t* pAlpha_block = reinterpret_cast(static_cast(pAlpha_blocks) + (block_x + block_y * num_blocks_x) * sizeof(uint32_t)); + + const endpoint* pAlpha_endpoints = &endpoints[pAlpha_block[0]]; + const selector* pAlpha_selector = &selectors[pAlpha_block[1]]; + + const color32& alpha_base_color = pAlpha_endpoints->m_color5; + const uint32_t alpha_inten_table = pAlpha_endpoints->m_inten5; + const uint32_t alpha_low_selector = pAlpha_selector->m_lo_selector; + const uint32_t alpha_high_selector = pAlpha_selector->m_hi_selector; + uint32_t alpha_block_colors[2]; + decoder_etc_block::get_block_colors5_bounds_g(alpha_block_colors, alpha_base_color, alpha_inten_table, alpha_low_selector, alpha_high_selector); + assert(alpha_block_colors[0] <= alpha_block_colors[1]); + block_colors[0].a = (uint8_t)alpha_block_colors[0]; + block_colors[1].a = (uint8_t)alpha_block_colors[1]; + + // Set PVRTC1 endpoints to floor/ceil of bounding box's coordinates. + pvrtc4_block temp; + temp.set_endpoint_floor(0, block_colors[0]); + temp.set_endpoint_ceil(1, block_colors[1]); + + pPVRTC_endpoints[block_x + block_y * num_blocks_x] = temp.m_endpoints; +#else + assert(0); +#endif + + break; + } + case block_format::cBC7: // for more consistency with UASTC + case block_format::cBC7_M5_COLOR: + { +#if BASISD_SUPPORT_BC7_MODE5 + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_bc7_m5_color(pDst_block, pEndpoints, pSelector); +#else + assert(0); +#endif + break; + } + case block_format::cBC7_M5_ALPHA: + { +#if BASISD_SUPPORT_BC7_MODE5 + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_bc7_m5_alpha(pDst_block, pEndpoints, pSelector); +#else + assert(0); +#endif + break; + } + case block_format::cETC2_EAC_A8: + { +#if BASISD_SUPPORT_ETC2_EAC_A8 + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_etc2_eac_a8(static_cast(pDst_block), pEndpoints, pSelector); +#else + assert(0); +#endif + break; + } + case block_format::cASTC_4x4: + { +#if BASISD_SUPPORT_ASTC + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_astc_4x4(pDst_block, pEndpoints, pSelector, transcode_alpha, &endpoints[0], &selectors[0]); +#else + assert(0); +#endif + break; + } + case block_format::cATC_RGB: + { +#if BASISD_SUPPORT_ATC + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_atc(pDst_block, pEndpoints, pSelector); +#else + assert(0); +#endif + break; + } + case block_format::cFXT1_RGB: + { +#if BASISD_SUPPORT_FXT1 + const uint32_t fxt1_block_x = block_x >> 1; + const uint32_t fxt1_block_y = block_y; + const uint32_t fxt1_subblock = block_x & 1; + + void* pDst_block = static_cast(pDst_blocks) + (fxt1_block_x + fxt1_block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + + convert_etc1s_to_fxt1(pDst_block, pEndpoints, pSelector, fxt1_subblock); +#else + assert(0); +#endif + break; + } + case block_format::cPVRTC2_4_RGB: + { +#if BASISD_SUPPORT_PVRTC2 + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_pvrtc2_rgb(pDst_block, pEndpoints, pSelector); +#endif + break; + } + case block_format::cPVRTC2_4_RGBA: + { +#if BASISD_SUPPORT_PVRTC2 + assert(transcode_alpha); + + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + + convert_etc1s_to_pvrtc2_rgba(pDst_block, pEndpoints, pSelector, &endpoints[0], &selectors[0]); +#endif + break; + } + case block_format::cIndices: + { + uint16_t* pDst_block = reinterpret_cast(static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes); + pDst_block[0] = static_cast(endpoint_index); + pDst_block[1] = static_cast(selector_index); + break; + } + case block_format::cA32: + { + assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + int colors[4]; + decoder_etc_block::get_block_colors5_g(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + if (max_x == 4) + { + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + pDst_pixels[3] = static_cast(colors[s & 3]); + pDst_pixels[3+4] = static_cast(colors[(s >> 2) & 3]); + pDst_pixels[3+8] = static_cast(colors[(s >> 4) & 3]); + pDst_pixels[3+12] = static_cast(colors[(s >> 6) & 3]); + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t); + } + } + else + { + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + pDst_pixels[3 + 4 * x] = static_cast(colors[(s >> (x * 2)) & 3]); + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t); + } + } + + break; + } + case block_format::cRGB32: + { + assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + color32 colors[4]; + decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + { + const color32& c = colors[(s >> (x * 2)) & 3]; + + pDst_pixels[0 + 4 * x] = c.r; + pDst_pixels[1 + 4 * x] = c.g; + pDst_pixels[2 + 4 * x] = c.b; + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t); + } + + break; + } + case block_format::cRGBA32: + { + assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + color32 colors[4]; + decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + { + const color32& c = colors[(s >> (x * 2)) & 3]; + + pDst_pixels[0 + 4 * x] = c.r; + pDst_pixels[1 + 4 * x] = c.g; + pDst_pixels[2 + 4 * x] = c.b; + pDst_pixels[3 + 4 * x] = 255; + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t); + } + + break; + } + case block_format::cRGB565: + case block_format::cBGR565: + { + assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + color32 colors[4]; + decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + uint16_t packed_colors[4]; + if (fmt == block_format::cRGB565) + { + for (uint32_t i = 0; i < 4; i++) + { + packed_colors[i] = static_cast((mul_8(colors[i].r, 31) << 11) | (mul_8(colors[i].g, 63) << 5) | mul_8(colors[i].b, 31)); + if (BASISD_IS_BIG_ENDIAN) + packed_colors[i] = byteswap_uint16(packed_colors[i]); + } + } + else + { + for (uint32_t i = 0; i < 4; i++) + { + packed_colors[i] = static_cast((mul_8(colors[i].b, 31) << 11) | (mul_8(colors[i].g, 63) << 5) | mul_8(colors[i].r, 31)); + if (BASISD_IS_BIG_ENDIAN) + packed_colors[i] = byteswap_uint16(packed_colors[i]); + } + } + + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + reinterpret_cast(pDst_pixels)[x] = packed_colors[(s >> (x * 2)) & 3]; + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t); + } + + break; + } + case block_format::cRGBA4444_COLOR: + { + assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + color32 colors[4]; + decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + uint16_t packed_colors[4]; + for (uint32_t i = 0; i < 4; i++) + { + packed_colors[i] = static_cast((mul_8(colors[i].r, 15) << 12) | (mul_8(colors[i].g, 15) << 8) | (mul_8(colors[i].b, 15) << 4)); + } + + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + { + uint16_t cur = reinterpret_cast(pDst_pixels)[x]; + if (BASISD_IS_BIG_ENDIAN) + cur = byteswap_uint16(cur); + + cur = (cur & 0xF) | packed_colors[(s >> (x * 2)) & 3]; + + if (BASISD_IS_BIG_ENDIAN) + cur = byteswap_uint16(cur); + + reinterpret_cast(pDst_pixels)[x] = cur; + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t); + } + + break; + } + case block_format::cRGBA4444_COLOR_OPAQUE: + { + assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + color32 colors[4]; + decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + uint16_t packed_colors[4]; + for (uint32_t i = 0; i < 4; i++) + { + packed_colors[i] = static_cast((mul_8(colors[i].r, 15) << 12) | (mul_8(colors[i].g, 15) << 8) | (mul_8(colors[i].b, 15) << 4) | 0xF); + if (BASISD_IS_BIG_ENDIAN) + packed_colors[i] = byteswap_uint16(packed_colors[i]); + } + + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + reinterpret_cast(pDst_pixels)[x] = packed_colors[(s >> (x * 2)) & 3]; + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t); + } + + break; + } + case block_format::cRGBA4444_ALPHA: + { + assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + color32 colors[4]; + decoder_etc_block::get_block_colors5(colors, pEndpoints->m_color5, pEndpoints->m_inten5); + + uint16_t packed_colors[4]; + for (uint32_t i = 0; i < 4; i++) + { + packed_colors[i] = mul_8(colors[i].g, 15); + if (BASISD_IS_BIG_ENDIAN) + packed_colors[i] = byteswap_uint16(packed_colors[i]); + } + + for (uint32_t y = 0; y < max_y; y++) + { + const uint32_t s = pSelector->m_selectors[y]; + + for (uint32_t x = 0; x < max_x; x++) + { + reinterpret_cast(pDst_pixels)[x] = packed_colors[(s >> (x * 2)) & 3]; + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t); + } + + break; + } + case block_format::cETC2_EAC_R11: + { +#if BASISD_SUPPORT_ETC2_EAC_RG11 + void* pDst_block = static_cast(pDst_blocks) + (block_x + block_y * output_row_pitch_in_blocks_or_pixels) * output_block_or_pixel_stride_in_bytes; + convert_etc1s_to_etc2_eac_r11(static_cast(pDst_block), pEndpoints, pSelector); +#else + assert(0); +#endif + break; + } + default: + { + assert(0); + break; + } + } + + } // block_x + + } // block-y + + if (endpoint_pred_repeat_count != 0) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_slice: endpoint_pred_repeat_count != 0. The file is corrupted or this is a bug\n"); + return false; + } + + //assert(endpoint_pred_repeat_count == 0); + +#if BASISD_SUPPORT_PVRTC1 + // PVRTC post process - create per-pixel modulation values. + if (fmt == block_format::cPVRTC1_4_RGB) + fixup_pvrtc1_4_modulation_rgb((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y); + else if (fmt == block_format::cPVRTC1_4_RGBA) + fixup_pvrtc1_4_modulation_rgba((decoder_etc_block*)pPVRTC_work_mem, pPVRTC_endpoints, pDst_blocks, num_blocks_x, num_blocks_y, pAlpha_blocks, &endpoints[0], &selectors[0]); +#endif // BASISD_SUPPORT_PVRTC1 + + if (pPVRTC_work_mem) + free(pPVRTC_work_mem); + + return true; + } + + bool basis_validate_output_buffer_size(transcoder_texture_format target_format, + uint32_t output_blocks_buf_size_in_blocks_or_pixels, + uint32_t orig_width, uint32_t orig_height, + uint32_t output_row_pitch_in_blocks_or_pixels, + uint32_t output_rows_in_pixels, + uint32_t total_slice_blocks) + { + if (basis_transcoder_format_is_uncompressed(target_format)) + { + // Assume the output buffer is orig_width by orig_height + if (!output_row_pitch_in_blocks_or_pixels) + output_row_pitch_in_blocks_or_pixels = orig_width; + + if (!output_rows_in_pixels) + output_rows_in_pixels = orig_height; + + // Now make sure the output buffer is large enough, or we'll overwrite memory. + if (output_blocks_buf_size_in_blocks_or_pixels < (output_rows_in_pixels * output_row_pitch_in_blocks_or_pixels)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: output_blocks_buf_size_in_blocks_or_pixels < (output_rows_in_pixels * output_row_pitch_in_blocks_or_pixels)\n"); + return false; + } + } + else if (target_format == transcoder_texture_format::cTFFXT1_RGB) + { + const uint32_t num_blocks_fxt1_x = (orig_width + 7) / 8; + const uint32_t num_blocks_fxt1_y = (orig_height + 3) / 4; + const uint32_t total_blocks_fxt1 = num_blocks_fxt1_x * num_blocks_fxt1_y; + + if (output_blocks_buf_size_in_blocks_or_pixels < total_blocks_fxt1) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: output_blocks_buf_size_in_blocks_or_pixels < total_blocks_fxt1\n"); + return false; + } + } + else + { + if (output_blocks_buf_size_in_blocks_or_pixels < total_slice_blocks) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: output_blocks_buf_size_in_blocks_or_pixels < transcode_image\n"); + return false; + } + } + return true; + } + + bool basisu_lowlevel_etc1s_transcoder::transcode_image( + transcoder_texture_format target_format, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + const uint8_t* pCompressed_data, uint32_t compressed_data_length, + uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index, + uint32_t rgb_offset, uint32_t rgb_length, uint32_t alpha_offset, uint32_t alpha_length, + uint32_t decode_flags, + bool basis_file_has_alpha_slices, + bool is_video, + uint32_t output_row_pitch_in_blocks_or_pixels, + basisu_transcoder_state* pState, + uint32_t output_rows_in_pixels) + { + if (((uint64_t)rgb_offset + rgb_length) > (uint64_t)compressed_data_length) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: source data buffer too small (color)\n"); + return false; + } + + if (alpha_length) + { + if (((uint64_t)alpha_offset + alpha_length) > (uint64_t)compressed_data_length) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: source data buffer too small (alpha)\n"); + return false; + } + } + else + { + assert(!basis_file_has_alpha_slices); + } + + if ((target_format == transcoder_texture_format::cTFPVRTC1_4_RGB) || (target_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)) + { + if ((!basisu::is_pow2(num_blocks_x * 4)) || (!basisu::is_pow2(num_blocks_y * 4))) + { + // PVRTC1 only supports power of 2 dimensions + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: PVRTC1 only supports power of 2 dimensions\n"); + return false; + } + } + + if ((target_format == transcoder_texture_format::cTFPVRTC1_4_RGBA) && (!basis_file_has_alpha_slices)) + { + // Switch to PVRTC1 RGB if the input doesn't have alpha. + target_format = transcoder_texture_format::cTFPVRTC1_4_RGB; + } + + const bool transcode_alpha_data_to_opaque_formats = (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0; + const uint32_t bytes_per_block_or_pixel = basis_get_bytes_per_block_or_pixel(target_format); + const uint32_t total_slice_blocks = num_blocks_x * num_blocks_y; + + if (!basis_validate_output_buffer_size(target_format, output_blocks_buf_size_in_blocks_or_pixels, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, output_rows_in_pixels, total_slice_blocks)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: output buffer size too small\n"); + return false; + } + + bool status = false; + + const uint8_t* pData = pCompressed_data + rgb_offset; + uint32_t data_len = rgb_length; + bool is_alpha_slice = false; + + // If the caller wants us to transcode the mip level's alpha data, then use the next slice. + if ((basis_file_has_alpha_slices) && (transcode_alpha_data_to_opaque_formats)) + { + pData = pCompressed_data + alpha_offset; + data_len = alpha_length; + is_alpha_slice = true; + } + + switch (target_format) + { + case transcoder_texture_format::cTFETC1_RGB: + { + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC1, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cETC1, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ETC1 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBC1_RGB: + { +#if !BASISD_SUPPORT_DXT1 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: BC1/DXT1 unsupported\n"); + return false; +#else + // status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC1, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cBC1, bytes_per_block_or_pixel, true, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC1 failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFBC4_R: + { +#if !BASISD_SUPPORT_DXT5A + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: BC4/DXT5A unsupported\n"); + return false; +#else + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cBC4, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC4 failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFPVRTC1_4_RGB: + { +#if !BASISD_SUPPORT_PVRTC1 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: PVRTC1 4 unsupported\n"); + return false; +#else + // output_row_pitch_in_blocks_or_pixels is actually ignored because we're transcoding to PVRTC1. (Print a dev warning if it's != 0?) + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cPVRTC1_4_RGB, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to PVRTC1 4 RGB failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFPVRTC1_4_RGBA: + { +#if !BASISD_SUPPORT_PVRTC1 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: PVRTC1 4 unsupported\n"); + return false; +#else + assert(basis_file_has_alpha_slices); + assert(alpha_length); + + // Temp buffer to hold alpha block endpoint/selector indices + basisu::vector temp_block_indices(total_slice_blocks); + + // First transcode alpha data to temp buffer + //status = transcode_slice(pData, data_size, slice_index + 1, &temp_block_indices[0], total_slice_blocks, block_format::cIndices, sizeof(uint32_t), decode_flags, pSlice_descs[slice_index].m_num_blocks_x, pState); + status = transcode_slice(&temp_block_indices[0], num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cIndices, sizeof(uint32_t), false, is_video, true, level_index, orig_width, orig_height, num_blocks_x, pState, false, nullptr, 0); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to PVRTC1 4 RGBA failed (0)\n"); + } + else + { + // output_row_pitch_in_blocks_or_pixels is actually ignored because we're transcoding to PVRTC1. (Print a dev warning if it's != 0?) + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGBA, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState, &temp_block_indices[0]); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cPVRTC1_4_RGBA, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, &temp_block_indices[0], 0); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to PVRTC1 4 RGBA failed (1)\n"); + } + } + + break; +#endif + } + case transcoder_texture_format::cTFBC7_RGBA: + case transcoder_texture_format::cTFBC7_ALT: + { +#if !BASISD_SUPPORT_BC7_MODE5 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: BC7 unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + // We used to support transcoding just alpha to BC7 - but is that useful at all? + + // First transcode the color slice. The cBC7_M5_COLOR transcoder will output opaque mode 5 blocks. + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7_M5_COLOR, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cBC7_M5_COLOR, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + + if ((status) && (basis_file_has_alpha_slices)) + { + // Now transcode the alpha slice. The cBC7_M5_ALPHA transcoder will now change the opaque mode 5 blocks to blocks with alpha. + //status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7_M5_ALPHA, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cBC7_M5_ALPHA, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + } + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC7 failed (0)\n"); + } + + break; +#endif + } + case transcoder_texture_format::cTFETC2_RGBA: + { +#if !BASISD_SUPPORT_ETC2_EAC_A8 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: ETC2 EAC A8 unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + + if (basis_file_has_alpha_slices) + { + // First decode the alpha data + //status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_A8, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cETC2_EAC_A8, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + } + else + { + //write_opaque_alpha_blocks(pSlice_descs[slice_index].m_num_blocks_x, pSlice_descs[slice_index].m_num_blocks_y, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_A8, 16, output_row_pitch_in_blocks_or_pixels); + basisu_transcoder::write_opaque_alpha_blocks(num_blocks_x, num_blocks_y, pOutput_blocks, block_format::cETC2_EAC_A8, 16, output_row_pitch_in_blocks_or_pixels); + status = true; + } + + if (status) + { + // Now decode the color data + //status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC1, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice((uint8_t *)pOutput_blocks + 8, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cETC1, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ETC2 RGB failed\n"); + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ETC2 A failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFBC3_RGBA: + { +#if !BASISD_SUPPORT_DXT1 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: DXT1 unsupported\n"); + return false; +#elif !BASISD_SUPPORT_DXT5A + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: DXT5A unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + + // First decode the alpha data + if (basis_file_has_alpha_slices) + { + //status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cBC4, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + } + else + { + basisu_transcoder::write_opaque_alpha_blocks(num_blocks_x, num_blocks_y, pOutput_blocks, block_format::cBC4, 16, output_row_pitch_in_blocks_or_pixels); + status = true; + } + + if (status) + { + // Now decode the color data. Forbid 3 color blocks, which aren't allowed in BC3. + //status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC1, 16, decode_flags | cDecodeFlagsBC1ForbidThreeColorBlocks, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice((uint8_t *)pOutput_blocks + 8, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cBC1, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC3 RGB failed\n"); + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC3 A failed\n"); + } + + break; +#endif + } + case transcoder_texture_format::cTFBC5_RG: + { +#if !BASISD_SUPPORT_DXT5A + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: DXT5A unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + + //bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + // uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const bool is_video, const bool is_alpha_slice, const uint32_t level_index, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels = 0, + // basisu_transcoder_state* pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0); + + // Decode the R data (actually the green channel of the color data slice in the basis file) + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cBC4, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (status) + { + if (basis_file_has_alpha_slices) + { + // Decode the G data (actually the green channel of the alpha data slice in the basis file) + //status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice((uint8_t *)pOutput_blocks + 8, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cBC4, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC5 1 failed\n"); + } + } + else + { + basisu_transcoder::write_opaque_alpha_blocks(num_blocks_x, num_blocks_y, (uint8_t*)pOutput_blocks + 8, block_format::cBC4, 16, output_row_pitch_in_blocks_or_pixels); + status = true; + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to BC5 channel 0 failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFASTC_4x4_RGBA: + { +#if !BASISD_SUPPORT_ASTC + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: ASTC unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + + if (basis_file_has_alpha_slices) + { + // First decode the alpha data to the output (we're using the output texture as a temp buffer here). + //status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cIndices, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cIndices, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (status) + { + // Now decode the color data and transcode to ASTC. The transcoder function will read the alpha selector data from the output texture as it converts and + // transcode both the alpha and color data at the same time to ASTC. + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cASTC_4x4, 16, decode_flags | cDecodeFlagsOutputHasAlphaIndices, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cASTC_4x4, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, true, nullptr, output_rows_in_pixels); + } + } + else + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cASTC_4x4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cASTC_4x4, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ASTC failed (0)\n"); + } + + break; +#endif + } + case transcoder_texture_format::cTFATC_RGB: + { +#if !BASISD_SUPPORT_ATC + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: ATC unsupported\n"); + return false; +#else + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cATC_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cATC_RGB, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ATC_RGB failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFATC_RGBA: + { +#if !BASISD_SUPPORT_ATC + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: ATC unsupported\n"); + return false; +#elif !BASISD_SUPPORT_DXT5A + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: DXT5A unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + + // First decode the alpha data + if (basis_file_has_alpha_slices) + { + //status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cBC4, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + } + else + { + basisu_transcoder::write_opaque_alpha_blocks(num_blocks_x, num_blocks_y, pOutput_blocks, block_format::cBC4, 16, output_row_pitch_in_blocks_or_pixels); + status = true; + } + + if (status) + { + //status = transcode_slice(pData, data_size, slice_index, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cATC_RGB, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice((uint8_t *)pOutput_blocks + 8, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cATC_RGB, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ATC RGB failed\n"); + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ATC A failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFPVRTC2_4_RGB: + { +#if !BASISD_SUPPORT_PVRTC2 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: PVRTC2 unsupported\n"); + return false; +#else + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC2_4_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cPVRTC2_4_RGB, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to cPVRTC2_4_RGB failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFPVRTC2_4_RGBA: + { +#if !BASISD_SUPPORT_PVRTC2 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: PVRTC2 unsupported\n"); + return false; +#else + if (basis_file_has_alpha_slices) + { + // First decode the alpha data to the output (we're using the output texture as a temp buffer here). + //status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cIndices, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cIndices, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to failed\n"); + } + else + { + // Now decode the color data and transcode to PVRTC2 RGBA. + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC2_4_RGBA, bytes_per_block_or_pixel, decode_flags | cDecodeFlagsOutputHasAlphaIndices, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cPVRTC2_4_RGBA, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, true, nullptr, output_rows_in_pixels); + } + } + else + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC2_4_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cPVRTC2_4_RGB, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to cPVRTC2_4_RGBA failed\n"); + } + + break; +#endif + } + case transcoder_texture_format::cTFRGBA32: + { + // Raw 32bpp pixels, decoded in the usual raster order (NOT block order) into an image in memory. + + // First decode the alpha data + if (basis_file_has_alpha_slices) + //status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cA32, sizeof(uint32_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cA32, sizeof(uint32_t), false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + else + status = true; + + if (status) + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, basis_file_has_alpha_slices ? block_format::cRGB32 : block_format::cRGBA32, sizeof(uint32_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, basis_file_has_alpha_slices ? block_format::cRGB32 : block_format::cRGBA32, sizeof(uint32_t), false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to RGBA32 RGB failed\n"); + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to RGBA32 A failed\n"); + } + + break; + } + case transcoder_texture_format::cTFRGB565: + case transcoder_texture_format::cTFBGR565: + { + // Raw 16bpp pixels, decoded in the usual raster order (NOT block order) into an image in memory. + + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, (fmt == transcoder_texture_format::cTFRGB565) ? block_format::cRGB565 : block_format::cBGR565, sizeof(uint16_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, (target_format == transcoder_texture_format::cTFRGB565) ? block_format::cRGB565 : block_format::cBGR565, sizeof(uint16_t), false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to RGB565 RGB failed\n"); + } + + break; + } + case transcoder_texture_format::cTFRGBA4444: + { + // Raw 16bpp pixels, decoded in the usual raster order (NOT block order) into an image in memory. + + // First decode the alpha data + if (basis_file_has_alpha_slices) + //status = transcode_slice(pData, data_size, slice_index + 1, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGBA4444_ALPHA, sizeof(uint16_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cRGBA4444_ALPHA, sizeof(uint16_t), false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + else + status = true; + + if (status) + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, basis_file_has_alpha_slices ? block_format::cRGBA4444_COLOR : block_format::cRGBA4444_COLOR_OPAQUE, sizeof(uint16_t), decode_flags, output_row_pitch_in_blocks_or_pixels, pState, nullptr, output_rows_in_pixels); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, basis_file_has_alpha_slices ? block_format::cRGBA4444_COLOR : block_format::cRGBA4444_COLOR_OPAQUE, sizeof(uint16_t), false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to RGBA4444 RGB failed\n"); + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to RGBA4444 A failed\n"); + } + + break; + } + case transcoder_texture_format::cTFFXT1_RGB: + { +#if !BASISD_SUPPORT_FXT1 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: FXT1 unsupported\n"); + return false; +#else + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cFXT1_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cFXT1_RGB, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to FXT1_RGB failed\n"); + } + break; +#endif + } + case transcoder_texture_format::cTFETC2_EAC_R11: + { +#if !BASISD_SUPPORT_ETC2_EAC_RG11 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: EAC_RG11 unsupported\n"); + return false; +#else + //status = transcode_slice(pData, data_size, slice_index_to_decode, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pData, data_len, block_format::cETC2_EAC_R11, bytes_per_block_or_pixel, false, is_video, is_alpha_slice, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ETC2_EAC_R11 failed\n"); + } + + break; +#endif + } + case transcoder_texture_format::cTFETC2_EAC_RG11: + { +#if !BASISD_SUPPORT_ETC2_EAC_RG11 + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: EAC_RG11 unsupported\n"); + return false; +#else + assert(bytes_per_block_or_pixel == 16); + + if (basis_file_has_alpha_slices) + { + // First decode the alpha data to G + //status = transcode_slice(pData, data_size, slice_index + 1, (uint8_t*)pOutput_blocks + 8, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice((uint8_t *)pOutput_blocks + 8, num_blocks_x, num_blocks_y, pCompressed_data + alpha_offset, alpha_length, block_format::cETC2_EAC_R11, bytes_per_block_or_pixel, false, is_video, true, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + } + else + { + basisu_transcoder::write_opaque_alpha_blocks(num_blocks_x, num_blocks_y, (uint8_t*)pOutput_blocks + 8, block_format::cETC2_EAC_R11, 16, output_row_pitch_in_blocks_or_pixels); + status = true; + } + + if (status) + { + // Now decode the color data to R + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, 16, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + rgb_offset, rgb_length, block_format::cETC2_EAC_R11, bytes_per_block_or_pixel, false, is_video, false, level_index, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, false, nullptr, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ETC2_EAC_R11 R failed\n"); + } + } + else + { + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: transcode_slice() to ETC2_EAC_R11 G failed\n"); + } + + break; +#endif + } + default: + { + assert(0); + BASISU_DEVEL_ERROR("basisu_lowlevel_etc1s_transcoder::transcode_image: Invalid fmt\n"); + break; + } + } + + return status; + } + + basisu_lowlevel_uastc_transcoder::basisu_lowlevel_uastc_transcoder() + { + } + + bool basisu_lowlevel_uastc_transcoder::transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, bool has_alpha, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels, + basisu_transcoder_state* pState, uint32_t output_rows_in_pixels, int channel0, int channel1, uint32_t decode_flags) + { + BASISU_NOTE_UNUSED(pState); + BASISU_NOTE_UNUSED(bc1_allow_threecolor_blocks); + + assert(g_transcoder_initialized); + if (!g_transcoder_initialized) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_slice: Transcoder not globally initialized.\n"); + return false; + } + +#if BASISD_SUPPORT_UASTC + const uint32_t total_blocks = num_blocks_x * num_blocks_y; + + if (!output_row_pitch_in_blocks_or_pixels) + { + if (basis_block_format_is_uncompressed(fmt)) + output_row_pitch_in_blocks_or_pixels = orig_width; + else + { + if (fmt == block_format::cFXT1_RGB) + output_row_pitch_in_blocks_or_pixels = (orig_width + 7) / 8; + else + output_row_pitch_in_blocks_or_pixels = num_blocks_x; + } + } + + if (basis_block_format_is_uncompressed(fmt)) + { + if (!output_rows_in_pixels) + output_rows_in_pixels = orig_height; + } + + uint32_t total_expected_block_bytes = sizeof(uastc_block) * total_blocks; + if (image_data_size < total_expected_block_bytes) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_slice: image_data_size < total_expected_block_bytes The file is corrupted or this is a bug.\n"); + return false; + } + + const uastc_block* pSource_block = reinterpret_cast(pImage_data); + + const bool high_quality = (decode_flags & cDecodeFlagsHighQuality) != 0; + const bool from_alpha = has_alpha && (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0; + + bool status = false; + if ((fmt == block_format::cPVRTC1_4_RGB) || (fmt == block_format::cPVRTC1_4_RGBA)) + { + if (fmt == block_format::cPVRTC1_4_RGBA) + transcode_uastc_to_pvrtc1_4_rgba((const uastc_block*)pImage_data, pDst_blocks, num_blocks_x, num_blocks_y, high_quality); + else + transcode_uastc_to_pvrtc1_4_rgb((const uastc_block *)pImage_data, pDst_blocks, num_blocks_x, num_blocks_y, high_quality, from_alpha); + } + else + { + for (uint32_t block_y = 0; block_y < num_blocks_y; ++block_y) + { + void* pDst_block = (uint8_t*)pDst_blocks + block_y * output_row_pitch_in_blocks_or_pixels * output_block_or_pixel_stride_in_bytes; + + for (uint32_t block_x = 0; block_x < num_blocks_x; ++block_x, ++pSource_block, pDst_block = (uint8_t *)pDst_block + output_block_or_pixel_stride_in_bytes) + { + switch (fmt) + { + case block_format::cUASTC_4x4: + { + memcpy(pDst_block, pSource_block, sizeof(uastc_block)); + status = true; + break; + } + case block_format::cETC1: + { + if (from_alpha) + status = transcode_uastc_to_etc1(*pSource_block, pDst_block, 3); + else + status = transcode_uastc_to_etc1(*pSource_block, pDst_block); + break; + } + case block_format::cETC2_RGBA: + { + status = transcode_uastc_to_etc2_rgba(*pSource_block, pDst_block); + break; + } + case block_format::cBC1: + { + status = transcode_uastc_to_bc1(*pSource_block, pDst_block, high_quality); + break; + } + case block_format::cBC3: + { + status = transcode_uastc_to_bc3(*pSource_block, pDst_block, high_quality); + break; + } + case block_format::cBC4: + { + if (channel0 < 0) + channel0 = 0; + status = transcode_uastc_to_bc4(*pSource_block, pDst_block, high_quality, channel0); + break; + } + case block_format::cBC5: + { + if (channel0 < 0) + channel0 = 0; + if (channel1 < 0) + channel1 = 3; + status = transcode_uastc_to_bc5(*pSource_block, pDst_block, high_quality, channel0, channel1); + break; + } + case block_format::cBC7: + case block_format::cBC7_M5_COLOR: // for consistently with ETC1S + { + status = transcode_uastc_to_bc7(*pSource_block, pDst_block); + break; + } + case block_format::cASTC_4x4: + { + status = transcode_uastc_to_astc(*pSource_block, pDst_block); + break; + } + case block_format::cETC2_EAC_R11: + { + if (channel0 < 0) + channel0 = 0; + status = transcode_uastc_to_etc2_eac_r11(*pSource_block, pDst_block, high_quality, channel0); + break; + } + case block_format::cETC2_EAC_RG11: + { + if (channel0 < 0) + channel0 = 0; + if (channel1 < 0) + channel1 = 3; + status = transcode_uastc_to_etc2_eac_rg11(*pSource_block, pDst_block, high_quality, channel0, channel1); + break; + } + case block_format::cRGBA32: + { + color32 block_pixels[4][4]; + status = unpack_uastc(*pSource_block, (color32 *)block_pixels, false); + + assert(sizeof(uint32_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint32_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + for (uint32_t y = 0; y < max_y; y++) + { + for (uint32_t x = 0; x < max_x; x++) + { + const color32& c = block_pixels[y][x]; + + pDst_pixels[0 + 4 * x] = c.r; + pDst_pixels[1 + 4 * x] = c.g; + pDst_pixels[2 + 4 * x] = c.b; + pDst_pixels[3 + 4 * x] = c.a; + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint32_t); + } + + break; + } + case block_format::cRGB565: + case block_format::cBGR565: + { + color32 block_pixels[4][4]; + status = unpack_uastc(*pSource_block, (color32*)block_pixels, false); + + assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + for (uint32_t y = 0; y < max_y; y++) + { + for (uint32_t x = 0; x < max_x; x++) + { + const color32& c = block_pixels[y][x]; + + const uint16_t packed = (fmt == block_format::cRGB565) ? static_cast((mul_8(c.r, 31) << 11) | (mul_8(c.g, 63) << 5) | mul_8(c.b, 31)) : + static_cast((mul_8(c.b, 31) << 11) | (mul_8(c.g, 63) << 5) | mul_8(c.r, 31)); + + pDst_pixels[x * 2 + 0] = (uint8_t)(packed & 0xFF); + pDst_pixels[x * 2 + 1] = (uint8_t)((packed >> 8) & 0xFF); + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t); + } + + break; + } + case block_format::cRGBA4444: + { + color32 block_pixels[4][4]; + status = unpack_uastc(*pSource_block, (color32*)block_pixels, false); + + assert(sizeof(uint16_t) == output_block_or_pixel_stride_in_bytes); + uint8_t* pDst_pixels = static_cast(pDst_blocks) + (block_x * 4 + block_y * 4 * output_row_pitch_in_blocks_or_pixels) * sizeof(uint16_t); + + const uint32_t max_x = basisu::minimum(4, (int)output_row_pitch_in_blocks_or_pixels - (int)block_x * 4); + const uint32_t max_y = basisu::minimum(4, (int)output_rows_in_pixels - (int)block_y * 4); + + for (uint32_t y = 0; y < max_y; y++) + { + for (uint32_t x = 0; x < max_x; x++) + { + const color32& c = block_pixels[y][x]; + + const uint16_t packed = static_cast((mul_8(c.r, 15) << 12) | (mul_8(c.g, 15) << 8) | (mul_8(c.b, 15) << 4) | mul_8(c.a, 15)); + + pDst_pixels[x * 2 + 0] = (uint8_t)(packed & 0xFF); + pDst_pixels[x * 2 + 1] = (uint8_t)((packed >> 8) & 0xFF); + } + + pDst_pixels += output_row_pitch_in_blocks_or_pixels * sizeof(uint16_t); + } + break; + } + default: + assert(0); + break; + + } + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_slice: Transcoder failed to unpack a UASTC block - this is a bug, or the data was corrupted\n"); + return false; + } + + } // block_x + + } // block_y + } + + return true; +#else + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_slice: UASTC is unsupported\n"); + + BASISU_NOTE_UNUSED(decode_flags); + BASISU_NOTE_UNUSED(channel0); + BASISU_NOTE_UNUSED(channel1); + BASISU_NOTE_UNUSED(output_rows_in_pixels); + BASISU_NOTE_UNUSED(output_row_pitch_in_blocks_or_pixels); + BASISU_NOTE_UNUSED(output_block_or_pixel_stride_in_bytes); + BASISU_NOTE_UNUSED(fmt); + BASISU_NOTE_UNUSED(image_data_size); + BASISU_NOTE_UNUSED(pImage_data); + BASISU_NOTE_UNUSED(num_blocks_x); + BASISU_NOTE_UNUSED(num_blocks_y); + BASISU_NOTE_UNUSED(pDst_blocks); + + return false; +#endif + } + + bool basisu_lowlevel_uastc_transcoder::transcode_image( + transcoder_texture_format target_format, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + const uint8_t* pCompressed_data, uint32_t compressed_data_length, + uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index, + uint32_t slice_offset, uint32_t slice_length, + uint32_t decode_flags, + bool has_alpha, + bool is_video, + uint32_t output_row_pitch_in_blocks_or_pixels, + basisu_transcoder_state* pState, + uint32_t output_rows_in_pixels, + int channel0, int channel1) + { + BASISU_NOTE_UNUSED(is_video); + BASISU_NOTE_UNUSED(level_index); + + if (((uint64_t)slice_offset + slice_length) > (uint64_t)compressed_data_length) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: source data buffer too small\n"); + return false; + } + + if ((target_format == transcoder_texture_format::cTFPVRTC1_4_RGB) || (target_format == transcoder_texture_format::cTFPVRTC1_4_RGBA)) + { + if ((!basisu::is_pow2(num_blocks_x * 4)) || (!basisu::is_pow2(num_blocks_y * 4))) + { + // PVRTC1 only supports power of 2 dimensions + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: PVRTC1 only supports power of 2 dimensions\n"); + return false; + } + } + + if ((target_format == transcoder_texture_format::cTFPVRTC1_4_RGBA) && (!has_alpha)) + { + // Switch to PVRTC1 RGB if the input doesn't have alpha. + target_format = transcoder_texture_format::cTFPVRTC1_4_RGB; + } + + const bool transcode_alpha_data_to_opaque_formats = (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0; + const uint32_t bytes_per_block_or_pixel = basis_get_bytes_per_block_or_pixel(target_format); + const uint32_t total_slice_blocks = num_blocks_x * num_blocks_y; + + if (!basis_validate_output_buffer_size(target_format, output_blocks_buf_size_in_blocks_or_pixels, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, output_rows_in_pixels, total_slice_blocks)) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: output buffer size too small\n"); + return false; + } + + bool status = false; + + // UASTC4x4 + switch (target_format) + { + case transcoder_texture_format::cTFETC1_RGB: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC1, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC1, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1); + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to ETC1 failed\n"); + } + break; + } + case transcoder_texture_format::cTFETC2_RGBA: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_RGBA, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC2_RGBA, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to ETC2 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBC1_RGB: + { + // TODO: ETC1S allows BC1 from alpha channel. That doesn't seem actually useful, though. + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC1, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC1, + bytes_per_block_or_pixel, true, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC1 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBC3_RGBA: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC3, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC3, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, channel0, channel1); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC3 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBC4_R: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC4, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState, + // nullptr, 0, + // ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC4, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, + ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC4 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBC5_RG: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC5, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState, + // nullptr, 0, + // 0, 3); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC5, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, + 0, 3); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC5 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBC7_RGBA: + case transcoder_texture_format::cTFBC7_ALT: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBC7, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBC7, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to BC7 failed\n"); + } + break; + } + case transcoder_texture_format::cTFPVRTC1_4_RGB: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGB, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cPVRTC1_4_RGB, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to PVRTC1 RGB 4bpp failed\n"); + } + break; + } + case transcoder_texture_format::cTFPVRTC1_4_RGBA: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cPVRTC1_4_RGBA, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cPVRTC1_4_RGBA, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to PVRTC1 RGBA 4bpp failed\n"); + } + break; + } + case transcoder_texture_format::cTFASTC_4x4_RGBA: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cASTC_4x4, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cASTC_4x4, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to ASTC 4x4 failed\n"); + } + break; + } + case transcoder_texture_format::cTFATC_RGB: + case transcoder_texture_format::cTFATC_RGBA: + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: UASTC->ATC currently unsupported\n"); + return false; + } + case transcoder_texture_format::cTFFXT1_RGB: + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: UASTC->FXT1 currently unsupported\n"); + return false; + } + case transcoder_texture_format::cTFPVRTC2_4_RGB: + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: UASTC->PVRTC2 currently unsupported\n"); + return false; + } + case transcoder_texture_format::cTFPVRTC2_4_RGBA: + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: UASTC->PVRTC2 currently unsupported\n"); + return false; + } + case transcoder_texture_format::cTFETC2_EAC_R11: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_R11, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState, + // nullptr, 0, + // ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC2_EAC_R11, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, + ((has_alpha) && (transcode_alpha_data_to_opaque_formats)) ? 3 : 0); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to EAC R11 failed\n"); + } + break; + } + case transcoder_texture_format::cTFETC2_EAC_RG11: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cETC2_EAC_RG11, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState, + // nullptr, 0, + // 0, 3); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cETC2_EAC_RG11, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels, + 0, 3); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_basisu_lowlevel_uastc_transcodertranscoder::transcode_image: transcode_slice() to EAC RG11 failed\n"); + } + break; + } + case transcoder_texture_format::cTFRGBA32: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGBA32, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cRGBA32, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGBA32 failed\n"); + } + break; + } + case transcoder_texture_format::cTFRGB565: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGB565, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cRGB565, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGB565 failed\n"); + } + break; + } + case transcoder_texture_format::cTFBGR565: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cBGR565, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cBGR565, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGB565 failed\n"); + } + break; + } + case transcoder_texture_format::cTFRGBA4444: + { + //status = transcode_slice(pData, data_size, slice_index, pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, block_format::cRGBA4444, bytes_per_block_or_pixel, decode_flags, output_row_pitch_in_blocks_or_pixels, pState); + status = transcode_slice(pOutput_blocks, num_blocks_x, num_blocks_y, pCompressed_data + slice_offset, slice_length, block_format::cRGBA4444, + bytes_per_block_or_pixel, false, has_alpha, orig_width, orig_height, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + if (!status) + { + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: transcode_slice() to RGBA4444 failed\n"); + } + break; + } + default: + { + assert(0); + BASISU_DEVEL_ERROR("basisu_lowlevel_uastc_transcoder::transcode_image: Invalid format\n"); + break; + } + } + + return status; + } + + basisu_transcoder::basisu_transcoder() : + m_ready_to_transcode(false) + { + } + + bool basisu_transcoder::validate_file_checksums(const void* pData, uint32_t data_size, bool full_validation) const + { + if (!validate_header(pData, data_size)) + return false; + + const basis_file_header* pHeader = reinterpret_cast(pData); + +#if !BASISU_NO_HEADER_OR_DATA_CRC16_CHECKS + if (crc16(&pHeader->m_data_size, sizeof(basis_file_header) - BASISU_OFFSETOF(basis_file_header, m_data_size), 0) != pHeader->m_header_crc16) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header CRC check failed\n"); + return false; + } + + if (full_validation) + { + if (crc16(reinterpret_cast(pData) + sizeof(basis_file_header), pHeader->m_data_size, 0) != pHeader->m_data_crc16) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: data CRC check failed\n"); + return false; + } + } +#endif + + return true; + } + + bool basisu_transcoder::validate_header_quick(const void* pData, uint32_t data_size) const + { + if (data_size <= sizeof(basis_file_header)) + return false; + + const basis_file_header* pHeader = reinterpret_cast(pData); + + if ((pHeader->m_sig != basis_file_header::cBASISSigValue) || (pHeader->m_ver != BASISD_SUPPORTED_BASIS_VERSION) || (pHeader->m_header_size != sizeof(basis_file_header))) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header has an invalid signature, or file version is unsupported\n"); + return false; + } + + uint32_t expected_file_size = sizeof(basis_file_header) + pHeader->m_data_size; + if (data_size < expected_file_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: source buffer is too small\n"); + return false; + } + + if ((!pHeader->m_total_slices) || (!pHeader->m_total_images)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: header is invalid\n"); + return false; + } + + if ((pHeader->m_slice_desc_file_ofs >= data_size) || + ((data_size - pHeader->m_slice_desc_file_ofs) < (sizeof(basis_slice_desc) * pHeader->m_total_slices)) + ) + { + BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: passed in buffer is too small or data is corrupted\n"); + return false; + } + + return true; + } + + bool basisu_transcoder::validate_header(const void* pData, uint32_t data_size) const + { + if (data_size <= sizeof(basis_file_header)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: input source buffer is too small\n"); + return false; + } + + const basis_file_header* pHeader = reinterpret_cast(pData); + + if ((pHeader->m_sig != basis_file_header::cBASISSigValue) || (pHeader->m_ver != BASISD_SUPPORTED_BASIS_VERSION) || (pHeader->m_header_size != sizeof(basis_file_header))) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header has an invalid signature, or file version is unsupported\n"); + return false; + } + + uint32_t expected_file_size = sizeof(basis_file_header) + pHeader->m_data_size; + if (data_size < expected_file_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: input source buffer is too small, or header is corrupted\n"); + return false; + } + + if ((!pHeader->m_total_images) || (!pHeader->m_total_slices)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (total images or slices are 0)\n"); + return false; + } + + if (pHeader->m_total_images > pHeader->m_total_slices) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid basis file (too many images)\n"); + return false; + } + + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + { + if (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) + { + if (pHeader->m_total_slices & 1) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: invalid alpha .basis file\n"); + return false; + } + } + + // This flag dates back to pre-Basis Universal, when .basis supported full ETC1 too. + if ((pHeader->m_flags & cBASISHeaderFlagETC1S) == 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: Invalid .basis file (ETC1S check)\n"); + return false; + } + } + else + { + if ((pHeader->m_flags & cBASISHeaderFlagETC1S) != 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: Invalid .basis file (ETC1S check)\n"); + return false; + } + } + + if ((pHeader->m_slice_desc_file_ofs >= data_size) || + ((data_size - pHeader->m_slice_desc_file_ofs) < (sizeof(basis_slice_desc) * pHeader->m_total_slices)) + ) + { + BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: passed in buffer is too small or data is corrupted\n"); + return false; + } + + return true; + } + + basis_texture_type basisu_transcoder::get_texture_type(const void* pData, uint32_t data_size) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_texture_type: header validation failed\n"); + return cBASISTexType2DArray; + } + + const basis_file_header* pHeader = static_cast(pData); + + basis_texture_type btt = static_cast(static_cast(pHeader->m_tex_type)); + + if (btt >= cBASISTexTypeTotal) + { + BASISU_DEVEL_ERROR("basisu_transcoder::validate_header_quick: header's texture type field is invalid\n"); + return cBASISTexType2DArray; + } + + return btt; + } + + bool basisu_transcoder::get_userdata(const void* pData, uint32_t data_size, uint32_t& userdata0, uint32_t& userdata1) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_userdata: header validation failed\n"); + return false; + } + + const basis_file_header* pHeader = static_cast(pData); + + userdata0 = pHeader->m_userdata0; + userdata1 = pHeader->m_userdata1; + return true; + } + + uint32_t basisu_transcoder::get_total_images(const void* pData, uint32_t data_size) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header validation failed\n"); + return 0; + } + + const basis_file_header* pHeader = static_cast(pData); + + return pHeader->m_total_images; + } + + basis_tex_format basisu_transcoder::get_tex_format(const void* pData, uint32_t data_size) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_images: header validation failed\n"); + return basis_tex_format::cETC1S; + } + + const basis_file_header* pHeader = static_cast(pData); + + return (basis_tex_format)(uint32_t)pHeader->m_tex_format; + } + + bool basisu_transcoder::get_image_info(const void* pData, uint32_t data_size, basisu_image_info& image_info, uint32_t image_index) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: header validation failed\n"); + return false; + } + + int slice_index = find_first_slice_index(pData, data_size, image_index, 0); + if (slice_index < 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid slice index\n"); + return false; + } + + const basis_file_header* pHeader = static_cast(pData); + + if (image_index >= pHeader->m_total_images) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid image_index\n"); + return false; + } + + const basis_slice_desc* pSlice_descs = reinterpret_cast(static_cast(pData) + pHeader->m_slice_desc_file_ofs); + + uint32_t total_levels = 1; + for (uint32_t i = slice_index + 1; i < pHeader->m_total_slices; i++) + if (pSlice_descs[i].m_image_index == image_index) + total_levels = basisu::maximum(total_levels, pSlice_descs[i].m_level_index + 1); + else + break; + + if (total_levels > 16) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_info: invalid image_index\n"); + return false; + } + + const basis_slice_desc& slice_desc = pSlice_descs[slice_index]; + + image_info.m_image_index = image_index; + image_info.m_total_levels = total_levels; + + image_info.m_alpha_flag = false; + + // For ETC1S, if anything has alpha all images have alpha. For UASTC, we only report alpha when the image actually has alpha. + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + image_info.m_alpha_flag = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0; + else + image_info.m_alpha_flag = (slice_desc.m_flags & cSliceDescFlagsHasAlpha) != 0; + + image_info.m_iframe_flag = (slice_desc.m_flags & cSliceDescFlagsFrameIsIFrame) != 0; + + image_info.m_width = slice_desc.m_num_blocks_x * 4; + image_info.m_height = slice_desc.m_num_blocks_y * 4; + image_info.m_orig_width = slice_desc.m_orig_width; + image_info.m_orig_height = slice_desc.m_orig_height; + image_info.m_num_blocks_x = slice_desc.m_num_blocks_x; + image_info.m_num_blocks_y = slice_desc.m_num_blocks_y; + image_info.m_total_blocks = image_info.m_num_blocks_x * image_info.m_num_blocks_y; + image_info.m_first_slice_index = slice_index; + + return true; + } + + uint32_t basisu_transcoder::get_total_image_levels(const void* pData, uint32_t data_size, uint32_t image_index) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: header validation failed\n"); + return false; + } + + int slice_index = find_first_slice_index(pData, data_size, image_index, 0); + if (slice_index < 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: failed finding slice\n"); + return false; + } + + const basis_file_header* pHeader = static_cast(pData); + + if (image_index >= pHeader->m_total_images) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: invalid image_index\n"); + return false; + } + + const basis_slice_desc* pSlice_descs = reinterpret_cast(static_cast(pData) + pHeader->m_slice_desc_file_ofs); + + uint32_t total_levels = 1; + for (uint32_t i = slice_index + 1; i < pHeader->m_total_slices; i++) + if (pSlice_descs[i].m_image_index == image_index) + total_levels = basisu::maximum(total_levels, pSlice_descs[i].m_level_index + 1); + else + break; + + const uint32_t cMaxSupportedLevels = 16; + if (total_levels > cMaxSupportedLevels) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_total_image_levels: invalid image levels!\n"); + return false; + } + + return total_levels; + } + + bool basisu_transcoder::get_image_level_desc(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, uint32_t& orig_width, uint32_t& orig_height, uint32_t& total_blocks) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: header validation failed\n"); + return false; + } + + int slice_index = find_first_slice_index(pData, data_size, image_index, level_index); + if (slice_index < 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: failed finding slice\n"); + return false; + } + + const basis_file_header* pHeader = static_cast(pData); + + if (image_index >= pHeader->m_total_images) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_desc: invalid image_index\n"); + return false; + } + + const basis_slice_desc* pSlice_descs = reinterpret_cast(static_cast(pData) + pHeader->m_slice_desc_file_ofs); + + const basis_slice_desc& slice_desc = pSlice_descs[slice_index]; + + orig_width = slice_desc.m_orig_width; + orig_height = slice_desc.m_orig_height; + total_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y; + + return true; + } + + bool basisu_transcoder::get_image_level_info(const void* pData, uint32_t data_size, basisu_image_level_info& image_info, uint32_t image_index, uint32_t level_index) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: validate_file_checksums failed\n"); + return false; + } + + int slice_index = find_first_slice_index(pData, data_size, image_index, level_index); + if (slice_index < 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: failed finding slice\n"); + return false; + } + + const basis_file_header* pHeader = static_cast(pData); + + if (image_index >= pHeader->m_total_images) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_image_level_info: invalid image_index\n"); + return false; + } + + const basis_slice_desc* pSlice_descs = reinterpret_cast(static_cast(pData) + pHeader->m_slice_desc_file_ofs); + + const basis_slice_desc& slice_desc = pSlice_descs[slice_index]; + + image_info.m_image_index = image_index; + image_info.m_level_index = level_index; + + // For ETC1S, if anything has alpha all images have alpha. For UASTC, we only report alpha when the image actually has alpha. + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + image_info.m_alpha_flag = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0; + else + image_info.m_alpha_flag = (slice_desc.m_flags & cSliceDescFlagsHasAlpha) != 0; + + image_info.m_iframe_flag = (slice_desc.m_flags & cSliceDescFlagsFrameIsIFrame) != 0; + image_info.m_width = slice_desc.m_num_blocks_x * 4; + image_info.m_height = slice_desc.m_num_blocks_y * 4; + image_info.m_orig_width = slice_desc.m_orig_width; + image_info.m_orig_height = slice_desc.m_orig_height; + image_info.m_num_blocks_x = slice_desc.m_num_blocks_x; + image_info.m_num_blocks_y = slice_desc.m_num_blocks_y; + image_info.m_total_blocks = image_info.m_num_blocks_x * image_info.m_num_blocks_y; + image_info.m_first_slice_index = slice_index; + + image_info.m_rgb_file_ofs = slice_desc.m_file_ofs; + image_info.m_rgb_file_len = slice_desc.m_file_size; + image_info.m_alpha_file_ofs = 0; + image_info.m_alpha_file_len = 0; + + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + { + if (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) + { + assert((slice_index + 1) < (int)pHeader->m_total_slices); + image_info.m_alpha_file_ofs = pSlice_descs[slice_index + 1].m_file_ofs; + image_info.m_alpha_file_len = pSlice_descs[slice_index + 1].m_file_size; + } + } + + return true; + } + + bool basisu_transcoder::get_file_info(const void* pData, uint32_t data_size, basisu_file_info& file_info) const + { + if (!validate_file_checksums(pData, data_size, false)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: validate_file_checksums failed\n"); + return false; + } + + const basis_file_header* pHeader = static_cast(pData); + const basis_slice_desc* pSlice_descs = reinterpret_cast(static_cast(pData) + pHeader->m_slice_desc_file_ofs); + + file_info.m_version = pHeader->m_ver; + + file_info.m_total_header_size = sizeof(basis_file_header) + pHeader->m_total_slices * sizeof(basis_slice_desc); + + file_info.m_total_selectors = pHeader->m_total_selectors; + file_info.m_selector_codebook_ofs = pHeader->m_selector_cb_file_ofs; + file_info.m_selector_codebook_size = pHeader->m_selector_cb_file_size; + + file_info.m_total_endpoints = pHeader->m_total_endpoints; + file_info.m_endpoint_codebook_ofs = pHeader->m_endpoint_cb_file_ofs; + file_info.m_endpoint_codebook_size = pHeader->m_endpoint_cb_file_size; + + file_info.m_tables_ofs = pHeader->m_tables_file_ofs; + file_info.m_tables_size = pHeader->m_tables_file_size; + + file_info.m_tex_format = static_cast(static_cast(pHeader->m_tex_format)); + + file_info.m_etc1s = (pHeader->m_tex_format == (int)basis_tex_format::cETC1S); + + file_info.m_y_flipped = (pHeader->m_flags & cBASISHeaderFlagYFlipped) != 0; + file_info.m_has_alpha_slices = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0; + + const uint32_t total_slices = pHeader->m_total_slices; + + file_info.m_slice_info.resize(total_slices); + + file_info.m_slices_size = 0; + + file_info.m_tex_type = static_cast(static_cast(pHeader->m_tex_type)); + + if (file_info.m_tex_type > cBASISTexTypeTotal) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: invalid texture type, file is corrupted\n"); + return false; + } + + file_info.m_us_per_frame = pHeader->m_us_per_frame; + file_info.m_userdata0 = pHeader->m_userdata0; + file_info.m_userdata1 = pHeader->m_userdata1; + + file_info.m_image_mipmap_levels.resize(0); + file_info.m_image_mipmap_levels.resize(pHeader->m_total_images); + + file_info.m_total_images = pHeader->m_total_images; + + for (uint32_t i = 0; i < total_slices; i++) + { + file_info.m_slices_size += pSlice_descs[i].m_file_size; + + basisu_slice_info& slice_info = file_info.m_slice_info[i]; + + slice_info.m_orig_width = pSlice_descs[i].m_orig_width; + slice_info.m_orig_height = pSlice_descs[i].m_orig_height; + slice_info.m_width = pSlice_descs[i].m_num_blocks_x * 4; + slice_info.m_height = pSlice_descs[i].m_num_blocks_y * 4; + slice_info.m_num_blocks_x = pSlice_descs[i].m_num_blocks_x; + slice_info.m_num_blocks_y = pSlice_descs[i].m_num_blocks_y; + slice_info.m_total_blocks = slice_info.m_num_blocks_x * slice_info.m_num_blocks_y; + slice_info.m_compressed_size = pSlice_descs[i].m_file_size; + slice_info.m_slice_index = i; + slice_info.m_image_index = pSlice_descs[i].m_image_index; + slice_info.m_level_index = pSlice_descs[i].m_level_index; + slice_info.m_unpacked_slice_crc16 = pSlice_descs[i].m_slice_data_crc16; + slice_info.m_alpha_flag = (pSlice_descs[i].m_flags & cSliceDescFlagsHasAlpha) != 0; + slice_info.m_iframe_flag = (pSlice_descs[i].m_flags & cSliceDescFlagsFrameIsIFrame) != 0; + + if (pSlice_descs[i].m_image_index >= pHeader->m_total_images) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: slice desc's image index is invalid\n"); + return false; + } + + file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index] = basisu::maximum(file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index], pSlice_descs[i].m_level_index + 1); + + if (file_info.m_image_mipmap_levels[pSlice_descs[i].m_image_index] > 16) + { + BASISU_DEVEL_ERROR("basisu_transcoder::get_file_info: slice mipmap level is invalid\n"); + return false; + } + } + + return true; + } + + bool basisu_transcoder::start_transcoding(const void* pData, uint32_t data_size) + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: header validation failed\n"); + return false; + } + + const basis_file_header* pHeader = reinterpret_cast(pData); + const uint8_t* pDataU8 = static_cast(pData); + + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + { + if (m_lowlevel_etc1s_decoder.m_local_endpoints.size()) + { + m_lowlevel_etc1s_decoder.clear(); + } + + if (pHeader->m_flags & cBASISHeaderFlagUsesGlobalCodebook) + { + if (!m_lowlevel_etc1s_decoder.get_global_codebooks()) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: File uses global codebooks, but set_global_codebooks() has not been called\n"); + return false; + } + if (!m_lowlevel_etc1s_decoder.get_global_codebooks()->get_endpoints().size()) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: Global codebooks must be unpacked first by calling start_transcoding()\n"); + return false; + } + if ((m_lowlevel_etc1s_decoder.get_global_codebooks()->get_endpoints().size() != pHeader->m_total_endpoints) || + (m_lowlevel_etc1s_decoder.get_global_codebooks()->get_selectors().size() != pHeader->m_total_selectors)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: Global codebook size mismatch (wrong codebooks for file).\n"); + return false; + } + if (!pHeader->m_tables_file_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted (2)\n"); + return false; + } + if (pHeader->m_tables_file_ofs > data_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (4)\n"); + return false; + } + if (pHeader->m_tables_file_size > (data_size - pHeader->m_tables_file_ofs)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (5)\n"); + return false; + } + } + else + { + if (!pHeader->m_endpoint_cb_file_size || !pHeader->m_selector_cb_file_size || !pHeader->m_tables_file_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted (0)\n"); + return false; + } + + if ((pHeader->m_endpoint_cb_file_ofs > data_size) || (pHeader->m_selector_cb_file_ofs > data_size) || (pHeader->m_tables_file_ofs > data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (1)\n"); + return false; + } + + if (pHeader->m_endpoint_cb_file_size > (data_size - pHeader->m_endpoint_cb_file_ofs)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (2)\n"); + return false; + } + + if (pHeader->m_selector_cb_file_size > (data_size - pHeader->m_selector_cb_file_ofs)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (3)\n"); + return false; + } + + if (pHeader->m_tables_file_size > (data_size - pHeader->m_tables_file_ofs)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: file is corrupted or passed in buffer too small (3)\n"); + return false; + } + + if (!m_lowlevel_etc1s_decoder.decode_palettes( + pHeader->m_total_endpoints, pDataU8 + pHeader->m_endpoint_cb_file_ofs, pHeader->m_endpoint_cb_file_size, + pHeader->m_total_selectors, pDataU8 + pHeader->m_selector_cb_file_ofs, pHeader->m_selector_cb_file_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: decode_palettes failed\n"); + return false; + } + } + + if (!m_lowlevel_etc1s_decoder.decode_tables(pDataU8 + pHeader->m_tables_file_ofs, pHeader->m_tables_file_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::start_transcoding: decode_tables failed\n"); + return false; + } + } + else + { + // Nothing special to do for UASTC. + if (m_lowlevel_etc1s_decoder.m_local_endpoints.size()) + { + m_lowlevel_etc1s_decoder.clear(); + } + } + + m_ready_to_transcode = true; + + return true; + } + + bool basisu_transcoder::stop_transcoding() + { + m_lowlevel_etc1s_decoder.clear(); + + m_ready_to_transcode = false; + + return true; + } + + bool basisu_transcoder::transcode_slice(const void* pData, uint32_t data_size, uint32_t slice_index, void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, uint32_t decode_flags, uint32_t output_row_pitch_in_blocks_or_pixels, basisu_transcoder_state* pState, void *pAlpha_blocks, uint32_t output_rows_in_pixels, int channel0, int channel1) const + { + if (!m_ready_to_transcode) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: must call start_transcoding first\n"); + return false; + } + + if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2) + { + // TODO: Not yet supported + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n"); + return false; + } + + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: header validation failed\n"); + return false; + } + + const basis_file_header* pHeader = reinterpret_cast(pData); + + const uint8_t* pDataU8 = static_cast(pData); + + if (slice_index >= pHeader->m_total_slices) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: slice_index >= pHeader->m_total_slices\n"); + return false; + } + + const basis_slice_desc& slice_desc = reinterpret_cast(pDataU8 + pHeader->m_slice_desc_file_ofs)[slice_index]; + + uint32_t total_4x4_blocks = slice_desc.m_num_blocks_x * slice_desc.m_num_blocks_y; + + if (basis_block_format_is_uncompressed(fmt)) + { + // Assume the output buffer is orig_width by orig_height + if (!output_row_pitch_in_blocks_or_pixels) + output_row_pitch_in_blocks_or_pixels = slice_desc.m_orig_width; + + if (!output_rows_in_pixels) + output_rows_in_pixels = slice_desc.m_orig_height; + + // Now make sure the output buffer is large enough, or we'll overwrite memory. + if (output_blocks_buf_size_in_blocks_or_pixels < (output_rows_in_pixels * output_row_pitch_in_blocks_or_pixels)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks_or_pixels < (output_rows_in_pixels * output_row_pitch_in_blocks_or_pixels)\n"); + return false; + } + } + else if (fmt == block_format::cFXT1_RGB) + { + const uint32_t num_blocks_fxt1_x = (slice_desc.m_orig_width + 7) / 8; + const uint32_t num_blocks_fxt1_y = (slice_desc.m_orig_height + 3) / 4; + const uint32_t total_blocks_fxt1 = num_blocks_fxt1_x * num_blocks_fxt1_y; + + if (output_blocks_buf_size_in_blocks_or_pixels < total_blocks_fxt1) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks_or_pixels < total_blocks_fxt1\n"); + return false; + } + } + else + { + if (output_blocks_buf_size_in_blocks_or_pixels < total_4x4_blocks) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: output_blocks_buf_size_in_blocks_or_pixels < total_blocks\n"); + return false; + } + } + + if (fmt != block_format::cETC1) + { + if ((fmt == block_format::cPVRTC1_4_RGB) || (fmt == block_format::cPVRTC1_4_RGBA)) + { + if ((!basisu::is_pow2(slice_desc.m_num_blocks_x * 4)) || (!basisu::is_pow2(slice_desc.m_num_blocks_y * 4))) + { + // PVRTC1 only supports power of 2 dimensions + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: PVRTC1 only supports power of 2 dimensions\n"); + return false; + } + } + } + + if (slice_desc.m_file_ofs > data_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: invalid slice_desc.m_file_ofs, or passed in buffer too small\n"); + return false; + } + + const uint32_t data_size_left = data_size - slice_desc.m_file_ofs; + if (data_size_left < slice_desc.m_file_size) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_slice: invalid slice_desc.m_file_size, or passed in buffer too small\n"); + return false; + } + + if (pHeader->m_tex_format == (int)basis_tex_format::cUASTC4x4) + { + return m_lowlevel_uastc_decoder.transcode_slice(pOutput_blocks, slice_desc.m_num_blocks_x, slice_desc.m_num_blocks_y, + pDataU8 + slice_desc.m_file_ofs, slice_desc.m_file_size, + fmt, output_block_or_pixel_stride_in_bytes, (decode_flags & cDecodeFlagsBC1ForbidThreeColorBlocks) == 0, *pHeader, slice_desc, output_row_pitch_in_blocks_or_pixels, pState, + output_rows_in_pixels, channel0, channel1, decode_flags); + } + else + { + return m_lowlevel_etc1s_decoder.transcode_slice(pOutput_blocks, slice_desc.m_num_blocks_x, slice_desc.m_num_blocks_y, + pDataU8 + slice_desc.m_file_ofs, slice_desc.m_file_size, + fmt, output_block_or_pixel_stride_in_bytes, (decode_flags & cDecodeFlagsBC1ForbidThreeColorBlocks) == 0, *pHeader, slice_desc, output_row_pitch_in_blocks_or_pixels, pState, + (decode_flags & cDecodeFlagsOutputHasAlphaIndices) != 0, pAlpha_blocks, output_rows_in_pixels); + } + } + + int basisu_transcoder::find_first_slice_index(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index) const + { + BASISU_NOTE_UNUSED(data_size); + + const basis_file_header* pHeader = reinterpret_cast(pData); + const uint8_t* pDataU8 = static_cast(pData); + + // For very large basis files this search could be painful + // TODO: Binary search this + for (uint32_t slice_iter = 0; slice_iter < pHeader->m_total_slices; slice_iter++) + { + const basis_slice_desc& slice_desc = reinterpret_cast(pDataU8 + pHeader->m_slice_desc_file_ofs)[slice_iter]; + if ((slice_desc.m_image_index == image_index) && (slice_desc.m_level_index == level_index)) + return slice_iter; + } + + BASISU_DEVEL_ERROR("basisu_transcoder::find_first_slice_index: didn't find slice\n"); + + return -1; + } + + int basisu_transcoder::find_slice(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const + { + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::find_slice: header validation failed\n"); + return false; + } + + const basis_file_header* pHeader = reinterpret_cast(pData); + const uint8_t* pDataU8 = static_cast(pData); + const basis_slice_desc* pSlice_descs = reinterpret_cast(pDataU8 + pHeader->m_slice_desc_file_ofs); + + // For very large basis files this search could be painful + // TODO: Binary search this + for (uint32_t slice_iter = 0; slice_iter < pHeader->m_total_slices; slice_iter++) + { + const basis_slice_desc& slice_desc = pSlice_descs[slice_iter]; + if ((slice_desc.m_image_index == image_index) && (slice_desc.m_level_index == level_index)) + { + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + { + const bool slice_alpha = (slice_desc.m_flags & cSliceDescFlagsHasAlpha) != 0; + if (slice_alpha == alpha_data) + return slice_iter; + } + else + { + return slice_iter; + } + } + } + + BASISU_DEVEL_ERROR("basisu_transcoder::find_slice: didn't find slice\n"); + + return -1; + } + + void basisu_transcoder::write_opaque_alpha_blocks( + uint32_t num_blocks_x, uint32_t num_blocks_y, + void* pOutput_blocks, block_format fmt, + uint32_t block_stride_in_bytes, uint32_t output_row_pitch_in_blocks_or_pixels) + { + // 'num_blocks_y', 'pOutput_blocks' & 'block_stride_in_bytes' unused + // when disabling BASISD_SUPPORT_ETC2_EAC_A8 *and* BASISD_SUPPORT_DXT5A + BASISU_NOTE_UNUSED(num_blocks_y); + BASISU_NOTE_UNUSED(pOutput_blocks); + BASISU_NOTE_UNUSED(block_stride_in_bytes); + + if (!output_row_pitch_in_blocks_or_pixels) + output_row_pitch_in_blocks_or_pixels = num_blocks_x; + + if ((fmt == block_format::cETC2_EAC_A8) || (fmt == block_format::cETC2_EAC_R11)) + { +#if BASISD_SUPPORT_ETC2_EAC_A8 + eac_block blk; + blk.m_base = 255; + blk.m_multiplier = 1; + blk.m_table = 13; + + // Selectors are all 4's + memcpy(&blk.m_selectors, g_etc2_eac_a8_sel4, sizeof(g_etc2_eac_a8_sel4)); + + for (uint32_t y = 0; y < num_blocks_y; y++) + { + uint32_t dst_ofs = y * output_row_pitch_in_blocks_or_pixels * block_stride_in_bytes; + for (uint32_t x = 0; x < num_blocks_x; x++) + { + memcpy((uint8_t*)pOutput_blocks + dst_ofs, &blk, sizeof(blk)); + dst_ofs += block_stride_in_bytes; + } + } +#endif + } + else if (fmt == block_format::cBC4) + { +#if BASISD_SUPPORT_DXT5A + dxt5a_block blk; + blk.m_endpoints[0] = 255; + blk.m_endpoints[1] = 255; + memset(blk.m_selectors, 0, sizeof(blk.m_selectors)); + + for (uint32_t y = 0; y < num_blocks_y; y++) + { + uint32_t dst_ofs = y * output_row_pitch_in_blocks_or_pixels * block_stride_in_bytes; + for (uint32_t x = 0; x < num_blocks_x; x++) + { + memcpy((uint8_t*)pOutput_blocks + dst_ofs, &blk, sizeof(blk)); + dst_ofs += block_stride_in_bytes; + } + } +#endif + } + } + + bool basisu_transcoder::transcode_image_level( + const void* pData, uint32_t data_size, + uint32_t image_index, uint32_t level_index, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + transcoder_texture_format fmt, + uint32_t decode_flags, uint32_t output_row_pitch_in_blocks_or_pixels, basisu_transcoder_state *pState, uint32_t output_rows_in_pixels) const + { + const uint32_t bytes_per_block_or_pixel = basis_get_bytes_per_block_or_pixel(fmt); + + if (!m_ready_to_transcode) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: must call start_transcoding() first\n"); + return false; + } + + //const bool transcode_alpha_data_to_opaque_formats = (decode_flags & cDecodeFlagsTranscodeAlphaDataToOpaqueFormats) != 0; + + if (decode_flags & cDecodeFlagsPVRTCDecodeToNextPow2) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: cDecodeFlagsPVRTCDecodeToNextPow2 currently unsupported\n"); + // TODO: Not yet supported + return false; + } + + if (!validate_header_quick(pData, data_size)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: header validation failed\n"); + return false; + } + + const basis_file_header* pHeader = reinterpret_cast(pData); + + const uint8_t* pDataU8 = static_cast(pData); + + const basis_slice_desc* pSlice_descs = reinterpret_cast(pDataU8 + pHeader->m_slice_desc_file_ofs); + + const bool basis_file_has_alpha_slices = (pHeader->m_flags & cBASISHeaderFlagHasAlphaSlices) != 0; + + int slice_index = find_first_slice_index(pData, data_size, image_index, level_index); + if (slice_index < 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: failed finding slice index\n"); + // Unable to find the requested image/level + return false; + } + + if ((fmt == transcoder_texture_format::cTFPVRTC1_4_RGBA) && (!basis_file_has_alpha_slices)) + { + // Switch to PVRTC1 RGB if the input doesn't have alpha. + fmt = transcoder_texture_format::cTFPVRTC1_4_RGB; + } + + if (pHeader->m_tex_format == (int)basis_tex_format::cETC1S) + { + if (pSlice_descs[slice_index].m_flags & cSliceDescFlagsHasAlpha) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has out of order alpha slice\n"); + + // The first slice shouldn't have alpha data in a properly formed basis file + return false; + } + + if (basis_file_has_alpha_slices) + { + // The alpha data should immediately follow the color data, and have the same resolution. + if ((slice_index + 1U) >= pHeader->m_total_slices) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has missing alpha slice\n"); + // basis file is missing the alpha slice + return false; + } + + // Basic sanity checks + if ((pSlice_descs[slice_index + 1].m_flags & cSliceDescFlagsHasAlpha) == 0) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file has missing alpha slice (flag check)\n"); + // This slice should have alpha data + return false; + } + + if ((pSlice_descs[slice_index].m_num_blocks_x != pSlice_descs[slice_index + 1].m_num_blocks_x) || (pSlice_descs[slice_index].m_num_blocks_y != pSlice_descs[slice_index + 1].m_num_blocks_y)) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: alpha basis file slice dimensions bad\n"); + // Alpha slice should have been the same res as the color slice + return false; + } + } + } + + bool status = false; + + const uint32_t total_slice_blocks = pSlice_descs[slice_index].m_num_blocks_x * pSlice_descs[slice_index].m_num_blocks_y; + + if (((fmt == transcoder_texture_format::cTFPVRTC1_4_RGB) || (fmt == transcoder_texture_format::cTFPVRTC1_4_RGBA)) && (output_blocks_buf_size_in_blocks_or_pixels > total_slice_blocks)) + { + // The transcoder doesn't write beyond total_slice_blocks, so we need to clear the rest ourselves. + // For GL usage, PVRTC1 4bpp image size is (max(width, 8)* max(height, 8) * 4 + 7) / 8. + // However, for KTX and internally in Basis this formula isn't used, it's just ((width+3)/4) * ((height+3)/4) * bytes_per_block_or_pixel. This is all the transcoder actually writes to memory. + memset(static_cast(pOutput_blocks) + total_slice_blocks * bytes_per_block_or_pixel, 0, (output_blocks_buf_size_in_blocks_or_pixels - total_slice_blocks) * bytes_per_block_or_pixel); + } + + if (pHeader->m_tex_format == (int)basis_tex_format::cUASTC4x4) + { + const basis_slice_desc* pSlice_desc = &pSlice_descs[slice_index]; + + // Use the container independent image transcode method. + status = m_lowlevel_uastc_decoder.transcode_image(fmt, + pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, + (const uint8_t*)pData, data_size, pSlice_desc->m_num_blocks_x, pSlice_desc->m_num_blocks_y, pSlice_desc->m_orig_width, pSlice_desc->m_orig_height, pSlice_desc->m_level_index, + pSlice_desc->m_file_ofs, pSlice_desc->m_file_size, + decode_flags, basis_file_has_alpha_slices, pHeader->m_tex_type == cBASISTexTypeVideoFrames, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + } + else + { + // ETC1S + const basis_slice_desc* pSlice_desc = &pSlice_descs[slice_index]; + const basis_slice_desc* pAlpha_slice_desc = basis_file_has_alpha_slices ? &pSlice_descs[slice_index + 1] : nullptr; + + assert((pSlice_desc->m_flags & cSliceDescFlagsHasAlpha) == 0); + + if (pAlpha_slice_desc) + { + // Basic sanity checks + assert((pAlpha_slice_desc->m_flags & cSliceDescFlagsHasAlpha) != 0); + assert(pSlice_desc->m_num_blocks_x == pAlpha_slice_desc->m_num_blocks_x); + assert(pSlice_desc->m_num_blocks_y == pAlpha_slice_desc->m_num_blocks_y); + assert(pSlice_desc->m_level_index == pAlpha_slice_desc->m_level_index); + } + + // Use the container independent image transcode method. + status = m_lowlevel_etc1s_decoder.transcode_image(fmt, + pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, + (const uint8_t *)pData, data_size, pSlice_desc->m_num_blocks_x, pSlice_desc->m_num_blocks_y, pSlice_desc->m_orig_width, pSlice_desc->m_orig_height, pSlice_desc->m_level_index, + pSlice_desc->m_file_ofs, pSlice_desc->m_file_size, + (pAlpha_slice_desc != nullptr) ? (uint32_t)pAlpha_slice_desc->m_file_ofs : 0U, (pAlpha_slice_desc != nullptr) ? (uint32_t)pAlpha_slice_desc->m_file_size : 0U, + decode_flags, basis_file_has_alpha_slices, pHeader->m_tex_type == cBASISTexTypeVideoFrames, output_row_pitch_in_blocks_or_pixels, pState, output_rows_in_pixels); + + } // if (pHeader->m_tex_format == (int)basis_tex_format::cUASTC4x4) + + if (!status) + { + BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: Returning false\n"); + } + else + { + //BASISU_DEVEL_ERROR("basisu_transcoder::transcode_image_level: Returning true\n"); + } + + return status; + } + + uint32_t basis_get_bytes_per_block_or_pixel(transcoder_texture_format fmt) + { + switch (fmt) + { + case transcoder_texture_format::cTFETC1_RGB: + case transcoder_texture_format::cTFBC1_RGB: + case transcoder_texture_format::cTFBC4_R: + case transcoder_texture_format::cTFPVRTC1_4_RGB: + case transcoder_texture_format::cTFPVRTC1_4_RGBA: + case transcoder_texture_format::cTFATC_RGB: + case transcoder_texture_format::cTFPVRTC2_4_RGB: + case transcoder_texture_format::cTFPVRTC2_4_RGBA: + case transcoder_texture_format::cTFETC2_EAC_R11: + return 8; + case transcoder_texture_format::cTFBC7_RGBA: + case transcoder_texture_format::cTFBC7_ALT: + case transcoder_texture_format::cTFETC2_RGBA: + case transcoder_texture_format::cTFBC3_RGBA: + case transcoder_texture_format::cTFBC5_RG: + case transcoder_texture_format::cTFASTC_4x4_RGBA: + case transcoder_texture_format::cTFATC_RGBA: + case transcoder_texture_format::cTFFXT1_RGB: + case transcoder_texture_format::cTFETC2_EAC_RG11: + return 16; + case transcoder_texture_format::cTFRGBA32: + return sizeof(uint32_t); + case transcoder_texture_format::cTFRGB565: + case transcoder_texture_format::cTFBGR565: + case transcoder_texture_format::cTFRGBA4444: + return sizeof(uint16_t); + default: + assert(0); + BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n"); + break; + } + return 0; + } + + const char* basis_get_format_name(transcoder_texture_format fmt) + { + switch (fmt) + { + case transcoder_texture_format::cTFETC1_RGB: return "ETC1_RGB"; + case transcoder_texture_format::cTFBC1_RGB: return "BC1_RGB"; + case transcoder_texture_format::cTFBC4_R: return "BC4_R"; + case transcoder_texture_format::cTFPVRTC1_4_RGB: return "PVRTC1_4_RGB"; + case transcoder_texture_format::cTFPVRTC1_4_RGBA: return "PVRTC1_4_RGBA"; + case transcoder_texture_format::cTFBC7_RGBA: return "BC7_RGBA"; + case transcoder_texture_format::cTFBC7_ALT: return "BC7_RGBA"; + case transcoder_texture_format::cTFETC2_RGBA: return "ETC2_RGBA"; + case transcoder_texture_format::cTFBC3_RGBA: return "BC3_RGBA"; + case transcoder_texture_format::cTFBC5_RG: return "BC5_RG"; + case transcoder_texture_format::cTFASTC_4x4_RGBA: return "ASTC_RGBA"; + case transcoder_texture_format::cTFATC_RGB: return "ATC_RGB"; + case transcoder_texture_format::cTFATC_RGBA: return "ATC_RGBA"; + case transcoder_texture_format::cTFRGBA32: return "RGBA32"; + case transcoder_texture_format::cTFRGB565: return "RGB565"; + case transcoder_texture_format::cTFBGR565: return "BGR565"; + case transcoder_texture_format::cTFRGBA4444: return "RGBA4444"; + case transcoder_texture_format::cTFFXT1_RGB: return "FXT1_RGB"; + case transcoder_texture_format::cTFPVRTC2_4_RGB: return "PVRTC2_4_RGB"; + case transcoder_texture_format::cTFPVRTC2_4_RGBA: return "PVRTC2_4_RGBA"; + case transcoder_texture_format::cTFETC2_EAC_R11: return "ETC2_EAC_R11"; + case transcoder_texture_format::cTFETC2_EAC_RG11: return "ETC2_EAC_RG11"; + default: + assert(0); + BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n"); + break; + } + return ""; + } + + const char* basis_get_block_format_name(block_format fmt) + { + switch (fmt) + { + case block_format::cETC1: return "ETC1"; + case block_format::cBC1: return "BC1"; + case block_format::cPVRTC1_4_RGB: return "PVRTC1_4_RGB"; + case block_format::cPVRTC1_4_RGBA: return "PVRTC1_4_RGBA"; + case block_format::cBC7: return "BC7"; + case block_format::cETC2_RGBA: return "ETC2_RGBA"; + case block_format::cBC3: return "BC3"; + case block_format::cASTC_4x4: return "ASTC_4x4"; + case block_format::cATC_RGB: return "ATC_RGB"; + case block_format::cRGBA32: return "RGBA32"; + case block_format::cRGB565: return "RGB565"; + case block_format::cBGR565: return "BGR565"; + case block_format::cRGBA4444: return "RGBA4444"; + case block_format::cUASTC_4x4: return "UASTC_4x4"; + case block_format::cFXT1_RGB: return "FXT1_RGB"; + case block_format::cPVRTC2_4_RGB: return "PVRTC2_4_RGB"; + case block_format::cPVRTC2_4_RGBA: return "PVRTC2_4_RGBA"; + case block_format::cETC2_EAC_R11: return "ETC2_EAC_R11"; + case block_format::cETC2_EAC_RG11: return "ETC2_EAC_RG11"; + default: + assert(0); + BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n"); + break; + } + return ""; + } + + const char* basis_get_texture_type_name(basis_texture_type tex_type) + { + switch (tex_type) + { + case cBASISTexType2D: return "2D"; + case cBASISTexType2DArray: return "2D array"; + case cBASISTexTypeCubemapArray: return "cubemap array"; + case cBASISTexTypeVideoFrames: return "video"; + case cBASISTexTypeVolume: return "3D"; + default: + assert(0); + BASISU_DEVEL_ERROR("basis_get_texture_type_name: Invalid tex_type\n"); + break; + } + return ""; + } + + bool basis_transcoder_format_has_alpha(transcoder_texture_format fmt) + { + switch (fmt) + { + case transcoder_texture_format::cTFETC2_RGBA: + case transcoder_texture_format::cTFBC3_RGBA: + case transcoder_texture_format::cTFASTC_4x4_RGBA: + case transcoder_texture_format::cTFBC7_RGBA: + case transcoder_texture_format::cTFBC7_ALT: + case transcoder_texture_format::cTFPVRTC1_4_RGBA: + case transcoder_texture_format::cTFPVRTC2_4_RGBA: + case transcoder_texture_format::cTFATC_RGBA: + case transcoder_texture_format::cTFRGBA32: + case transcoder_texture_format::cTFRGBA4444: + return true; + default: + break; + } + return false; + } + + basisu::texture_format basis_get_basisu_texture_format(transcoder_texture_format fmt) + { + switch (fmt) + { + case transcoder_texture_format::cTFETC1_RGB: return basisu::texture_format::cETC1; + case transcoder_texture_format::cTFBC1_RGB: return basisu::texture_format::cBC1; + case transcoder_texture_format::cTFBC4_R: return basisu::texture_format::cBC4; + case transcoder_texture_format::cTFPVRTC1_4_RGB: return basisu::texture_format::cPVRTC1_4_RGB; + case transcoder_texture_format::cTFPVRTC1_4_RGBA: return basisu::texture_format::cPVRTC1_4_RGBA; + case transcoder_texture_format::cTFBC7_RGBA: return basisu::texture_format::cBC7; + case transcoder_texture_format::cTFBC7_ALT: return basisu::texture_format::cBC7; + case transcoder_texture_format::cTFETC2_RGBA: return basisu::texture_format::cETC2_RGBA; + case transcoder_texture_format::cTFBC3_RGBA: return basisu::texture_format::cBC3; + case transcoder_texture_format::cTFBC5_RG: return basisu::texture_format::cBC5; + case transcoder_texture_format::cTFASTC_4x4_RGBA: return basisu::texture_format::cASTC4x4; + case transcoder_texture_format::cTFATC_RGB: return basisu::texture_format::cATC_RGB; + case transcoder_texture_format::cTFATC_RGBA: return basisu::texture_format::cATC_RGBA_INTERPOLATED_ALPHA; + case transcoder_texture_format::cTFRGBA32: return basisu::texture_format::cRGBA32; + case transcoder_texture_format::cTFRGB565: return basisu::texture_format::cRGB565; + case transcoder_texture_format::cTFBGR565: return basisu::texture_format::cBGR565; + case transcoder_texture_format::cTFRGBA4444: return basisu::texture_format::cRGBA4444; + case transcoder_texture_format::cTFFXT1_RGB: return basisu::texture_format::cFXT1_RGB; + case transcoder_texture_format::cTFPVRTC2_4_RGB: return basisu::texture_format::cPVRTC2_4_RGBA; + case transcoder_texture_format::cTFPVRTC2_4_RGBA: return basisu::texture_format::cPVRTC2_4_RGBA; + case transcoder_texture_format::cTFETC2_EAC_R11: return basisu::texture_format::cETC2_R11_EAC; + case transcoder_texture_format::cTFETC2_EAC_RG11: return basisu::texture_format::cETC2_RG11_EAC; + default: + assert(0); + BASISU_DEVEL_ERROR("basis_get_basisu_texture_format: Invalid fmt\n"); + break; + } + return basisu::texture_format::cInvalidTextureFormat; + } + + bool basis_transcoder_format_is_uncompressed(transcoder_texture_format tex_type) + { + switch (tex_type) + { + case transcoder_texture_format::cTFRGBA32: + case transcoder_texture_format::cTFRGB565: + case transcoder_texture_format::cTFBGR565: + case transcoder_texture_format::cTFRGBA4444: + return true; + default: + break; + } + return false; + } + + bool basis_block_format_is_uncompressed(block_format blk_fmt) + { + switch (blk_fmt) + { + case block_format::cRGB32: + case block_format::cRGBA32: + case block_format::cA32: + case block_format::cRGB565: + case block_format::cBGR565: + case block_format::cRGBA4444: + case block_format::cRGBA4444_COLOR: + case block_format::cRGBA4444_ALPHA: + case block_format::cRGBA4444_COLOR_OPAQUE: + return true; + default: + break; + } + return false; + } + + uint32_t basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format fmt) + { + switch (fmt) + { + case transcoder_texture_format::cTFRGBA32: + return sizeof(uint32_t); + case transcoder_texture_format::cTFRGB565: + case transcoder_texture_format::cTFBGR565: + case transcoder_texture_format::cTFRGBA4444: + return sizeof(uint16_t); + default: + break; + } + return 0; + } + + uint32_t basis_get_block_width(transcoder_texture_format tex_type) + { + switch (tex_type) + { + case transcoder_texture_format::cTFFXT1_RGB: + return 8; + default: + break; + } + return 4; + } + + uint32_t basis_get_block_height(transcoder_texture_format tex_type) + { + BASISU_NOTE_UNUSED(tex_type); + return 4; + } + + bool basis_is_format_supported(transcoder_texture_format tex_type, basis_tex_format fmt) + { + if (fmt == basis_tex_format::cUASTC4x4) + { +#if BASISD_SUPPORT_UASTC + switch (tex_type) + { + // These niche formats aren't currently supported for UASTC - everything else is. + case transcoder_texture_format::cTFPVRTC2_4_RGB: + case transcoder_texture_format::cTFPVRTC2_4_RGBA: + case transcoder_texture_format::cTFATC_RGB: + case transcoder_texture_format::cTFATC_RGBA: + case transcoder_texture_format::cTFFXT1_RGB: + return false; + default: + return true; + } +#endif + } + else + { + switch (tex_type) + { + // ETC1 and uncompressed are always supported. + case transcoder_texture_format::cTFETC1_RGB: + case transcoder_texture_format::cTFRGBA32: + case transcoder_texture_format::cTFRGB565: + case transcoder_texture_format::cTFBGR565: + case transcoder_texture_format::cTFRGBA4444: + return true; +#if BASISD_SUPPORT_DXT1 + case transcoder_texture_format::cTFBC1_RGB: + return true; +#endif +#if BASISD_SUPPORT_DXT5A + case transcoder_texture_format::cTFBC4_R: + case transcoder_texture_format::cTFBC5_RG: + return true; +#endif +#if BASISD_SUPPORT_DXT1 && BASISD_SUPPORT_DXT5A + case transcoder_texture_format::cTFBC3_RGBA: + return true; +#endif +#if BASISD_SUPPORT_PVRTC1 + case transcoder_texture_format::cTFPVRTC1_4_RGB: + case transcoder_texture_format::cTFPVRTC1_4_RGBA: + return true; +#endif +#if BASISD_SUPPORT_BC7_MODE5 + case transcoder_texture_format::cTFBC7_RGBA: + case transcoder_texture_format::cTFBC7_ALT: + return true; +#endif +#if BASISD_SUPPORT_ETC2_EAC_A8 + case transcoder_texture_format::cTFETC2_RGBA: + return true; +#endif +#if BASISD_SUPPORT_ASTC + case transcoder_texture_format::cTFASTC_4x4_RGBA: + return true; +#endif +#if BASISD_SUPPORT_ATC + case transcoder_texture_format::cTFATC_RGB: + case transcoder_texture_format::cTFATC_RGBA: + return true; +#endif +#if BASISD_SUPPORT_FXT1 + case transcoder_texture_format::cTFFXT1_RGB: + return true; +#endif +#if BASISD_SUPPORT_PVRTC2 + case transcoder_texture_format::cTFPVRTC2_4_RGB: + case transcoder_texture_format::cTFPVRTC2_4_RGBA: + return true; +#endif +#if BASISD_SUPPORT_ETC2_EAC_RG11 + case transcoder_texture_format::cTFETC2_EAC_R11: + case transcoder_texture_format::cTFETC2_EAC_RG11: + return true; +#endif + default: + break; + } + } + + return false; + } + + // ------------------------------------------------------------------------------------------------------ + // UASTC + // ------------------------------------------------------------------------------------------------------ + +#if BASISD_SUPPORT_UASTC + const astc_bc7_common_partition2_desc g_astc_bc7_common_partitions2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2] = + { + { 0, 28, false }, { 1, 20, false }, { 2, 16, true }, { 3, 29, false }, + { 4, 91, true }, { 5, 9, false }, { 6, 107, true }, { 7, 72, true }, + { 8, 149, false }, { 9, 204, true }, { 10, 50, false }, { 11, 114, true }, + { 12, 496, true }, { 13, 17, true }, { 14, 78, false }, { 15, 39, true }, + { 17, 252, true }, { 18, 828, true }, { 19, 43, false }, { 20, 156, false }, + { 21, 116, false }, { 22, 210, true }, { 23, 476, true }, { 24, 273, false }, + { 25, 684, true }, { 26, 359, false }, { 29, 246, true }, { 32, 195, true }, + { 33, 694, true }, { 52, 524, true } + }; + + const bc73_astc2_common_partition_desc g_bc7_3_astc2_common_partitions[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS] = + { + { 10, 36, 4 }, { 11, 48, 4 }, { 0, 61, 3 }, { 2, 137, 4 }, + { 8, 161, 5 }, { 13, 183, 4 }, { 1, 226, 2 }, { 33, 281, 2 }, + { 40, 302, 3 }, { 20, 307, 4 }, { 21, 479, 0 }, { 58, 495, 3 }, + { 3, 593, 0 }, { 32, 594, 2 }, { 59, 605, 1 }, { 34, 799, 3 }, + { 20, 812, 1 }, { 14, 988, 4 }, { 31, 993, 3 } + }; + + const astc_bc7_common_partition3_desc g_astc_bc7_common_partitions3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3] = + { + { 4, 260, 0 }, { 8, 74, 5 }, { 9, 32, 5 }, { 10, 156, 2 }, + { 11, 183, 2 }, { 12, 15, 0 }, { 13, 745, 4 }, { 20, 0, 1 }, + { 35, 335, 1 }, { 36, 902, 5 }, { 57, 254, 0 } + }; + + const uint8_t g_astc_to_bc7_partition_index_perm_tables[6][3] = { { 0, 1, 2 }, { 1, 2, 0 }, { 2, 0, 1 }, { 2, 1, 0 }, { 0, 2, 1 }, { 1, 0, 2 } }; + + const uint8_t g_bc7_to_astc_partition_index_perm_tables[6][3] = { { 0, 1, 2 }, { 2, 0, 1 }, { 1, 2, 0 }, { 2, 1, 0 }, { 0, 2, 1 }, { 1, 0, 2 } }; + + uint32_t bc7_convert_partition_index_3_to_2(uint32_t p, uint32_t k) + { + assert(k < 6); + switch (k >> 1) + { + case 0: + if (p <= 1) + p = 0; + else + p = 1; + break; + case 1: + if (p == 0) + p = 0; + else + p = 1; + break; + case 2: + if ((p == 0) || (p == 2)) + p = 0; + else + p = 1; + break; + } + if (k & 1) + p = 1 - p; + return p; + } + + static const uint8_t g_zero_pattern[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + + const uint8_t g_astc_bc7_patterns2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][16] = + { + { 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1 }, { 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1 }, { 1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0 }, { 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1 }, + { 1,1,1,1,1,1,1,0,1,1,1,0,1,1,0,0 }, { 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1 }, { 1,1,1,0,1,1,0,0,1,0,0,0,0,0,0,0 }, { 1,1,1,1,1,1,1,0,1,1,0,0,1,0,0,0 }, + { 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1 }, { 1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0 }, { 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1 }, { 1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0 }, + { 1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0 }, { 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 }, { 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1 }, { 1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0 }, + { 1,0,0,0,1,1,1,0,1,1,1,1,1,1,1,1 }, { 1,1,1,1,1,1,1,1,0,1,1,1,0,0,0,1 }, { 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0 }, { 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0 }, + { 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0 }, { 1,1,1,1,1,1,1,1,0,1,1,1,0,0,1,1 }, { 1,0,0,0,1,1,0,0,1,1,0,0,1,1,1,0 }, { 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0 }, + { 1,1,1,1,0,1,1,1,0,1,1,1,0,0,1,1 }, { 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0 }, { 1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1 }, { 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 }, + { 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0 }, { 1,0,0,1,0,0,1,1,0,1,1,0,1,1,0,0 } + }; + + const uint8_t g_astc_bc7_patterns3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][16] = + { + { 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2 }, { 1,1,1,1,1,1,1,1,0,0,0,0,2,2,2,2 }, { 1,1,1,1,0,0,0,0,0,0,0,0,2,2,2,2 }, { 1,1,1,1,2,2,2,2,0,0,0,0,0,0,0,0 }, + { 1,1,2,0,1,1,2,0,1,1,2,0,1,1,2,0 }, { 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2 }, { 0,2,1,1,0,2,1,1,0,2,1,1,0,2,1,1 }, { 2,0,0,0,2,0,0,0,2,1,1,1,2,1,1,1 }, + { 2,0,1,2,2,0,1,2,2,0,1,2,2,0,1,2 }, { 1,1,1,1,0,0,0,0,2,2,2,2,1,1,1,1 }, { 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2 } + }; + + const uint8_t g_bc7_3_astc2_patterns2[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][16] = + { + { 0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0 }, { 0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0 }, { 1,1,0,0,1,1,0,0,1,0,0,0,0,0,0,0 }, { 0,0,0,0,0,0,0,1,0,0,1,1,0,0,1,1 }, + { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 }, { 0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0 }, { 0,0,0,1,0,0,1,1,1,1,1,1,1,1,1,1 }, { 0,1,1,1,0,0,1,1,0,0,1,1,0,0,1,1 }, + { 1,1,0,0,0,0,0,0,0,0,1,1,1,1,0,0 }, { 0,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0 }, { 0,0,0,0,0,0,0,0,1,1,1,0,1,1,1,0 }, { 1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0 }, + { 0,1,1,1,0,0,1,1,0,0,0,0,0,0,0,0 }, { 0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 }, { 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0 }, { 1,1,0,0,1,1,0,0,1,1,0,0,1,0,0,0 }, + { 1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0 }, { 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,0 }, { 1,1,1,1,0,1,1,1,0,0,0,0,0,0,0,0 } + }; + + const uint8_t g_astc_bc7_pattern2_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][3] = + { + { 0, 2 }, { 0, 3 }, { 1, 0 }, { 0, 3 }, { 7, 0 }, { 0, 2 }, { 3, 0 }, { 7, 0 }, + { 0, 11 }, { 2, 0 }, { 0, 7 }, { 11, 0 }, { 3, 0 }, { 8, 0 }, { 0, 4 }, { 12, 0 }, + { 1, 0 }, { 8, 0 }, { 0, 1 }, { 0, 2 }, { 0, 4 }, { 8, 0 }, { 1, 0 }, { 0, 2 }, + { 4, 0 }, { 0, 1 }, { 4, 0 }, { 1, 0 }, { 4, 0 }, { 1, 0 } + }; + + const uint8_t g_astc_bc7_pattern3_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][3] = + { + { 0, 8, 10 }, { 8, 0, 12 }, { 4, 0, 12 }, { 8, 0, 4 }, { 3, 0, 2 }, { 0, 1, 3 }, { 0, 2, 1 }, { 1, 9, 0 }, { 1, 2, 0 }, { 4, 0, 8 }, { 0, 6, 2 } + }; + + const uint8_t g_bc7_3_astc2_patterns2_anchors[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][3] = + { + { 0, 4 }, { 0, 2 }, { 2, 0 }, { 0, 7 }, { 8, 0 }, { 0, 1 }, { 0, 3 }, { 0, 1 }, { 2, 0 }, { 0, 1 }, { 0, 8 }, { 2, 0 }, { 0, 1 }, { 0, 7 }, { 12, 0 }, { 2, 0 }, { 9, 0 }, { 0, 2 }, { 4, 0 } + }; + + const uint32_t g_uastc_mode_huff_codes[TOTAL_UASTC_MODES + 1][2] = + { + { 0x1, 4 }, + { 0x35, 6 }, + { 0x1D, 5 }, + { 0x3, 5 }, + + { 0x13, 5 }, + { 0xB, 5 }, + { 0x1B, 5 }, + { 0x7, 5 }, + + { 0x17, 5 }, + { 0xF, 5 }, + { 0x2, 3 }, + { 0x0, 2 }, + + { 0x6, 3 }, + { 0x1F, 5 }, + { 0xD, 5 }, + { 0x5, 7 }, + + { 0x15, 6 }, + { 0x25, 6 }, + { 0x9, 4 }, + { 0x45, 7 } // future expansion + }; + + // If g_uastc_mode_huff_codes[] changes this table must be updated! + static const uint8_t g_uastc_huff_modes[128] = + { + 11,0,10,3,11,15,12,7,11,18,10,5,11,14,12,9,11,0,10,4,11,16,12,8,11,18,10,6,11,2,12,13,11,0,10,3,11,17,12,7,11,18,10,5,11,14,12,9,11,0,10,4,11,1,12,8,11,18,10,6,11,2,12,13,11,0,10,3,11, + 19,12,7,11,18,10,5,11,14,12,9,11,0,10,4,11,16,12,8,11,18,10,6,11,2,12,13,11,0,10,3,11,17,12,7,11,18,10,5,11,14,12,9,11,0,10,4,11,1,12,8,11,18,10,6,11,2,12,13 + }; + + const uint8_t g_uastc_mode_weight_bits[TOTAL_UASTC_MODES] = { 4, 2, 3, 2, 2, 3, 2, 2, 0, 2, 4, 2, 3, 1, 2, 4, 2, 2, 5 }; + const uint8_t g_uastc_mode_weight_ranges[TOTAL_UASTC_MODES] = { 8, 2, 5, 2, 2, 5, 2, 2, 0, 2, 8, 2, 5, 0, 2, 8, 2, 2, 11 }; + const uint8_t g_uastc_mode_endpoint_ranges[TOTAL_UASTC_MODES] = { 19, 20, 8, 7, 12, 20, 18, 12, 0, 8, 13, 13, 19, 20, 20, 20, 20, 20, 11 }; + const uint8_t g_uastc_mode_subsets[TOTAL_UASTC_MODES] = { 1, 1, 2, 3, 2, 1, 1, 2, 0, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1 }; + const uint8_t g_uastc_mode_planes[TOTAL_UASTC_MODES] = { 1, 1, 1, 1, 1, 1, 2, 1, 0, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1 }; + const uint8_t g_uastc_mode_comps[TOTAL_UASTC_MODES] = { 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 3 }; + const uint8_t g_uastc_mode_has_etc1_bias[TOTAL_UASTC_MODES] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; + const uint8_t g_uastc_mode_has_bc1_hint0[TOTAL_UASTC_MODES] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; + const uint8_t g_uastc_mode_has_bc1_hint1[TOTAL_UASTC_MODES] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }; + const uint8_t g_uastc_mode_cem[TOTAL_UASTC_MODES] = { 8, 8, 8, 8, 8, 8, 8, 8, 0, 12, 12, 12, 12, 12, 12, 4, 4, 4, 8 }; + const uint8_t g_uastc_mode_has_alpha[TOTAL_UASTC_MODES] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; + const uint8_t g_uastc_mode_is_la[TOTAL_UASTC_MODES] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0 }; + const uint8_t g_uastc_mode_total_hint_bits[TOTAL_UASTC_MODES] = { 15, 15, 15, 15, 15, 15, 15, 15, 0, 23, 17, 17, 17, 23, 23, 23, 23, 23, 15 }; + + // bits, trits, quints + const int g_astc_bise_range_table[TOTAL_ASTC_RANGES][3] = + { + { 1, 0, 0 }, // 0-1 0 + { 0, 1, 0 }, // 0-2 1 + { 2, 0, 0 }, // 0-3 2 + { 0, 0, 1 }, // 0-4 3 + + { 1, 1, 0 }, // 0-5 4 + { 3, 0, 0 }, // 0-7 5 + { 1, 0, 1 }, // 0-9 6 + { 2, 1, 0 }, // 0-11 7 + + { 4, 0, 0 }, // 0-15 8 + { 2, 0, 1 }, // 0-19 9 + { 3, 1, 0 }, // 0-23 10 + { 5, 0, 0 }, // 0-31 11 + + { 3, 0, 1 }, // 0-39 12 + { 4, 1, 0 }, // 0-47 13 + { 6, 0, 0 }, // 0-63 14 + { 4, 0, 1 }, // 0-79 15 + + { 5, 1, 0 }, // 0-95 16 + { 7, 0, 0 }, // 0-127 17 + { 5, 0, 1 }, // 0-159 18 + { 6, 1, 0 }, // 0-191 19 + + { 8, 0, 0 }, // 0-255 20 + }; + + int astc_get_levels(int range) + { + assert(range < (int)BC7ENC_TOTAL_ASTC_RANGES); + return (1 + 2 * g_astc_bise_range_table[range][1] + 4 * g_astc_bise_range_table[range][2]) << g_astc_bise_range_table[range][0]; + } + + // g_astc_unquant[] is the inverse of g_astc_sorted_order_unquant[] + astc_quant_bin g_astc_unquant[BC7ENC_TOTAL_ASTC_RANGES][256]; // [ASTC encoded endpoint index] + + // Taken right from the ASTC spec. + static struct + { + const char* m_pB_str; + uint32_t m_c; + } g_astc_endpoint_unquant_params[BC7ENC_TOTAL_ASTC_RANGES] = + { + { "", 0 }, + { "", 0 }, + { "", 0 }, + { "", 0 }, + { "000000000", 204, }, // 0-5 + { "", 0 }, + { "000000000", 113, }, // 0-9 + { "b000b0bb0", 93 }, // 0-11 + { "", 0 }, + { "b0000bb00", 54 }, // 0-19 + { "cb000cbcb", 44 }, // 0-23 + { "", 0 }, + { "cb0000cbc", 26 }, // 0-39 + { "dcb000dcb", 22 }, // 0-47 + { "", 0 }, + { "dcb0000dc", 13 }, // 0-79 + { "edcb000ed", 11 }, // 0-95 + { "", 0 }, + { "edcb0000e", 6 }, // 0-159 + { "fedcb000f", 5 }, // 0-191 + { "", 0 }, + }; + + bool astc_is_valid_endpoint_range(uint32_t range) + { + if ((g_astc_bise_range_table[range][1] == 0) && (g_astc_bise_range_table[range][2] == 0)) + return true; + + return g_astc_endpoint_unquant_params[range].m_c != 0; + } + + uint32_t unquant_astc_endpoint(uint32_t packed_bits, uint32_t packed_trits, uint32_t packed_quints, uint32_t range) + { + assert(range < BC7ENC_TOTAL_ASTC_RANGES); + + const uint32_t bits = g_astc_bise_range_table[range][0]; + const uint32_t trits = g_astc_bise_range_table[range][1]; + const uint32_t quints = g_astc_bise_range_table[range][2]; + + uint32_t val = 0; + if ((!trits) && (!quints)) + { + assert(!packed_trits && !packed_quints); + + int bits_left = 8; + while (bits_left > 0) + { + uint32_t v = packed_bits; + + int n = basisu::minimumi(bits_left, bits); + if (n < (int)bits) + v >>= (bits - n); + + assert(v < (1U << n)); + + val |= (v << (bits_left - n)); + bits_left -= n; + } + } + else + { + const uint32_t A = (packed_bits & 1) ? 511 : 0; + const uint32_t C = g_astc_endpoint_unquant_params[range].m_c; + const uint32_t D = trits ? packed_trits : packed_quints; + + assert(C); + + uint32_t B = 0; + for (uint32_t i = 0; i < 9; i++) + { + B <<= 1; + + char c = g_astc_endpoint_unquant_params[range].m_pB_str[i]; + if (c != '0') + { + c -= 'a'; + B |= ((packed_bits >> c) & 1); + } + } + + val = D * C + B; + val = val ^ A; + val = (A & 0x80) | (val >> 2); + } + + return val; + } + + uint32_t unquant_astc_endpoint_val(uint32_t packed_val, uint32_t range) + { + assert(range < BC7ENC_TOTAL_ASTC_RANGES); + assert(packed_val < (uint32_t)astc_get_levels(range)); + + const uint32_t bits = g_astc_bise_range_table[range][0]; + const uint32_t trits = g_astc_bise_range_table[range][1]; + const uint32_t quints = g_astc_bise_range_table[range][2]; + + if ((!trits) && (!quints)) + return unquant_astc_endpoint(packed_val, 0, 0, range); + else if (trits) + return unquant_astc_endpoint(packed_val & ((1 << bits) - 1), packed_val >> bits, 0, range); + else + return unquant_astc_endpoint(packed_val & ((1 << bits) - 1), 0, packed_val >> bits, range); + } + + // BC7 - Various BC7 tables/helpers + const uint32_t g_bc7_weights1[2] = { 0, 64 }; + const uint32_t g_bc7_weights2[4] = { 0, 21, 43, 64 }; + const uint32_t g_bc7_weights3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 }; + const uint32_t g_bc7_weights4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; + const uint32_t g_astc_weights4[16] = { 0, 4, 8, 12, 17, 21, 25, 29, 35, 39, 43, 47, 52, 56, 60, 64 }; + const uint32_t g_astc_weights5[32] = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64 }; + const uint32_t g_astc_weights_3levels[3] = { 0, 32, 64 }; + + const uint8_t g_bc7_partition1[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; + + const uint8_t g_bc7_partition2[64 * 16] = + { + 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1, 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1, 0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1, + 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1, 0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, + 0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1, 0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0, 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0, 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1, + 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0, 0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0, 0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0, 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, 0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0, 0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0, + 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, 0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0, 0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0, 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0, 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0, 0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1, 0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1, + 0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0, 0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0, 0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0, 0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1, 0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1, 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0, + 0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0, 0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0, 0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0, 0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0, 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0, + 0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1, 0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1, 0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1, 0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1, 0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0, 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0, 0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1 + }; + + const uint8_t g_bc7_partition3[64 * 16] = + { + 0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2, 0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1, 0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1, 0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2, 0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2, 0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1, 0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1, + 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2, 0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2, 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2, 0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2, 0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2, 0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0, + 0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2, 0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0, 0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2, 0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1, 0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2, 0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1, 0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2, 0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0, + 0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0, 0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2, 0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0, 0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1, 0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2, 0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2, 0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1, 0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1, + 0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2, 0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1, 0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2, 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0, 0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0, 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0, 0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0, 0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1, + 0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1, 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1, 0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2, 0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1, 0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1, 0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1, 0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1, + 0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2, 0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1, 0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2, 0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2, 0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2, 0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2, 0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2, + 0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2, 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2, 0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2, 0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2, 0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1, 0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2, 0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2, 0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0, + }; + + const uint8_t g_bc7_table_anchor_index_second_subset[64] = { 15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15, 15, 2, 8, 2, 2, 8, 8,15, 2, 8, 2, 2, 8, 8, 2, 2, 15,15, 6, 8, 2, 8,15,15, 2, 8, 2, 2, 2,15,15, 6, 6, 2, 6, 8,15,15, 2, 2, 15,15,15,15,15, 2, 2,15 }; + + const uint8_t g_bc7_table_anchor_index_third_subset_1[64] = + { + 3, 3,15,15, 8, 3,15,15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8,15, 3, 3, 6,10, 5, 8, 8, 6, 8, 5,15,15, 8,15, 3, 5, 6,10, 8,15, 15, 3,15, 5,15,15,15,15, 3,15, 5, 5, 5, 8, 5,10, 5,10, 8,13,15,12, 3, 3 + }; + + const uint8_t g_bc7_table_anchor_index_third_subset_2[64] = + { + 15, 8, 8, 3,15,15, 3, 8, 15,15,15,15,15,15,15, 8, 15, 8,15, 3,15, 8,15, 8, 3,15, 6,10,15,15,10, 8, 15, 3,15,10,10, 8, 9,10, 6,15, 8,15, 3, 6, 6, 8, 15, 3,15,15,15,15,15,15, 15,15,15,15, 3,15,15, 8 + }; + + const uint8_t g_bc7_num_subsets[8] = { 3, 2, 3, 2, 1, 1, 1, 2 }; + const uint8_t g_bc7_partition_bits[8] = { 4, 6, 6, 6, 0, 0, 0, 6 }; + const uint8_t g_bc7_color_index_bitcount[8] = { 3, 3, 2, 2, 2, 2, 4, 2 }; + + const uint8_t g_bc7_mode_has_p_bits[8] = { 1, 1, 0, 1, 0, 0, 1, 1 }; + const uint8_t g_bc7_mode_has_shared_p_bits[8] = { 0, 1, 0, 0, 0, 0, 0, 0 }; + const uint8_t g_bc7_color_precision_table[8] = { 4, 6, 5, 7, 5, 7, 7, 5 }; + const int8_t g_bc7_alpha_precision_table[8] = { 0, 0, 0, 0, 6, 8, 7, 5 }; + + const uint8_t g_bc7_alpha_index_bitcount[8] = { 0, 0, 0, 0, 3, 2, 4, 2 }; + + endpoint_err g_bc7_mode_6_optimal_endpoints[256][2]; // [c][pbit] + endpoint_err g_bc7_mode_5_optimal_endpoints[256]; // [c] + + static inline void bc7_set_block_bits(uint8_t* pBytes, uint32_t val, uint32_t num_bits, uint32_t* pCur_ofs) + { + assert((num_bits <= 32) && (val < (1ULL << num_bits))); + while (num_bits) + { + const uint32_t n = basisu::minimumu(8 - (*pCur_ofs & 7), num_bits); + pBytes[*pCur_ofs >> 3] |= (uint8_t)(val << (*pCur_ofs & 7)); + val >>= n; + num_bits -= n; + *pCur_ofs += n; + } + assert(*pCur_ofs <= 128); + } + + // TODO: Optimize this. + void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults) + { + const uint32_t best_mode = pResults->m_mode; + + const uint32_t total_subsets = g_bc7_num_subsets[best_mode]; + const uint32_t total_partitions = 1 << g_bc7_partition_bits[best_mode]; + //const uint32_t num_rotations = 1 << g_bc7_rotation_bits[best_mode]; + //const uint32_t num_index_selectors = (best_mode == 4) ? 2 : 1; + + const uint8_t* pPartition; + if (total_subsets == 1) + pPartition = &g_bc7_partition1[0]; + else if (total_subsets == 2) + pPartition = &g_bc7_partition2[pResults->m_partition * 16]; + else + pPartition = &g_bc7_partition3[pResults->m_partition * 16]; + + uint8_t color_selectors[16]; + memcpy(color_selectors, pResults->m_selectors, 16); + + uint8_t alpha_selectors[16]; + memcpy(alpha_selectors, pResults->m_alpha_selectors, 16); + + color_quad_u8 low[3], high[3]; + memcpy(low, pResults->m_low, sizeof(low)); + memcpy(high, pResults->m_high, sizeof(high)); + + uint32_t pbits[3][2]; + memcpy(pbits, pResults->m_pbits, sizeof(pbits)); + + int anchor[3] = { -1, -1, -1 }; + + for (uint32_t k = 0; k < total_subsets; k++) + { + uint32_t anchor_index = 0; + if (k) + { + if ((total_subsets == 3) && (k == 1)) + anchor_index = g_bc7_table_anchor_index_third_subset_1[pResults->m_partition]; + else if ((total_subsets == 3) && (k == 2)) + anchor_index = g_bc7_table_anchor_index_third_subset_2[pResults->m_partition]; + else + anchor_index = g_bc7_table_anchor_index_second_subset[pResults->m_partition]; + } + + anchor[k] = anchor_index; + + const uint32_t color_index_bits = get_bc7_color_index_size(best_mode, pResults->m_index_selector); + const uint32_t num_color_indices = 1 << color_index_bits; + + if (color_selectors[anchor_index] & (num_color_indices >> 1)) + { + for (uint32_t i = 0; i < 16; i++) + if (pPartition[i] == k) + color_selectors[i] = (uint8_t)((num_color_indices - 1) - color_selectors[i]); + + if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) + { + for (uint32_t q = 0; q < 3; q++) + { + uint8_t t = low[k].m_c[q]; + low[k].m_c[q] = high[k].m_c[q]; + high[k].m_c[q] = t; + } + } + else + { + color_quad_u8 tmp = low[k]; + low[k] = high[k]; + high[k] = tmp; + } + + if (!g_bc7_mode_has_shared_p_bits[best_mode]) + { + uint32_t t = pbits[k][0]; + pbits[k][0] = pbits[k][1]; + pbits[k][1] = t; + } + } + + if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) + { + const uint32_t alpha_index_bits = get_bc7_alpha_index_size(best_mode, pResults->m_index_selector); + const uint32_t num_alpha_indices = 1 << alpha_index_bits; + + if (alpha_selectors[anchor_index] & (num_alpha_indices >> 1)) + { + for (uint32_t i = 0; i < 16; i++) + if (pPartition[i] == k) + alpha_selectors[i] = (uint8_t)((num_alpha_indices - 1) - alpha_selectors[i]); + + uint8_t t = low[k].m_c[3]; + low[k].m_c[3] = high[k].m_c[3]; + high[k].m_c[3] = t; + } + } + } + + uint8_t* pBlock_bytes = (uint8_t*)(pBlock); + memset(pBlock_bytes, 0, BC7ENC_BLOCK_SIZE); + + uint32_t cur_bit_ofs = 0; + bc7_set_block_bits(pBlock_bytes, 1 << best_mode, best_mode + 1, &cur_bit_ofs); + + if ((best_mode == 4) || (best_mode == 5)) + bc7_set_block_bits(pBlock_bytes, pResults->m_rotation, 2, &cur_bit_ofs); + + if (best_mode == 4) + bc7_set_block_bits(pBlock_bytes, pResults->m_index_selector, 1, &cur_bit_ofs); + + if (total_partitions > 1) + bc7_set_block_bits(pBlock_bytes, pResults->m_partition, (total_partitions == 64) ? 6 : 4, &cur_bit_ofs); + + const uint32_t total_comps = (best_mode >= 4) ? 4 : 3; + for (uint32_t comp = 0; comp < total_comps; comp++) + { + for (uint32_t subset = 0; subset < total_subsets; subset++) + { + bc7_set_block_bits(pBlock_bytes, low[subset].m_c[comp], (comp == 3) ? g_bc7_alpha_precision_table[best_mode] : g_bc7_color_precision_table[best_mode], &cur_bit_ofs); + bc7_set_block_bits(pBlock_bytes, high[subset].m_c[comp], (comp == 3) ? g_bc7_alpha_precision_table[best_mode] : g_bc7_color_precision_table[best_mode], &cur_bit_ofs); + } + } + + if (g_bc7_mode_has_p_bits[best_mode]) + { + for (uint32_t subset = 0; subset < total_subsets; subset++) + { + bc7_set_block_bits(pBlock_bytes, pbits[subset][0], 1, &cur_bit_ofs); + if (!g_bc7_mode_has_shared_p_bits[best_mode]) + bc7_set_block_bits(pBlock_bytes, pbits[subset][1], 1, &cur_bit_ofs); + } + } + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + int idx = x + y * 4; + + uint32_t n = pResults->m_index_selector ? get_bc7_alpha_index_size(best_mode, pResults->m_index_selector) : get_bc7_color_index_size(best_mode, pResults->m_index_selector); + + if ((idx == anchor[0]) || (idx == anchor[1]) || (idx == anchor[2])) + n--; + + bc7_set_block_bits(pBlock_bytes, pResults->m_index_selector ? alpha_selectors[idx] : color_selectors[idx], n, &cur_bit_ofs); + } + } + + if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) + { + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + int idx = x + y * 4; + + uint32_t n = pResults->m_index_selector ? get_bc7_color_index_size(best_mode, pResults->m_index_selector) : get_bc7_alpha_index_size(best_mode, pResults->m_index_selector); + + if ((idx == anchor[0]) || (idx == anchor[1]) || (idx == anchor[2])) + n--; + + bc7_set_block_bits(pBlock_bytes, pResults->m_index_selector ? color_selectors[idx] : alpha_selectors[idx], n, &cur_bit_ofs); + } + } + } + + assert(cur_bit_ofs == 128); + } + + // ASTC + static inline void astc_set_bits_1_to_9(uint32_t* pDst, int& bit_offset, uint32_t code, uint32_t codesize) + { + uint8_t* pBuf = reinterpret_cast(pDst); + + assert(codesize <= 9); + if (codesize) + { + uint32_t byte_bit_offset = bit_offset & 7; + uint32_t val = code << byte_bit_offset; + + uint32_t index = bit_offset >> 3; + pBuf[index] |= (uint8_t)val; + + if (codesize > (8 - byte_bit_offset)) + pBuf[index + 1] |= (uint8_t)(val >> 8); + + bit_offset += codesize; + } + } + + void pack_astc_solid_block(void* pDst_block, const color32& color) + { + uint32_t r = color[0], g = color[1], b = color[2]; + uint32_t a = color[3]; + + uint32_t* pOutput = static_cast(pDst_block); + uint8_t* pBytes = reinterpret_cast(pDst_block); + + pBytes[0] = 0xfc; pBytes[1] = 0xfd; pBytes[2] = 0xff; pBytes[3] = 0xff; + + pOutput[1] = 0xffffffff; + pOutput[2] = 0; + pOutput[3] = 0; + + int bit_pos = 64; + astc_set_bits(reinterpret_cast(pDst_block), bit_pos, r | (r << 8), 16); + astc_set_bits(reinterpret_cast(pDst_block), bit_pos, g | (g << 8), 16); + astc_set_bits(reinterpret_cast(pDst_block), bit_pos, b | (b << 8), 16); + astc_set_bits(reinterpret_cast(pDst_block), bit_pos, a | (a << 8), 16); + } + + // See 23.21 https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.inline.html#_partition_pattern_generation +#ifdef _DEBUG + static inline uint32_t astc_hash52(uint32_t v) + { + uint32_t p = v; + p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4; + p ^= p >> 5; p += p << 16; p ^= p >> 7; p ^= p >> 3; + p ^= p << 6; p ^= p >> 17; + return p; + } + + int astc_compute_texel_partition(int seed, int x, int y, int z, int partitioncount, bool small_block) + { + if (small_block) + { + x <<= 1; y <<= 1; z <<= 1; + } + seed += (partitioncount - 1) * 1024; + uint32_t rnum = astc_hash52(seed); + uint8_t seed1 = rnum & 0xF; + uint8_t seed2 = (rnum >> 4) & 0xF; + uint8_t seed3 = (rnum >> 8) & 0xF; + uint8_t seed4 = (rnum >> 12) & 0xF; + uint8_t seed5 = (rnum >> 16) & 0xF; + uint8_t seed6 = (rnum >> 20) & 0xF; + uint8_t seed7 = (rnum >> 24) & 0xF; + uint8_t seed8 = (rnum >> 28) & 0xF; + uint8_t seed9 = (rnum >> 18) & 0xF; + uint8_t seed10 = (rnum >> 22) & 0xF; + uint8_t seed11 = (rnum >> 26) & 0xF; + uint8_t seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF; + + seed1 *= seed1; seed2 *= seed2; + seed3 *= seed3; seed4 *= seed4; + seed5 *= seed5; seed6 *= seed6; + seed7 *= seed7; seed8 *= seed8; + seed9 *= seed9; seed10 *= seed10; + seed11 *= seed11; seed12 *= seed12; + + int sh1, sh2, sh3; + if (seed & 1) + { + sh1 = (seed & 2 ? 4 : 5); sh2 = (partitioncount == 3 ? 6 : 5); + } + else + { + sh1 = (partitioncount == 3 ? 6 : 5); sh2 = (seed & 2 ? 4 : 5); + } + sh3 = (seed & 0x10) ? sh1 : sh2; + + seed1 >>= sh1; seed2 >>= sh2; seed3 >>= sh1; seed4 >>= sh2; + seed5 >>= sh1; seed6 >>= sh2; seed7 >>= sh1; seed8 >>= sh2; + seed9 >>= sh3; seed10 >>= sh3; seed11 >>= sh3; seed12 >>= sh3; + + int a = seed1 * x + seed2 * y + seed11 * z + (rnum >> 14); + int b = seed3 * x + seed4 * y + seed12 * z + (rnum >> 10); + int c = seed5 * x + seed6 * y + seed9 * z + (rnum >> 6); + int d = seed7 * x + seed8 * y + seed10 * z + (rnum >> 2); + + a &= 0x3F; b &= 0x3F; c &= 0x3F; d &= 0x3F; + + if (partitioncount < 4) d = 0; + if (partitioncount < 3) c = 0; + + if (a >= b && a >= c && a >= d) + return 0; + else if (b >= c && b >= d) + return 1; + else if (c >= d) + return 2; + else + return 3; + } +#endif + + static const uint8_t g_astc_quint_encode[125] = + { + 0, 1, 2, 3, 4, 8, 9, 10, 11, 12, 16, 17, 18, 19, 20, 24, 25, 26, 27, 28, 5, 13, 21, 29, 6, 32, 33, 34, 35, 36, 40, 41, 42, 43, 44, 48, 49, 50, 51, 52, 56, 57, + 58, 59, 60, 37, 45, 53, 61, 14, 64, 65, 66, 67, 68, 72, 73, 74, 75, 76, 80, 81, 82, 83, 84, 88, 89, 90, 91, 92, 69, 77, 85, 93, 22, 96, 97, 98, 99, 100, 104, + 105, 106, 107, 108, 112, 113, 114, 115, 116, 120, 121, 122, 123, 124, 101, 109, 117, 125, 30, 102, 103, 70, 71, 38, 110, 111, 78, 79, 46, 118, 119, 86, 87, 54, + 126, 127, 94, 95, 62, 39, 47, 55, 63, 31 + }; + + // Encodes 3 values to output, usable for any range that uses quints and bits + static inline void astc_encode_quints(uint32_t* pOutput, const uint8_t* pValues, int& bit_pos, int n) + { + // First extract the trits and the bits from the 5 input values + int quints = 0, bits[3]; + const uint32_t bit_mask = (1 << n) - 1; + for (int i = 0; i < 3; i++) + { + static const int s_muls[3] = { 1, 5, 25 }; + + const int t = pValues[i] >> n; + + quints += t * s_muls[i]; + bits[i] = pValues[i] & bit_mask; + } + + // Encode the quints, by inverting the bit manipulations done by the decoder, converting 3 quints into 7-bits. + // See https://www.khronos.org/registry/DataFormat/specs/1.2/dataformat.1.2.html#astc-integer-sequence-encoding + + assert(quints < 125); + const int T = g_astc_quint_encode[quints]; + + // Now interleave the 7 encoded quint bits with the bits to form the encoded output. See table 95-96. + astc_set_bits(pOutput, bit_pos, bits[0] | (astc_extract_bits(T, 0, 2) << n) | (bits[1] << (3 + n)) | (astc_extract_bits(T, 3, 4) << (3 + n * 2)) | + (bits[2] << (5 + n * 2)) | (astc_extract_bits(T, 5, 6) << (5 + n * 3)), 7 + n * 3); + } + + // Packs values using ASTC's BISE to output buffer. + static void astc_pack_bise(uint32_t* pDst, const uint8_t* pSrc_vals, int bit_pos, int num_vals, int range) + { + uint32_t temp[5] = { 0, 0, 0, 0, 0 }; + + const int num_bits = g_astc_bise_range_table[range][0]; + + int group_size = 0; + if (g_astc_bise_range_table[range][1]) + group_size = 5; + else if (g_astc_bise_range_table[range][2]) + group_size = 3; + + if (group_size) + { + // Range has trits or quints - pack each group of 5 or 3 values + const int total_groups = (group_size == 5) ? ((num_vals + 4) / 5) : ((num_vals + 2) / 3); + + for (int group_index = 0; group_index < total_groups; group_index++) + { + uint8_t vals[5] = { 0, 0, 0, 0, 0 }; + + const int limit = basisu::minimum(group_size, num_vals - group_index * group_size); + for (int i = 0; i < limit; i++) + vals[i] = pSrc_vals[group_index * group_size + i]; + + if (group_size == 5) + astc_encode_trits(temp, vals, bit_pos, num_bits); + else + astc_encode_quints(temp, vals, bit_pos, num_bits); + } + } + else + { + for (int i = 0; i < num_vals; i++) + astc_set_bits_1_to_9(temp, bit_pos, pSrc_vals[i], num_bits); + } + + pDst[0] |= temp[0]; pDst[1] |= temp[1]; + pDst[2] |= temp[2]; pDst[3] |= temp[3]; + } + + const uint32_t ASTC_BLOCK_MODE_BITS = 11; + const uint32_t ASTC_PART_BITS = 2; + const uint32_t ASTC_CEM_BITS = 4; + const uint32_t ASTC_PARTITION_INDEX_BITS = 10; + const uint32_t ASTC_CCS_BITS = 2; + + const uint32_t g_uastc_mode_astc_block_mode[TOTAL_UASTC_MODES] = { 0x242, 0x42, 0x53, 0x42, 0x42, 0x53, 0x442, 0x42, 0, 0x42, 0x242, 0x442, 0x53, 0x441, 0x42, 0x242, 0x42, 0x442, 0x253 }; + + bool pack_astc_block(uint32_t* pDst, const astc_block_desc* pBlock, uint32_t uastc_mode) + { + assert(uastc_mode < TOTAL_UASTC_MODES); + uint8_t* pDst_bytes = reinterpret_cast(pDst); + + const int total_weights = pBlock->m_dual_plane ? 32 : 16; + + // Set mode bits - see Table 146-147 + uint32_t mode = g_uastc_mode_astc_block_mode[uastc_mode]; + pDst_bytes[0] = (uint8_t)mode; + pDst_bytes[1] = (uint8_t)(mode >> 8); + + memset(pDst_bytes + 2, 0, 16 - 2); + + int bit_pos = ASTC_BLOCK_MODE_BITS; + + // We only support 1-5 bit weight indices + assert(!g_astc_bise_range_table[pBlock->m_weight_range][1] && !g_astc_bise_range_table[pBlock->m_weight_range][2]); + const int bits_per_weight = g_astc_bise_range_table[pBlock->m_weight_range][0]; + + // See table 143 - PART + astc_set_bits_1_to_9(pDst, bit_pos, pBlock->m_subsets - 1, ASTC_PART_BITS); + + if (pBlock->m_subsets == 1) + astc_set_bits_1_to_9(pDst, bit_pos, pBlock->m_cem, ASTC_CEM_BITS); + else + { + // See table 145 + astc_set_bits(pDst, bit_pos, pBlock->m_partition_seed, ASTC_PARTITION_INDEX_BITS); + + // Table 150 - we assume all CEM's are equal, so write 2 0's along with the CEM + astc_set_bits_1_to_9(pDst, bit_pos, (pBlock->m_cem << 2) & 63, ASTC_CEM_BITS + 2); + } + + if (pBlock->m_dual_plane) + { + const int total_weight_bits = total_weights * bits_per_weight; + + // See Illegal Encodings 23.24 + // https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.inline.html#_illegal_encodings + assert((total_weight_bits >= 24) && (total_weight_bits <= 96)); + + int ccs_bit_pos = 128 - total_weight_bits - ASTC_CCS_BITS; + astc_set_bits_1_to_9(pDst, ccs_bit_pos, pBlock->m_ccs, ASTC_CCS_BITS); + } + + const int num_cem_pairs = (1 + (pBlock->m_cem >> 2)) * pBlock->m_subsets; + assert(num_cem_pairs <= 9); + + astc_pack_bise(pDst, pBlock->m_endpoints, bit_pos, num_cem_pairs * 2, g_uastc_mode_endpoint_ranges[uastc_mode]); + + // Write the weight bits in reverse bit order. + switch (bits_per_weight) + { + case 1: + { + const uint32_t N = 1; + for (int i = 0; i < total_weights; i++) + { + const uint32_t ofs = 128 - N - i; + assert((ofs >> 3) < 16); + pDst_bytes[ofs >> 3] |= (pBlock->m_weights[i] << (ofs & 7)); + } + break; + } + case 2: + { + const uint32_t N = 2; + for (int i = 0; i < total_weights; i++) + { + static const uint8_t s_reverse_bits2[4] = { 0, 2, 1, 3 }; + const uint32_t ofs = 128 - N - (i * N); + assert((ofs >> 3) < 16); + pDst_bytes[ofs >> 3] |= (s_reverse_bits2[pBlock->m_weights[i]] << (ofs & 7)); + } + break; + } + case 3: + { + const uint32_t N = 3; + for (int i = 0; i < total_weights; i++) + { + static const uint8_t s_reverse_bits3[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; + + const uint32_t ofs = 128 - N - (i * N); + const uint32_t rev = s_reverse_bits3[pBlock->m_weights[i]] << (ofs & 7); + + uint32_t index = ofs >> 3; + assert(index < 16); + pDst_bytes[index++] |= rev & 0xFF; + if (index < 16) + pDst_bytes[index++] |= (rev >> 8); + } + break; + } + case 4: + { + const uint32_t N = 4; + for (int i = 0; i < total_weights; i++) + { + static const uint8_t s_reverse_bits4[16] = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; + const int ofs = 128 - N - (i * N); + assert(ofs >= 0 && (ofs >> 3) < 16); + pDst_bytes[ofs >> 3] |= (s_reverse_bits4[pBlock->m_weights[i]] << (ofs & 7)); + } + break; + } + case 5: + { + const uint32_t N = 5; + for (int i = 0; i < total_weights; i++) + { + static const uint8_t s_reverse_bits5[32] = { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 }; + + const uint32_t ofs = 128 - N - (i * N); + const uint32_t rev = s_reverse_bits5[pBlock->m_weights[i]] << (ofs & 7); + + uint32_t index = ofs >> 3; + assert(index < 16); + pDst_bytes[index++] |= rev & 0xFF; + if (index < 16) + pDst_bytes[index++] |= (rev >> 8); + } + + break; + } + default: + assert(0); + break; + } + + return true; + } + + const uint8_t* get_anchor_indices(uint32_t subsets, uint32_t mode, uint32_t common_pattern, const uint8_t*& pPartition_pattern) + { + const uint8_t* pSubset_anchor_indices = g_zero_pattern; + pPartition_pattern = g_zero_pattern; + + if (subsets >= 2) + { + if (subsets == 3) + { + pPartition_pattern = &g_astc_bc7_patterns3[common_pattern][0]; + pSubset_anchor_indices = &g_astc_bc7_pattern3_anchors[common_pattern][0]; + } + else if (mode == 7) + { + pPartition_pattern = &g_bc7_3_astc2_patterns2[common_pattern][0]; + pSubset_anchor_indices = &g_bc7_3_astc2_patterns2_anchors[common_pattern][0]; + } + else + { + pPartition_pattern = &g_astc_bc7_patterns2[common_pattern][0]; + pSubset_anchor_indices = &g_astc_bc7_pattern2_anchors[common_pattern][0]; + } + } + + return pSubset_anchor_indices; + } + + static inline uint32_t read_bit(const uint8_t* pBuf, uint32_t& bit_offset) + { + uint32_t byte_bits = pBuf[bit_offset >> 3] >> (bit_offset & 7); + bit_offset += 1; + return byte_bits & 1; + } + + static inline uint32_t read_bits1_to_9(const uint8_t* pBuf, uint32_t& bit_offset, uint32_t codesize) + { + assert(codesize <= 9); + if (!codesize) + return 0; + + if ((BASISD_IS_BIG_ENDIAN) || (!BASISD_USE_UNALIGNED_WORD_READS) || (bit_offset >= 112)) + { + const uint8_t* pBytes = &pBuf[bit_offset >> 3U]; + + uint32_t byte_bit_offset = bit_offset & 7U; + + uint32_t bits = pBytes[0] >> byte_bit_offset; + uint32_t bits_read = basisu::minimum(codesize, 8 - byte_bit_offset); + + uint32_t bits_remaining = codesize - bits_read; + if (bits_remaining) + bits |= ((uint32_t)pBytes[1]) << bits_read; + + bit_offset += codesize; + + return bits & ((1U << codesize) - 1U); + } + + uint32_t byte_bit_offset = bit_offset & 7U; + const uint16_t w = *(const uint16_t *)(&pBuf[bit_offset >> 3U]); + bit_offset += codesize; + return (w >> byte_bit_offset) & ((1U << codesize) - 1U); + } + + inline uint64_t read_bits64(const uint8_t* pBuf, uint32_t& bit_offset, uint32_t codesize) + { + assert(codesize <= 64U); + uint64_t bits = 0; + uint32_t total_bits = 0; + + while (total_bits < codesize) + { + uint32_t byte_bit_offset = bit_offset & 7U; + uint32_t bits_to_read = basisu::minimum(codesize - total_bits, 8U - byte_bit_offset); + + uint32_t byte_bits = pBuf[bit_offset >> 3U] >> byte_bit_offset; + byte_bits &= ((1U << bits_to_read) - 1U); + + bits |= ((uint64_t)(byte_bits) << total_bits); + + total_bits += bits_to_read; + bit_offset += bits_to_read; + } + + return bits; + } + + static inline uint32_t read_bits1_to_9_fst(const uint8_t* pBuf, uint32_t& bit_offset, uint32_t codesize) + { + assert(codesize <= 9); + if (!codesize) + return 0; + assert(bit_offset < 112); + + if ((BASISD_IS_BIG_ENDIAN) || (!BASISD_USE_UNALIGNED_WORD_READS)) + { + const uint8_t* pBytes = &pBuf[bit_offset >> 3U]; + + uint32_t byte_bit_offset = bit_offset & 7U; + + uint32_t bits = pBytes[0] >> byte_bit_offset; + uint32_t bits_read = basisu::minimum(codesize, 8 - byte_bit_offset); + + uint32_t bits_remaining = codesize - bits_read; + if (bits_remaining) + bits |= ((uint32_t)pBytes[1]) << bits_read; + + bit_offset += codesize; + + return bits & ((1U << codesize) - 1U); + } + + uint32_t byte_bit_offset = bit_offset & 7U; + const uint16_t w = *(const uint16_t*)(&pBuf[bit_offset >> 3U]); + bit_offset += codesize; + return (w >> byte_bit_offset)& ((1U << codesize) - 1U); + } + + bool unpack_uastc(const uastc_block& blk, unpacked_uastc_block& unpacked, bool blue_contract_check, bool read_hints) + { + //memset(&unpacked, 0, sizeof(unpacked)); + +#if 0 + uint8_t table[128]; + memset(table, 0xFF, sizeof(table)); + + { + for (uint32_t mode = 0; mode <= TOTAL_UASTC_MODES; mode++) + { + const uint32_t code = g_uastc_mode_huff_codes[mode][0]; + const uint32_t codesize = g_uastc_mode_huff_codes[mode][1]; + + table[code] = mode; + + uint32_t bits_left = 7 - codesize; + for (uint32_t i = 0; i < (1 << bits_left); i++) + table[code | (i << codesize)] = mode; + } + + for (uint32_t i = 0; i < 128; i++) + printf("%u,", table[i]); + exit(0); + } +#endif + + const int mode = g_uastc_huff_modes[blk.m_bytes[0] & 127]; + if (mode >= (int)TOTAL_UASTC_MODES) + return false; + + unpacked.m_mode = mode; + + uint32_t bit_ofs = g_uastc_mode_huff_codes[mode][1]; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + unpacked.m_solid_color.r = (uint8_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 8); + unpacked.m_solid_color.g = (uint8_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 8); + unpacked.m_solid_color.b = (uint8_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 8); + unpacked.m_solid_color.a = (uint8_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 8); + + if (read_hints) + { + unpacked.m_etc1_flip = false; + unpacked.m_etc1_diff = read_bit(blk.m_bytes, bit_ofs) != 0; + unpacked.m_etc1_inten0 = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 3); + unpacked.m_etc1_inten1 = 0; + unpacked.m_etc1_selector = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 2); + unpacked.m_etc1_r = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 5); + unpacked.m_etc1_g = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 5); + unpacked.m_etc1_b = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 5); + unpacked.m_etc1_bias = 0; + unpacked.m_etc2_hints = 0; + } + + return true; + } + + if (read_hints) + { + if (g_uastc_mode_has_bc1_hint0[mode]) + unpacked.m_bc1_hint0 = read_bit(blk.m_bytes, bit_ofs) != 0; + else + unpacked.m_bc1_hint0 = false; + + if (g_uastc_mode_has_bc1_hint1[mode]) + unpacked.m_bc1_hint1 = read_bit(blk.m_bytes, bit_ofs) != 0; + else + unpacked.m_bc1_hint1 = false; + + unpacked.m_etc1_flip = read_bit(blk.m_bytes, bit_ofs) != 0; + unpacked.m_etc1_diff = read_bit(blk.m_bytes, bit_ofs) != 0; + unpacked.m_etc1_inten0 = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 3); + unpacked.m_etc1_inten1 = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 3); + + if (g_uastc_mode_has_etc1_bias[mode]) + unpacked.m_etc1_bias = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 5); + else + unpacked.m_etc1_bias = 0; + + if (g_uastc_mode_has_alpha[mode]) + { + unpacked.m_etc2_hints = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 8); + //assert(unpacked.m_etc2_hints > 0); + } + else + unpacked.m_etc2_hints = 0; + } + else + bit_ofs += g_uastc_mode_total_hint_bits[mode]; + + uint32_t subsets = 1; + switch (mode) + { + case 2: + case 4: + case 7: + case 9: + case 16: + unpacked.m_common_pattern = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 5); + subsets = 2; + break; + case 3: + unpacked.m_common_pattern = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 4); + subsets = 3; + break; + default: + break; + } + + uint32_t part_seed = 0; + switch (mode) + { + case 2: + case 4: + case 9: + case 16: + if (unpacked.m_common_pattern >= TOTAL_ASTC_BC7_COMMON_PARTITIONS2) + return false; + + part_seed = g_astc_bc7_common_partitions2[unpacked.m_common_pattern].m_astc; + break; + case 3: + if (unpacked.m_common_pattern >= TOTAL_ASTC_BC7_COMMON_PARTITIONS3) + return false; + + part_seed = g_astc_bc7_common_partitions3[unpacked.m_common_pattern].m_astc; + break; + case 7: + if (unpacked.m_common_pattern >= TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS) + return false; + + part_seed = g_bc7_3_astc2_common_partitions[unpacked.m_common_pattern].m_astc2; + break; + default: + break; + } + + uint32_t total_planes = 1; + switch (mode) + { + case 6: + case 11: + case 13: + unpacked.m_astc.m_ccs = (int)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, 2); + total_planes = 2; + break; + case 17: + unpacked.m_astc.m_ccs = 3; + total_planes = 2; + break; + default: + break; + } + + unpacked.m_astc.m_dual_plane = (total_planes == 2); + + unpacked.m_astc.m_subsets = subsets; + unpacked.m_astc.m_partition_seed = part_seed; + + const uint32_t total_comps = g_uastc_mode_comps[mode]; + + const uint32_t weight_bits = g_uastc_mode_weight_bits[mode]; + + unpacked.m_astc.m_weight_range = g_uastc_mode_weight_ranges[mode]; + + const uint32_t total_values = total_comps * 2 * subsets; + const uint32_t endpoint_range = g_uastc_mode_endpoint_ranges[mode]; + + const uint32_t cem = g_uastc_mode_cem[mode]; + unpacked.m_astc.m_cem = cem; + + const uint32_t ep_bits = g_astc_bise_range_table[endpoint_range][0]; + const uint32_t ep_trits = g_astc_bise_range_table[endpoint_range][1]; + const uint32_t ep_quints = g_astc_bise_range_table[endpoint_range][2]; + + uint32_t total_tqs = 0; + uint32_t bundle_size = 0, mul = 0; + if (ep_trits) + { + total_tqs = (total_values + 4) / 5; + bundle_size = 5; + mul = 3; + } + else if (ep_quints) + { + total_tqs = (total_values + 2) / 3; + bundle_size = 3; + mul = 5; + } + + uint32_t tq_values[8]; + for (uint32_t i = 0; i < total_tqs; i++) + { + uint32_t num_bits = ep_trits ? 8 : 7; + if (i == (total_tqs - 1)) + { + uint32_t num_remaining = total_values - (total_tqs - 1) * bundle_size; + if (ep_trits) + { + switch (num_remaining) + { + case 1: num_bits = 2; break; + case 2: num_bits = 4; break; + case 3: num_bits = 5; break; + case 4: num_bits = 7; break; + default: break; + } + } + else if (ep_quints) + { + switch (num_remaining) + { + case 1: num_bits = 3; break; + case 2: num_bits = 5; break; + default: break; + } + } + } + + tq_values[i] = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, num_bits); + } // i + + uint32_t accum = 0; + uint32_t accum_remaining = 0; + uint32_t next_tq_index = 0; + + for (uint32_t i = 0; i < total_values; i++) + { + uint32_t value = (uint32_t)read_bits1_to_9_fst(blk.m_bytes, bit_ofs, ep_bits); + + if (total_tqs) + { + if (!accum_remaining) + { + assert(next_tq_index < total_tqs); + accum = tq_values[next_tq_index++]; + accum_remaining = bundle_size; + } + + // TODO: Optimize with tables + uint32_t v = accum % mul; + accum /= mul; + accum_remaining--; + + value |= (v << ep_bits); + } + + unpacked.m_astc.m_endpoints[i] = (uint8_t)value; + } + + const uint8_t* pPartition_pattern; + const uint8_t* pSubset_anchor_indices = get_anchor_indices(subsets, mode, unpacked.m_common_pattern, pPartition_pattern); + +#ifdef _DEBUG + for (uint32_t i = 0; i < 16; i++) + assert(pPartition_pattern[i] == astc_compute_texel_partition(part_seed, i & 3, i >> 2, 0, subsets, true)); + + for (uint32_t subset_index = 0; subset_index < subsets; subset_index++) + { + uint32_t anchor_index = 0; + + for (uint32_t i = 0; i < 16; i++) + { + if (pPartition_pattern[i] == subset_index) + { + anchor_index = i; + break; + } + } + + assert(pSubset_anchor_indices[subset_index] == anchor_index); + } +#endif + +#if 0 + const uint32_t total_planes_shift = total_planes - 1; + for (uint32_t i = 0; i < 16 * total_planes; i++) + { + uint32_t num_bits = weight_bits; + for (uint32_t s = 0; s < subsets; s++) + { + if (pSubset_anchor_indices[s] == (i >> total_planes_shift)) + { + num_bits--; + break; + } + } + + unpacked.m_astc.m_weights[i] = (uint8_t)read_bits1_to_9(blk.m_bytes, bit_ofs, num_bits); + } +#endif + + if (mode == 18) + { + // Mode 18 is the only mode with more than 64 weight bits. + for (uint32_t i = 0; i < 16; i++) + unpacked.m_astc.m_weights[i] = (uint8_t)read_bits1_to_9(blk.m_bytes, bit_ofs, i ? weight_bits : (weight_bits - 1)); + } + else + { + // All other modes have <= 64 weight bits. + uint64_t bits; + + // Read the weight bits + if ((BASISD_IS_BIG_ENDIAN) || (!BASISD_USE_UNALIGNED_WORD_READS)) + bits = read_bits64(blk.m_bytes, bit_ofs, basisu::minimum(64, 128 - (int)bit_ofs)); + else + { + bits = blk.m_dwords[2]; + bits |= (((uint64_t)blk.m_dwords[3]) << 32U); + + if (bit_ofs >= 64U) + bits >>= (bit_ofs - 64U); + else + { + assert(bit_ofs >= 56U); + + uint32_t bits_needed = 64U - bit_ofs; + bits <<= bits_needed; + bits |= (blk.m_bytes[7] >> (8U - bits_needed)); + } + } + + bit_ofs = 0; + + const uint32_t mask = (1U << weight_bits) - 1U; + const uint32_t anchor_mask = (1U << (weight_bits - 1U)) - 1U; + + if (total_planes == 2) + { + // Dual plane modes always have a single subset, and the first 2 weights are anchors. + + unpacked.m_astc.m_weights[0] = (uint8_t)((uint32_t)(bits >> bit_ofs) & anchor_mask); + bit_ofs += (weight_bits - 1); + + unpacked.m_astc.m_weights[1] = (uint8_t)((uint32_t)(bits >> bit_ofs) & anchor_mask); + bit_ofs += (weight_bits - 1); + + for (uint32_t i = 2; i < 32; i++) + { + unpacked.m_astc.m_weights[i] = (uint8_t)((uint32_t)(bits >> bit_ofs) & mask); + bit_ofs += weight_bits; + } + } + else + { + if (subsets == 1) + { + // Specialize the single subset case. + if (weight_bits == 4) + { + assert(bit_ofs == 0); + + // Specialize the most common case: 4-bit weights. + unpacked.m_astc.m_weights[0] = (uint8_t)((uint32_t)(bits) & 7); + unpacked.m_astc.m_weights[1] = (uint8_t)((uint32_t)(bits >> 3) & 15); + unpacked.m_astc.m_weights[2] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 1)) & 15); + unpacked.m_astc.m_weights[3] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 2)) & 15); + + unpacked.m_astc.m_weights[4] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 3)) & 15); + unpacked.m_astc.m_weights[5] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 4)) & 15); + unpacked.m_astc.m_weights[6] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 5)) & 15); + unpacked.m_astc.m_weights[7] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 6)) & 15); + + unpacked.m_astc.m_weights[8] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 7)) & 15); + unpacked.m_astc.m_weights[9] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 8)) & 15); + unpacked.m_astc.m_weights[10] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 9)) & 15); + unpacked.m_astc.m_weights[11] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 10)) & 15); + + unpacked.m_astc.m_weights[12] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 11)) & 15); + unpacked.m_astc.m_weights[13] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 12)) & 15); + unpacked.m_astc.m_weights[14] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 13)) & 15); + unpacked.m_astc.m_weights[15] = (uint8_t)((uint32_t)(bits >> (3 + 4 * 14)) & 15); + } + else + { + // First weight is always an anchor. + unpacked.m_astc.m_weights[0] = (uint8_t)((uint32_t)(bits >> bit_ofs) & anchor_mask); + bit_ofs += (weight_bits - 1); + + for (uint32_t i = 1; i < 16; i++) + { + unpacked.m_astc.m_weights[i] = (uint8_t)((uint32_t)(bits >> bit_ofs) & mask); + bit_ofs += weight_bits; + } + } + } + else + { + const uint32_t a0 = pSubset_anchor_indices[0], a1 = pSubset_anchor_indices[1], a2 = pSubset_anchor_indices[2]; + + for (uint32_t i = 0; i < 16; i++) + { + if ((i == a0) || (i == a1) || (i == a2)) + { + unpacked.m_astc.m_weights[i] = (uint8_t)((uint32_t)(bits >> bit_ofs) & anchor_mask); + bit_ofs += (weight_bits - 1); + } + else + { + unpacked.m_astc.m_weights[i] = (uint8_t)((uint32_t)(bits >> bit_ofs) & mask); + bit_ofs += weight_bits; + } + } + } + } + } + + if ((blue_contract_check) && (total_comps >= 3)) + { + // We only need to disable ASTC Blue Contraction when we'll be packing to ASTC. The other transcoders don't care. + bool invert_subset[3] = { false, false, false }; + bool any_flag = false; + + for (uint32_t subset_index = 0; subset_index < subsets; subset_index++) + { + const int s0 = g_astc_unquant[endpoint_range][unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + 0]].m_unquant + + g_astc_unquant[endpoint_range][unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + 2]].m_unquant + + g_astc_unquant[endpoint_range][unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + 4]].m_unquant; + + const int s1 = g_astc_unquant[endpoint_range][unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + 1]].m_unquant + + g_astc_unquant[endpoint_range][unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + 3]].m_unquant + + g_astc_unquant[endpoint_range][unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + 5]].m_unquant; + + if (s1 < s0) + { + for (uint32_t c = 0; c < total_comps; c++) + std::swap(unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + c * 2 + 0], unpacked.m_astc.m_endpoints[subset_index * total_comps * 2 + c * 2 + 1]); + + invert_subset[subset_index] = true; + any_flag = true; + } + } + + if (any_flag) + { + const uint32_t weight_mask = (1 << weight_bits) - 1; + + for (uint32_t i = 0; i < 16; i++) + { + uint32_t subset = pPartition_pattern[i]; + + if (invert_subset[subset]) + { + unpacked.m_astc.m_weights[i * total_planes] = (uint8_t)(weight_mask - unpacked.m_astc.m_weights[i * total_planes]); + + if (total_planes == 2) + unpacked.m_astc.m_weights[i * total_planes + 1] = (uint8_t)(weight_mask - unpacked.m_astc.m_weights[i * total_planes + 1]); + } + } + } + } + + return true; + } + + static const uint32_t* g_astc_weight_tables[6] = { nullptr, g_bc7_weights1, g_bc7_weights2, g_bc7_weights3, g_astc_weights4, g_astc_weights5 }; + + bool unpack_uastc(uint32_t mode, uint32_t common_pattern, const color32& solid_color, const astc_block_desc& astc, color32* pPixels, bool srgb) + { + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + for (uint32_t i = 0; i < 16; i++) + pPixels[i] = solid_color; + return true; + } + + color32 endpoints[3][2]; + + const uint32_t total_subsets = g_uastc_mode_subsets[mode]; + const uint32_t total_comps = basisu::minimum(4U, g_uastc_mode_comps[mode]); + const uint32_t endpoint_range = g_uastc_mode_endpoint_ranges[mode]; + const uint32_t total_planes = g_uastc_mode_planes[mode]; + const uint32_t weight_bits = g_uastc_mode_weight_bits[mode]; + const uint32_t weight_levels = 1 << weight_bits; + + for (uint32_t subset_index = 0; subset_index < total_subsets; subset_index++) + { + if (total_comps == 2) + { + const uint32_t ll = g_astc_unquant[endpoint_range][astc.m_endpoints[subset_index * total_comps * 2 + 0 * 2 + 0]].m_unquant; + const uint32_t lh = g_astc_unquant[endpoint_range][astc.m_endpoints[subset_index * total_comps * 2 + 0 * 2 + 1]].m_unquant; + + const uint32_t al = g_astc_unquant[endpoint_range][astc.m_endpoints[subset_index * total_comps * 2 + 1 * 2 + 0]].m_unquant; + const uint32_t ah = g_astc_unquant[endpoint_range][astc.m_endpoints[subset_index * total_comps * 2 + 1 * 2 + 1]].m_unquant; + + endpoints[subset_index][0].set_noclamp_rgba(ll, ll, ll, al); + endpoints[subset_index][1].set_noclamp_rgba(lh, lh, lh, ah); + } + else + { + for (uint32_t comp_index = 0; comp_index < total_comps; comp_index++) + { + endpoints[subset_index][0][comp_index] = g_astc_unquant[endpoint_range][astc.m_endpoints[subset_index * total_comps * 2 + comp_index * 2 + 0]].m_unquant; + endpoints[subset_index][1][comp_index] = g_astc_unquant[endpoint_range][astc.m_endpoints[subset_index * total_comps * 2 + comp_index * 2 + 1]].m_unquant; + } + for (uint32_t comp_index = total_comps; comp_index < 4; comp_index++) + { + endpoints[subset_index][0][comp_index] = 255; + endpoints[subset_index][1][comp_index] = 255; + } + } + } + + color32 block_colors[3][32]; + + const uint32_t* pWeights = g_astc_weight_tables[weight_bits]; + + for (uint32_t subset_index = 0; subset_index < total_subsets; subset_index++) + { + for (uint32_t l = 0; l < weight_levels; l++) + { + if (total_comps == 2) + { + const uint8_t lc = (uint8_t)astc_interpolate(endpoints[subset_index][0][0], endpoints[subset_index][1][0], pWeights[l], srgb); + const uint8_t ac = (uint8_t)astc_interpolate(endpoints[subset_index][0][3], endpoints[subset_index][1][3], pWeights[l], srgb); + + block_colors[subset_index][l].set(lc, lc, lc, ac); + } + else + { + uint32_t comp_index; + for (comp_index = 0; comp_index < total_comps; comp_index++) + block_colors[subset_index][l][comp_index] = (uint8_t)astc_interpolate(endpoints[subset_index][0][comp_index], endpoints[subset_index][1][comp_index], pWeights[l], srgb); + + for (; comp_index < 4; comp_index++) + block_colors[subset_index][l][comp_index] = 255; + } + } + } + + const uint8_t* pPartition_pattern = g_zero_pattern; + + if (total_subsets >= 2) + { + if (total_subsets == 3) + pPartition_pattern = &g_astc_bc7_patterns3[common_pattern][0]; + else if (mode == 7) + pPartition_pattern = &g_bc7_3_astc2_patterns2[common_pattern][0]; + else + pPartition_pattern = &g_astc_bc7_patterns2[common_pattern][0]; + +#ifdef _DEBUG + for (uint32_t i = 0; i < 16; i++) + { + assert(pPartition_pattern[i] == (uint8_t)astc_compute_texel_partition(astc.m_partition_seed, i & 3, i >> 2, 0, total_subsets, true)); + } +#endif + } + + if (total_planes == 1) + { + if (total_subsets == 1) + { + for (uint32_t i = 0; i < 16; i++) + { + assert(astc.m_weights[i] < weight_levels); + pPixels[i] = block_colors[0][astc.m_weights[i]]; + } + } + else + { + for (uint32_t i = 0; i < 16; i++) + { + assert(astc.m_weights[i] < weight_levels); + pPixels[i] = block_colors[pPartition_pattern[i]][astc.m_weights[i]]; + } + } + } + else + { + assert(total_subsets == 1); + + for (uint32_t i = 0; i < 16; i++) + { + const uint32_t subset_index = 0; // pPartition_pattern[i]; + + const uint32_t weight_index0 = astc.m_weights[i * 2]; + const uint32_t weight_index1 = astc.m_weights[i * 2 + 1]; + + assert(weight_index0 < weight_levels && weight_index1 < weight_levels); + + color32& c = pPixels[i]; + for (uint32_t comp = 0; comp < 4; comp++) + { + if ((int)comp == astc.m_ccs) + c[comp] = block_colors[subset_index][weight_index1][comp]; + else + c[comp] = block_colors[subset_index][weight_index0][comp]; + } + } + } + + return true; + } + + bool unpack_uastc(const unpacked_uastc_block& unpacked_blk, color32* pPixels, bool srgb) + { + return unpack_uastc(unpacked_blk.m_mode, unpacked_blk.m_common_pattern, unpacked_blk.m_solid_color, unpacked_blk.m_astc, pPixels, srgb); + } + + bool unpack_uastc(const uastc_block& blk, color32* pPixels, bool srgb) + { + unpacked_uastc_block unpacked_blk; + + if (!unpack_uastc(blk, unpacked_blk, false, false)) + return false; + + return unpack_uastc(unpacked_blk, pPixels, srgb); + } + + // Determines the best shared pbits to use to encode xl/xh + static void determine_shared_pbits( + uint32_t total_comps, uint32_t comp_bits, float xl[4], float xh[4], + color_quad_u8& bestMinColor, color_quad_u8& bestMaxColor, uint32_t best_pbits[2]) + { + const uint32_t total_bits = comp_bits + 1; + assert(total_bits >= 4 && total_bits <= 8); + + const int iscalep = (1 << total_bits) - 1; + const float scalep = (float)iscalep; + + float best_err = 1e+9f; + + for (int p = 0; p < 2; p++) + { + color_quad_u8 xMinColor, xMaxColor; + for (uint32_t c = 0; c < 4; c++) + { + xMinColor.m_c[c] = (uint8_t)(clampi(((int)((xl[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); + xMaxColor.m_c[c] = (uint8_t)(clampi(((int)((xh[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); + } + + color_quad_u8 scaledLow, scaledHigh; + + for (uint32_t i = 0; i < 4; i++) + { + scaledLow.m_c[i] = (xMinColor.m_c[i] << (8 - total_bits)); + scaledLow.m_c[i] |= (scaledLow.m_c[i] >> total_bits); + assert(scaledLow.m_c[i] <= 255); + + scaledHigh.m_c[i] = (xMaxColor.m_c[i] << (8 - total_bits)); + scaledHigh.m_c[i] |= (scaledHigh.m_c[i] >> total_bits); + assert(scaledHigh.m_c[i] <= 255); + } + + float err = 0; + for (uint32_t i = 0; i < total_comps; i++) + err += basisu::squaref((scaledLow.m_c[i] / 255.0f) - xl[i]) + basisu::squaref((scaledHigh.m_c[i] / 255.0f) - xh[i]); + + if (err < best_err) + { + best_err = err; + best_pbits[0] = p; + best_pbits[1] = p; + for (uint32_t j = 0; j < 4; j++) + { + bestMinColor.m_c[j] = xMinColor.m_c[j] >> 1; + bestMaxColor.m_c[j] = xMaxColor.m_c[j] >> 1; + } + } + } + } + + // Determines the best unique pbits to use to encode xl/xh + static void determine_unique_pbits( + uint32_t total_comps, uint32_t comp_bits, float xl[4], float xh[4], + color_quad_u8& bestMinColor, color_quad_u8& bestMaxColor, uint32_t best_pbits[2]) + { + const uint32_t total_bits = comp_bits + 1; + const int iscalep = (1 << total_bits) - 1; + const float scalep = (float)iscalep; + + float best_err0 = 1e+9f; + float best_err1 = 1e+9f; + + for (int p = 0; p < 2; p++) + { + color_quad_u8 xMinColor, xMaxColor; + + for (uint32_t c = 0; c < 4; c++) + { + xMinColor.m_c[c] = (uint8_t)(clampi(((int)((xl[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); + xMaxColor.m_c[c] = (uint8_t)(clampi(((int)((xh[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); + } + + color_quad_u8 scaledLow, scaledHigh; + for (uint32_t i = 0; i < 4; i++) + { + scaledLow.m_c[i] = (xMinColor.m_c[i] << (8 - total_bits)); + scaledLow.m_c[i] |= (scaledLow.m_c[i] >> total_bits); + assert(scaledLow.m_c[i] <= 255); + + scaledHigh.m_c[i] = (xMaxColor.m_c[i] << (8 - total_bits)); + scaledHigh.m_c[i] |= (scaledHigh.m_c[i] >> total_bits); + assert(scaledHigh.m_c[i] <= 255); + } + + float err0 = 0, err1 = 0; + for (uint32_t i = 0; i < total_comps; i++) + { + err0 += basisu::squaref(scaledLow.m_c[i] - xl[i] * 255.0f); + err1 += basisu::squaref(scaledHigh.m_c[i] - xh[i] * 255.0f); + } + + if (err0 < best_err0) + { + best_err0 = err0; + best_pbits[0] = p; + + bestMinColor.m_c[0] = xMinColor.m_c[0] >> 1; + bestMinColor.m_c[1] = xMinColor.m_c[1] >> 1; + bestMinColor.m_c[2] = xMinColor.m_c[2] >> 1; + bestMinColor.m_c[3] = xMinColor.m_c[3] >> 1; + } + + if (err1 < best_err1) + { + best_err1 = err1; + best_pbits[1] = p; + + bestMaxColor.m_c[0] = xMaxColor.m_c[0] >> 1; + bestMaxColor.m_c[1] = xMaxColor.m_c[1] >> 1; + bestMaxColor.m_c[2] = xMaxColor.m_c[2] >> 1; + bestMaxColor.m_c[3] = xMaxColor.m_c[3] >> 1; + } + } + } + + bool transcode_uastc_to_astc(const uastc_block& src_blk, void* pDst) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, true, false)) + return false; + + bool success = false; + if (unpacked_src_blk.m_mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + pack_astc_solid_block(pDst, unpacked_src_blk.m_solid_color); + success = true; + } + else + { + success = pack_astc_block(static_cast(pDst), &unpacked_src_blk.m_astc, unpacked_src_blk.m_mode); + } + + return success; + } + + bool transcode_uastc_to_bc7(const unpacked_uastc_block& unpacked_src_blk, bc7_optimization_results& dst_blk) + { + memset(&dst_blk, 0, sizeof(dst_blk)); + + const uint32_t mode = unpacked_src_blk.m_mode; + + const uint32_t endpoint_range = g_uastc_mode_endpoint_ranges[mode]; + const uint32_t total_comps = g_uastc_mode_comps[mode]; + + switch (mode) + { + case 0: + case 5: + case 10: + case 12: + case 14: + case 15: + case 18: + { + // MODE 0: DualPlane: 0, WeightRange: 8 (16), Subsets: 1, EndpointRange: 19 (192) - BC7 MODE6 RGB + // MODE 5: DualPlane: 0, WeightRange : 5 (8), Subsets : 1, EndpointRange : 20 (256) - BC7 MODE6 RGB + // MODE 10 DualPlane: 0, WeightRange: 8 (16), Subsets: 1, EndpointRange: 13 (48) - BC7 MODE6 + // MODE 12: DualPlane: 0, WeightRange : 5 (8), Subsets : 1, EndpointRange : 19 (192) - BC7 MODE6 + // MODE 14: DualPlane: 0, WeightRange : 2 (4), Subsets : 1, EndpointRange : 20 (256) - BC7 MODE6 + // MODE 18: DualPlane: 0, WeightRange : 11 (32), Subsets : 1, CEM : 8, EndpointRange : 11 (32) - BC7 MODE6 + // MODE 15: DualPlane: 0, WeightRange : 8 (16), Subsets : 1, CEM : 4 (LA Direct), EndpointRange : 20 (256) - BC7 MODE6 + dst_blk.m_mode = 6; + + float xl[4], xh[4]; + if (total_comps == 2) + { + xl[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[0]].m_unquant / 255.0f; + xh[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[1]].m_unquant / 255.0f; + + xl[1] = xl[0]; + xh[1] = xh[0]; + + xl[2] = xl[0]; + xh[2] = xh[0]; + + xl[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[2]].m_unquant / 255.0f; + xh[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[3]].m_unquant / 255.0f; + } + else + { + xl[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[0]].m_unquant / 255.0f; + xl[1] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[2]].m_unquant / 255.0f; + xl[2] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[4]].m_unquant / 255.0f; + + xh[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[1]].m_unquant / 255.0f; + xh[1] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[3]].m_unquant / 255.0f; + xh[2] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[5]].m_unquant / 255.0f; + + if (total_comps == 4) + { + xl[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[6]].m_unquant / 255.0f; + xh[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[7]].m_unquant / 255.0f; + } + else + { + xl[3] = 1.0f; + xh[3] = 1.0f; + } + } + + uint32_t best_pbits[2]; + color_quad_u8 bestMinColor, bestMaxColor; + determine_unique_pbits((total_comps == 2) ? 4 : total_comps, 7, xl, xh, bestMinColor, bestMaxColor, best_pbits); + + dst_blk.m_low[0] = bestMinColor; + dst_blk.m_high[0] = bestMaxColor; + + if (total_comps == 3) + { + dst_blk.m_low[0].m_c[3] = 127; + dst_blk.m_high[0].m_c[3] = 127; + } + + dst_blk.m_pbits[0][0] = best_pbits[0]; + dst_blk.m_pbits[0][1] = best_pbits[1]; + + if (mode == 18) + { + const uint8_t s_bc7_5_to_4[32] = { 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 8, 9, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15 }; + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = s_bc7_5_to_4[unpacked_src_blk.m_astc.m_weights[i]]; + } + else if (mode == 14) + { + const uint8_t s_bc7_2_to_4[4] = { 0, 5, 10, 15 }; + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = s_bc7_2_to_4[unpacked_src_blk.m_astc.m_weights[i]]; + } + else if ((mode == 5) || (mode == 12)) + { + const uint8_t s_bc7_3_to_4[8] = { 0, 2, 4, 6, 9, 11, 13, 15 }; + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = s_bc7_3_to_4[unpacked_src_blk.m_astc.m_weights[i]]; + } + else + { + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + } + + break; + } + case 1: + { + // DualPlane: 0, WeightRange : 2 (4), Subsets : 1, EndpointRange : 20 (256) - BC7 MODE3 + // Mode 1 uses endpoint range 20 - no need to use ASTC dequant tables. + dst_blk.m_mode = 3; + + float xl[4], xh[4]; + xl[0] = unpacked_src_blk.m_astc.m_endpoints[0] / 255.0f; + xl[1] = unpacked_src_blk.m_astc.m_endpoints[2] / 255.0f; + xl[2] = unpacked_src_blk.m_astc.m_endpoints[4] / 255.0f; + xl[3] = 1.0f; + + xh[0] = unpacked_src_blk.m_astc.m_endpoints[1] / 255.0f; + xh[1] = unpacked_src_blk.m_astc.m_endpoints[3] / 255.0f; + xh[2] = unpacked_src_blk.m_astc.m_endpoints[5] / 255.0f; + xh[3] = 1.0f; + + uint32_t best_pbits[2]; + color_quad_u8 bestMinColor, bestMaxColor; + memset(&bestMinColor, 0, sizeof(bestMinColor)); + memset(&bestMaxColor, 0, sizeof(bestMaxColor)); + determine_unique_pbits(3, 7, xl, xh, bestMinColor, bestMaxColor, best_pbits); + + for (uint32_t i = 0; i < 3; i++) + { + dst_blk.m_low[0].m_c[i] = bestMinColor.m_c[i]; + dst_blk.m_high[0].m_c[i] = bestMaxColor.m_c[i]; + dst_blk.m_low[1].m_c[i] = bestMinColor.m_c[i]; + dst_blk.m_high[1].m_c[i] = bestMaxColor.m_c[i]; + } + dst_blk.m_pbits[0][0] = best_pbits[0]; + dst_blk.m_pbits[0][1] = best_pbits[1]; + dst_blk.m_pbits[1][0] = best_pbits[0]; + dst_blk.m_pbits[1][1] = best_pbits[1]; + + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + + break; + } + case 2: + { + // 2. DualPlane: 0, WeightRange : 5 (8), Subsets : 2, EndpointRange : 8 (16) - BC7 MODE1 + dst_blk.m_mode = 1; + dst_blk.m_partition = g_astc_bc7_common_partitions2[unpacked_src_blk.m_common_pattern].m_bc7; + + const bool invert_partition = g_astc_bc7_common_partitions2[unpacked_src_blk.m_common_pattern].m_invert; + + float xl[4], xh[4]; + xl[3] = 1.0f; + xh[3] = 1.0f; + + for (uint32_t subset = 0; subset < 2; subset++) + { + for (uint32_t i = 0; i < 3; i++) + { + uint32_t v = unpacked_src_blk.m_astc.m_endpoints[i * 2 + subset * 6]; + v = (v << 4) | v; + xl[i] = v / 255.0f; + + v = unpacked_src_blk.m_astc.m_endpoints[i * 2 + subset * 6 + 1]; + v = (v << 4) | v; + xh[i] = v / 255.0f; + } + + uint32_t best_pbits[2] = { 0, 0 }; + color_quad_u8 bestMinColor, bestMaxColor; + memset(&bestMinColor, 0, sizeof(bestMinColor)); + memset(&bestMaxColor, 0, sizeof(bestMaxColor)); + determine_shared_pbits(3, 6, xl, xh, bestMinColor, bestMaxColor, best_pbits); + + const uint32_t bc7_subset_index = invert_partition ? (1 - subset) : subset; + + for (uint32_t i = 0; i < 3; i++) + { + dst_blk.m_low[bc7_subset_index].m_c[i] = bestMinColor.m_c[i]; + dst_blk.m_high[bc7_subset_index].m_c[i] = bestMaxColor.m_c[i]; + } + + dst_blk.m_pbits[bc7_subset_index][0] = best_pbits[0]; + } // subset + + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + + break; + } + case 3: + { + // DualPlane: 0, WeightRange : 2 (4), Subsets : 3, EndpointRange : 7 (12) - BC7 MODE2 + dst_blk.m_mode = 2; + dst_blk.m_partition = g_astc_bc7_common_partitions3[unpacked_src_blk.m_common_pattern].m_bc7; + + const uint32_t perm = g_astc_bc7_common_partitions3[unpacked_src_blk.m_common_pattern].m_astc_to_bc7_perm; + + for (uint32_t subset = 0; subset < 3; subset++) + { + for (uint32_t comp = 0; comp < 3; comp++) + { + uint32_t lo = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[comp * 2 + 0 + subset * 6]].m_unquant; + uint32_t hi = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[comp * 2 + 1 + subset * 6]].m_unquant; + + // TODO: I think this can be improved by using tables like Basis Universal does with ETC1S conversion. + lo = (lo * 31 + 127) / 255; + hi = (hi * 31 + 127) / 255; + + const uint32_t bc7_subset_index = g_astc_to_bc7_partition_index_perm_tables[perm][subset]; + + dst_blk.m_low[bc7_subset_index].m_c[comp] = (uint8_t)lo; + dst_blk.m_high[bc7_subset_index].m_c[comp] = (uint8_t)hi; + } + } + + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + + break; + } + case 4: + { + // 4. DualPlane: 0, WeightRange: 2 (4), Subsets: 2, EndpointRange: 12 (40) - BC7 MODE3 + dst_blk.m_mode = 3; + dst_blk.m_partition = g_astc_bc7_common_partitions2[unpacked_src_blk.m_common_pattern].m_bc7; + + const bool invert_partition = g_astc_bc7_common_partitions2[unpacked_src_blk.m_common_pattern].m_invert; + + float xl[4], xh[4]; + xl[3] = 1.0f; + xh[3] = 1.0f; + + for (uint32_t subset = 0; subset < 2; subset++) + { + for (uint32_t i = 0; i < 3; i++) + { + xl[i] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[i * 2 + subset * 6]].m_unquant / 255.0f; + xh[i] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[i * 2 + subset * 6 + 1]].m_unquant / 255.0f; + } + + uint32_t best_pbits[2] = { 0, 0 }; + color_quad_u8 bestMinColor, bestMaxColor; + memset(&bestMinColor, 0, sizeof(bestMinColor)); + memset(&bestMaxColor, 0, sizeof(bestMaxColor)); + determine_unique_pbits(3, 7, xl, xh, bestMinColor, bestMaxColor, best_pbits); + + const uint32_t bc7_subset_index = invert_partition ? (1 - subset) : subset; + + for (uint32_t i = 0; i < 3; i++) + { + dst_blk.m_low[bc7_subset_index].m_c[i] = bestMinColor.m_c[i]; + dst_blk.m_high[bc7_subset_index].m_c[i] = bestMaxColor.m_c[i]; + } + dst_blk.m_low[bc7_subset_index].m_c[3] = 127; + dst_blk.m_high[bc7_subset_index].m_c[3] = 127; + + dst_blk.m_pbits[bc7_subset_index][0] = best_pbits[0]; + dst_blk.m_pbits[bc7_subset_index][1] = best_pbits[1]; + + } // subset + + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + + break; + } + case 6: + case 11: + case 13: + case 17: + { + // MODE 6: DualPlane: 1, WeightRange : 2 (4), Subsets : 1, EndpointRange : 18 (160) - BC7 MODE5 RGB + // MODE 11: DualPlane: 1, WeightRange: 2 (4), Subsets: 1, EndpointRange: 13 (48) - BC7 MODE5 + // MODE 13: DualPlane: 1, WeightRange: 0 (2), Subsets : 1, EndpointRange : 20 (256) - BC7 MODE5 + // MODE 17: DualPlane: 1, WeightRange: 2 (4), Subsets: 1, CEM: 4 (LA Direct), EndpointRange: 20 (256) - BC7 MODE5 + dst_blk.m_mode = 5; + dst_blk.m_rotation = (unpacked_src_blk.m_astc.m_ccs + 1) & 3; + + if (total_comps == 2) + { + assert(unpacked_src_blk.m_astc.m_ccs == 3); + + dst_blk.m_low->m_c[0] = (uint8_t)((g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[0]].m_unquant * 127 + 127) / 255); + dst_blk.m_high->m_c[0] = (uint8_t)((g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[1]].m_unquant * 127 + 127) / 255); + + dst_blk.m_low->m_c[1] = dst_blk.m_low->m_c[0]; + dst_blk.m_high->m_c[1] = dst_blk.m_high->m_c[0]; + + dst_blk.m_low->m_c[2] = dst_blk.m_low->m_c[0]; + dst_blk.m_high->m_c[2] = dst_blk.m_high->m_c[0]; + + dst_blk.m_low->m_c[3] = (uint8_t)(g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[2]].m_unquant); + dst_blk.m_high->m_c[3] = (uint8_t)(g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[3]].m_unquant); + } + else + { + for (uint32_t astc_comp = 0; astc_comp < 4; astc_comp++) + { + uint32_t bc7_comp = astc_comp; + // ASTC and BC7 handle dual plane component rotations differently: + // ASTC: 2nd plane separately interpolates the CCS channel. + // BC7: 2nd plane channel is swapped with alpha, 2nd plane controls alpha interpolation, then we swap alpha with the desired channel. + if (astc_comp == (uint32_t)unpacked_src_blk.m_astc.m_ccs) + bc7_comp = 3; + else if (astc_comp == 3) + bc7_comp = unpacked_src_blk.m_astc.m_ccs; + + uint32_t l = 255, h = 255; + if (astc_comp < total_comps) + { + l = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[astc_comp * 2 + 0]].m_unquant; + h = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[astc_comp * 2 + 1]].m_unquant; + } + + if (bc7_comp < 3) + { + l = (l * 127 + 127) / 255; + h = (h * 127 + 127) / 255; + } + + dst_blk.m_low->m_c[bc7_comp] = (uint8_t)l; + dst_blk.m_high->m_c[bc7_comp] = (uint8_t)h; + } + } + + if (mode == 13) + { + for (uint32_t i = 0; i < 16; i++) + { + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i * 2] ? 3 : 0; + dst_blk.m_alpha_selectors[i] = unpacked_src_blk.m_astc.m_weights[i * 2 + 1] ? 3 : 0; + } + } + else + { + for (uint32_t i = 0; i < 16; i++) + { + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i * 2]; + dst_blk.m_alpha_selectors[i] = unpacked_src_blk.m_astc.m_weights[i * 2 + 1]; + } + } + + break; + } + case 7: + { + // DualPlane: 0, WeightRange : 2 (4), Subsets : 2, EndpointRange : 12 (40) - BC7 MODE2 + dst_blk.m_mode = 2; + dst_blk.m_partition = g_bc7_3_astc2_common_partitions[unpacked_src_blk.m_common_pattern].m_bc73; + + const uint32_t common_pattern_k = g_bc7_3_astc2_common_partitions[unpacked_src_blk.m_common_pattern].k; + + for (uint32_t bc7_part = 0; bc7_part < 3; bc7_part++) + { + const uint32_t astc_part = bc7_convert_partition_index_3_to_2(bc7_part, common_pattern_k); + + for (uint32_t c = 0; c < 3; c++) + { + dst_blk.m_low[bc7_part].m_c[c] = (g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[c * 2 + 0 + astc_part * 6]].m_unquant * 31 + 127) / 255; + dst_blk.m_high[bc7_part].m_c[c] = (g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[c * 2 + 1 + astc_part * 6]].m_unquant * 31 + 127) / 255; + } + } + + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + + break; + } + case UASTC_MODE_INDEX_SOLID_COLOR: + { + // Void-Extent: Solid Color RGBA (BC7 MODE5 or MODE6) + const color32& solid_color = unpacked_src_blk.m_solid_color; + + uint32_t best_err0 = g_bc7_mode_6_optimal_endpoints[solid_color.r][0].m_error + g_bc7_mode_6_optimal_endpoints[solid_color.g][0].m_error + + g_bc7_mode_6_optimal_endpoints[solid_color.b][0].m_error + g_bc7_mode_6_optimal_endpoints[solid_color.a][0].m_error; + + uint32_t best_err1 = g_bc7_mode_6_optimal_endpoints[solid_color.r][1].m_error + g_bc7_mode_6_optimal_endpoints[solid_color.g][1].m_error + + g_bc7_mode_6_optimal_endpoints[solid_color.b][1].m_error + g_bc7_mode_6_optimal_endpoints[solid_color.a][1].m_error; + + if (best_err0 > 0 && best_err1 > 0) + { + dst_blk.m_mode = 5; + + for (uint32_t c = 0; c < 3; c++) + { + dst_blk.m_low[0].m_c[c] = g_bc7_mode_5_optimal_endpoints[solid_color.c[c]].m_lo; + dst_blk.m_high[0].m_c[c] = g_bc7_mode_5_optimal_endpoints[solid_color.c[c]].m_hi; + } + + memset(dst_blk.m_selectors, BC7ENC_MODE_5_OPTIMAL_INDEX, 16); + + dst_blk.m_low[0].m_c[3] = solid_color.c[3]; + dst_blk.m_high[0].m_c[3] = solid_color.c[3]; + + //memset(dst_blk.m_alpha_selectors, 0, 16); + } + else + { + dst_blk.m_mode = 6; + + uint32_t best_p = 0; + if (best_err1 < best_err0) + best_p = 1; + + for (uint32_t c = 0; c < 4; c++) + { + dst_blk.m_low[0].m_c[c] = g_bc7_mode_6_optimal_endpoints[solid_color.c[c]][best_p].m_lo; + dst_blk.m_high[0].m_c[c] = g_bc7_mode_6_optimal_endpoints[solid_color.c[c]][best_p].m_hi; + } + + dst_blk.m_pbits[0][0] = best_p; + dst_blk.m_pbits[0][1] = best_p; + memset(dst_blk.m_selectors, BC7ENC_MODE_6_OPTIMAL_INDEX, 16); + } + + break; + } + case 9: + case 16: + { + // 9. DualPlane: 0, WeightRange : 2 (4), Subsets : 2, EndpointRange : 8 (16) - BC7 MODE7 + // 16. DualPlane: 0, WeightRange: 2 (4), Subsets: 2, CEM: 4 (LA Direct), EndpointRange: 20 (256) - BC7 MODE7 + + dst_blk.m_mode = 7; + dst_blk.m_partition = g_astc_bc7_common_partitions2[unpacked_src_blk.m_common_pattern].m_bc7; + + const bool invert_partition = g_astc_bc7_common_partitions2[unpacked_src_blk.m_common_pattern].m_invert; + + for (uint32_t astc_subset = 0; astc_subset < 2; astc_subset++) + { + float xl[4], xh[4]; + + if (total_comps == 2) + { + xl[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[0 + astc_subset * 4]].m_unquant / 255.0f; + xh[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[1 + astc_subset * 4]].m_unquant / 255.0f; + + xl[1] = xl[0]; + xh[1] = xh[0]; + + xl[2] = xl[0]; + xh[2] = xh[0]; + + xl[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[2 + astc_subset * 4]].m_unquant / 255.0f; + xh[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[3 + astc_subset * 4]].m_unquant / 255.0f; + } + else + { + xl[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[0 + astc_subset * 8]].m_unquant / 255.0f; + xl[1] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[2 + astc_subset * 8]].m_unquant / 255.0f; + xl[2] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[4 + astc_subset * 8]].m_unquant / 255.0f; + xl[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[6 + astc_subset * 8]].m_unquant / 255.0f; + + xh[0] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[1 + astc_subset * 8]].m_unquant / 255.0f; + xh[1] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[3 + astc_subset * 8]].m_unquant / 255.0f; + xh[2] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[5 + astc_subset * 8]].m_unquant / 255.0f; + xh[3] = g_astc_unquant[endpoint_range][unpacked_src_blk.m_astc.m_endpoints[7 + astc_subset * 8]].m_unquant / 255.0f; + } + + uint32_t best_pbits[2] = { 0, 0 }; + color_quad_u8 bestMinColor, bestMaxColor; + memset(&bestMinColor, 0, sizeof(bestMinColor)); + memset(&bestMaxColor, 0, sizeof(bestMaxColor)); + determine_unique_pbits(4, 5, xl, xh, bestMinColor, bestMaxColor, best_pbits); + + const uint32_t bc7_subset_index = invert_partition ? (1 - astc_subset) : astc_subset; + + dst_blk.m_low[bc7_subset_index] = bestMinColor; + dst_blk.m_high[bc7_subset_index] = bestMaxColor; + + dst_blk.m_pbits[bc7_subset_index][0] = best_pbits[0]; + dst_blk.m_pbits[bc7_subset_index][1] = best_pbits[1]; + } // astc_subset + + for (uint32_t i = 0; i < 16; i++) + dst_blk.m_selectors[i] = unpacked_src_blk.m_astc.m_weights[i]; + + break; + } + default: + return false; + } + + return true; + } + + bool transcode_uastc_to_bc7(const uastc_block& src_blk, bc7_optimization_results& dst_blk) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false, false)) + return false; + + return transcode_uastc_to_bc7(unpacked_src_blk, dst_blk); + } + + bool transcode_uastc_to_bc7(const uastc_block& src_blk, void* pDst) + { + bc7_optimization_results temp; + if (!transcode_uastc_to_bc7(src_blk, temp)) + return false; + + encode_bc7_block(pDst, &temp); + return true; + } + + color32 apply_etc1_bias(const color32 &block_color, uint32_t bias, uint32_t limit, uint32_t subblock) + { + color32 result; + + for (uint32_t c = 0; c < 3; c++) + { + static const int s_divs[3] = { 1, 3, 9 }; + + int delta = 0; + + switch (bias) + { + case 2: delta = subblock ? 0 : ((c == 0) ? -1 : 0); break; + case 5: delta = subblock ? 0 : ((c == 1) ? -1 : 0); break; + case 6: delta = subblock ? 0 : ((c == 2) ? -1 : 0); break; + + case 7: delta = subblock ? 0 : ((c == 0) ? 1 : 0); break; + case 11: delta = subblock ? 0 : ((c == 1) ? 1 : 0); break; + case 15: delta = subblock ? 0 : ((c == 2) ? 1 : 0); break; + + case 18: delta = subblock ? ((c == 0) ? -1 : 0) : 0; break; + case 19: delta = subblock ? ((c == 1) ? -1 : 0) : 0; break; + case 20: delta = subblock ? ((c == 2) ? -1 : 0) : 0; break; + + case 21: delta = subblock ? ((c == 0) ? 1 : 0) : 0; break; + case 24: delta = subblock ? ((c == 1) ? 1 : 0) : 0; break; + case 8: delta = subblock ? ((c == 2) ? 1 : 0) : 0; break; + + case 10: delta = -2; break; + + case 27: delta = subblock ? 0 : -1; break; + case 28: delta = subblock ? -1 : 1; break; + case 29: delta = subblock ? 1 : 0; break; + case 30: delta = subblock ? -1 : 0; break; + case 31: delta = subblock ? 0 : 1; break; + + default: + delta = ((bias / s_divs[c]) % 3) - 1; + break; + } + + int v = block_color[c]; + if (v == 0) + { + if (delta == -2) + v += 3; + else + v += delta + 1; + } + else if (v == (int)limit) + { + v += (delta - 1); + } + else + { + v += delta; + if ((v < 0) || (v > (int)limit)) + v = (v - delta) - delta; + } + + assert(v >= 0); + assert(v <= (int)limit); + + result[c] = (uint8_t)v; + } + + return result; + } + + static void etc1_determine_selectors(decoder_etc_block& dst_blk, const color32* pSource_pixels, uint32_t first_subblock, uint32_t last_subblock) + { + static const uint8_t s_tran[4] = { 1, 0, 2, 3 }; + + uint16_t l_bitmask = 0; + uint16_t h_bitmask = 0; + + for (uint32_t subblock = first_subblock; subblock < last_subblock; subblock++) + { + color32 block_colors[4]; + dst_blk.get_block_colors(block_colors, subblock); + + uint32_t block_y[4]; + for (uint32_t i = 0; i < 4; i++) + block_y[i] = block_colors[i][0] * 54 + block_colors[i][1] * 183 + block_colors[i][2] * 19; + + const uint32_t block_y01 = block_y[0] + block_y[1]; + const uint32_t block_y12 = block_y[1] + block_y[2]; + const uint32_t block_y23 = block_y[2] + block_y[3]; + + // X0 X0 X0 X0 X1 X1 X1 X1 X2 X2 X2 X2 X3 X3 X3 X3 + // Y0 Y1 Y2 Y3 Y0 Y1 Y2 Y3 Y0 Y1 Y2 Y3 Y0 Y1 Y2 Y3 + + if (dst_blk.get_flip_bit()) + { + uint32_t ofs = subblock * 2; + + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const color32& c = pSource_pixels[x + (subblock * 2 + y) * 4]; + const uint32_t l = c[0] * 108 + c[1] * 366 + c[2] * 38; + + uint32_t t = s_tran[(l < block_y01) + (l < block_y12) + (l < block_y23)]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ofs += 4; + } + + ofs = (int)ofs + 1 - 4 * 4; + } + } + else + { + uint32_t ofs = (subblock * 2) * 4; + for (uint32_t x = 0; x < 2; x++) + { + for (uint32_t y = 0; y < 4; y++) + { + const color32& c = pSource_pixels[subblock * 2 + x + y * 4]; + const uint32_t l = c[0] * 108 + c[1] * 366 + c[2] * 38; + + uint32_t t = s_tran[(l < block_y01) + (l < block_y12) + (l < block_y23)]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ++ofs; + } + } + } + } + + dst_blk.m_bytes[7] = (uint8_t)(l_bitmask); + dst_blk.m_bytes[6] = (uint8_t)(l_bitmask >> 8); + dst_blk.m_bytes[5] = (uint8_t)(h_bitmask); + dst_blk.m_bytes[4] = (uint8_t)(h_bitmask >> 8); + } + + static const uint8_t s_etc1_solid_selectors[4][4] = { { 255, 255, 255, 255 }, { 255, 255, 0, 0 }, { 0, 0, 0, 0 }, {0, 0, 255, 255 } }; + + struct etc_coord2 + { + uint8_t m_x, m_y; + }; + + // [flip][subblock][pixel_index] + const etc_coord2 g_etc1_pixel_coords[2][2][8] = + { + { + { + { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 1, 0 }, { 1, 1 }, { 1, 2 }, { 1, 3 } + }, + { + { 2, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, + { 3, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 } + } + }, + { + { + { 0, 0 }, { 1, 0 }, { 2, 0 }, { 3, 0 }, + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 } + }, + { + { 0, 2 }, { 1, 2 }, { 2, 2 }, { 3, 2 }, + { 0, 3 }, { 1, 3 }, { 2, 3 }, { 3, 3 } + }, + } + }; + + void transcode_uastc_to_etc1(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst) + { + decoder_etc_block& dst_blk = *static_cast(pDst); + + if (unpacked_src_blk.m_mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + dst_blk.m_bytes[3] = (uint8_t)((unpacked_src_blk.m_etc1_diff << 1) | (unpacked_src_blk.m_etc1_inten0 << 5) | (unpacked_src_blk.m_etc1_inten0 << 2)); + + if (unpacked_src_blk.m_etc1_diff) + { + dst_blk.m_bytes[0] = (uint8_t)(unpacked_src_blk.m_etc1_r << 3); + dst_blk.m_bytes[1] = (uint8_t)(unpacked_src_blk.m_etc1_g << 3); + dst_blk.m_bytes[2] = (uint8_t)(unpacked_src_blk.m_etc1_b << 3); + } + else + { + dst_blk.m_bytes[0] = (uint8_t)(unpacked_src_blk.m_etc1_r | (unpacked_src_blk.m_etc1_r << 4)); + dst_blk.m_bytes[1] = (uint8_t)(unpacked_src_blk.m_etc1_g | (unpacked_src_blk.m_etc1_g << 4)); + dst_blk.m_bytes[2] = (uint8_t)(unpacked_src_blk.m_etc1_b | (unpacked_src_blk.m_etc1_b << 4)); + } + + memcpy(dst_blk.m_bytes + 4, &s_etc1_solid_selectors[unpacked_src_blk.m_etc1_selector][0], 4); + + return; + } + + const bool flip = unpacked_src_blk.m_etc1_flip != 0; + const bool diff = unpacked_src_blk.m_etc1_diff != 0; + + dst_blk.m_bytes[3] = (uint8_t)((int)flip | (diff << 1) | (unpacked_src_blk.m_etc1_inten0 << 5) | (unpacked_src_blk.m_etc1_inten1 << 2)); + + const uint32_t limit = diff ? 31 : 15; + + color32 block_colors[2]; + + for (uint32_t subset = 0; subset < 2; subset++) + { + uint32_t avg_color[3]; + memset(avg_color, 0, sizeof(avg_color)); + + for (uint32_t j = 0; j < 8; j++) + { + const etc_coord2& c = g_etc1_pixel_coords[flip][subset][j]; + + avg_color[0] += block_pixels[c.m_y][c.m_x].r; + avg_color[1] += block_pixels[c.m_y][c.m_x].g; + avg_color[2] += block_pixels[c.m_y][c.m_x].b; + } // j + + block_colors[subset][0] = (uint8_t)((avg_color[0] * limit + 1020) / (8 * 255)); + block_colors[subset][1] = (uint8_t)((avg_color[1] * limit + 1020) / (8 * 255)); + block_colors[subset][2] = (uint8_t)((avg_color[2] * limit + 1020) / (8 * 255)); + block_colors[subset][3] = 0; + + if (g_uastc_mode_has_etc1_bias[unpacked_src_blk.m_mode]) + { + block_colors[subset] = apply_etc1_bias(block_colors[subset], unpacked_src_blk.m_etc1_bias, limit, subset); + } + + } // subset + + if (diff) + { + int dr = block_colors[1].r - block_colors[0].r; + int dg = block_colors[1].g - block_colors[0].g; + int db = block_colors[1].b - block_colors[0].b; + + dr = basisu::clamp(dr, cETC1ColorDeltaMin, cETC1ColorDeltaMax); + dg = basisu::clamp(dg, cETC1ColorDeltaMin, cETC1ColorDeltaMax); + db = basisu::clamp(db, cETC1ColorDeltaMin, cETC1ColorDeltaMax); + + if (dr < 0) dr += 8; + if (dg < 0) dg += 8; + if (db < 0) db += 8; + + dst_blk.m_bytes[0] = (uint8_t)((block_colors[0].r << 3) | dr); + dst_blk.m_bytes[1] = (uint8_t)((block_colors[0].g << 3) | dg); + dst_blk.m_bytes[2] = (uint8_t)((block_colors[0].b << 3) | db); + } + else + { + dst_blk.m_bytes[0] = (uint8_t)(block_colors[1].r | (block_colors[0].r << 4)); + dst_blk.m_bytes[1] = (uint8_t)(block_colors[1].g | (block_colors[0].g << 4)); + dst_blk.m_bytes[2] = (uint8_t)(block_colors[1].b | (block_colors[0].b << 4)); + } + + etc1_determine_selectors(dst_blk, &block_pixels[0][0], 0, 2); + } + + bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + color32 block_pixels[4][4]; + if (unpacked_src_blk.m_mode != UASTC_MODE_INDEX_SOLID_COLOR) + { + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + } + + transcode_uastc_to_etc1(unpacked_src_blk, block_pixels, pDst); + + return true; + } + + static inline int gray_distance2(const uint8_t c, int y) + { + int gray_dist = (int)c - y; + return gray_dist * gray_dist; + } + + static bool pack_etc1_y_estimate_flipped(const uint8_t* pSrc_pixels, + int& upper_avg, int& lower_avg, int& left_avg, int& right_avg) + { + int sums[2][2]; + +#define GET_XY(x, y) pSrc_pixels[(x) + ((y) * 4)] + + sums[0][0] = GET_XY(0, 0) + GET_XY(0, 1) + GET_XY(1, 0) + GET_XY(1, 1); + sums[1][0] = GET_XY(2, 0) + GET_XY(2, 1) + GET_XY(3, 0) + GET_XY(3, 1); + sums[0][1] = GET_XY(0, 2) + GET_XY(0, 3) + GET_XY(1, 2) + GET_XY(1, 3); + sums[1][1] = GET_XY(2, 2) + GET_XY(2, 3) + GET_XY(3, 2) + GET_XY(3, 3); + + upper_avg = (sums[0][0] + sums[1][0] + 4) / 8; + lower_avg = (sums[0][1] + sums[1][1] + 4) / 8; + left_avg = (sums[0][0] + sums[0][1] + 4) / 8; + right_avg = (sums[1][0] + sums[1][1] + 4) / 8; + +#undef GET_XY +#define GET_XY(x, y, a) gray_distance2(pSrc_pixels[(x) + ((y) * 4)], a) + + int upper_gray_dist = 0, lower_gray_dist = 0, left_gray_dist = 0, right_gray_dist = 0; + for (uint32_t i = 0; i < 4; i++) + { + for (uint32_t j = 0; j < 2; j++) + { + upper_gray_dist += GET_XY(i, j, upper_avg); + lower_gray_dist += GET_XY(i, 2 + j, lower_avg); + left_gray_dist += GET_XY(j, i, left_avg); + right_gray_dist += GET_XY(2 + j, i, right_avg); + } + } + +#undef GET_XY + + int upper_lower_sum = upper_gray_dist + lower_gray_dist; + int left_right_sum = left_gray_dist + right_gray_dist; + + return upper_lower_sum < left_right_sum; + } + + // Base Sel Table + // XXXXX XX XXX + static const uint16_t g_etc1_y_solid_block_configs[256] = + { + 0,781,64,161,260,192,33,131,96,320,65,162,261,193,34,291,97,224,66,163,262,194,35,549,98,4,67,653,164,195,523,36,99,5,578,68,165,353,196,37,135,100,324,69,166,354,197,38,295,101,228,70,167, + 355,198,39,553,102,8,71,608,168,199,527,40,103,9,582,72,169,357,200,41,139,104,328,73,170,358,201,42,299,105,232,74,171,359,202,43,557,106,12,75,612,172,203,531,44,107,13,586,76,173,361, + 204,45,143,108,332,77,174,362,205,46,303,109,236,78,175,363,206,47,561,110,16,79,616,176,207,535,48,111,17,590,80,177,365,208,49,147,112,336,81,178,366,209,50,307,113,240,82,179,367,210, + 51,565,114,20,83,620,180,211,539,52,115,21,594,84,181,369,212,53,151,116,340,85,182,370,213,54,311,117,244,86,183,371,214,55,569,118,24,87,624,184,215,543,56,119,25,598,88,185,373,216,57, + 155,120,344,89,186,374,217,58,315,121,248,90,187,375,218,59,573,122,28,91,628,188,219,754,60,123,29,602,92,189,377,220,61,159,124,348,93,190,378,221,62,319,125,252,94,191,379,222,63,882,126 + }; + + // individual + // table base sel0 sel1 sel2 sel3 + static const uint16_t g_etc1_y_solid_block_4i_configs[256] = + { + 0xA000,0xA800,0x540B,0xAA01,0xAA01,0xFE00,0xFF00,0xFF00,0x8,0x5515,0x5509,0x5509,0xAA03,0x5508,0x5508,0x9508,0xA508,0xA908,0xAA08,0x5513,0xAA09,0xAA09,0xAA05,0xFF08,0xFF08,0x10,0x551D,0x5511,0x5511, + 0xAA0B,0x5510,0x5510,0x9510,0xA510,0xA910,0xAA10,0x551B,0xAA11,0xAA11,0xAA0D,0xFF10,0xFF10,0x18,0x5525,0x5519,0x5519,0xAA13,0x5518,0x5518,0x9518,0xA518,0xA918,0xAA18,0x5523,0xAA19,0xAA19,0xAA15, + 0xFF18,0xFF18,0x20,0x552D,0x5521,0x5521,0xAA1B,0x5520,0x5520,0x9520,0xA520,0xA920,0xAA20,0x552B,0xAA21,0xAA21,0xAA1D,0xFF20,0xFF20,0x28,0x5535,0x5529,0x5529,0xAA23,0x5528,0x5528,0x9528,0xA528,0xA928, + 0xAA28,0x5533,0xAA29,0xAA29,0xAA25,0xFF28,0xFF28,0x30,0x553D,0x5531,0x5531,0xAA2B,0x5530,0x5530,0x9530,0xA530,0xA930,0xAA30,0x553B,0xAA31,0xAA31,0xAA2D,0xFF30,0xFF30,0x38,0x5545,0x5539,0x5539,0xAA33, + 0x5538,0x5538,0x9538,0xA538,0xA938,0xAA38,0x5543,0xAA39,0xAA39,0xAA35,0xFF38,0xFF38,0x40,0x554D,0x5541,0x5541,0xAA3B,0x5540,0x5540,0x9540,0xA540,0xA940,0xAA40,0x554B,0xAA41,0xAA41,0xAA3D,0xFF40,0xFF40, + 0x48,0x5555,0x5549,0x5549,0xAA43,0x5548,0x5548,0x9548,0xA548,0xA948,0xAA48,0x5553,0xAA49,0xAA49,0xAA45,0xFF48,0xFF48,0x50,0x555D,0x5551,0x5551,0xAA4B,0x5550,0x5550,0x9550,0xA550,0xA950,0xAA50,0x555B, + 0xAA51,0xAA51,0xAA4D,0xFF50,0xFF50,0x58,0x5565,0x5559,0x5559,0xAA53,0x5558,0x5558,0x9558,0xA558,0xA958,0xAA58,0x5563,0xAA59,0xAA59,0xAA55,0xFF58,0xFF58,0x60,0x556D,0x5561,0x5561,0xAA5B,0x5560,0x5560, + 0x9560,0xA560,0xA960,0xAA60,0x556B,0xAA61,0xAA61,0xAA5D,0xFF60,0xFF60,0x68,0x5575,0x5569,0x5569,0xAA63,0x5568,0x5568,0x9568,0xA568,0xA968,0xAA68,0x5573,0xAA69,0xAA69,0xAA65,0xFF68,0xFF68,0x70,0x557D, + 0x5571,0x5571,0xAA6B,0x5570,0x5570,0x9570,0xA570,0xA970,0xAA70,0x557B,0xAA71,0xAA71,0xAA6D,0xFF70,0xFF70,0x78,0x78,0x5579,0x5579,0xAA73,0x5578,0x9578,0x2578,0xE6E,0x278 + }; + + static const uint16_t g_etc1_y_solid_block_2i_configs[256] = + { + 0x416,0x800,0xA00,0x50B,0xA01,0xA01,0xF00,0xF00,0xF00,0x8,0x515,0x509,0x509,0xA03,0x508,0x508,0xF01,0xF01,0xA08,0xA08,0x513,0xA09,0xA09,0xA05,0xF08,0xF08,0x10,0x51D,0x511,0x511,0xA0B,0x510,0x510,0xF09, + 0xF09,0xA10,0xA10,0x51B,0xA11,0xA11,0xA0D,0xF10,0xF10,0x18,0x525,0x519,0x519,0xA13,0x518,0x518,0xF11,0xF11,0xA18,0xA18,0x523,0xA19,0xA19,0xA15,0xF18,0xF18,0x20,0x52D,0x521,0x521,0xA1B,0x520,0x520,0xF19, + 0xF19,0xA20,0xA20,0x52B,0xA21,0xA21,0xA1D,0xF20,0xF20,0x28,0x535,0x529,0x529,0xA23,0x528,0x528,0xF21,0xF21,0xA28,0xA28,0x533,0xA29,0xA29,0xA25,0xF28,0xF28,0x30,0x53D,0x531,0x531,0xA2B,0x530,0x530,0xF29, + 0xF29,0xA30,0xA30,0x53B,0xA31,0xA31,0xA2D,0xF30,0xF30,0x38,0x545,0x539,0x539,0xA33,0x538,0x538,0xF31,0xF31,0xA38,0xA38,0x543,0xA39,0xA39,0xA35,0xF38,0xF38,0x40,0x54D,0x541,0x541,0xA3B,0x540,0x540,0xF39, + 0xF39,0xA40,0xA40,0x54B,0xA41,0xA41,0xA3D,0xF40,0xF40,0x48,0x555,0x549,0x549,0xA43,0x548,0x548,0xF41,0xF41,0xA48,0xA48,0x553,0xA49,0xA49,0xA45,0xF48,0xF48,0x50,0x55D,0x551,0x551,0xA4B,0x550,0x550,0xF49, + 0xF49,0xA50,0xA50,0x55B,0xA51,0xA51,0xA4D,0xF50,0xF50,0x58,0x565,0x559,0x559,0xA53,0x558,0x558,0xF51,0xF51,0xA58,0xA58,0x563,0xA59,0xA59,0xA55,0xF58,0xF58,0x60,0x56D,0x561,0x561,0xA5B,0x560,0x560,0xF59, + 0xF59,0xA60,0xA60,0x56B,0xA61,0xA61,0xA5D,0xF60,0xF60,0x68,0x575,0x569,0x569,0xA63,0x568,0x568,0xF61,0xF61,0xA68,0xA68,0x573,0xA69,0xA69,0xA65,0xF68,0xF68,0x70,0x57D,0x571,0x571,0xA6B,0x570,0x570,0xF69, + 0xF69,0xA70,0xA70,0x57B,0xA71,0xA71,0xA6D,0xF70,0xF70,0x78,0x78,0x579,0x579,0xA73,0x578,0x578,0xE6E,0x278 + }; + + static const uint16_t g_etc1_y_solid_block_1i_configs[256] = + { + 0x0,0x116,0x200,0x200,0x10B,0x201,0x201,0x300,0x300,0x8,0x115,0x109,0x109,0x203,0x108,0x108,0x114,0x301,0x204,0x208,0x208,0x113,0x209,0x209,0x205,0x308,0x10,0x11D,0x111,0x111,0x20B,0x110,0x110,0x11C,0x309, + 0x20C,0x210,0x210,0x11B,0x211,0x211,0x20D,0x310,0x18,0x125,0x119,0x119,0x213,0x118,0x118,0x124,0x311,0x214,0x218,0x218,0x123,0x219,0x219,0x215,0x318,0x20,0x12D,0x121,0x121,0x21B,0x120,0x120,0x12C,0x319,0x21C, + 0x220,0x220,0x12B,0x221,0x221,0x21D,0x320,0x28,0x135,0x129,0x129,0x223,0x128,0x128,0x134,0x321,0x224,0x228,0x228,0x133,0x229,0x229,0x225,0x328,0x30,0x13D,0x131,0x131,0x22B,0x130,0x130,0x13C,0x329,0x22C,0x230, + 0x230,0x13B,0x231,0x231,0x22D,0x330,0x38,0x145,0x139,0x139,0x233,0x138,0x138,0x144,0x331,0x234,0x238,0x238,0x143,0x239,0x239,0x235,0x338,0x40,0x14D,0x141,0x141,0x23B,0x140,0x140,0x14C,0x339,0x23C,0x240,0x240, + 0x14B,0x241,0x241,0x23D,0x340,0x48,0x155,0x149,0x149,0x243,0x148,0x148,0x154,0x341,0x244,0x248,0x248,0x153,0x249,0x249,0x245,0x348,0x50,0x15D,0x151,0x151,0x24B,0x150,0x150,0x15C,0x349,0x24C,0x250,0x250,0x15B, + 0x251,0x251,0x24D,0x350,0x58,0x165,0x159,0x159,0x253,0x158,0x158,0x164,0x351,0x254,0x258,0x258,0x163,0x259,0x259,0x255,0x358,0x60,0x16D,0x161,0x161,0x25B,0x160,0x160,0x16C,0x359,0x25C,0x260,0x260,0x16B,0x261, + 0x261,0x25D,0x360,0x68,0x175,0x169,0x169,0x263,0x168,0x168,0x174,0x361,0x264,0x268,0x268,0x173,0x269,0x269,0x265,0x368,0x70,0x17D,0x171,0x171,0x26B,0x170,0x170,0x17C,0x369,0x26C,0x270,0x270,0x17B,0x271,0x271, + 0x26D,0x370,0x78,0x78,0x179,0x179,0x273,0x178,0x178,0x26E,0x278 + }; + + // We don't have any useful hints to accelerate single channel ETC1, so we need to real-time encode from scratch. + bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst, uint32_t channel) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + +#if 0 + for (uint32_t individ = 0; individ < 2; individ++) + { + uint32_t overall_error = 0; + + for (uint32_t c = 0; c < 256; c++) + { + uint32_t best_err = UINT32_MAX; + uint32_t best_individ = 0; + uint32_t best_base = 0; + uint32_t best_sels[4] = { 0,0,0,0 }; + uint32_t best_table = 0; + + const uint32_t limit = individ ? 16 : 32; + + for (uint32_t table = 0; table < 8; table++) + { + for (uint32_t base = 0; base < limit; base++) + { + uint32_t total_e = 0; + uint32_t sels[4] = { 0,0,0,0 }; + + const uint32_t N = 4; + for (uint32_t i = 0; i < basisu::minimum(N, (256 - c)); i++) + { + uint32_t best_sel_e = UINT32_MAX; + uint32_t best_sel = 0; + + for (uint32_t sel = 0; sel < 4; sel++) + { + int val = individ ? ((base << 4) | base) : ((base << 3) | (base >> 2)); + val = clamp255(val + g_etc1_inten_tables[table][sel]); + + int e = iabs(val - clamp255(c + i)); + if (e < best_sel_e) + { + best_sel_e = e; + best_sel = sel; + } + + } // sel + + sels[i] = best_sel; + total_e += best_sel_e * best_sel_e; + + } // i + + if (total_e < best_err) + { + best_err = total_e; + best_individ = individ; + best_base = base; + memcpy(best_sels, sels, sizeof(best_sels)); + best_table = table; + } + + } // base + } // table + + //printf("%u: %u,%u,%u,%u,%u,%u,%u,%u\n", c, best_err, best_individ, best_table, best_base, best_sels[0], best_sels[1], best_sels[2], best_sels[3]); + + uint32_t encoded = best_table | (best_base << 3) | + (best_sels[0] << 8) | + (best_sels[1] << 10) | + (best_sels[2] << 12) | + (best_sels[3] << 14); + + printf("0x%X,", encoded); + + overall_error += best_err; + } // c + + printf("\n"); + printf("Overall error: %u\n", overall_error); + + } // individ + + exit(0); +#endif + +#if 0 + for (uint32_t individ = 0; individ < 2; individ++) + { + uint32_t overall_error = 0; + + for (uint32_t c = 0; c < 256; c++) + { + uint32_t best_err = UINT32_MAX; + uint32_t best_individ = 0; + uint32_t best_base = 0; + uint32_t best_sels[4] = { 0,0,0,0 }; + uint32_t best_table = 0; + + const uint32_t limit = individ ? 16 : 32; + + for (uint32_t table = 0; table < 8; table++) + { + for (uint32_t base = 0; base < limit; base++) + { + uint32_t total_e = 0; + uint32_t sels[4] = { 0,0,0,0 }; + + const uint32_t N = 1; + for (uint32_t i = 0; i < basisu::minimum(N, (256 - c)); i++) + { + uint32_t best_sel_e = UINT32_MAX; + uint32_t best_sel = 0; + + for (uint32_t sel = 0; sel < 4; sel++) + { + int val = individ ? ((base << 4) | base) : ((base << 3) | (base >> 2)); + val = clamp255(val + g_etc1_inten_tables[table][sel]); + + int e = iabs(val - clamp255(c + i)); + if (e < best_sel_e) + { + best_sel_e = e; + best_sel = sel; + } + + } // sel + + sels[i] = best_sel; + total_e += best_sel_e * best_sel_e; + + } // i + + if (total_e < best_err) + { + best_err = total_e; + best_individ = individ; + best_base = base; + memcpy(best_sels, sels, sizeof(best_sels)); + best_table = table; + } + + } // base + } // table + + //printf("%u: %u,%u,%u,%u,%u,%u,%u,%u\n", c, best_err, best_individ, best_table, best_base, best_sels[0], best_sels[1], best_sels[2], best_sels[3]); + + uint32_t encoded = best_table | (best_base << 3) | + (best_sels[0] << 8) | + (best_sels[1] << 10) | + (best_sels[2] << 12) | + (best_sels[3] << 14); + + printf("0x%X,", encoded); + + overall_error += best_err; + } // c + + printf("\n"); + printf("Overall error: %u\n", overall_error); + + } // individ + + exit(0); +#endif + + decoder_etc_block& dst_blk = *static_cast(pDst); + + if (unpacked_src_blk.m_mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + const uint32_t y = unpacked_src_blk.m_solid_color[channel]; + const uint32_t encoded_config = g_etc1_y_solid_block_configs[y]; + + const uint32_t base = encoded_config & 31; + const uint32_t sel = (encoded_config >> 5) & 3; + const uint32_t table = encoded_config >> 7; + + dst_blk.m_bytes[3] = (uint8_t)(2 | (table << 5) | (table << 2)); + + dst_blk.m_bytes[0] = (uint8_t)(base << 3); + dst_blk.m_bytes[1] = (uint8_t)(base << 3); + dst_blk.m_bytes[2] = (uint8_t)(base << 3); + + memcpy(dst_blk.m_bytes + 4, &s_etc1_solid_selectors[sel][0], 4); + return true; + } + + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + uint8_t block_y[4][4]; + for (uint32_t i = 0; i < 16; i++) + ((uint8_t*)block_y)[i] = ((color32*)block_pixels)[i][channel]; + + int upper_avg, lower_avg, left_avg, right_avg; + bool flip = pack_etc1_y_estimate_flipped(&block_y[0][0], upper_avg, lower_avg, left_avg, right_avg); + + // non-flipped: | | + // vs. + // flipped: -- + // -- + + uint32_t low[2] = { 255, 255 }, high[2] = { 0, 0 }; + + if (flip) + { + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const uint32_t v = block_y[y][x]; + low[0] = basisu::minimum(low[0], v); + high[0] = basisu::maximum(high[0], v); + } + } + for (uint32_t y = 2; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const uint32_t v = block_y[y][x]; + low[1] = basisu::minimum(low[1], v); + high[1] = basisu::maximum(high[1], v); + } + } + } + else + { + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 2; x++) + { + const uint32_t v = block_y[y][x]; + low[0] = basisu::minimum(low[0], v); + high[0] = basisu::maximum(high[0], v); + } + } + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 2; x < 4; x++) + { + const uint32_t v = block_y[y][x]; + low[1] = basisu::minimum(low[1], v); + high[1] = basisu::maximum(high[1], v); + } + } + } + + const uint32_t range[2] = { high[0] - low[0], high[1] - low[1] }; + + dst_blk.m_bytes[3] = (uint8_t)((int)flip); + + if ((range[0] <= 3) && (range[1] <= 3)) + { + // This is primarily for better gradients. + dst_blk.m_bytes[0] = 0; + dst_blk.m_bytes[1] = 0; + dst_blk.m_bytes[2] = 0; + + uint16_t l_bitmask = 0, h_bitmask = 0; + + for (uint32_t subblock = 0; subblock < 2; subblock++) + { + const uint32_t encoded = (range[subblock] == 0) ? g_etc1_y_solid_block_1i_configs[low[subblock]] : ((range[subblock] < 2) ? g_etc1_y_solid_block_2i_configs[low[subblock]] : g_etc1_y_solid_block_4i_configs[low[subblock]]); + + const uint32_t table = encoded & 7; + const uint32_t base = (encoded >> 3) & 31; + assert(base <= 15); + const uint32_t sels[4] = { (encoded >> 8) & 3, (encoded >> 10) & 3, (encoded >> 12) & 3, (encoded >> 14) & 3 }; + + dst_blk.m_bytes[3] |= (uint8_t)(table << (subblock ? 2 : 5)); + + const uint32_t sv = base << (subblock ? 0 : 4); + dst_blk.m_bytes[0] |= (uint8_t)(sv); + dst_blk.m_bytes[1] |= (uint8_t)(sv); + dst_blk.m_bytes[2] |= (uint8_t)(sv); + + if (flip) + { + uint32_t ofs = subblock * 2; + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t t = block_y[y + subblock * 2][x]; + assert(t >= low[subblock] && t <= high[subblock]); + t -= low[subblock]; + assert(t <= 3); + + t = g_selector_index_to_etc1[sels[t]]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ofs += 4; + } + + ofs = (int)ofs + 1 - 4 * 4; + } + } + else + { + uint32_t ofs = (subblock * 2) * 4; + for (uint32_t x = 0; x < 2; x++) + { + for (uint32_t y = 0; y < 4; y++) + { + uint32_t t = block_y[y][x + subblock * 2]; + assert(t >= low[subblock] && t <= high[subblock]); + t -= low[subblock]; + assert(t <= 3); + + t = g_selector_index_to_etc1[sels[t]]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ++ofs; + } + } + } + } // subblock + + dst_blk.m_bytes[7] = (uint8_t)(l_bitmask); + dst_blk.m_bytes[6] = (uint8_t)(l_bitmask >> 8); + dst_blk.m_bytes[5] = (uint8_t)(h_bitmask); + dst_blk.m_bytes[4] = (uint8_t)(h_bitmask >> 8); + + return true; + } + + uint32_t y0 = ((flip ? upper_avg : left_avg) * 31 + 127) / 255; + uint32_t y1 = ((flip ? lower_avg : right_avg) * 31 + 127) / 255; + + bool diff = true; + + int dy = y1 - y0; + + if ((dy < cETC1ColorDeltaMin) || (dy > cETC1ColorDeltaMax)) + { + diff = false; + + y0 = ((flip ? upper_avg : left_avg) * 15 + 127) / 255; + y1 = ((flip ? lower_avg : right_avg) * 15 + 127) / 255; + + dst_blk.m_bytes[0] = (uint8_t)(y1 | (y0 << 4)); + dst_blk.m_bytes[1] = (uint8_t)(y1 | (y0 << 4)); + dst_blk.m_bytes[2] = (uint8_t)(y1 | (y0 << 4)); + } + else + { + dy = basisu::clamp(dy, cETC1ColorDeltaMin, cETC1ColorDeltaMax); + + y1 = y0 + dy; + + if (dy < 0) dy += 8; + + dst_blk.m_bytes[0] = (uint8_t)((y0 << 3) | dy); + dst_blk.m_bytes[1] = (uint8_t)((y0 << 3) | dy); + dst_blk.m_bytes[2] = (uint8_t)((y0 << 3) | dy); + + dst_blk.m_bytes[3] |= 2; + } + + const uint32_t base_y[2] = { diff ? ((y0 << 3) | (y0 >> 2)) : ((y0 << 4) | y0), diff ? ((y1 << 3) | (y1 >> 2)) : ((y1 << 4) | y1) }; + + uint32_t enc_range[2]; + for (uint32_t subset = 0; subset < 2; subset++) + { + const int pos = basisu::iabs((int)high[subset] - (int)base_y[subset]); + const int neg = basisu::iabs((int)base_y[subset] - (int)low[subset]); + + enc_range[subset] = basisu::maximum(pos, neg); + } + + uint16_t l_bitmask = 0, h_bitmask = 0; + for (uint32_t subblock = 0; subblock < 2; subblock++) + { + if ((!diff) && (range[subblock] <= 3)) + { + const uint32_t encoded = (range[subblock] == 0) ? g_etc1_y_solid_block_1i_configs[low[subblock]] : ((range[subblock] < 2) ? g_etc1_y_solid_block_2i_configs[low[subblock]] : g_etc1_y_solid_block_4i_configs[low[subblock]]); + + const uint32_t table = encoded & 7; + const uint32_t base = (encoded >> 3) & 31; + assert(base <= 15); + const uint32_t sels[4] = { (encoded >> 8) & 3, (encoded >> 10) & 3, (encoded >> 12) & 3, (encoded >> 14) & 3 }; + + dst_blk.m_bytes[3] |= (uint8_t)(table << (subblock ? 2 : 5)); + + const uint32_t mask = ~(0xF << (subblock ? 0 : 4)); + + dst_blk.m_bytes[0] &= mask; + dst_blk.m_bytes[1] &= mask; + dst_blk.m_bytes[2] &= mask; + + const uint32_t sv = base << (subblock ? 0 : 4); + dst_blk.m_bytes[0] |= (uint8_t)(sv); + dst_blk.m_bytes[1] |= (uint8_t)(sv); + dst_blk.m_bytes[2] |= (uint8_t)(sv); + + if (flip) + { + uint32_t ofs = subblock * 2; + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t t = block_y[y + subblock * 2][x]; + assert(t >= low[subblock] && t <= high[subblock]); + t -= low[subblock]; + assert(t <= 3); + + t = g_selector_index_to_etc1[sels[t]]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ofs += 4; + } + + ofs = (int)ofs + 1 - 4 * 4; + } + } + else + { + uint32_t ofs = (subblock * 2) * 4; + for (uint32_t x = 0; x < 2; x++) + { + for (uint32_t y = 0; y < 4; y++) + { + uint32_t t = block_y[y][x + subblock * 2]; + assert(t >= low[subblock] && t <= high[subblock]); + t -= low[subblock]; + assert(t <= 3); + + t = g_selector_index_to_etc1[sels[t]]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ++ofs; + } + } + } + + continue; + } // if + + uint32_t best_err = UINT32_MAX; + uint8_t best_sels[8]; + uint32_t best_inten = 0; + + const int base = base_y[subblock]; + + const int low_limit = -base; + const int high_limit = 255 - base; + + assert(low_limit <= 0 && high_limit >= 0); + + uint32_t inten_table_mask = 0xFF; + const uint32_t er = enc_range[subblock]; + // Each one of these tables is expensive to evaluate, so let's only examine the ones we know may be useful. + if (er <= 51) + { + inten_table_mask = 0xF; + + if (er > 22) + inten_table_mask &= ~(1 << 0); + + if ((er < 4) || (er > 39)) + inten_table_mask &= ~(1 << 1); + + if (er < 9) + inten_table_mask &= ~(1 << 2); + + if (er < 12) + inten_table_mask &= ~(1 << 3); + } + else + { + inten_table_mask &= ~((1 << 0) | (1 << 1)); + + if (er > 60) + inten_table_mask &= ~(1 << 2); + + if (er > 89) + inten_table_mask &= ~(1 << 3); + + if (er > 120) + inten_table_mask &= ~(1 << 4); + + if (er > 136) + inten_table_mask &= ~(1 << 5); + + if (er > 174) + inten_table_mask &= ~(1 << 6); + } + + for (uint32_t inten = 0; inten < 8; inten++) + { + if ((inten_table_mask & (1 << inten)) == 0) + continue; + + const int t0 = basisu::maximum(low_limit, g_etc1_inten_tables[inten][0]); + const int t1 = basisu::maximum(low_limit, g_etc1_inten_tables[inten][1]); + const int t2 = basisu::minimum(high_limit, g_etc1_inten_tables[inten][2]); + const int t3 = basisu::minimum(high_limit, g_etc1_inten_tables[inten][3]); + assert((t0 <= t1) && (t1 <= t2) && (t2 <= t3)); + + const int tv[4] = { t2, t3, t1, t0 }; + + const int thresh01 = t0 + t1; + const int thresh12 = t1 + t2; + const int thresh23 = t2 + t3; + + assert(thresh01 <= thresh12 && thresh12 <= thresh23); + + static const uint8_t s_table[4] = { 1, 0, 2, 3 }; + + uint32_t total_err = 0; + uint8_t sels[8]; + + if (flip) + { + if (((int)high[subblock] - base) * 2 < thresh01) + { + memset(sels, 3, 8); + + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const int delta = (int)block_y[y + subblock * 2][x] - base; + + const uint32_t c = 3; + + uint32_t e = basisu::iabs(tv[c] - delta); + total_err += e * e; + } + if (total_err >= best_err) + break; + } + } + else if (((int)low[subblock] - base) * 2 >= thresh23) + { + memset(sels, 1, 8); + + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const int delta = (int)block_y[y + subblock * 2][x] - base; + + const uint32_t c = 1; + + uint32_t e = basisu::iabs(tv[c] - delta); + total_err += e * e; + } + if (total_err >= best_err) + break; + } + } + else + { + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + const int delta = (int)block_y[y + subblock * 2][x] - base; + const int delta2 = delta * 2; + + uint32_t c = s_table[(delta2 < thresh01) + (delta2 < thresh12) + (delta2 < thresh23)]; + sels[y * 4 + x] = (uint8_t)c; + + uint32_t e = basisu::iabs(tv[c] - delta); + total_err += e * e; + } + if (total_err >= best_err) + break; + } + } + } + else + { + if (((int)high[subblock] - base) * 2 < thresh01) + { + memset(sels, 3, 8); + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 2; x++) + { + const int delta = (int)block_y[y][x + subblock * 2] - base; + + const uint32_t c = 3; + + uint32_t e = basisu::iabs(tv[c] - delta); + total_err += e * e; + } + if (total_err >= best_err) + break; + } + } + else if (((int)low[subblock] - base) * 2 >= thresh23) + { + memset(sels, 1, 8); + + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 2; x++) + { + const int delta = (int)block_y[y][x + subblock * 2] - base; + + const uint32_t c = 1; + + uint32_t e = basisu::iabs(tv[c] - delta); + total_err += e * e; + } + if (total_err >= best_err) + break; + } + } + else + { + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 2; x++) + { + const int delta = (int)block_y[y][x + subblock * 2] - base; + const int delta2 = delta * 2; + + uint32_t c = s_table[(delta2 < thresh01) + (delta2 < thresh12) + (delta2 < thresh23)]; + sels[y * 2 + x] = (uint8_t)c; + + uint32_t e = basisu::iabs(tv[c] - delta); + total_err += e * e; + } + if (total_err >= best_err) + break; + } + } + } + + if (total_err < best_err) + { + best_err = total_err; + best_inten = inten; + memcpy(best_sels, sels, 8); + } + + } // inten + + //g_inten_hist[best_inten][enc_range[subblock]]++; + + dst_blk.m_bytes[3] |= (uint8_t)(best_inten << (subblock ? 2 : 5)); + + if (flip) + { + uint32_t ofs = subblock * 2; + for (uint32_t y = 0; y < 2; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t t = best_sels[y * 4 + x]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ofs += 4; + } + + ofs = (int)ofs + 1 - 4 * 4; + } + } + else + { + uint32_t ofs = (subblock * 2) * 4; + for (uint32_t x = 0; x < 2; x++) + { + for (uint32_t y = 0; y < 4; y++) + { + uint32_t t = best_sels[y * 2 + x]; + + assert(ofs < 16); + l_bitmask |= ((t & 1) << ofs); + h_bitmask |= ((t >> 1) << ofs); + ++ofs; + } + } + } + + } // subblock + + dst_blk.m_bytes[7] = (uint8_t)(l_bitmask); + dst_blk.m_bytes[6] = (uint8_t)(l_bitmask >> 8); + dst_blk.m_bytes[5] = (uint8_t)(h_bitmask); + dst_blk.m_bytes[4] = (uint8_t)(h_bitmask >> 8); + + return true; + } + + const uint32_t ETC2_EAC_MIN_VALUE_SELECTOR = 3, ETC2_EAC_MAX_VALUE_SELECTOR = 7; + + void transcode_uastc_to_etc2_eac_a8(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst) + { + eac_block& dst = *static_cast(pDst); + const color32* pSrc_pixels = &block_pixels[0][0]; + + if ((!g_uastc_mode_has_alpha[unpacked_src_blk.m_mode]) || (unpacked_src_blk.m_mode == UASTC_MODE_INDEX_SOLID_COLOR)) + { + const uint32_t a = (unpacked_src_blk.m_mode == UASTC_MODE_INDEX_SOLID_COLOR) ? unpacked_src_blk.m_solid_color[3] : 255; + + dst.m_base = a; + dst.m_table = 13; + dst.m_multiplier = 1; + + memcpy(dst.m_selectors, g_etc2_eac_a8_sel4, sizeof(g_etc2_eac_a8_sel4)); + + return; + } + + uint32_t min_a = 255, max_a = 0; + for (uint32_t i = 0; i < 16; i++) + { + min_a = basisu::minimum(min_a, pSrc_pixels[i].a); + max_a = basisu::maximum(max_a, pSrc_pixels[i].a); + } + + if (min_a == max_a) + { + dst.m_base = min_a; + dst.m_table = 13; + dst.m_multiplier = 1; + + memcpy(dst.m_selectors, g_etc2_eac_a8_sel4, sizeof(g_etc2_eac_a8_sel4)); + return; + } + + const uint32_t table = unpacked_src_blk.m_etc2_hints & 0xF; + const int multiplier = unpacked_src_blk.m_etc2_hints >> 4; + + assert(multiplier >= 1); + + dst.m_multiplier = multiplier; + dst.m_table = table; + + const float range = (float)(g_eac_modifier_table[dst.m_table][ETC2_EAC_MAX_VALUE_SELECTOR] - g_eac_modifier_table[dst.m_table][ETC2_EAC_MIN_VALUE_SELECTOR]); + const int center = (int)roundf(basisu::lerp((float)min_a, (float)max_a, (float)(0 - g_eac_modifier_table[dst.m_table][ETC2_EAC_MIN_VALUE_SELECTOR]) / range)); + + dst.m_base = center; + + const int8_t* pTable = &g_eac_modifier_table[dst.m_table][0]; + + uint32_t vals[8]; + for (uint32_t j = 0; j < 8; j++) + vals[j] = clamp255(center + (pTable[j] * multiplier)); + + uint64_t sels = 0; + for (uint32_t i = 0; i < 16; i++) + { + const uint32_t a = block_pixels[i & 3][i >> 2].a; + + const uint32_t err0 = (basisu::iabs(vals[0] - a) << 3) | 0; + const uint32_t err1 = (basisu::iabs(vals[1] - a) << 3) | 1; + const uint32_t err2 = (basisu::iabs(vals[2] - a) << 3) | 2; + const uint32_t err3 = (basisu::iabs(vals[3] - a) << 3) | 3; + const uint32_t err4 = (basisu::iabs(vals[4] - a) << 3) | 4; + const uint32_t err5 = (basisu::iabs(vals[5] - a) << 3) | 5; + const uint32_t err6 = (basisu::iabs(vals[6] - a) << 3) | 6; + const uint32_t err7 = (basisu::iabs(vals[7] - a) << 3) | 7; + + const uint32_t min_err = basisu::minimum(basisu::minimum(basisu::minimum(basisu::minimum(basisu::minimum(basisu::minimum(err0, err1, err2), err3), err4), err5), err6), err7); + + const uint64_t best_index = min_err & 7; + sels |= (best_index << (45 - i * 3)); + } + + dst.set_selector_bits(sels); + } + + bool transcode_uastc_to_etc2_rgba(const uastc_block& src_blk, void* pDst) + { + eac_block& dst_etc2_eac_a8_blk = *static_cast(pDst); + decoder_etc_block& dst_etc1_blk = static_cast(pDst)[1]; + + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + color32 block_pixels[4][4]; + if (unpacked_src_blk.m_mode != UASTC_MODE_INDEX_SOLID_COLOR) + { + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + } + + transcode_uastc_to_etc2_eac_a8(unpacked_src_blk, block_pixels, &dst_etc2_eac_a8_blk); + + transcode_uastc_to_etc1(unpacked_src_blk, block_pixels, &dst_etc1_blk); + + return true; + } + + static const uint8_t s_uastc5_to_bc1[32] = { 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1 }; + static const uint8_t s_uastc4_to_bc1[16] = { 0, 0, 0, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 1, 1 }; + static const uint8_t s_uastc3_to_bc1[8] = { 0, 0, 2, 2, 3, 3, 1, 1 }; + static const uint8_t s_uastc2_to_bc1[4] = { 0, 2, 3, 1 }; + static const uint8_t s_uastc1_to_bc1[2] = { 0, 1 }; + const uint8_t* s_uastc_to_bc1_weights[6] = { nullptr, s_uastc1_to_bc1, s_uastc2_to_bc1, s_uastc3_to_bc1, s_uastc4_to_bc1, s_uastc5_to_bc1 }; + + void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride) + { + uint32_t min0_v, max0_v, min1_v, max1_v,min2_v, max2_v, min3_v, max3_v; + + { + min0_v = max0_v = pPixels[0 * stride]; + min1_v = max1_v = pPixels[1 * stride]; + min2_v = max2_v = pPixels[2 * stride]; + min3_v = max3_v = pPixels[3 * stride]; + } + + { + uint32_t v0 = pPixels[4 * stride]; min0_v = basisu::minimum(min0_v, v0); max0_v = basisu::maximum(max0_v, v0); + uint32_t v1 = pPixels[5 * stride]; min1_v = basisu::minimum(min1_v, v1); max1_v = basisu::maximum(max1_v, v1); + uint32_t v2 = pPixels[6 * stride]; min2_v = basisu::minimum(min2_v, v2); max2_v = basisu::maximum(max2_v, v2); + uint32_t v3 = pPixels[7 * stride]; min3_v = basisu::minimum(min3_v, v3); max3_v = basisu::maximum(max3_v, v3); + } + + { + uint32_t v0 = pPixels[8 * stride]; min0_v = basisu::minimum(min0_v, v0); max0_v = basisu::maximum(max0_v, v0); + uint32_t v1 = pPixels[9 * stride]; min1_v = basisu::minimum(min1_v, v1); max1_v = basisu::maximum(max1_v, v1); + uint32_t v2 = pPixels[10 * stride]; min2_v = basisu::minimum(min2_v, v2); max2_v = basisu::maximum(max2_v, v2); + uint32_t v3 = pPixels[11 * stride]; min3_v = basisu::minimum(min3_v, v3); max3_v = basisu::maximum(max3_v, v3); + } + + { + uint32_t v0 = pPixels[12 * stride]; min0_v = basisu::minimum(min0_v, v0); max0_v = basisu::maximum(max0_v, v0); + uint32_t v1 = pPixels[13 * stride]; min1_v = basisu::minimum(min1_v, v1); max1_v = basisu::maximum(max1_v, v1); + uint32_t v2 = pPixels[14 * stride]; min2_v = basisu::minimum(min2_v, v2); max2_v = basisu::maximum(max2_v, v2); + uint32_t v3 = pPixels[15 * stride]; min3_v = basisu::minimum(min3_v, v3); max3_v = basisu::maximum(max3_v, v3); + } + + const uint32_t min_v = basisu::minimum(min0_v, min1_v, min2_v, min3_v); + const uint32_t max_v = basisu::maximum(max0_v, max1_v, max2_v, max3_v); + + uint8_t* pDst_bytes = static_cast(pDst); + pDst_bytes[0] = (uint8_t)max_v; + pDst_bytes[1] = (uint8_t)min_v; + + if (max_v == min_v) + { + memset(pDst_bytes + 2, 0, 6); + return; + } + + const uint32_t delta = max_v - min_v; + + // min_v is now 0. Compute thresholds between values by scaling max_v. It's x14 because we're adding two x7 scale factors. + const int t0 = delta * 13; + const int t1 = delta * 11; + const int t2 = delta * 9; + const int t3 = delta * 7; + const int t4 = delta * 5; + const int t5 = delta * 3; + const int t6 = delta * 1; + + // BC4 floors in its divisions, which we compensate for with the 4 bias. + // This function is optimal for all possible inputs (i.e. it outputs the same results as checking all 8 values and choosing the closest one). + const int bias = 4 - min_v * 14; + + static const uint32_t s_tran0[8] = { 1U , 7U , 6U , 5U , 4U , 3U , 2U , 0U }; + static const uint32_t s_tran1[8] = { 1U << 3U, 7U << 3U, 6U << 3U, 5U << 3U, 4U << 3U, 3U << 3U, 2U << 3U, 0U << 3U }; + static const uint32_t s_tran2[8] = { 1U << 6U, 7U << 6U, 6U << 6U, 5U << 6U, 4U << 6U, 3U << 6U, 2U << 6U, 0U << 6U }; + static const uint32_t s_tran3[8] = { 1U << 9U, 7U << 9U, 6U << 9U, 5U << 9U, 4U << 9U, 3U << 9U, 2U << 9U, 0U << 9U }; + + uint64_t a0, a1, a2, a3; + { + const int v0 = pPixels[0 * stride] * 14 + bias; + const int v1 = pPixels[1 * stride] * 14 + bias; + const int v2 = pPixels[2 * stride] * 14 + bias; + const int v3 = pPixels[3 * stride] * 14 + bias; + a0 = s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]; + a1 = s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]; + a2 = s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]; + a3 = s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]; + } + + { + const int v0 = pPixels[4 * stride] * 14 + bias; + const int v1 = pPixels[5 * stride] * 14 + bias; + const int v2 = pPixels[6 * stride] * 14 + bias; + const int v3 = pPixels[7 * stride] * 14 + bias; + a0 |= (s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)] << 12U); + a1 |= (s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)] << 12U); + a2 |= (s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)] << 12U); + a3 |= (s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)] << 12U); + } + + { + const int v0 = pPixels[8 * stride] * 14 + bias; + const int v1 = pPixels[9 * stride] * 14 + bias; + const int v2 = pPixels[10 * stride] * 14 + bias; + const int v3 = pPixels[11 * stride] * 14 + bias; + a0 |= (((uint64_t)s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]) << 24U); + a1 |= (((uint64_t)s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]) << 24U); + a2 |= (((uint64_t)s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]) << 24U); + a3 |= (((uint64_t)s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]) << 24U); + } + + { + const int v0 = pPixels[12 * stride] * 14 + bias; + const int v1 = pPixels[13 * stride] * 14 + bias; + const int v2 = pPixels[14 * stride] * 14 + bias; + const int v3 = pPixels[15 * stride] * 14 + bias; + a0 |= (((uint64_t)s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]) << 36U); + a1 |= (((uint64_t)s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]) << 36U); + a2 |= (((uint64_t)s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]) << 36U); + a3 |= (((uint64_t)s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]) << 36U); + } + + const uint64_t f = a0 | a1 | a2 | a3; + + pDst_bytes[2] = (uint8_t)f; + pDst_bytes[3] = (uint8_t)(f >> 8U); + pDst_bytes[4] = (uint8_t)(f >> 16U); + pDst_bytes[5] = (uint8_t)(f >> 24U); + pDst_bytes[6] = (uint8_t)(f >> 32U); + pDst_bytes[7] = (uint8_t)(f >> 40U); + } + + static void bc1_find_sels(const color32 *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16]) + { + uint32_t block_r[4], block_g[4], block_b[4]; + + block_r[0] = (lr << 3) | (lr >> 2); block_g[0] = (lg << 2) | (lg >> 4); block_b[0] = (lb << 3) | (lb >> 2); + block_r[3] = (hr << 3) | (hr >> 2); block_g[3] = (hg << 2) | (hg >> 4); block_b[3] = (hb << 3) | (hb >> 2); + block_r[1] = (block_r[0] * 2 + block_r[3]) / 3; block_g[1] = (block_g[0] * 2 + block_g[3]) / 3; block_b[1] = (block_b[0] * 2 + block_b[3]) / 3; + block_r[2] = (block_r[3] * 2 + block_r[0]) / 3; block_g[2] = (block_g[3] * 2 + block_g[0]) / 3; block_b[2] = (block_b[3] * 2 + block_b[0]) / 3; + + int ar = block_r[3] - block_r[0], ag = block_g[3] - block_g[0], ab = block_b[3] - block_b[0]; + + int dots[4]; + for (uint32_t i = 0; i < 4; i++) + dots[i] = (int)block_r[i] * ar + (int)block_g[i] * ag + (int)block_b[i] * ab; + + int t0 = dots[0] + dots[1], t1 = dots[1] + dots[2], t2 = dots[2] + dots[3]; + + ar *= 2; ag *= 2; ab *= 2; + + for (uint32_t i = 0; i < 16; i++) + { + const int d = pSrc_pixels[i].r * ar + pSrc_pixels[i].g * ag + pSrc_pixels[i].b * ab; + static const uint8_t s_sels[4] = { 3, 2, 1, 0 }; + + // Rounding matters here! + // d <= t0: <=, not <, to the later LS step "sees" a wider range of selectors. It matters for quality. + sels[i] = s_sels[(d <= t0) + (d < t1) + (d < t2)]; + } + } + + static inline void bc1_find_sels_2(const color32* pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t sels[16]) + { + uint32_t block_r[4], block_g[4], block_b[4]; + + block_r[0] = (lr << 3) | (lr >> 2); block_g[0] = (lg << 2) | (lg >> 4); block_b[0] = (lb << 3) | (lb >> 2); + block_r[3] = (hr << 3) | (hr >> 2); block_g[3] = (hg << 2) | (hg >> 4); block_b[3] = (hb << 3) | (hb >> 2); + block_r[1] = (block_r[0] * 2 + block_r[3]) / 3; block_g[1] = (block_g[0] * 2 + block_g[3]) / 3; block_b[1] = (block_b[0] * 2 + block_b[3]) / 3; + block_r[2] = (block_r[3] * 2 + block_r[0]) / 3; block_g[2] = (block_g[3] * 2 + block_g[0]) / 3; block_b[2] = (block_b[3] * 2 + block_b[0]) / 3; + + int ar = block_r[3] - block_r[0], ag = block_g[3] - block_g[0], ab = block_b[3] - block_b[0]; + + int dots[4]; + for (uint32_t i = 0; i < 4; i++) + dots[i] = (int)block_r[i] * ar + (int)block_g[i] * ag + (int)block_b[i] * ab; + + int t0 = dots[0] + dots[1], t1 = dots[1] + dots[2], t2 = dots[2] + dots[3]; + + ar *= 2; ag *= 2; ab *= 2; + + static const uint8_t s_sels[4] = { 3, 2, 1, 0 }; + + for (uint32_t i = 0; i < 16; i += 4) + { + const int d0 = pSrc_pixels[i+0].r * ar + pSrc_pixels[i+0].g * ag + pSrc_pixels[i+0].b * ab; + const int d1 = pSrc_pixels[i+1].r * ar + pSrc_pixels[i+1].g * ag + pSrc_pixels[i+1].b * ab; + const int d2 = pSrc_pixels[i+2].r * ar + pSrc_pixels[i+2].g * ag + pSrc_pixels[i+2].b * ab; + const int d3 = pSrc_pixels[i+3].r * ar + pSrc_pixels[i+3].g * ag + pSrc_pixels[i+3].b * ab; + + sels[i+0] = s_sels[(d0 <= t0) + (d0 < t1) + (d0 < t2)]; + sels[i+1] = s_sels[(d1 <= t0) + (d1 < t1) + (d1 < t2)]; + sels[i+2] = s_sels[(d2 <= t0) + (d2 < t1) + (d2 < t2)]; + sels[i+3] = s_sels[(d3 <= t0) + (d3 < t1) + (d3 < t2)]; + } + } + + struct vec3F { float c[3]; }; + + static bool compute_least_squares_endpoints_rgb(const color32* pColors, const uint8_t* pSelectors, vec3F* pXl, vec3F* pXh) + { + // Derived from bc7enc16's LS function. + // Least squares using normal equations: http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf + // I did this in matrix form first, expanded out all the ops, then optimized it a bit. + uint32_t uq00_r = 0, uq10_r = 0, ut_r = 0, uq00_g = 0, uq10_g = 0, ut_g = 0, uq00_b = 0, uq10_b = 0, ut_b = 0; + + // This table is: 9 * (w * w), 9 * ((1.0f - w) * w), 9 * ((1.0f - w) * (1.0f - w)) + // where w is [0,1/3,2/3,1]. 9 is the perfect multiplier. + static const uint32_t s_weight_vals[4] = { 0x000009, 0x010204, 0x040201, 0x090000 }; + + uint32_t weight_accum = 0; + for (uint32_t i = 0; i < 16; i++) + { + const uint32_t r = pColors[i].c[0], g = pColors[i].c[1], b = pColors[i].c[2]; + const uint32_t sel = pSelectors[i]; + ut_r += r; + ut_g += g; + ut_b += b; + weight_accum += s_weight_vals[sel]; + uq00_r += sel * r; + uq00_g += sel * g; + uq00_b += sel * b; + } + + float q00_r = (float)uq00_r, q10_r = (float)uq10_r, t_r = (float)ut_r; + float q00_g = (float)uq00_g, q10_g = (float)uq10_g, t_g = (float)ut_g; + float q00_b = (float)uq00_b, q10_b = (float)uq10_b, t_b = (float)ut_b; + + q10_r = t_r * 3.0f - q00_r; + q10_g = t_g * 3.0f - q00_g; + q10_b = t_b * 3.0f - q00_b; + + float z00 = (float)((weight_accum >> 16) & 0xFF); + float z10 = (float)((weight_accum >> 8) & 0xFF); + float z11 = (float)(weight_accum & 0xFF); + float z01 = z10; + + float det = z00 * z11 - z01 * z10; + if (fabs(det) < 1e-8f) + return false; + + det = 3.0f / det; + + float iz00, iz01, iz10, iz11; + iz00 = z11 * det; + iz01 = -z01 * det; + iz10 = -z10 * det; + iz11 = z00 * det; + + pXl->c[0] = iz00 * q00_r + iz01 * q10_r; pXh->c[0] = iz10 * q00_r + iz11 * q10_r; + pXl->c[1] = iz00 * q00_g + iz01 * q10_g; pXh->c[1] = iz10 * q00_g + iz11 * q10_g; + pXl->c[2] = iz00 * q00_b + iz01 * q10_b; pXh->c[2] = iz10 * q00_b + iz11 * q10_b; + + // Check and fix channel singularities - might not be needed, but is in UASTC's encoder. + for (uint32_t c = 0; c < 3; c++) + { + if ((pXl->c[c] < 0.0f) || (pXh->c[c] > 255.0f)) + { + uint32_t lo_v = UINT32_MAX, hi_v = 0; + for (uint32_t i = 0; i < 16; i++) + { + lo_v = basisu::minimumu(lo_v, pColors[i].c[c]); + hi_v = basisu::maximumu(hi_v, pColors[i].c[c]); + } + + if (lo_v == hi_v) + { + pXl->c[c] = (float)lo_v; + pXh->c[c] = (float)hi_v; + } + } + } + + return true; + } + + void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb) + { + dxt1_block* pDst_block = static_cast(pDst); + + uint32_t mask = 0xAA; + uint32_t max16 = (g_bc1_match5_equals_1[fr].m_hi << 11) | (g_bc1_match6_equals_1[fg].m_hi << 5) | g_bc1_match5_equals_1[fb].m_hi; + uint32_t min16 = (g_bc1_match5_equals_1[fr].m_lo << 11) | (g_bc1_match6_equals_1[fg].m_lo << 5) | g_bc1_match5_equals_1[fb].m_lo; + + if (min16 == max16) + { + // Always forbid 3 color blocks + // This is to guarantee that BC3 blocks never use punchthrough alpha (3 color) mode, which isn't supported on some (all?) GPU's. + mask = 0; + + // Make l > h + if (min16 > 0) + min16--; + else + { + // l = h = 0 + assert(min16 == max16 && max16 == 0); + + max16 = 1; + min16 = 0; + mask = 0x55; + } + + assert(max16 > min16); + } + + if (max16 < min16) + { + std::swap(max16, min16); + mask ^= 0x55; + } + + pDst_block->set_low_color(static_cast(max16)); + pDst_block->set_high_color(static_cast(min16)); + pDst_block->m_selectors[0] = static_cast(mask); + pDst_block->m_selectors[1] = static_cast(mask); + pDst_block->m_selectors[2] = static_cast(mask); + pDst_block->m_selectors[3] = static_cast(mask); + } + + static inline uint8_t to_5(uint32_t v) { v = v * 31 + 128; return (uint8_t)((v + (v >> 8)) >> 8); } + static inline uint8_t to_6(uint32_t v) { v = v * 63 + 128; return (uint8_t)((v + (v >> 8)) >> 8); } + + // Good references: squish library, stb_dxt. + void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags) + { + const color32* pSrc_pixels = (const color32*)pPixels; + dxt1_block* pDst_block = static_cast(pDst); + + int avg_r = -1, avg_g = 0, avg_b = 0; + int lr = 0, lg = 0, lb = 0, hr = 0, hg = 0, hb = 0; + uint8_t sels[16]; + + const bool use_sels = (flags & cEncodeBC1UseSelectors) != 0; + if (use_sels) + { + // Caller is jamming in their own selectors for us to try. + const uint32_t s = pDst_block->m_selectors[0] | (pDst_block->m_selectors[1] << 8) | (pDst_block->m_selectors[2] << 16) | (pDst_block->m_selectors[3] << 24); + + static const uint8_t s_sel_tran[4] = { 0, 3, 1, 2 }; + + for (uint32_t i = 0; i < 16; i++) + sels[i] = s_sel_tran[(s >> (i * 2)) & 3]; + } + else + { + const uint32_t fr = pSrc_pixels[0].r, fg = pSrc_pixels[0].g, fb = pSrc_pixels[0].b; + + uint32_t j; + for (j = 1; j < 16; j++) + if ((pSrc_pixels[j].r != fr) || (pSrc_pixels[j].g != fg) || (pSrc_pixels[j].b != fb)) + break; + + if (j == 16) + { + encode_bc1_solid_block(pDst, fr, fg, fb); + return; + } + + // Select 2 colors along the principle axis. (There must be a faster/simpler way.) + int total_r = fr, total_g = fg, total_b = fb; + int max_r = fr, max_g = fg, max_b = fb; + int min_r = fr, min_g = fg, min_b = fb; + for (uint32_t i = 1; i < 16; i++) + { + const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; + max_r = basisu::maximum(max_r, r); max_g = basisu::maximum(max_g, g); max_b = basisu::maximum(max_b, b); + min_r = basisu::minimum(min_r, r); min_g = basisu::minimum(min_g, g); min_b = basisu::minimum(min_b, b); + total_r += r; total_g += g; total_b += b; + } + + avg_r = (total_r + 8) >> 4; + avg_g = (total_g + 8) >> 4; + avg_b = (total_b + 8) >> 4; + + int icov[6] = { 0, 0, 0, 0, 0, 0 }; + for (uint32_t i = 0; i < 16; i++) + { + int r = (int)pSrc_pixels[i].r - avg_r; + int g = (int)pSrc_pixels[i].g - avg_g; + int b = (int)pSrc_pixels[i].b - avg_b; + icov[0] += r * r; + icov[1] += r * g; + icov[2] += r * b; + icov[3] += g * g; + icov[4] += g * b; + icov[5] += b * b; + } + + float cov[6]; + for (uint32_t i = 0; i < 6; i++) + cov[i] = static_cast(icov[i])* (1.0f / 255.0f); + +#if 0 + // Seems silly to use full PCA to choose 2 colors. The diff in avg. PSNR between using PCA vs. not is small (~.025 difference). + // TODO: Try 2 or 3 different normalized diagonal vectors, choose the one that results in the largest dot delta + int saxis_r = max_r - min_r; + int saxis_g = max_g - min_g; + int saxis_b = max_b - min_b; +#else + float xr = (float)(max_r - min_r); + float xg = (float)(max_g - min_g); + float xb = (float)(max_b - min_b); + //float xr = (float)(max_r - avg_r); // max-avg is nearly the same, and doesn't require computing min's + //float xg = (float)(max_g - avg_g); + //float xb = (float)(max_b - avg_b); + for (uint32_t power_iter = 0; power_iter < 4; power_iter++) + { + float r = xr * cov[0] + xg * cov[1] + xb * cov[2]; + float g = xr * cov[1] + xg * cov[3] + xb * cov[4]; + float b = xr * cov[2] + xg * cov[4] + xb * cov[5]; + xr = r; xg = g; xb = b; + } + + float k = basisu::maximum(fabsf(xr), fabsf(xg), fabsf(xb)); + int saxis_r = 306, saxis_g = 601, saxis_b = 117; + if (k >= 2) + { + float m = 1024.0f / k; + saxis_r = (int)(xr * m); + saxis_g = (int)(xg * m); + saxis_b = (int)(xb * m); + } +#endif + + int low_dot = INT_MAX, high_dot = INT_MIN, low_c = 0, high_c = 0; + for (uint32_t i = 0; i < 16; i++) + { + int dot = pSrc_pixels[i].r * saxis_r + pSrc_pixels[i].g * saxis_g + pSrc_pixels[i].b * saxis_b; + if (dot < low_dot) + { + low_dot = dot; + low_c = i; + } + if (dot > high_dot) + { + high_dot = dot; + high_c = i; + } + } + + lr = to_5(pSrc_pixels[low_c].r); + lg = to_6(pSrc_pixels[low_c].g); + lb = to_5(pSrc_pixels[low_c].b); + + hr = to_5(pSrc_pixels[high_c].r); + hg = to_6(pSrc_pixels[high_c].g); + hb = to_5(pSrc_pixels[high_c].b); + + bc1_find_sels(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels); + } // if (use_sels) + + const uint32_t total_ls_passes = (flags & cEncodeBC1HigherQuality) ? 3 : (flags & cEncodeBC1HighQuality ? 2 : 1); + for (uint32_t ls_pass = 0; ls_pass < total_ls_passes; ls_pass++) + { + // This is where the real magic happens. We have an array of candidate selectors, so let's use least squares to compute the optimal low/high endpoint colors. + vec3F xl, xh; + if (!compute_least_squares_endpoints_rgb(pSrc_pixels, sels, &xl, &xh)) + { + if (avg_r < 0) + { + int total_r = 0, total_g = 0, total_b = 0; + for (uint32_t i = 0; i < 16; i++) + { + total_r += pSrc_pixels[i].r; + total_g += pSrc_pixels[i].g; + total_b += pSrc_pixels[i].b; + } + + avg_r = (total_r + 8) >> 4; + avg_g = (total_g + 8) >> 4; + avg_b = (total_b + 8) >> 4; + } + + // All selectors equal - treat it as a solid block which should always be equal or better. + lr = g_bc1_match5_equals_1[avg_r].m_hi; + lg = g_bc1_match6_equals_1[avg_g].m_hi; + lb = g_bc1_match5_equals_1[avg_b].m_hi; + + hr = g_bc1_match5_equals_1[avg_r].m_lo; + hg = g_bc1_match6_equals_1[avg_g].m_lo; + hb = g_bc1_match5_equals_1[avg_b].m_lo; + + // In high/higher quality mode, let it try again in case the optimal tables have caused the sels to diverge. + } + else + { + lr = basisu::clamp((int)((xl.c[0]) * (31.0f / 255.0f) + .5f), 0, 31); + lg = basisu::clamp((int)((xl.c[1]) * (63.0f / 255.0f) + .5f), 0, 63); + lb = basisu::clamp((int)((xl.c[2]) * (31.0f / 255.0f) + .5f), 0, 31); + + hr = basisu::clamp((int)((xh.c[0]) * (31.0f / 255.0f) + .5f), 0, 31); + hg = basisu::clamp((int)((xh.c[1]) * (63.0f / 255.0f) + .5f), 0, 63); + hb = basisu::clamp((int)((xh.c[2]) * (31.0f / 255.0f) + .5f), 0, 31); + } + + bc1_find_sels(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels); + } + + uint32_t lc16 = dxt1_block::pack_unscaled_color(lr, lg, lb); + uint32_t hc16 = dxt1_block::pack_unscaled_color(hr, hg, hb); + + // Always forbid 3 color blocks + if (lc16 == hc16) + { + uint8_t mask = 0; + + // Make l > h + if (hc16 > 0) + hc16--; + else + { + // lc16 = hc16 = 0 + assert(lc16 == hc16 && hc16 == 0); + + hc16 = 0; + lc16 = 1; + mask = 0x55; // select hc16 + } + + assert(lc16 > hc16); + pDst_block->set_low_color(static_cast(lc16)); + pDst_block->set_high_color(static_cast(hc16)); + + pDst_block->m_selectors[0] = mask; + pDst_block->m_selectors[1] = mask; + pDst_block->m_selectors[2] = mask; + pDst_block->m_selectors[3] = mask; + } + else + { + uint8_t invert_mask = 0; + if (lc16 < hc16) + { + std::swap(lc16, hc16); + invert_mask = 0x55; + } + + assert(lc16 > hc16); + pDst_block->set_low_color((uint16_t)lc16); + pDst_block->set_high_color((uint16_t)hc16); + + uint32_t packed_sels = 0; + static const uint8_t s_sel_trans[4] = { 0, 2, 3, 1 }; + for (uint32_t i = 0; i < 16; i++) + packed_sels |= ((uint32_t)s_sel_trans[sels[i]] << (i * 2)); + + pDst_block->m_selectors[0] = (uint8_t)packed_sels ^ invert_mask; + pDst_block->m_selectors[1] = (uint8_t)(packed_sels >> 8) ^ invert_mask; + pDst_block->m_selectors[2] = (uint8_t)(packed_sels >> 16) ^ invert_mask; + pDst_block->m_selectors[3] = (uint8_t)(packed_sels >> 24) ^ invert_mask; + } + } + + void encode_bc1_alt(void* pDst, const uint8_t* pPixels, uint32_t flags) + { + const color32* pSrc_pixels = (const color32*)pPixels; + dxt1_block* pDst_block = static_cast(pDst); + + int avg_r = -1, avg_g = 0, avg_b = 0; + int lr = 0, lg = 0, lb = 0, hr = 0, hg = 0, hb = 0; + uint8_t sels[16]; + + const bool use_sels = (flags & cEncodeBC1UseSelectors) != 0; + if (use_sels) + { + // Caller is jamming in their own selectors for us to try. + const uint32_t s = pDst_block->m_selectors[0] | (pDst_block->m_selectors[1] << 8) | (pDst_block->m_selectors[2] << 16) | (pDst_block->m_selectors[3] << 24); + + static const uint8_t s_sel_tran[4] = { 0, 3, 1, 2 }; + + for (uint32_t i = 0; i < 16; i++) + sels[i] = s_sel_tran[(s >> (i * 2)) & 3]; + } + else + { + const uint32_t fr = pSrc_pixels[0].r, fg = pSrc_pixels[0].g, fb = pSrc_pixels[0].b; + + uint32_t j; + for (j = 1; j < 16; j++) + if ((pSrc_pixels[j].r != fr) || (pSrc_pixels[j].g != fg) || (pSrc_pixels[j].b != fb)) + break; + + if (j == 16) + { + encode_bc1_solid_block(pDst, fr, fg, fb); + return; + } + + // Select 2 colors along the principle axis. (There must be a faster/simpler way.) + int total_r = fr, total_g = fg, total_b = fb; + int max_r = fr, max_g = fg, max_b = fb; + int min_r = fr, min_g = fg, min_b = fb; + uint32_t grayscale_flag = (fr == fg) && (fr == fb); + for (uint32_t i = 1; i < 16; i++) + { + const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; + grayscale_flag &= ((r == g) && (r == b)); + max_r = basisu::maximum(max_r, r); max_g = basisu::maximum(max_g, g); max_b = basisu::maximum(max_b, b); + min_r = basisu::minimum(min_r, r); min_g = basisu::minimum(min_g, g); min_b = basisu::minimum(min_b, b); + total_r += r; total_g += g; total_b += b; + } + + if (grayscale_flag) + { + // Grayscale blocks are a common enough case to specialize. + if ((max_r - min_r) < 2) + { + lr = lb = hr = hb = to_5(fr); + lg = hg = to_6(fr); + } + else + { + lr = lb = to_5(min_r); + lg = to_6(min_r); + + hr = hb = to_5(max_r); + hg = to_6(max_r); + } + } + else + { + avg_r = (total_r + 8) >> 4; + avg_g = (total_g + 8) >> 4; + avg_b = (total_b + 8) >> 4; + + // Find the shortest vector from a AABB corner to the block's average color. + // This is to help avoid outliers. + + uint32_t dist[3][2]; + dist[0][0] = basisu::square(min_r - avg_r) << 3; dist[0][1] = basisu::square(max_r - avg_r) << 3; + dist[1][0] = basisu::square(min_g - avg_g) << 3; dist[1][1] = basisu::square(max_g - avg_g) << 3; + dist[2][0] = basisu::square(min_b - avg_b) << 3; dist[2][1] = basisu::square(max_b - avg_b) << 3; + + uint32_t min_d0 = (dist[0][0] + dist[1][0] + dist[2][0]); + uint32_t d4 = (dist[0][0] + dist[1][0] + dist[2][1]) | 4; + min_d0 = basisu::minimum(min_d0, d4); + + uint32_t min_d1 = (dist[0][1] + dist[1][0] + dist[2][0]) | 1; + uint32_t d5 = (dist[0][1] + dist[1][0] + dist[2][1]) | 5; + min_d1 = basisu::minimum(min_d1, d5); + + uint32_t d2 = (dist[0][0] + dist[1][1] + dist[2][0]) | 2; + min_d0 = basisu::minimum(min_d0, d2); + + uint32_t d3 = (dist[0][1] + dist[1][1] + dist[2][0]) | 3; + min_d1 = basisu::minimum(min_d1, d3); + + uint32_t d6 = (dist[0][0] + dist[1][1] + dist[2][1]) | 6; + min_d0 = basisu::minimum(min_d0, d6); + + uint32_t d7 = (dist[0][1] + dist[1][1] + dist[2][1]) | 7; + min_d1 = basisu::minimum(min_d1, d7); + + uint32_t min_d = basisu::minimum(min_d0, min_d1); + uint32_t best_i = min_d & 7; + + int delta_r = (best_i & 1) ? (max_r - avg_r) : (avg_r - min_r); + int delta_g = (best_i & 2) ? (max_g - avg_g) : (avg_g - min_g); + int delta_b = (best_i & 4) ? (max_b - avg_b) : (avg_b - min_b); + + // Note: if delta_r/g/b==0, we actually want to choose a single color, so the block average color optimization kicks in. + uint32_t low_c = 0, high_c = 0; + if ((delta_r | delta_g | delta_b) != 0) + { + // Now we have a smaller AABB going from the block's average color to a cornerpoint of the larger AABB. + // Project all pixels colors along the 4 vectors going from a smaller AABB cornerpoint to the opposite cornerpoint, find largest projection. + // One of these vectors will be a decent approximation of the block's PCA. + const int saxis0_r = delta_r, saxis0_g = delta_g, saxis0_b = delta_b; + + int low_dot0 = INT_MAX, high_dot0 = INT_MIN; + int low_dot1 = INT_MAX, high_dot1 = INT_MIN; + int low_dot2 = INT_MAX, high_dot2 = INT_MIN; + int low_dot3 = INT_MAX, high_dot3 = INT_MIN; + + //int low_c0, low_c1, low_c2, low_c3; + //int high_c0, high_c1, high_c2, high_c3; + + for (uint32_t i = 0; i < 16; i++) + { + const int dotx = pSrc_pixels[i].r * saxis0_r; + const int doty = pSrc_pixels[i].g * saxis0_g; + const int dotz = pSrc_pixels[i].b * saxis0_b; + + const int dot0 = ((dotz + dotx + doty) << 4) + i; + const int dot1 = ((dotz - dotx - doty) << 4) + i; + const int dot2 = ((dotz - dotx + doty) << 4) + i; + const int dot3 = ((dotz + dotx - doty) << 4) + i; + + if (dot0 < low_dot0) + { + low_dot0 = dot0; + //low_c0 = i; + } + if ((dot0 ^ 15) > high_dot0) + { + high_dot0 = dot0 ^ 15; + //high_c0 = i; + } + + if (dot1 < low_dot1) + { + low_dot1 = dot1; + //low_c1 = i; + } + if ((dot1 ^ 15) > high_dot1) + { + high_dot1 = dot1 ^ 15; + //high_c1 = i; + } + + if (dot2 < low_dot2) + { + low_dot2 = dot2; + //low_c2 = i; + } + if ((dot2 ^ 15) > high_dot2) + { + high_dot2 = dot2 ^ 15; + //high_c2 = i; + } + + if (dot3 < low_dot3) + { + low_dot3 = dot3; + //low_c3 = i; + } + if ((dot3 ^ 15) > high_dot3) + { + high_dot3 = dot3 ^ 15; + //high_c3 = i; + } + } + + low_c = low_dot0 & 15; + high_c = ~high_dot0 & 15; + uint32_t r = (high_dot0 & ~15) - (low_dot0 & ~15); + + uint32_t tr = (high_dot1 & ~15) - (low_dot1 & ~15); + if (tr > r) { + low_c = low_dot1 & 15; + high_c = ~high_dot1 & 15; + r = tr; + } + + tr = (high_dot2 & ~15) - (low_dot2 & ~15); + if (tr > r) { + low_c = low_dot2 & 15; + high_c = ~high_dot2 & 15; + r = tr; + } + + tr = (high_dot3 & ~15) - (low_dot3 & ~15); + if (tr > r) { + low_c = low_dot3 & 15; + high_c = ~high_dot3 & 15; + } + } + + lr = to_5(pSrc_pixels[low_c].r); + lg = to_6(pSrc_pixels[low_c].g); + lb = to_5(pSrc_pixels[low_c].b); + + hr = to_5(pSrc_pixels[high_c].r); + hg = to_6(pSrc_pixels[high_c].g); + hb = to_5(pSrc_pixels[high_c].b); + } + + bc1_find_sels_2(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels); + } // if (use_sels) + + const uint32_t total_ls_passes = (flags & cEncodeBC1HigherQuality) ? 3 : (flags & cEncodeBC1HighQuality ? 2 : 1); + for (uint32_t ls_pass = 0; ls_pass < total_ls_passes; ls_pass++) + { + int prev_lr = lr, prev_lg = lg, prev_lb = lb, prev_hr = hr, prev_hg = hg, prev_hb = hb; + + // This is where the real magic happens. We have an array of candidate selectors, so let's use least squares to compute the optimal low/high endpoint colors. + vec3F xl, xh; + if (!compute_least_squares_endpoints_rgb(pSrc_pixels, sels, &xl, &xh)) + { + if (avg_r < 0) + { + int total_r = 0, total_g = 0, total_b = 0; + for (uint32_t i = 0; i < 16; i++) + { + total_r += pSrc_pixels[i].r; + total_g += pSrc_pixels[i].g; + total_b += pSrc_pixels[i].b; + } + + avg_r = (total_r + 8) >> 4; + avg_g = (total_g + 8) >> 4; + avg_b = (total_b + 8) >> 4; + } + + // All selectors equal - treat it as a solid block which should always be equal or better. + lr = g_bc1_match5_equals_1[avg_r].m_hi; + lg = g_bc1_match6_equals_1[avg_g].m_hi; + lb = g_bc1_match5_equals_1[avg_b].m_hi; + + hr = g_bc1_match5_equals_1[avg_r].m_lo; + hg = g_bc1_match6_equals_1[avg_g].m_lo; + hb = g_bc1_match5_equals_1[avg_b].m_lo; + + // In high/higher quality mode, let it try again in case the optimal tables have caused the sels to diverge. + } + else + { + lr = basisu::clamp((int)((xl.c[0]) * (31.0f / 255.0f) + .5f), 0, 31); + lg = basisu::clamp((int)((xl.c[1]) * (63.0f / 255.0f) + .5f), 0, 63); + lb = basisu::clamp((int)((xl.c[2]) * (31.0f / 255.0f) + .5f), 0, 31); + + hr = basisu::clamp((int)((xh.c[0]) * (31.0f / 255.0f) + .5f), 0, 31); + hg = basisu::clamp((int)((xh.c[1]) * (63.0f / 255.0f) + .5f), 0, 63); + hb = basisu::clamp((int)((xh.c[2]) * (31.0f / 255.0f) + .5f), 0, 31); + } + + if ((prev_lr == lr) && (prev_lg == lg) && (prev_lb == lb) && (prev_hr == hr) && (prev_hg == hg) && (prev_hb == hb)) + break; + + bc1_find_sels_2(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels); + } + + uint32_t lc16 = dxt1_block::pack_unscaled_color(lr, lg, lb); + uint32_t hc16 = dxt1_block::pack_unscaled_color(hr, hg, hb); + + // Always forbid 3 color blocks + if (lc16 == hc16) + { + uint8_t mask = 0; + + // Make l > h + if (hc16 > 0) + hc16--; + else + { + // lc16 = hc16 = 0 + assert(lc16 == hc16 && hc16 == 0); + + hc16 = 0; + lc16 = 1; + mask = 0x55; // select hc16 + } + + assert(lc16 > hc16); + pDst_block->set_low_color(static_cast(lc16)); + pDst_block->set_high_color(static_cast(hc16)); + + pDst_block->m_selectors[0] = mask; + pDst_block->m_selectors[1] = mask; + pDst_block->m_selectors[2] = mask; + pDst_block->m_selectors[3] = mask; + } + else + { + uint8_t invert_mask = 0; + if (lc16 < hc16) + { + std::swap(lc16, hc16); + invert_mask = 0x55; + } + + assert(lc16 > hc16); + pDst_block->set_low_color((uint16_t)lc16); + pDst_block->set_high_color((uint16_t)hc16); + + uint32_t packed_sels = 0; + static const uint8_t s_sel_trans[4] = { 0, 2, 3, 1 }; + for (uint32_t i = 0; i < 16; i++) + packed_sels |= ((uint32_t)s_sel_trans[sels[i]] << (i * 2)); + + pDst_block->m_selectors[0] = (uint8_t)packed_sels ^ invert_mask; + pDst_block->m_selectors[1] = (uint8_t)(packed_sels >> 8) ^ invert_mask; + pDst_block->m_selectors[2] = (uint8_t)(packed_sels >> 16) ^ invert_mask; + pDst_block->m_selectors[3] = (uint8_t)(packed_sels >> 24) ^ invert_mask; + } + } + + // Scale the UASTC first subset endpoints and first plane's weight indices directly to BC1's - fastest. + void transcode_uastc_to_bc1_hint0(const unpacked_uastc_block& unpacked_src_blk, void* pDst) + { + const uint32_t mode = unpacked_src_blk.m_mode; + const astc_block_desc& astc_blk = unpacked_src_blk.m_astc; + + dxt1_block& b = *static_cast(pDst); + + const uint32_t endpoint_range = g_uastc_mode_endpoint_ranges[mode]; + + const uint32_t total_comps = g_uastc_mode_comps[mode]; + + if (total_comps == 2) + { + const uint32_t l = g_astc_unquant[endpoint_range][astc_blk.m_endpoints[0]].m_unquant; + const uint32_t h = g_astc_unquant[endpoint_range][astc_blk.m_endpoints[1]].m_unquant; + + b.set_low_color(dxt1_block::pack_color(color32(l, l, l, 255), true, 127)); + b.set_high_color(dxt1_block::pack_color(color32(h, h, h, 255), true, 127)); + } + else + { + b.set_low_color(dxt1_block::pack_color( + color32(g_astc_unquant[endpoint_range][astc_blk.m_endpoints[0]].m_unquant, + g_astc_unquant[endpoint_range][astc_blk.m_endpoints[2]].m_unquant, + g_astc_unquant[endpoint_range][astc_blk.m_endpoints[4]].m_unquant, + 255), true, 127) + ); + + b.set_high_color(dxt1_block::pack_color( + color32(g_astc_unquant[endpoint_range][astc_blk.m_endpoints[1]].m_unquant, + g_astc_unquant[endpoint_range][astc_blk.m_endpoints[3]].m_unquant, + g_astc_unquant[endpoint_range][astc_blk.m_endpoints[5]].m_unquant, + 255), true, 127) + ); + } + + if (b.get_low_color() == b.get_high_color()) + { + // Always forbid 3 color blocks + uint16_t lc16 = (uint16_t)b.get_low_color(); + uint16_t hc16 = (uint16_t)b.get_high_color(); + + uint8_t mask = 0; + + // Make l > h + if (hc16 > 0) + hc16--; + else + { + // lc16 = hc16 = 0 + assert(lc16 == hc16 && hc16 == 0); + + hc16 = 0; + lc16 = 1; + mask = 0x55; // select hc16 + } + + assert(lc16 > hc16); + b.set_low_color(static_cast(lc16)); + b.set_high_color(static_cast(hc16)); + + b.m_selectors[0] = mask; + b.m_selectors[1] = mask; + b.m_selectors[2] = mask; + b.m_selectors[3] = mask; + } + else + { + bool invert = false; + if (b.get_low_color() < b.get_high_color()) + { + std::swap(b.m_low_color[0], b.m_high_color[0]); + std::swap(b.m_low_color[1], b.m_high_color[1]); + invert = true; + } + + const uint8_t* pTran = s_uastc_to_bc1_weights[g_uastc_mode_weight_bits[mode]]; + + const uint32_t plane_shift = g_uastc_mode_planes[mode] - 1; + + uint32_t sels = 0; + for (int i = 15; i >= 0; --i) + { + uint32_t s = pTran[astc_blk.m_weights[i << plane_shift]]; + + if (invert) + s ^= 1; + + sels = (sels << 2) | s; + } + b.m_selectors[0] = sels & 0xFF; + b.m_selectors[1] = (sels >> 8) & 0xFF; + b.m_selectors[2] = (sels >> 16) & 0xFF; + b.m_selectors[3] = (sels >> 24) & 0xFF; + } + } + + // Scale the UASTC first plane's weight indices to BC1, use 1 or 2 least squares passes to compute endpoints - no PCA needed. + void transcode_uastc_to_bc1_hint1(const unpacked_uastc_block& unpacked_src_blk, const color32 block_pixels[4][4], void* pDst, bool high_quality) + { + const uint32_t mode = unpacked_src_blk.m_mode; + + const astc_block_desc& astc_blk = unpacked_src_blk.m_astc; + + dxt1_block& b = *static_cast(pDst); + + b.set_low_color(1); + b.set_high_color(0); + + const uint8_t* pTran = s_uastc_to_bc1_weights[g_uastc_mode_weight_bits[mode]]; + + const uint32_t plane_shift = g_uastc_mode_planes[mode] - 1; + + uint32_t sels = 0; + for (int i = 15; i >= 0; --i) + { + sels <<= 2; + sels |= pTran[astc_blk.m_weights[i << plane_shift]]; + } + + b.m_selectors[0] = sels & 0xFF; + b.m_selectors[1] = (sels >> 8) & 0xFF; + b.m_selectors[2] = (sels >> 16) & 0xFF; + b.m_selectors[3] = (sels >> 24) & 0xFF; + + encode_bc1(&b, (const uint8_t*)&block_pixels[0][0].c[0], (high_quality ? cEncodeBC1HighQuality : 0) | cEncodeBC1UseSelectors); + } + + bool transcode_uastc_to_bc1(const uastc_block& src_blk, void* pDst, bool high_quality) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + const uint32_t mode = unpacked_src_blk.m_mode; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + encode_bc1_solid_block(pDst, unpacked_src_blk.m_solid_color.r, unpacked_src_blk.m_solid_color.g, unpacked_src_blk.m_solid_color.b); + return true; + } + + if ((!high_quality) && (unpacked_src_blk.m_bc1_hint0)) + transcode_uastc_to_bc1_hint0(unpacked_src_blk, pDst); + else + { + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + if (unpacked_src_blk.m_bc1_hint1) + transcode_uastc_to_bc1_hint1(unpacked_src_blk, block_pixels, pDst, high_quality); + else + encode_bc1(pDst, &block_pixels[0][0].r, high_quality ? cEncodeBC1HighQuality : 0); + } + + return true; + } + + static void write_bc4_solid_block(uint8_t* pDst, uint32_t a) + { + pDst[0] = (uint8_t)a; + pDst[1] = (uint8_t)a; + memset(pDst + 2, 0, 6); + } + + bool transcode_uastc_to_bc3(const uastc_block& src_blk, void* pDst, bool high_quality) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + const uint32_t mode = unpacked_src_blk.m_mode; + + void* pBC4_block = pDst; + dxt1_block* pBC1_block = &static_cast(pDst)[1]; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + write_bc4_solid_block(static_cast(pBC4_block), unpacked_src_blk.m_solid_color.a); + encode_bc1_solid_block(pBC1_block, unpacked_src_blk.m_solid_color.r, unpacked_src_blk.m_solid_color.g, unpacked_src_blk.m_solid_color.b); + return true; + } + + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + basist::encode_bc4(pBC4_block, &block_pixels[0][0].a, sizeof(color32)); + + if ((!high_quality) && (unpacked_src_blk.m_bc1_hint0)) + transcode_uastc_to_bc1_hint0(unpacked_src_blk, pBC1_block); + else + { + if (unpacked_src_blk.m_bc1_hint1) + transcode_uastc_to_bc1_hint1(unpacked_src_blk, block_pixels, pBC1_block, high_quality); + else + encode_bc1(pBC1_block, &block_pixels[0][0].r, high_quality ? cEncodeBC1HighQuality : 0); + } + + return true; + } + + bool transcode_uastc_to_bc4(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0) + { + BASISU_NOTE_UNUSED(high_quality); + + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + const uint32_t mode = unpacked_src_blk.m_mode; + + void* pBC4_block = pDst; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + write_bc4_solid_block(static_cast(pBC4_block), unpacked_src_blk.m_solid_color.c[chan0]); + return true; + } + + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + basist::encode_bc4(pBC4_block, &block_pixels[0][0].c[chan0], sizeof(color32)); + + return true; + } + + bool transcode_uastc_to_bc5(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1) + { + BASISU_NOTE_UNUSED(high_quality); + + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + const uint32_t mode = unpacked_src_blk.m_mode; + + void* pBC4_block0 = pDst; + void* pBC4_block1 = (uint8_t*)pDst + 8; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + write_bc4_solid_block(static_cast(pBC4_block0), unpacked_src_blk.m_solid_color.c[chan0]); + write_bc4_solid_block(static_cast(pBC4_block1), unpacked_src_blk.m_solid_color.c[chan1]); + return true; + } + + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + basist::encode_bc4(pBC4_block0, &block_pixels[0][0].c[chan0], sizeof(color32)); + basist::encode_bc4(pBC4_block1, &block_pixels[0][0].c[chan1], sizeof(color32)); + + return true; + } + + static const uint8_t s_etc2_eac_bit_ofs[16] = { 45, 33, 21, 9, 42, 30, 18, 6, 39, 27, 15, 3, 36, 24, 12, 0 }; + + static void pack_eac_solid_block(eac_block& blk, uint32_t a) + { + blk.m_base = static_cast(a); + blk.m_table = 13; + blk.m_multiplier = 0; + + memcpy(blk.m_selectors, g_etc2_eac_a8_sel4, sizeof(g_etc2_eac_a8_sel4)); + + return; + } + + // Only checks 4 tables. + static void pack_eac(eac_block& blk, const uint8_t* pPixels, uint32_t stride) + { + uint32_t min_alpha = 255, max_alpha = 0; + for (uint32_t i = 0; i < 16; i++) + { + const uint32_t a = pPixels[i * stride]; + if (a < min_alpha) min_alpha = a; + if (a > max_alpha) max_alpha = a; + } + + if (min_alpha == max_alpha) + { + pack_eac_solid_block(blk, min_alpha); + return; + } + + const uint32_t alpha_range = max_alpha - min_alpha; + + const uint32_t SINGLE_TABLE_THRESH = 5; + if (alpha_range <= SINGLE_TABLE_THRESH) + { + // If alpha_range <= 5 table 13 is lossless + int base = clamp255((int)max_alpha - 2); + + blk.m_base = base; + blk.m_multiplier = 1; + blk.m_table = 13; + + base -= 3; + + uint64_t packed_sels = 0; + for (uint32_t i = 0; i < 16; i++) + { + const int a = pPixels[i * stride]; + + static const uint8_t s_sels[6] = { 2, 1, 0, 4, 5, 6 }; + + int sel = a - base; + assert(sel >= 0 && sel <= 5); + + packed_sels |= (static_cast(s_sels[sel]) << s_etc2_eac_bit_ofs[i]); + } + + blk.set_selector_bits(packed_sels); + + return; + } + + const uint32_t T0 = 2, T1 = 8, T2 = 11, T3 = 13; + static const uint8_t s_tables[4] = { T0, T1, T2, T3 }; + + int base[4], mul[4]; + uint32_t mul_or = 0; + for (uint32_t i = 0; i < 4; i++) + { + const uint32_t table = s_tables[i]; + + const float range = (float)(g_eac_modifier_table[table][ETC2_EAC_MAX_VALUE_SELECTOR] - g_eac_modifier_table[table][ETC2_EAC_MIN_VALUE_SELECTOR]); + + base[i] = clamp255((int)roundf(basisu::lerp((float)min_alpha, (float)max_alpha, (float)(0 - g_eac_modifier_table[table][ETC2_EAC_MIN_VALUE_SELECTOR]) / range))); + mul[i] = clampi((int)roundf(alpha_range / range), 1, 15); + mul_or |= mul[i]; + } + + uint32_t total_err[4] = { 0, 0, 0, 0 }; + uint8_t sels[4][16]; + + for (uint32_t i = 0; i < 16; i++) + { + const int a = pPixels[i * stride]; + + uint32_t l0 = UINT32_MAX, l1 = UINT32_MAX, l2 = UINT32_MAX, l3 = UINT32_MAX; + + if ((a < 7) || (a > (255 - 7))) + { + for (uint32_t s = 0; s < 8; s++) + { + const int v0 = clamp255(mul[0] * g_eac_modifier_table[T0][s] + base[0]); + const int v1 = clamp255(mul[1] * g_eac_modifier_table[T1][s] + base[1]); + const int v2 = clamp255(mul[2] * g_eac_modifier_table[T2][s] + base[2]); + const int v3 = clamp255(mul[3] * g_eac_modifier_table[T3][s] + base[3]); + + l0 = basisu::minimum(l0, (basisu::iabs(v0 - a) << 3) | s); + l1 = basisu::minimum(l1, (basisu::iabs(v1 - a) << 3) | s); + l2 = basisu::minimum(l2, (basisu::iabs(v2 - a) << 3) | s); + l3 = basisu::minimum(l3, (basisu::iabs(v3 - a) << 3) | s); + } + } + else if (mul_or == 1) + { + const int a0 = base[0] - a, a1 = base[1] - a, a2 = base[2] - a, a3 = base[3] - a; + + for (uint32_t s = 0; s < 8; s++) + { + const int v0 = g_eac_modifier_table[T0][s] + a0; + const int v1 = g_eac_modifier_table[T1][s] + a1; + const int v2 = g_eac_modifier_table[T2][s] + a2; + const int v3 = g_eac_modifier_table[T3][s] + a3; + + l0 = basisu::minimum(l0, (basisu::iabs(v0) << 3) | s); + l1 = basisu::minimum(l1, (basisu::iabs(v1) << 3) | s); + l2 = basisu::minimum(l2, (basisu::iabs(v2) << 3) | s); + l3 = basisu::minimum(l3, (basisu::iabs(v3) << 3) | s); + } + } + else + { + const int a0 = base[0] - a, a1 = base[1] - a, a2 = base[2] - a, a3 = base[3] - a; + + for (uint32_t s = 0; s < 8; s++) + { + const int v0 = mul[0] * g_eac_modifier_table[T0][s] + a0; + const int v1 = mul[1] * g_eac_modifier_table[T1][s] + a1; + const int v2 = mul[2] * g_eac_modifier_table[T2][s] + a2; + const int v3 = mul[3] * g_eac_modifier_table[T3][s] + a3; + + l0 = basisu::minimum(l0, (basisu::iabs(v0) << 3) | s); + l1 = basisu::minimum(l1, (basisu::iabs(v1) << 3) | s); + l2 = basisu::minimum(l2, (basisu::iabs(v2) << 3) | s); + l3 = basisu::minimum(l3, (basisu::iabs(v3) << 3) | s); + } + } + + sels[0][i] = l0 & 7; + sels[1][i] = l1 & 7; + sels[2][i] = l2 & 7; + sels[3][i] = l3 & 7; + + total_err[0] += basisu::square(l0 >> 3); + total_err[1] += basisu::square(l1 >> 3); + total_err[2] += basisu::square(l2 >> 3); + total_err[3] += basisu::square(l3 >> 3); + } + + uint32_t min_err = total_err[0], min_index = 0; + for (uint32_t i = 1; i < 4; i++) + { + if (total_err[i] < min_err) + { + min_err = total_err[i]; + min_index = i; + } + } + + blk.m_base = base[min_index]; + blk.m_multiplier = mul[min_index]; + blk.m_table = s_tables[min_index]; + + uint64_t packed_sels = 0; + const uint8_t* pSels = &sels[min_index][0]; + for (uint32_t i = 0; i < 16; i++) + packed_sels |= (static_cast(pSels[i]) << s_etc2_eac_bit_ofs[i]); + + blk.set_selector_bits(packed_sels); + } + + // Checks all 16 tables. Around ~2 dB better vs. pack_eac(), ~1.2 dB less than near-optimal. + static void pack_eac_high_quality(eac_block& blk, const uint8_t* pPixels, uint32_t stride) + { + uint32_t min_alpha = 255, max_alpha = 0; + for (uint32_t i = 0; i < 16; i++) + { + const uint32_t a = pPixels[i * stride]; + if (a < min_alpha) min_alpha = a; + if (a > max_alpha) max_alpha = a; + } + + if (min_alpha == max_alpha) + { + pack_eac_solid_block(blk, min_alpha); + return; + } + + const uint32_t alpha_range = max_alpha - min_alpha; + + const uint32_t SINGLE_TABLE_THRESH = 5; + if (alpha_range <= SINGLE_TABLE_THRESH) + { + // If alpha_range <= 5 table 13 is lossless + int base = clamp255((int)max_alpha - 2); + + blk.m_base = base; + blk.m_multiplier = 1; + blk.m_table = 13; + + base -= 3; + + uint64_t packed_sels = 0; + for (uint32_t i = 0; i < 16; i++) + { + const int a = pPixels[i * stride]; + + static const uint8_t s_sels[6] = { 2, 1, 0, 4, 5, 6 }; + + int sel = a - base; + assert(sel >= 0 && sel <= 5); + + packed_sels |= (static_cast(s_sels[sel]) << s_etc2_eac_bit_ofs[i]); + } + + blk.set_selector_bits(packed_sels); + + return; + } + + int base[16], mul[16]; + for (uint32_t table = 0; table < 16; table++) + { + const float range = (float)(g_eac_modifier_table[table][ETC2_EAC_MAX_VALUE_SELECTOR] - g_eac_modifier_table[table][ETC2_EAC_MIN_VALUE_SELECTOR]); + + base[table] = clamp255((int)roundf(basisu::lerp((float)min_alpha, (float)max_alpha, (float)(0 - g_eac_modifier_table[table][ETC2_EAC_MIN_VALUE_SELECTOR]) / range))); + mul[table] = clampi((int)roundf(alpha_range / range), 1, 15); + } + + uint32_t total_err[16]; + memset(total_err, 0, sizeof(total_err)); + + uint8_t sels[16][16]; + + for (uint32_t table = 0; table < 16; table++) + { + const int8_t* pTable = &g_eac_modifier_table[table][0]; + const int m = mul[table], b = base[table]; + + uint32_t prev_l = 0, prev_a = UINT32_MAX; + + for (uint32_t i = 0; i < 16; i++) + { + const int a = pPixels[i * stride]; + + if ((uint32_t)a == prev_a) + { + sels[table][i] = prev_l & 7; + total_err[table] += basisu::square(prev_l >> 3); + } + else + { + uint32_t l = basisu::iabs(clamp255(m * pTable[0] + b) - a) << 3; + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[1] + b) - a) << 3) | 1); + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[2] + b) - a) << 3) | 2); + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[3] + b) - a) << 3) | 3); + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[4] + b) - a) << 3) | 4); + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[5] + b) - a) << 3) | 5); + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[6] + b) - a) << 3) | 6); + l = basisu::minimum(l, (basisu::iabs(clamp255(m * pTable[7] + b) - a) << 3) | 7); + + sels[table][i] = l & 7; + total_err[table] += basisu::square(l >> 3); + + prev_l = l; + prev_a = a; + } + } + } + + uint32_t min_err = total_err[0], min_index = 0; + for (uint32_t i = 1; i < 16; i++) + { + if (total_err[i] < min_err) + { + min_err = total_err[i]; + min_index = i; + } + } + + blk.m_base = base[min_index]; + blk.m_multiplier = mul[min_index]; + blk.m_table = min_index; + + uint64_t packed_sels = 0; + const uint8_t* pSels = &sels[min_index][0]; + for (uint32_t i = 0; i < 16; i++) + packed_sels |= (static_cast(pSels[i]) << s_etc2_eac_bit_ofs[i]); + + blk.set_selector_bits(packed_sels); + } + + bool transcode_uastc_to_etc2_eac_r11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + const uint32_t mode = unpacked_src_blk.m_mode; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + pack_eac_solid_block(*static_cast(pDst), unpacked_src_blk.m_solid_color.c[chan0]); + return true; + } + + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + if (chan0 == 3) + transcode_uastc_to_etc2_eac_a8(unpacked_src_blk, block_pixels, pDst); + else + (high_quality ? pack_eac_high_quality : pack_eac)(*static_cast(pDst), &block_pixels[0][0].c[chan0], sizeof(color32)); + + return true; + } + + bool transcode_uastc_to_etc2_eac_rg11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1) + { + unpacked_uastc_block unpacked_src_blk; + if (!unpack_uastc(src_blk, unpacked_src_blk, false)) + return false; + + const uint32_t mode = unpacked_src_blk.m_mode; + + if (mode == UASTC_MODE_INDEX_SOLID_COLOR) + { + pack_eac_solid_block(static_cast(pDst)[0], unpacked_src_blk.m_solid_color.c[chan0]); + pack_eac_solid_block(static_cast(pDst)[1], unpacked_src_blk.m_solid_color.c[chan1]); + return true; + } + + color32 block_pixels[4][4]; + const bool unpack_srgb = false; + if (!unpack_uastc(unpacked_src_blk, &block_pixels[0][0], unpack_srgb)) + return false; + + if (chan0 == 3) + transcode_uastc_to_etc2_eac_a8(unpacked_src_blk, block_pixels, &static_cast(pDst)[0]); + else + (high_quality ? pack_eac_high_quality : pack_eac)(static_cast(pDst)[0], &block_pixels[0][0].c[chan0], sizeof(color32)); + + if (chan1 == 3) + transcode_uastc_to_etc2_eac_a8(unpacked_src_blk, block_pixels, &static_cast(pDst)[1]); + else + (high_quality ? pack_eac_high_quality : pack_eac)(static_cast(pDst)[1], &block_pixels[0][0].c[chan1], sizeof(color32)); + return true; + } + + // PVRTC1 + static void fixup_pvrtc1_4_modulation_rgb( + const uastc_block* pSrc_blocks, + const uint32_t* pPVRTC_endpoints, + void* pDst_blocks, + uint32_t num_blocks_x, uint32_t num_blocks_y, bool from_alpha) + { + const uint32_t x_mask = num_blocks_x - 1; + const uint32_t y_mask = num_blocks_y - 1; + const uint32_t x_bits = basisu::total_bits(x_mask); + const uint32_t y_bits = basisu::total_bits(y_mask); + const uint32_t min_bits = basisu::minimum(x_bits, y_bits); + //const uint32_t max_bits = basisu::maximum(x_bits, y_bits); + const uint32_t swizzle_mask = (1 << (min_bits * 2)) - 1; + + uint32_t block_index = 0; + + // really 3x3 + int e0[4][4], e1[4][4]; + + for (int y = 0; y < static_cast(num_blocks_y); y++) + { + const uint32_t* pE_rows[3]; + + for (int ey = 0; ey < 3; ey++) + { + int by = y + ey - 1; + + const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x]; + + pE_rows[ey] = pE; + + for (int ex = 0; ex < 3; ex++) + { + int bx = 0 + ex - 1; + + const uint32_t e = pE[bx & x_mask]; + + e0[ex][ey] = (get_opaque_endpoint_l0(e) * 255) / 31; + e1[ex][ey] = (get_opaque_endpoint_l1(e) * 255) / 31; + } + } + + const uint32_t y_swizzle = (g_pvrtc_swizzle_table[y >> 8] << 16) | g_pvrtc_swizzle_table[y & 0xFF]; + + for (int x = 0; x < static_cast(num_blocks_x); x++, block_index++) + { + const uastc_block& src_block = pSrc_blocks[block_index]; + + color32 block_pixels[4][4]; + unpack_uastc(src_block, &block_pixels[0][0], false); + if (from_alpha) + { + // Just set RGB to alpha to avoid adding complexity below. + for (uint32_t i = 0; i < 16; i++) + { + const uint8_t a = ((color32*)block_pixels)[i].a; + ((color32*)block_pixels)[i].set(a, a, a, 255); + } + } + + const uint32_t x_swizzle = (g_pvrtc_swizzle_table[x >> 8] << 17) | (g_pvrtc_swizzle_table[x & 0xFF] << 1); + + uint32_t swizzled = x_swizzle | y_swizzle; + if (num_blocks_x != num_blocks_y) + { + swizzled &= swizzle_mask; + + if (num_blocks_x > num_blocks_y) + swizzled |= ((x >> min_bits) << (min_bits * 2)); + else + swizzled |= ((y >> min_bits) << (min_bits * 2)); + } + + pvrtc4_block* pDst_block = static_cast(pDst_blocks) + swizzled; + pDst_block->m_endpoints = pPVRTC_endpoints[block_index]; + + { + const uint32_t ex = 2; + int bx = x + ex - 1; + bx &= x_mask; + +#define DO_ROW(ey) \ + { \ + const uint32_t e = pE_rows[ey][bx]; \ + e0[ex][ey] = (get_opaque_endpoint_l0(e) * 255) / 31; \ + e1[ex][ey] = (get_opaque_endpoint_l1(e) * 255) / 31; \ + } + + DO_ROW(0); + DO_ROW(1); + DO_ROW(2); +#undef DO_ROW + } + + uint32_t mod = 0; + +#define DO_PIX(lx, ly, w0, w1, w2, w3) \ + { \ + int ca_l = a0 * w0 + a1 * w1 + a2 * w2 + a3 * w3; \ + int cb_l = b0 * w0 + b1 * w1 + b2 * w2 + b3 * w3; \ + int cl = (block_pixels[ly][lx].r + block_pixels[ly][lx].g + block_pixels[ly][lx].b) * 16; \ + int dl = cb_l - ca_l; \ + int vl = cl - ca_l; \ + int p = vl * 16; \ + if (ca_l > cb_l) { p = -p; dl = -dl; } \ + uint32_t m = 0; \ + if (p > 3 * dl) m = (uint32_t)(1 << ((ly) * 8 + (lx) * 2)); \ + if (p > 8 * dl) m = (uint32_t)(2 << ((ly) * 8 + (lx) * 2)); \ + if (p > 13 * dl) m = (uint32_t)(3 << ((ly) * 8 + (lx) * 2)); \ + mod |= m; \ + } + + { + const uint32_t ex = 0, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 0, 4, 4, 4, 4); + DO_PIX(1, 0, 2, 6, 2, 6); + DO_PIX(0, 1, 2, 2, 6, 6); + DO_PIX(1, 1, 1, 3, 3, 9); + } + + { + const uint32_t ex = 1, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 0, 8, 0, 8, 0); + DO_PIX(3, 0, 6, 2, 6, 2); + DO_PIX(2, 1, 4, 0, 12, 0); + DO_PIX(3, 1, 3, 1, 9, 3); + } + + { + const uint32_t ex = 0, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 2, 8, 8, 0, 0); + DO_PIX(1, 2, 4, 12, 0, 0); + DO_PIX(0, 3, 6, 6, 2, 2); + DO_PIX(1, 3, 3, 9, 1, 3); + } + + { + const uint32_t ex = 1, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 2, 16, 0, 0, 0); + DO_PIX(3, 2, 12, 4, 0, 0); + DO_PIX(2, 3, 12, 0, 4, 0); + DO_PIX(3, 3, 9, 3, 3, 1); + } +#undef DO_PIX + + pDst_block->m_modulation = mod; + + e0[0][0] = e0[1][0]; e0[1][0] = e0[2][0]; + e0[0][1] = e0[1][1]; e0[1][1] = e0[2][1]; + e0[0][2] = e0[1][2]; e0[1][2] = e0[2][2]; + + e1[0][0] = e1[1][0]; e1[1][0] = e1[2][0]; + e1[0][1] = e1[1][1]; e1[1][1] = e1[2][1]; + e1[0][2] = e1[1][2]; e1[1][2] = e1[2][2]; + + } // x + } // y + } + + static void fixup_pvrtc1_4_modulation_rgba( + const uastc_block* pSrc_blocks, + const uint32_t* pPVRTC_endpoints, + void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y) + { + const uint32_t x_mask = num_blocks_x - 1; + const uint32_t y_mask = num_blocks_y - 1; + const uint32_t x_bits = basisu::total_bits(x_mask); + const uint32_t y_bits = basisu::total_bits(y_mask); + const uint32_t min_bits = basisu::minimum(x_bits, y_bits); + //const uint32_t max_bits = basisu::maximum(x_bits, y_bits); + const uint32_t swizzle_mask = (1 << (min_bits * 2)) - 1; + + uint32_t block_index = 0; + + // really 3x3 + int e0[4][4], e1[4][4]; + + for (int y = 0; y < static_cast(num_blocks_y); y++) + { + const uint32_t* pE_rows[3]; + + for (int ey = 0; ey < 3; ey++) + { + int by = y + ey - 1; + + const uint32_t* pE = &pPVRTC_endpoints[(by & y_mask) * num_blocks_x]; + + pE_rows[ey] = pE; + + for (int ex = 0; ex < 3; ex++) + { + int bx = 0 + ex - 1; + + const uint32_t e = pE[bx & x_mask]; + + e0[ex][ey] = get_endpoint_l8(e, 0); + e1[ex][ey] = get_endpoint_l8(e, 1); + } + } + + const uint32_t y_swizzle = (g_pvrtc_swizzle_table[y >> 8] << 16) | g_pvrtc_swizzle_table[y & 0xFF]; + + for (int x = 0; x < static_cast(num_blocks_x); x++, block_index++) + { + const uastc_block& src_block = pSrc_blocks[block_index]; + + color32 block_pixels[4][4]; + unpack_uastc(src_block, &block_pixels[0][0], false); + + const uint32_t x_swizzle = (g_pvrtc_swizzle_table[x >> 8] << 17) | (g_pvrtc_swizzle_table[x & 0xFF] << 1); + + uint32_t swizzled = x_swizzle | y_swizzle; + if (num_blocks_x != num_blocks_y) + { + swizzled &= swizzle_mask; + + if (num_blocks_x > num_blocks_y) + swizzled |= ((x >> min_bits) << (min_bits * 2)); + else + swizzled |= ((y >> min_bits) << (min_bits * 2)); + } + + pvrtc4_block* pDst_block = static_cast(pDst_blocks) + swizzled; + pDst_block->m_endpoints = pPVRTC_endpoints[block_index]; + + { + const uint32_t ex = 2; + int bx = x + ex - 1; + bx &= x_mask; + +#define DO_ROW(ey) \ + { \ + const uint32_t e = pE_rows[ey][bx]; \ + e0[ex][ey] = get_endpoint_l8(e, 0); \ + e1[ex][ey] = get_endpoint_l8(e, 1); \ + } + + DO_ROW(0); + DO_ROW(1); + DO_ROW(2); +#undef DO_ROW + } + + uint32_t mod = 0; + +#define DO_PIX(lx, ly, w0, w1, w2, w3) \ + { \ + int ca_l = a0 * w0 + a1 * w1 + a2 * w2 + a3 * w3; \ + int cb_l = b0 * w0 + b1 * w1 + b2 * w2 + b3 * w3; \ + int cl = 16 * (block_pixels[ly][lx].r + block_pixels[ly][lx].g + block_pixels[ly][lx].b + block_pixels[ly][lx].a); \ + int dl = cb_l - ca_l; \ + int vl = cl - ca_l; \ + int p = vl * 16; \ + if (ca_l > cb_l) { p = -p; dl = -dl; } \ + uint32_t m = 0; \ + if (p > 3 * dl) m = (uint32_t)(1 << ((ly) * 8 + (lx) * 2)); \ + if (p > 8 * dl) m = (uint32_t)(2 << ((ly) * 8 + (lx) * 2)); \ + if (p > 13 * dl) m = (uint32_t)(3 << ((ly) * 8 + (lx) * 2)); \ + mod |= m; \ + } + + { + const uint32_t ex = 0, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 0, 4, 4, 4, 4); + DO_PIX(1, 0, 2, 6, 2, 6); + DO_PIX(0, 1, 2, 2, 6, 6); + DO_PIX(1, 1, 1, 3, 3, 9); + } + + { + const uint32_t ex = 1, ey = 0; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 0, 8, 0, 8, 0); + DO_PIX(3, 0, 6, 2, 6, 2); + DO_PIX(2, 1, 4, 0, 12, 0); + DO_PIX(3, 1, 3, 1, 9, 3); + } + + { + const uint32_t ex = 0, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(0, 2, 8, 8, 0, 0); + DO_PIX(1, 2, 4, 12, 0, 0); + DO_PIX(0, 3, 6, 6, 2, 2); + DO_PIX(1, 3, 3, 9, 1, 3); + } + + { + const uint32_t ex = 1, ey = 1; + const int a0 = e0[ex][ey], a1 = e0[ex + 1][ey], a2 = e0[ex][ey + 1], a3 = e0[ex + 1][ey + 1]; + const int b0 = e1[ex][ey], b1 = e1[ex + 1][ey], b2 = e1[ex][ey + 1], b3 = e1[ex + 1][ey + 1]; + DO_PIX(2, 2, 16, 0, 0, 0); + DO_PIX(3, 2, 12, 4, 0, 0); + DO_PIX(2, 3, 12, 0, 4, 0); + DO_PIX(3, 3, 9, 3, 3, 1); + } +#undef DO_PIX + + pDst_block->m_modulation = mod; + + e0[0][0] = e0[1][0]; e0[1][0] = e0[2][0]; + e0[0][1] = e0[1][1]; e0[1][1] = e0[2][1]; + e0[0][2] = e0[1][2]; e0[1][2] = e0[2][2]; + + e1[0][0] = e1[1][0]; e1[1][0] = e1[2][0]; + e1[0][1] = e1[1][1]; e1[1][1] = e1[2][1]; + e1[0][2] = e1[1][2]; e1[1][2] = e1[2][2]; + + } // x + } // y + } + + bool transcode_uastc_to_pvrtc1_4_rgb(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality, bool from_alpha) + { + BASISU_NOTE_UNUSED(high_quality); + + if ((!num_blocks_x) || (!num_blocks_y)) + return false; + + const uint32_t width = num_blocks_x * 4; + const uint32_t height = num_blocks_y * 4; + if (!basisu::is_pow2(width) || !basisu::is_pow2(height)) + return false; + + basisu::vector temp_endpoints(num_blocks_x * num_blocks_y); + + for (uint32_t y = 0; y < num_blocks_y; y++) + { + for (uint32_t x = 0; x < num_blocks_x; x++) + { + color32 block_pixels[16]; + if (!unpack_uastc(pSrc_blocks[x + y * num_blocks_x], block_pixels, false)) + return false; + + // Get block's RGB bounding box + color32 low_color(255, 255, 255, 255), high_color(0, 0, 0, 0); + + if (from_alpha) + { + uint32_t low_a = 255, high_a = 0; + for (uint32_t i = 0; i < 16; i++) + { + low_a = basisu::minimum(low_a, block_pixels[i].a); + high_a = basisu::maximum(high_a, block_pixels[i].a); + } + low_color.set(low_a, low_a, low_a, 255); + high_color.set(high_a, high_a, high_a, 255); + } + else + { + for (uint32_t i = 0; i < 16; i++) + { + low_color = color32::comp_min(low_color, block_pixels[i]); + high_color = color32::comp_max(high_color, block_pixels[i]); + } + } + + // Set PVRTC1 endpoints to floor/ceil of bounding box's coordinates. + pvrtc4_block temp; + temp.set_opaque_endpoint_floor(0, low_color); + temp.set_opaque_endpoint_ceil(1, high_color); + + temp_endpoints[x + y * num_blocks_x] = temp.m_endpoints; + } + } + + fixup_pvrtc1_4_modulation_rgb(pSrc_blocks, &temp_endpoints[0], pDst_blocks, num_blocks_x, num_blocks_y, from_alpha); + + return true; + } + + bool transcode_uastc_to_pvrtc1_4_rgba(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality) + { + BASISU_NOTE_UNUSED(high_quality); + + if ((!num_blocks_x) || (!num_blocks_y)) + return false; + + const uint32_t width = num_blocks_x * 4; + const uint32_t height = num_blocks_y * 4; + if (!basisu::is_pow2(width) || !basisu::is_pow2(height)) + return false; + + basisu::vector temp_endpoints(num_blocks_x * num_blocks_y); + + for (uint32_t y = 0; y < num_blocks_y; y++) + { + for (uint32_t x = 0; x < num_blocks_x; x++) + { + color32 block_pixels[16]; + if (!unpack_uastc(pSrc_blocks[x + y * num_blocks_x], block_pixels, false)) + return false; + + // Get block's RGBA bounding box + color32 low_color(255, 255, 255, 255), high_color(0, 0, 0, 0); + + for (uint32_t i = 0; i < 16; i++) + { + low_color = color32::comp_min(low_color, block_pixels[i]); + high_color = color32::comp_max(high_color, block_pixels[i]); + } + + // Set PVRTC1 endpoints to floor/ceil of bounding box's coordinates. + pvrtc4_block temp; + temp.set_endpoint_floor(0, low_color); + temp.set_endpoint_ceil(1, high_color); + + temp_endpoints[x + y * num_blocks_x] = temp.m_endpoints; + } + } + + fixup_pvrtc1_4_modulation_rgba(pSrc_blocks, &temp_endpoints[0], pDst_blocks, num_blocks_x, num_blocks_y); + + return true; + } + + void uastc_init() + { + for (uint32_t range = 0; range < BC7ENC_TOTAL_ASTC_RANGES; range++) + { + if (!astc_is_valid_endpoint_range(range)) + continue; + + const uint32_t levels = astc_get_levels(range); + + uint32_t vals[256]; + for (uint32_t i = 0; i < levels; i++) + vals[i] = (unquant_astc_endpoint_val(i, range) << 8) | i; + + std::sort(vals, vals + levels); + + for (uint32_t i = 0; i < levels; i++) + { + const uint32_t order = vals[i] & 0xFF; + const uint32_t unq = vals[i] >> 8; + + g_astc_unquant[range][order].m_unquant = (uint8_t)unq; + g_astc_unquant[range][order].m_index = (uint8_t)i; + + } // i + } + + // TODO: Precompute? + // BC7 777.1 + for (int c = 0; c < 256; c++) + { + for (uint32_t lp = 0; lp < 2; lp++) + { + endpoint_err best; + best.m_error = (uint16_t)UINT16_MAX; + + for (uint32_t l = 0; l < 128; l++) + { + const uint32_t low = (l << 1) | lp; + + for (uint32_t h = 0; h < 128; h++) + { + const uint32_t high = (h << 1) | lp; + + const int k = (low * (64 - g_bc7_weights4[BC7ENC_MODE_6_OPTIMAL_INDEX]) + high * g_bc7_weights4[BC7ENC_MODE_6_OPTIMAL_INDEX] + 32) >> 6; + + const int err = (k - c) * (k - c); + if (err < best.m_error) + { + best.m_error = (uint16_t)err; + best.m_lo = (uint8_t)l; + best.m_hi = (uint8_t)h; + } + } // h + } // l + + g_bc7_mode_6_optimal_endpoints[c][lp] = best; + } // lp + + } // c + + // BC7 777 + for (int c = 0; c < 256; c++) + { + endpoint_err best; + best.m_error = (uint16_t)UINT16_MAX; + + for (uint32_t l = 0; l < 128; l++) + { + const uint32_t low = (l << 1) | (l >> 6); + + for (uint32_t h = 0; h < 128; h++) + { + const uint32_t high = (h << 1) | (h >> 6); + + const int k = (low * (64 - g_bc7_weights2[BC7ENC_MODE_5_OPTIMAL_INDEX]) + high * g_bc7_weights2[BC7ENC_MODE_5_OPTIMAL_INDEX] + 32) >> 6; + + const int err = (k - c) * (k - c); + if (err < best.m_error) + { + best.m_error = (uint16_t)err; + best.m_lo = (uint8_t)l; + best.m_hi = (uint8_t)h; + } + } // h + } // l + + g_bc7_mode_5_optimal_endpoints[c] = best; + + } // c + } + +#endif // #if BASISD_SUPPORT_UASTC + +// ------------------------------------------------------------------------------------------------------ +// KTX2 +// ------------------------------------------------------------------------------------------------------ + +#if BASISD_SUPPORT_KTX2 + const uint8_t g_ktx2_file_identifier[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A }; + + ktx2_transcoder::ktx2_transcoder() : + m_etc1s_transcoder() + { + clear(); + } + + void ktx2_transcoder::clear() + { + m_pData = nullptr; + m_data_size = 0; + + memset(&m_header, 0, sizeof(m_header)); + m_levels.clear(); + m_dfd.clear(); + m_key_values.clear(); + memset(&m_etc1s_header, 0, sizeof(m_etc1s_header)); + m_etc1s_image_descs.clear(); + + m_format = basist::basis_tex_format::cETC1S; + + m_dfd_color_model = 0; + m_dfd_color_prims = KTX2_DF_PRIMARIES_UNSPECIFIED; + m_dfd_transfer_func = 0; + m_dfd_flags = 0; + m_dfd_samples = 0; + m_dfd_chan0 = KTX2_DF_CHANNEL_UASTC_RGB; + m_dfd_chan1 = KTX2_DF_CHANNEL_UASTC_RGB; + + m_etc1s_transcoder.clear(); + + m_def_transcoder_state.clear(); + + m_has_alpha = false; + m_is_video = false; + } + + bool ktx2_transcoder::init(const void* pData, uint32_t data_size) + { + clear(); + + if (!pData) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: pData is nullptr\n"); + assert(0); + return false; + } + + if (data_size <= sizeof(ktx2_header)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: File is impossibly too small to be a valid KTX2 file\n"); + return false; + } + + if (memcmp(pData, g_ktx2_file_identifier, sizeof(g_ktx2_file_identifier)) != 0) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: KTX2 file identifier is not present\n"); + return false; + } + + m_pData = static_cast(pData); + m_data_size = data_size; + + memcpy(&m_header, pData, sizeof(m_header)); + + // We only support UASTC and ETC1S + if (m_header.m_vk_format != KTX2_VK_FORMAT_UNDEFINED) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: KTX2 file must be in ETC1S or UASTC format\n"); + return false; + } + + // 3.3: "When format is VK_FORMAT_UNDEFINED, typeSize must equal 1." + if (m_header.m_type_size != 1) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid type_size\n"); + return false; + } + + // We only currently support 2D textures (plain, cubemapped, or texture array), which is by far the most common use case. + // The BasisU library does not support 1D or 3D textures at all. + if ((m_header.m_pixel_width < 1) || (m_header.m_pixel_height < 1) || (m_header.m_pixel_depth > 0)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Only 2D or cubemap textures are supported\n"); + return false; + } + + // Face count must be 1 or 6 + if ((m_header.m_face_count != 1) && (m_header.m_face_count != 6)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid face count, file is corrupted or invalid\n"); + return false; + } + + if (m_header.m_face_count > 1) + { + // 3.4: Make sure cubemaps are square. + if (m_header.m_pixel_width != m_header.m_pixel_height) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Cubemap is not square\n"); + return false; + } + } + + // 3.7 levelCount: "levelCount=0 is allowed, except for block-compressed formats" + if (m_header.m_level_count < 1) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid level count\n"); + return false; + } + + // Sanity check the level count. + if (m_header.m_level_count > KTX2_MAX_SUPPORTED_LEVEL_COUNT) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Too many levels or file is corrupted or invalid\n"); + return false; + } + + if (m_header.m_supercompression_scheme > KTX2_SS_ZSTANDARD) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid/unsupported supercompression or file is corrupted or invalid\n"); + return false; + } + + if (m_header.m_supercompression_scheme == KTX2_SS_BASISLZ) + { + if (m_header.m_sgd_byte_length <= sizeof(ktx2_etc1s_global_data_header)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Supercompression global data is too small\n"); + return false; + } + + if (m_header.m_sgd_byte_offset < sizeof(ktx2_header)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Supercompression global data offset is too low\n"); + return false; + } + + if (m_header.m_sgd_byte_offset + m_header.m_sgd_byte_length > m_data_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Supercompression global data offset and/or length is too high\n"); + return false; + } + } + + if (!m_levels.try_resize(m_header.m_level_count)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Out of memory\n"); + return false; + } + + const uint32_t level_index_size_in_bytes = basisu::maximum(1U, (uint32_t)m_header.m_level_count) * sizeof(ktx2_level_index); + + if ((sizeof(ktx2_header) + level_index_size_in_bytes) > m_data_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: File is too small (can't read level index array)\n"); + return false; + } + + memcpy(&m_levels[0], m_pData + sizeof(ktx2_header), level_index_size_in_bytes); + + // Sanity check the level offsets and byte sizes + for (uint32_t i = 0; i < m_levels.size(); i++) + { + if (m_levels[i].m_byte_offset < sizeof(ktx2_header)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid level offset (too low)\n"); + return false; + } + + if (!m_levels[i].m_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid level byte length\n"); + } + + if ((m_levels[i].m_byte_offset + m_levels[i].m_byte_length) > m_data_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid level offset and/or length\n"); + return false; + } + + const uint64_t MAX_SANE_LEVEL_UNCOMP_SIZE = 2048ULL * 1024ULL * 1024ULL; + + if (m_levels[i].m_uncompressed_byte_length >= MAX_SANE_LEVEL_UNCOMP_SIZE) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid level offset (too large)\n"); + return false; + } + + if (m_header.m_supercompression_scheme == KTX2_SS_BASISLZ) + { + if (m_levels[i].m_uncompressed_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid uncompressed length (0)\n"); + return false; + } + } + else if (m_header.m_supercompression_scheme >= KTX2_SS_ZSTANDARD) + { + if (!m_levels[i].m_uncompressed_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid uncompressed length (1)\n"); + return false; + } + } + } + + const uint32_t DFD_MINIMUM_SIZE = 44, DFD_MAXIMUM_SIZE = 60; + if ((m_header.m_dfd_byte_length != DFD_MINIMUM_SIZE) && (m_header.m_dfd_byte_length != DFD_MAXIMUM_SIZE)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Unsupported DFD size\n"); + return false; + } + + if (((m_header.m_dfd_byte_offset + m_header.m_dfd_byte_length) > m_data_size) || (m_header.m_dfd_byte_offset < sizeof(ktx2_header))) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid DFD offset and/or length\n"); + return false; + } + + const uint8_t* pDFD = m_pData + m_header.m_dfd_byte_offset; + + if (!m_dfd.try_resize(m_header.m_dfd_byte_length)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Out of memory\n"); + return false; + } + + memcpy(m_dfd.data(), pDFD, m_header.m_dfd_byte_length); + + // This is all hard coded for only ETC1S and UASTC. + uint32_t dfd_total_size = basisu::read_le_dword(pDFD); + + // 3.10.3: Sanity check + if (dfd_total_size != m_header.m_dfd_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: DFD size validation failed (1)\n"); + return false; + } + + // 3.10.3: More sanity checking + if (m_header.m_kvd_byte_length) + { + if (dfd_total_size != m_header.m_kvd_byte_offset - m_header.m_dfd_byte_offset) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: DFD size validation failed (2)\n"); + return false; + } + } + + const uint32_t dfd_bits = basisu::read_le_dword(pDFD + 3 * sizeof(uint32_t)); + const uint32_t sample_channel0 = basisu::read_le_dword(pDFD + 7 * sizeof(uint32_t)); + + m_dfd_color_model = dfd_bits & 255; + m_dfd_color_prims = (ktx2_df_color_primaries)((dfd_bits >> 8) & 255); + m_dfd_transfer_func = (dfd_bits >> 16) & 255; + m_dfd_flags = (dfd_bits >> 24) & 255; + + // See 3.10.1.Restrictions + if ((m_dfd_transfer_func != KTX2_KHR_DF_TRANSFER_LINEAR) && (m_dfd_transfer_func != KTX2_KHR_DF_TRANSFER_SRGB)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Invalid DFD transfer function\n"); + return false; + } + + if (m_dfd_color_model == KTX2_KDF_DF_MODEL_ETC1S) + { + m_format = basist::basis_tex_format::cETC1S; + + // 3.10.2: "Whether the image has 1 or 2 slices can be determined from the DFD's sample count." + // If m_has_alpha is true it may be 2-channel RRRG or 4-channel RGBA, but we let the caller deal with that. + m_has_alpha = (m_header.m_dfd_byte_length == 60); + + m_dfd_samples = m_has_alpha ? 2 : 1; + m_dfd_chan0 = (ktx2_df_channel_id)((sample_channel0 >> 24) & 15); + + if (m_has_alpha) + { + const uint32_t sample_channel1 = basisu::read_le_dword(pDFD + 11 * sizeof(uint32_t)); + m_dfd_chan1 = (ktx2_df_channel_id)((sample_channel1 >> 24) & 15); + } + } + else if (m_dfd_color_model == KTX2_KDF_DF_MODEL_UASTC) + { + m_format = basist::basis_tex_format::cUASTC4x4; + + m_dfd_samples = 1; + m_dfd_chan0 = (ktx2_df_channel_id)((sample_channel0 >> 24) & 15); + + // We're assuming "DATA" means RGBA so it has alpha. + m_has_alpha = (m_dfd_chan0 == KTX2_DF_CHANNEL_UASTC_RGBA) || (m_dfd_chan0 == KTX2_DF_CHANNEL_UASTC_RRRG); + } + else + { + // Unsupported DFD color model. + BASISU_DEVEL_ERROR("ktx2_transcoder::init: Unsupported DFD color model\n"); + return false; + } + + if (!read_key_values()) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::init: read_key_values() failed\n"); + return false; + } + + // Check for a KTXanimData key + for (uint32_t i = 0; i < m_key_values.size(); i++) + { + if (strcmp(reinterpret_cast(m_key_values[i].m_key.data()), "KTXanimData") == 0) + { + m_is_video = true; + break; + } + } + + return true; + } + + uint32_t ktx2_transcoder::get_etc1s_image_descs_image_flags(uint32_t level_index, uint32_t layer_index, uint32_t face_index) const + { + const uint32_t etc1s_image_index = + (level_index * basisu::maximum(m_header.m_layer_count, 1) * m_header.m_face_count) + + layer_index * m_header.m_face_count + + face_index; + + if (etc1s_image_index >= get_etc1s_image_descs().size()) + { + assert(0); + return 0; + } + + return get_etc1s_image_descs()[etc1s_image_index].m_image_flags; + } + + const basisu::uint8_vec* ktx2_transcoder::find_key(const std::string& key_name) const + { + for (uint32_t i = 0; i < m_key_values.size(); i++) + if (strcmp((const char *)m_key_values[i].m_key.data(), key_name.c_str()) == 0) + return &m_key_values[i].m_value; + + return nullptr; + } + + bool ktx2_transcoder::start_transcoding() + { + if (!m_pData) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::start_transcoding: Must call init() first\n"); + return false; + } + + if (m_header.m_supercompression_scheme == KTX2_SS_BASISLZ) + { + // Check if we've already decompressed the ETC1S global data. If so don't unpack it again. + if (!m_etc1s_transcoder.get_endpoints().empty()) + return true; + + if (!decompress_etc1s_global_data()) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::start_transcoding: decompress_etc1s_global_data() failed\n"); + return false; + } + + if (!m_is_video) + { + // See if there are any P-frames. If so it must be a video, even if there wasn't a KTXanimData key. + // Video cannot be a cubemap, and it must be a texture array. + if ((m_header.m_face_count == 1) && (m_header.m_layer_count > 1)) + { + for (uint32_t i = 0; i < m_etc1s_image_descs.size(); i++) + { + if (m_etc1s_image_descs[i].m_image_flags & KTX2_IMAGE_IS_P_FRAME) + { + m_is_video = true; + break; + } + } + } + } + } + else if (m_header.m_supercompression_scheme == KTX2_SS_ZSTANDARD) + { +#if !BASISD_SUPPORT_KTX2_ZSTD + BASISU_DEVEL_ERROR("ktx2_transcoder::start_transcoding: File uses zstd supercompression, but zstd support was not enabled at compilation time (BASISD_SUPPORT_KTX2_ZSTD == 0)\n"); + return false; +#endif + } + + return true; + } + + bool ktx2_transcoder::get_image_level_info(ktx2_image_level_info& level_info, uint32_t level_index, uint32_t layer_index, uint32_t face_index) const + { + if (level_index >= m_levels.size()) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::get_image_level_info: level_index >= m_levels.size()\n"); + return false; + } + + if (m_header.m_face_count > 1) + { + if (face_index >= 6) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::get_image_level_info: face_index >= 6\n"); + return false; + } + } + else if (face_index != 0) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::get_image_level_info: face_index != 0\n"); + return false; + } + + if (layer_index >= basisu::maximum(m_header.m_layer_count, 1)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::get_image_level_info: layer_index >= maximum(m_header.m_layer_count, 1)\n"); + return false; + } + + const uint32_t level_width = basisu::maximum(m_header.m_pixel_width >> level_index, 1); + const uint32_t level_height = basisu::maximum(m_header.m_pixel_height >> level_index, 1); + const uint32_t num_blocks_x = (level_width + 3) >> 2; + const uint32_t num_blocks_y = (level_height + 3) >> 2; + + level_info.m_face_index = face_index; + level_info.m_layer_index = layer_index; + level_info.m_level_index = level_index; + level_info.m_orig_width = level_width; + level_info.m_orig_height = level_height; + level_info.m_width = num_blocks_x * 4; + level_info.m_height = num_blocks_y * 4; + level_info.m_num_blocks_x = num_blocks_x; + level_info.m_num_blocks_y = num_blocks_y; + level_info.m_total_blocks = num_blocks_x * num_blocks_y; + level_info.m_alpha_flag = m_has_alpha; + level_info.m_iframe_flag = false; + if (m_etc1s_image_descs.size()) + { + const uint32_t etc1s_image_index = + (level_index * basisu::maximum(m_header.m_layer_count, 1) * m_header.m_face_count) + + layer_index * m_header.m_face_count + + face_index; + + level_info.m_iframe_flag = (m_etc1s_image_descs[etc1s_image_index].m_image_flags & KTX2_IMAGE_IS_P_FRAME) == 0; + } + + return true; + } + + bool ktx2_transcoder::transcode_image_level( + uint32_t level_index, uint32_t layer_index, uint32_t face_index, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + basist::transcoder_texture_format fmt, + uint32_t decode_flags, uint32_t output_row_pitch_in_blocks_or_pixels, uint32_t output_rows_in_pixels, int channel0, int channel1, + ktx2_transcoder_state* pState) + { + if (!m_pData) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: Must call init() first\n"); + return false; + } + + if (!pState) + pState = &m_def_transcoder_state; + + if (level_index >= m_levels.size()) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: level_index >= m_levels.size()\n"); + return false; + } + + if (m_header.m_face_count > 1) + { + if (face_index >= 6) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: face_index >= 6\n"); + return false; + } + } + else if (face_index != 0) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: face_index != 0\n"); + return false; + } + + if (layer_index >= basisu::maximum(m_header.m_layer_count, 1)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: layer_index >= maximum(m_header.m_layer_count, 1)\n"); + return false; + } + + const uint8_t* pComp_level_data = m_pData + m_levels[level_index].m_byte_offset; + uint64_t comp_level_data_size = m_levels[level_index].m_byte_length; + + const uint8_t* pUncomp_level_data = pComp_level_data; + uint64_t uncomp_level_data_size = comp_level_data_size; + + if (uncomp_level_data_size > UINT32_MAX) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: uncomp_level_data_size > UINT32_MAX\n"); + return false; + } + + if (m_header.m_supercompression_scheme == KTX2_SS_ZSTANDARD) + { + // Check if we've already decompressed this level's supercompressed data. + if ((int)level_index != pState->m_uncomp_data_level_index) + { + // Uncompress the entire level's supercompressed data. + if (!decompress_level_data(level_index, pState->m_level_uncomp_data)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: decompress_level_data() failed\n"); + return false; + } + pState->m_uncomp_data_level_index = level_index; + } + + pUncomp_level_data = pState->m_level_uncomp_data.data(); + uncomp_level_data_size = pState->m_level_uncomp_data.size(); + } + + const uint32_t level_width = basisu::maximum(m_header.m_pixel_width >> level_index, 1); + const uint32_t level_height = basisu::maximum(m_header.m_pixel_height >> level_index, 1); + const uint32_t num_blocks_x = (level_width + 3) >> 2; + const uint32_t num_blocks_y = (level_height + 3) >> 2; + + if (m_format == basist::basis_tex_format::cETC1S) + { + // Ensure start_transcoding() was called. + if (m_etc1s_transcoder.get_endpoints().empty()) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: must call start_transcoding() first\n"); + return false; + } + + const uint32_t etc1s_image_index = + (level_index * basisu::maximum(m_header.m_layer_count, 1) * m_header.m_face_count) + + layer_index * m_header.m_face_count + + face_index; + + // Sanity check + if (etc1s_image_index >= m_etc1s_image_descs.size()) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: etc1s_image_index >= m_etc1s_image_descs.size()\n"); + assert(0); + return false; + } + + if (static_cast(m_data_size) != m_data_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: File is too large\n"); + return false; + } + + const ktx2_etc1s_image_desc& image_desc = m_etc1s_image_descs[etc1s_image_index]; + + if (!m_etc1s_transcoder.transcode_image(fmt, + pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, m_pData, static_cast(m_data_size), + num_blocks_x, num_blocks_y, level_width, level_height, + level_index, + m_levels[level_index].m_byte_offset + image_desc.m_rgb_slice_byte_offset, image_desc.m_rgb_slice_byte_length, + image_desc.m_alpha_slice_byte_length ? (m_levels[level_index].m_byte_offset + image_desc.m_alpha_slice_byte_offset) : 0, image_desc.m_alpha_slice_byte_length, + decode_flags, m_has_alpha, + m_is_video, output_row_pitch_in_blocks_or_pixels, &pState->m_transcoder_state, output_rows_in_pixels)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: ETC1S transcode_image() failed, this is either a bug or the file is corrupted/invalid\n"); + return false; + } + } + else if (m_format == basist::basis_tex_format::cUASTC4x4) + { + // Compute length and offset to uncompressed 2D UASTC texture data, given the face/layer indices. + assert(uncomp_level_data_size == m_levels[level_index].m_uncompressed_byte_length); + const uint32_t total_2D_image_size = num_blocks_x * num_blocks_y * KTX2_UASTC_BLOCK_SIZE; + + const uint32_t uncomp_ofs = (layer_index * m_header.m_face_count + face_index) * total_2D_image_size; + + // Sanity checks + if (uncomp_ofs >= uncomp_level_data_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: uncomp_ofs >= total_2D_image_size\n"); + return false; + } + + if ((uncomp_level_data_size - uncomp_ofs) < total_2D_image_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: (uncomp_level_data_size - uncomp_ofs) < total_2D_image_size\n"); + return false; + } + + if (!m_uastc_transcoder.transcode_image(fmt, + pOutput_blocks, output_blocks_buf_size_in_blocks_or_pixels, + (const uint8_t*)pUncomp_level_data + uncomp_ofs, (uint32_t)total_2D_image_size, num_blocks_x, num_blocks_y, level_width, level_height, level_index, + 0, (uint32_t)total_2D_image_size, + decode_flags, m_has_alpha, m_is_video, output_row_pitch_in_blocks_or_pixels, nullptr, output_rows_in_pixels, channel0, channel1)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: UASTC transcode_image() failed, this is either a bug or the file is corrupted/invalid\n"); + return false; + } + } + else + { + // Shouldn't get here. + BASISU_DEVEL_ERROR("ktx2_transcoder::transcode_image_2D: Internal error\n"); + assert(0); + return false; + } + + return true; + } + + bool ktx2_transcoder::decompress_level_data(uint32_t level_index, basisu::uint8_vec& uncomp_data) + { + const uint8_t* pComp_data = m_levels[level_index].m_byte_offset + m_pData; + const uint64_t comp_size = m_levels[level_index].m_byte_length; + + const uint64_t uncomp_size = m_levels[level_index].m_uncompressed_byte_length; + + if (((size_t)comp_size) != comp_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Compressed data too large\n"); + return false; + } + if (((size_t)uncomp_size) != uncomp_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Uncompressed data too large\n"); + return false; + } + + if (!uncomp_data.try_resize((size_t)uncomp_size)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Out of memory\n"); + return false; + } + + if (m_header.m_supercompression_scheme == KTX2_SS_ZSTANDARD) + { +#if BASISD_SUPPORT_KTX2_ZSTD + size_t actualUncompSize = ZSTD_decompress(uncomp_data.data(), (size_t)uncomp_size, pComp_data, (size_t)comp_size); + if (ZSTD_isError(actualUncompSize)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Zstd decompression failed, file is invalid or corrupted\n"); + return false; + } + if (actualUncompSize != uncomp_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: Zstd decompression returned too few bytes, file is invalid or corrupted\n"); + return false; + } +#else + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: File uses Zstd supercompression, but Zstd support was not enabled at compile time (BASISD_SUPPORT_KTX2_ZSTD is 0)\n"); + return false; +#endif + } + + return true; + } + + bool ktx2_transcoder::decompress_etc1s_global_data() + { + // Note: we don't actually support 3D textures in here yet + //uint32_t layer_pixel_depth = basisu::maximum(m_header.m_pixel_depth, 1); + //for (uint32_t i = 1; i < m_header.m_level_count; i++) + // layer_pixel_depth += basisu::maximum(m_header.m_pixel_depth >> i, 1); + + const uint32_t image_count = basisu::maximum(m_header.m_layer_count, 1) * m_header.m_face_count * m_header.m_level_count; + assert(image_count); + + const uint8_t* pSrc = m_pData + m_header.m_sgd_byte_offset; + + memcpy(&m_etc1s_header, pSrc, sizeof(ktx2_etc1s_global_data_header)); + pSrc += sizeof(ktx2_etc1s_global_data_header); + + if ((!m_etc1s_header.m_endpoints_byte_length) || (!m_etc1s_header.m_selectors_byte_length) || (!m_etc1s_header.m_tables_byte_length)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: Invalid ETC1S global data\n"); + return false; + } + + if ((!m_etc1s_header.m_endpoint_count) || (!m_etc1s_header.m_selector_count)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: endpoint and/or selector count is 0, file is invalid or corrupted\n"); + return false; + } + + // Sanity check the ETC1S header. + if ((sizeof(ktx2_etc1s_global_data_header) + + sizeof(ktx2_etc1s_image_desc) * image_count + + m_etc1s_header.m_endpoints_byte_length + + m_etc1s_header.m_selectors_byte_length + + m_etc1s_header.m_tables_byte_length + + m_etc1s_header.m_extended_byte_length) > m_header.m_sgd_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: SGD byte length is too small, file is invalid or corrupted\n"); + return false; + } + + if (!m_etc1s_image_descs.try_resize(image_count)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: Out of memory\n"); + return false; + } + + memcpy(m_etc1s_image_descs.data(), pSrc, sizeof(ktx2_etc1s_image_desc) * image_count); + pSrc += sizeof(ktx2_etc1s_image_desc) * image_count; + + // Sanity check the ETC1S image descs + for (uint32_t i = 0; i < image_count; i++) + { + // m_etc1s_transcoder.transcode_image() will validate the slice offsets/lengths before transcoding. + + if (!m_etc1s_image_descs[i].m_rgb_slice_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: ETC1S image descs sanity check failed (1)\n"); + return false; + } + + if (m_has_alpha) + { + if (!m_etc1s_image_descs[i].m_alpha_slice_byte_length) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: ETC1S image descs sanity check failed (2)\n"); + return false; + } + } + } + + const uint8_t* pEndpoint_data = pSrc; + const uint8_t* pSelector_data = pSrc + m_etc1s_header.m_endpoints_byte_length; + const uint8_t* pTables_data = pSrc + m_etc1s_header.m_endpoints_byte_length + m_etc1s_header.m_selectors_byte_length; + + if (!m_etc1s_transcoder.decode_tables(pTables_data, m_etc1s_header.m_tables_byte_length)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: decode_tables() failed, file is invalid or corrupted\n"); + return false; + } + + if (!m_etc1s_transcoder.decode_palettes( + m_etc1s_header.m_endpoint_count, pEndpoint_data, m_etc1s_header.m_endpoints_byte_length, + m_etc1s_header.m_selector_count, pSelector_data, m_etc1s_header.m_selectors_byte_length)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_etc1s_global_data: decode_palettes() failed, file is likely corrupted\n"); + return false; + } + + return true; + } + + bool ktx2_transcoder::read_key_values() + { + if (!m_header.m_kvd_byte_length) + { + if (m_header.m_kvd_byte_offset) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Invalid KVD byte offset (it should be zero when the length is zero)\n"); + return false; + } + + return true; + } + + if (m_header.m_kvd_byte_offset < sizeof(ktx2_header)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Invalid KVD byte offset\n"); + return false; + } + + if ((m_header.m_kvd_byte_offset + m_header.m_kvd_byte_length) > m_data_size) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Invalid KVD byte offset and/or length\n"); + return false; + } + + const uint8_t* pSrc = m_pData + m_header.m_kvd_byte_offset; + uint32_t src_left = m_header.m_kvd_byte_length; + + if (!m_key_values.try_reserve(8)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Out of memory\n"); + return false; + } + + while (src_left > sizeof(uint32_t)) + { + uint32_t l = basisu::read_le_dword(pSrc); + + pSrc += sizeof(uint32_t); + src_left -= sizeof(uint32_t); + + if (l < 2) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Failed reading key value fields (0)\n"); + return false; + } + + if (src_left < l) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Failed reading key value fields (1)\n"); + return false; + } + + if (!m_key_values.try_resize(m_key_values.size() + 1)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Out of memory\n"); + return false; + } + + basisu::uint8_vec& key_data = m_key_values.back().m_key; + basisu::uint8_vec& value_data = m_key_values.back().m_value; + + do + { + if (!l) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Failed reading key value fields (2)\n"); + return false; + } + + if (!key_data.try_push_back(*pSrc++)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Out of memory\n"); + return false; + } + + src_left--; + l--; + + } while (key_data.back()); + + if (!value_data.try_resize(l)) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Out of memory\n"); + return false; + } + + if (l) + { + memcpy(value_data.data(), pSrc, l); + pSrc += l; + src_left -= l; + } + + uint32_t ofs = (uint32_t)(pSrc - m_pData) & 3; + uint32_t alignment_bytes = (4 - ofs) & 3; + + if (src_left < alignment_bytes) + { + BASISU_DEVEL_ERROR("ktx2_transcoder::read_key_values: Failed reading key value fields (3)\n"); + return false; + } + + pSrc += alignment_bytes; + src_left -= alignment_bytes; + } + + return true; + } + +#endif // BASISD_SUPPORT_KTX2 + + bool basisu_transcoder_supports_ktx2() + { +#if BASISD_SUPPORT_KTX2 + return true; +#else + return false; +#endif + } + + bool basisu_transcoder_supports_ktx2_zstd() + { +#if BASISD_SUPPORT_KTX2_ZSTD + return true; +#else + return false; +#endif + } + +} // namespace basist diff --git a/ext/basis_universal/basisu_transcoder.h b/ext/basis_universal/basisu_transcoder.h new file mode 100644 index 0000000000..3327e8ddb7 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder.h @@ -0,0 +1,936 @@ +// basisu_transcoder.h +// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved. +// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +// By default KTX2 support is enabled to simplify compilation. This implies the need for the Zstandard library (which we distribute as a single source file in the "zstd" directory) by default. +// Set BASISD_SUPPORT_KTX2 to 0 to completely disable KTX2 support as well as Zstd/miniz usage which is only required for UASTC supercompression in KTX2 files. +// Also see BASISD_SUPPORT_KTX2_ZSTD in basisu_transcoder.cpp, which individually disables Zstd usage. +#ifndef BASISD_SUPPORT_KTX2 + #define BASISD_SUPPORT_KTX2 1 +#endif + +// Set BASISD_SUPPORT_KTX2_ZSTD to 0 to disable Zstd usage and KTX2 UASTC Zstd supercompression support +#ifndef BASISD_SUPPORT_KTX2_ZSTD + #define BASISD_SUPPORT_KTX2_ZSTD 1 +#endif + +// Set BASISU_FORCE_DEVEL_MESSAGES to 1 to enable debug printf()'s whenever an error occurs, for easier debugging during development. +#ifndef BASISU_FORCE_DEVEL_MESSAGES + #define BASISU_FORCE_DEVEL_MESSAGES 0 +#endif + +#include "basisu_transcoder_internal.h" +#include "basisu_transcoder_uastc.h" +#include "basisu_file_headers.h" + +namespace basist +{ + // High-level composite texture formats supported by the transcoder. + // Each of these texture formats directly correspond to OpenGL/D3D/Vulkan etc. texture formats. + // Notes: + // - If you specify a texture format that supports alpha, but the .basis file doesn't have alpha, the transcoder will automatically output a + // fully opaque (255) alpha channel. + // - The PVRTC1 texture formats only support power of 2 dimension .basis files, but this may be relaxed in a future version. + // - The PVRTC1 transcoders are real-time encoders, so don't expect the highest quality. We may add a slower encoder with improved quality. + // - These enums must be kept in sync with Javascript code that calls the transcoder. + enum class transcoder_texture_format + { + // Compressed formats + + // ETC1-2 + cTFETC1_RGB = 0, // Opaque only, returns RGB or alpha data if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified + cTFETC2_RGBA = 1, // Opaque+alpha, ETC2_EAC_A8 block followed by a ETC1 block, alpha channel will be opaque for opaque .basis files + + // BC1-5, BC7 (desktop, some mobile devices) + cTFBC1_RGB = 2, // Opaque only, no punchthrough alpha support yet, transcodes alpha slice if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified + cTFBC3_RGBA = 3, // Opaque+alpha, BC4 followed by a BC1 block, alpha channel will be opaque for opaque .basis files + cTFBC4_R = 4, // Red only, alpha slice is transcoded to output if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified + cTFBC5_RG = 5, // XY: Two BC4 blocks, X=R and Y=Alpha, .basis file should have alpha data (if not Y will be all 255's) + cTFBC7_RGBA = 6, // RGB or RGBA, mode 5 for ETC1S, modes (1,2,3,5,6,7) for UASTC + + // PVRTC1 4bpp (mobile, PowerVR devices) + cTFPVRTC1_4_RGB = 8, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified, nearly lowest quality of any texture format. + cTFPVRTC1_4_RGBA = 9, // Opaque+alpha, most useful for simple opacity maps. If .basis file doesn't have alpha cTFPVRTC1_4_RGB will be used instead. Lowest quality of any supported texture format. + + // ASTC (mobile, Intel devices, hopefully all desktop GPU's one day) + cTFASTC_4x4_RGBA = 10, // Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files. Transcoder uses RGB/RGBA/L/LA modes, void extent, and up to two ([0,47] and [0,255]) endpoint precisions. + + // ATC (mobile, Adreno devices, this is a niche format) + cTFATC_RGB = 11, // Opaque, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. ATI ATC (GL_ATC_RGB_AMD) + cTFATC_RGBA = 12, // Opaque+alpha, alpha channel will be opaque for opaque .basis files. ATI ATC (GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD) + + // FXT1 (desktop, Intel devices, this is a super obscure format) + cTFFXT1_RGB = 17, // Opaque only, uses exclusively CC_MIXED blocks. Notable for having a 8x4 block size. GL_3DFX_texture_compression_FXT1 is supported on Intel integrated GPU's (such as HD 630). + // Punch-through alpha is relatively easy to support, but full alpha is harder. This format is only here for completeness so opaque-only is fine for now. + // See the BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING macro in basisu_transcoder_internal.h. + + cTFPVRTC2_4_RGB = 18, // Opaque-only, almost BC1 quality, much faster to transcode and supports arbitrary texture dimensions (unlike PVRTC1 RGB). + cTFPVRTC2_4_RGBA = 19, // Opaque+alpha, slower to encode than cTFPVRTC2_4_RGB. Premultiplied alpha is highly recommended, otherwise the color channel can leak into the alpha channel on transparent blocks. + + cTFETC2_EAC_R11 = 20, // R only (ETC2 EAC R11 unsigned) + cTFETC2_EAC_RG11 = 21, // RG only (ETC2 EAC RG11 unsigned), R=opaque.r, G=alpha - for tangent space normal maps + + // Uncompressed (raw pixel) formats + cTFRGBA32 = 13, // 32bpp RGBA image stored in raster (not block) order in memory, R is first byte, A is last byte. + cTFRGB565 = 14, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 11 + cTFBGR565 = 15, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 0 + cTFRGBA4444 = 16, // 16bpp RGBA image stored in raster (not block) order in memory, R at bit position 12, A at bit position 0 + + cTFTotalTextureFormats = 22, + + // Old enums for compatibility with code compiled against previous versions + cTFETC1 = cTFETC1_RGB, + cTFETC2 = cTFETC2_RGBA, + cTFBC1 = cTFBC1_RGB, + cTFBC3 = cTFBC3_RGBA, + cTFBC4 = cTFBC4_R, + cTFBC5 = cTFBC5_RG, + + // Previously, the caller had some control over which BC7 mode the transcoder output. We've simplified this due to UASTC, which supports numerous modes. + cTFBC7_M6_RGB = cTFBC7_RGBA, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. Highest quality of all the non-ETC1 formats. + cTFBC7_M5_RGBA = cTFBC7_RGBA, // Opaque+alpha, alpha channel will be opaque for opaque .basis files + cTFBC7_M6_OPAQUE_ONLY = cTFBC7_RGBA, + cTFBC7_M5 = cTFBC7_RGBA, + cTFBC7_ALT = 7, + + cTFASTC_4x4 = cTFASTC_4x4_RGBA, + + cTFATC_RGBA_INTERPOLATED_ALPHA = cTFATC_RGBA, + }; + + // For compressed texture formats, this returns the # of bytes per block. For uncompressed, it returns the # of bytes per pixel. + // NOTE: Previously, this function was called basis_get_bytes_per_block(), and it always returned 16*bytes_per_pixel for uncompressed formats which was confusing. + uint32_t basis_get_bytes_per_block_or_pixel(transcoder_texture_format fmt); + + // Returns format's name in ASCII + const char* basis_get_format_name(transcoder_texture_format fmt); + + // Returns block format name in ASCII + const char* basis_get_block_format_name(block_format fmt); + + // Returns true if the format supports an alpha channel. + bool basis_transcoder_format_has_alpha(transcoder_texture_format fmt); + + // Returns the basisu::texture_format corresponding to the specified transcoder_texture_format. + basisu::texture_format basis_get_basisu_texture_format(transcoder_texture_format fmt); + + // Returns the texture type's name in ASCII. + const char* basis_get_texture_type_name(basis_texture_type tex_type); + + // Returns true if the transcoder texture type is an uncompressed (raw pixel) format. + bool basis_transcoder_format_is_uncompressed(transcoder_texture_format tex_type); + + // Returns the # of bytes per pixel for uncompressed formats, or 0 for block texture formats. + uint32_t basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format fmt); + + // Returns the block width for the specified texture format, which is currently either 4 or 8 for FXT1. + uint32_t basis_get_block_width(transcoder_texture_format tex_type); + + // Returns the block height for the specified texture format, which is currently always 4. + uint32_t basis_get_block_height(transcoder_texture_format tex_type); + + // Returns true if the specified format was enabled at compile time. + bool basis_is_format_supported(transcoder_texture_format tex_type, basis_tex_format fmt = basis_tex_format::cETC1S); + + // Validates that the output buffer is large enough to hold the entire transcoded texture. + // For uncompressed texture formats, most input parameters are in pixels, not blocks. Blocks are 4x4 pixels. + bool basis_validate_output_buffer_size(transcoder_texture_format target_format, + uint32_t output_blocks_buf_size_in_blocks_or_pixels, + uint32_t orig_width, uint32_t orig_height, + uint32_t output_row_pitch_in_blocks_or_pixels, + uint32_t output_rows_in_pixels, + uint32_t total_slice_blocks); + + class basisu_transcoder; + + // This struct holds all state used during transcoding. For video, it needs to persist between image transcodes (it holds the previous frame). + // For threading you can use one state per thread. + struct basisu_transcoder_state + { + struct block_preds + { + uint16_t m_endpoint_index; + uint8_t m_pred_bits; + }; + + basisu::vector m_block_endpoint_preds[2]; + + enum { cMaxPrevFrameLevels = 16 }; + basisu::vector m_prev_frame_indices[2][cMaxPrevFrameLevels]; // [alpha_flag][level_index] + + void clear() + { + for (uint32_t i = 0; i < 2; i++) + { + m_block_endpoint_preds[i].clear(); + + for (uint32_t j = 0; j < cMaxPrevFrameLevels; j++) + m_prev_frame_indices[i][j].clear(); + } + } + }; + + // Low-level helper class that does the actual transcoding. + class basisu_lowlevel_etc1s_transcoder + { + friend class basisu_transcoder; + + public: + basisu_lowlevel_etc1s_transcoder(); + + void set_global_codebooks(const basisu_lowlevel_etc1s_transcoder* pGlobal_codebook) { m_pGlobal_codebook = pGlobal_codebook; } + const basisu_lowlevel_etc1s_transcoder* get_global_codebooks() const { return m_pGlobal_codebook; } + + bool decode_palettes( + uint32_t num_endpoints, const uint8_t* pEndpoints_data, uint32_t endpoints_data_size, + uint32_t num_selectors, const uint8_t* pSelectors_data, uint32_t selectors_data_size); + + bool decode_tables(const uint8_t* pTable_data, uint32_t table_data_size); + + bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const bool is_video, const bool is_alpha_slice, const uint32_t level_index, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels = 0, + basisu_transcoder_state* pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0); + + bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0, + basisu_transcoder_state* pState = nullptr, bool astc_transcode_alpha = false, void* pAlpha_blocks = nullptr, uint32_t output_rows_in_pixels = 0) + { + return transcode_slice(pDst_blocks, num_blocks_x, num_blocks_y, pImage_data, image_data_size, fmt, output_block_or_pixel_stride_in_bytes, bc1_allow_threecolor_blocks, + header.m_tex_type == cBASISTexTypeVideoFrames, (slice_desc.m_flags & cSliceDescFlagsHasAlpha) != 0, slice_desc.m_level_index, + slice_desc.m_orig_width, slice_desc.m_orig_height, output_row_pitch_in_blocks_or_pixels, pState, + astc_transcode_alpha, + pAlpha_blocks, + output_rows_in_pixels); + } + + // Container independent transcoding + bool transcode_image( + transcoder_texture_format target_format, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + const uint8_t* pCompressed_data, uint32_t compressed_data_length, + uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index, + uint32_t rgb_offset, uint32_t rgb_length, uint32_t alpha_offset, uint32_t alpha_length, + uint32_t decode_flags = 0, + bool basis_file_has_alpha_slices = false, + bool is_video = false, + uint32_t output_row_pitch_in_blocks_or_pixels = 0, + basisu_transcoder_state* pState = nullptr, + uint32_t output_rows_in_pixels = 0); + + void clear() + { + m_local_endpoints.clear(); + m_local_selectors.clear(); + m_endpoint_pred_model.clear(); + m_delta_endpoint_model.clear(); + m_selector_model.clear(); + m_selector_history_buf_rle_model.clear(); + m_selector_history_buf_size = 0; + } + + // Low-level methods + typedef basisu::vector endpoint_vec; + const endpoint_vec& get_endpoints() const { return m_local_endpoints; } + + typedef basisu::vector selector_vec; + const selector_vec& get_selectors() const { return m_local_selectors; } + + private: + const basisu_lowlevel_etc1s_transcoder* m_pGlobal_codebook; + + endpoint_vec m_local_endpoints; + selector_vec m_local_selectors; + + huffman_decoding_table m_endpoint_pred_model, m_delta_endpoint_model, m_selector_model, m_selector_history_buf_rle_model; + + uint32_t m_selector_history_buf_size; + + basisu_transcoder_state m_def_state; + }; + + enum basisu_decode_flags + { + // PVRTC1: decode non-pow2 ETC1S texture level to the next larger power of 2 (not implemented yet, but we're going to support it). Ignored if the slice's dimensions are already a power of 2. + cDecodeFlagsPVRTCDecodeToNextPow2 = 2, + + // When decoding to an opaque texture format, if the basis file has alpha, decode the alpha slice instead of the color slice to the output texture format. + // This is primarily to allow decoding of textures with alpha to multiple ETC1 textures (one for color, another for alpha). + cDecodeFlagsTranscodeAlphaDataToOpaqueFormats = 4, + + // Forbid usage of BC1 3 color blocks (we don't support BC1 punchthrough alpha yet). + // This flag is used internally when decoding to BC3. + cDecodeFlagsBC1ForbidThreeColorBlocks = 8, + + // The output buffer contains alpha endpoint/selector indices. + // Used internally when decoding formats like ASTC that require both color and alpha data to be available when transcoding to the output format. + cDecodeFlagsOutputHasAlphaIndices = 16, + + cDecodeFlagsHighQuality = 32 + }; + + class basisu_lowlevel_uastc_transcoder + { + friend class basisu_transcoder; + + public: + basisu_lowlevel_uastc_transcoder(); + + bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, bool has_alpha, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels = 0, + basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, uint32_t decode_flags = 0); + + bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt, + uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0, + basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, uint32_t decode_flags = 0) + { + return transcode_slice(pDst_blocks, num_blocks_x, num_blocks_y, pImage_data, image_data_size, fmt, + output_block_or_pixel_stride_in_bytes, bc1_allow_threecolor_blocks, (header.m_flags & cBASISHeaderFlagHasAlphaSlices) != 0, slice_desc.m_orig_width, slice_desc.m_orig_height, output_row_pitch_in_blocks_or_pixels, + pState, output_rows_in_pixels, channel0, channel1, decode_flags); + } + + // Container independent transcoding + bool transcode_image( + transcoder_texture_format target_format, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + const uint8_t* pCompressed_data, uint32_t compressed_data_length, + uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index, + uint32_t slice_offset, uint32_t slice_length, + uint32_t decode_flags = 0, + bool has_alpha = false, + bool is_video = false, + uint32_t output_row_pitch_in_blocks_or_pixels = 0, + basisu_transcoder_state* pState = nullptr, + uint32_t output_rows_in_pixels = 0, + int channel0 = -1, int channel1 = -1); + }; + + struct basisu_slice_info + { + uint32_t m_orig_width; + uint32_t m_orig_height; + + uint32_t m_width; + uint32_t m_height; + + uint32_t m_num_blocks_x; + uint32_t m_num_blocks_y; + uint32_t m_total_blocks; + + uint32_t m_compressed_size; + + uint32_t m_slice_index; // the slice index in the .basis file + uint32_t m_image_index; // the source image index originally provided to the encoder + uint32_t m_level_index; // the mipmap level within this image + + uint32_t m_unpacked_slice_crc16; + + bool m_alpha_flag; // true if the slice has alpha data + bool m_iframe_flag; // true if the slice is an I-Frame + }; + + typedef basisu::vector basisu_slice_info_vec; + + struct basisu_image_info + { + uint32_t m_image_index; + uint32_t m_total_levels; + + uint32_t m_orig_width; + uint32_t m_orig_height; + + uint32_t m_width; + uint32_t m_height; + + uint32_t m_num_blocks_x; + uint32_t m_num_blocks_y; + uint32_t m_total_blocks; + + uint32_t m_first_slice_index; + + bool m_alpha_flag; // true if the image has alpha data + bool m_iframe_flag; // true if the image is an I-Frame + }; + + struct basisu_image_level_info + { + uint32_t m_image_index; + uint32_t m_level_index; + + uint32_t m_orig_width; + uint32_t m_orig_height; + + uint32_t m_width; + uint32_t m_height; + + uint32_t m_num_blocks_x; + uint32_t m_num_blocks_y; + uint32_t m_total_blocks; + + uint32_t m_first_slice_index; + + uint32_t m_rgb_file_ofs; + uint32_t m_rgb_file_len; + uint32_t m_alpha_file_ofs; + uint32_t m_alpha_file_len; + + bool m_alpha_flag; // true if the image has alpha data + bool m_iframe_flag; // true if the image is an I-Frame + }; + + struct basisu_file_info + { + uint32_t m_version; + uint32_t m_total_header_size; + + uint32_t m_total_selectors; + // will be 0 for UASTC or if the file uses global codebooks + uint32_t m_selector_codebook_ofs; + uint32_t m_selector_codebook_size; + + uint32_t m_total_endpoints; + // will be 0 for UASTC or if the file uses global codebooks + uint32_t m_endpoint_codebook_ofs; + uint32_t m_endpoint_codebook_size; + + uint32_t m_tables_ofs; + uint32_t m_tables_size; + + uint32_t m_slices_size; + + basis_texture_type m_tex_type; + uint32_t m_us_per_frame; + + // Low-level slice information (1 slice per image for color-only basis files, 2 for alpha basis files) + basisu_slice_info_vec m_slice_info; + + uint32_t m_total_images; // total # of images + basisu::vector m_image_mipmap_levels; // the # of mipmap levels for each image + + uint32_t m_userdata0; + uint32_t m_userdata1; + + basis_tex_format m_tex_format; // ETC1S, UASTC, etc. + + bool m_y_flipped; // true if the image was Y flipped + bool m_etc1s; // true if the file is ETC1S + bool m_has_alpha_slices; // true if the texture has alpha slices (for ETC1S: even slices RGB, odd slices alpha) + }; + + // High-level transcoder class which accepts .basis file data and allows the caller to query information about the file and transcode image levels to various texture formats. + // If you're just starting out this is the class you care about. + class basisu_transcoder + { + basisu_transcoder(basisu_transcoder&); + basisu_transcoder& operator= (const basisu_transcoder&); + + public: + basisu_transcoder(); + + // Validates the .basis file. This computes a crc16 over the entire file, so it's slow. + bool validate_file_checksums(const void* pData, uint32_t data_size, bool full_validation) const; + + // Quick header validation - no crc16 checks. + bool validate_header(const void* pData, uint32_t data_size) const; + + basis_texture_type get_texture_type(const void* pData, uint32_t data_size) const; + bool get_userdata(const void* pData, uint32_t data_size, uint32_t& userdata0, uint32_t& userdata1) const; + + // Returns the total number of images in the basis file (always 1 or more). + // Note that the number of mipmap levels for each image may differ, and that images may have different resolutions. + uint32_t get_total_images(const void* pData, uint32_t data_size) const; + + basis_tex_format get_tex_format(const void* pData, uint32_t data_size) const; + + // Returns the number of mipmap levels in an image. + uint32_t get_total_image_levels(const void* pData, uint32_t data_size, uint32_t image_index) const; + + // Returns basic information about an image. Note that orig_width/orig_height may not be a multiple of 4. + bool get_image_level_desc(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, uint32_t& orig_width, uint32_t& orig_height, uint32_t& total_blocks) const; + + // Returns information about the specified image. + bool get_image_info(const void* pData, uint32_t data_size, basisu_image_info& image_info, uint32_t image_index) const; + + // Returns information about the specified image's mipmap level. + bool get_image_level_info(const void* pData, uint32_t data_size, basisu_image_level_info& level_info, uint32_t image_index, uint32_t level_index) const; + + // Get a description of the basis file and low-level information about each slice. + bool get_file_info(const void* pData, uint32_t data_size, basisu_file_info& file_info) const; + + // start_transcoding() must be called before calling transcode_slice() or transcode_image_level(). + // For ETC1S files, this call decompresses the selector/endpoint codebooks, so ideally you would only call this once per .basis file (not each image/mipmap level). + bool start_transcoding(const void* pData, uint32_t data_size); + + bool stop_transcoding(); + + // Returns true if start_transcoding() has been called. + bool get_ready_to_transcode() const { return m_ready_to_transcode; } + + // transcode_image_level() decodes a single mipmap level from the .basis file to any of the supported output texture formats. + // It'll first find the slice(s) to transcode, then call transcode_slice() one or two times to decode both the color and alpha texture data (or RG texture data from two slices for BC5). + // If the .basis file doesn't have alpha slices, the output alpha blocks will be set to fully opaque (all 255's). + // Currently, to decode to PVRTC1 the basis texture's dimensions in pixels must be a power of 2, due to PVRTC1 format requirements. + // output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32. + // output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling). + // output_rows_in_pixels: Ignored unless fmt is uncompressed (cRGBA32, etc.). The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4). + // Notes: + // - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function. + // - This method assumes the output texture buffer is readable. In some cases to handle alpha, the transcoder will write temporary data to the output texture in + // a first pass, which will be read in a second pass. + bool transcode_image_level( + const void* pData, uint32_t data_size, + uint32_t image_index, uint32_t level_index, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + transcoder_texture_format fmt, + uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0) const; + + // Finds the basis slice corresponding to the specified image/level/alpha params, or -1 if the slice can't be found. + int find_slice(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index, bool alpha_data) const; + + // transcode_slice() decodes a single slice from the .basis file. It's a low-level API - most likely you want to use transcode_image_level(). + // This is a low-level API, and will be needed to be called multiple times to decode some texture formats (like BC3, BC5, or ETC2). + // output_blocks_buf_size_in_blocks_or_pixels is just used for verification to make sure the output buffer is large enough. + // output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32. + // output_block_stride_in_bytes: Number of bytes between each output block. + // output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling). + // output_rows_in_pixels: Ignored unless fmt is cRGBA32. The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4). + // Notes: + // - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function. + bool transcode_slice(const void* pData, uint32_t data_size, uint32_t slice_index, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + block_format fmt, uint32_t output_block_stride_in_bytes, uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, basisu_transcoder_state* pState = nullptr, void* pAlpha_blocks = nullptr, + uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1) const; + + static void write_opaque_alpha_blocks( + uint32_t num_blocks_x, uint32_t num_blocks_y, + void* pOutput_blocks, block_format fmt, + uint32_t block_stride_in_bytes, uint32_t output_row_pitch_in_blocks_or_pixels); + + void set_global_codebooks(const basisu_lowlevel_etc1s_transcoder* pGlobal_codebook) { m_lowlevel_etc1s_decoder.set_global_codebooks(pGlobal_codebook); } + const basisu_lowlevel_etc1s_transcoder* get_global_codebooks() const { return m_lowlevel_etc1s_decoder.get_global_codebooks(); } + + const basisu_lowlevel_etc1s_transcoder& get_lowlevel_etc1s_decoder() const { return m_lowlevel_etc1s_decoder; } + basisu_lowlevel_etc1s_transcoder& get_lowlevel_etc1s_decoder() { return m_lowlevel_etc1s_decoder; } + + const basisu_lowlevel_uastc_transcoder& get_lowlevel_uastc_decoder() const { return m_lowlevel_uastc_decoder; } + basisu_lowlevel_uastc_transcoder& get_lowlevel_uastc_decoder() { return m_lowlevel_uastc_decoder; } + + private: + mutable basisu_lowlevel_etc1s_transcoder m_lowlevel_etc1s_decoder; + mutable basisu_lowlevel_uastc_transcoder m_lowlevel_uastc_decoder; + + bool m_ready_to_transcode; + + int find_first_slice_index(const void* pData, uint32_t data_size, uint32_t image_index, uint32_t level_index) const; + + bool validate_header_quick(const void* pData, uint32_t data_size) const; + }; + + // basisu_transcoder_init() MUST be called before a .basis file can be transcoded. + void basisu_transcoder_init(); + + enum debug_flags_t + { + cDebugFlagVisCRs = 1, + cDebugFlagVisBC1Sels = 2, + cDebugFlagVisBC1Endpoints = 4 + }; + uint32_t get_debug_flags(); + void set_debug_flags(uint32_t f); + + // ------------------------------------------------------------------------------------------------------ + // Optional .KTX2 file format support + // KTX2 reading optionally requires miniz or Zstd decompressors for supercompressed UASTC files. + // ------------------------------------------------------------------------------------------------------ +#if BASISD_SUPPORT_KTX2 +#pragma pack(push) +#pragma pack(1) + struct ktx2_header + { + uint8_t m_identifier[12]; + basisu::packed_uint<4> m_vk_format; + basisu::packed_uint<4> m_type_size; + basisu::packed_uint<4> m_pixel_width; + basisu::packed_uint<4> m_pixel_height; + basisu::packed_uint<4> m_pixel_depth; + basisu::packed_uint<4> m_layer_count; + basisu::packed_uint<4> m_face_count; + basisu::packed_uint<4> m_level_count; + basisu::packed_uint<4> m_supercompression_scheme; + basisu::packed_uint<4> m_dfd_byte_offset; + basisu::packed_uint<4> m_dfd_byte_length; + basisu::packed_uint<4> m_kvd_byte_offset; + basisu::packed_uint<4> m_kvd_byte_length; + basisu::packed_uint<8> m_sgd_byte_offset; + basisu::packed_uint<8> m_sgd_byte_length; + }; + + struct ktx2_level_index + { + basisu::packed_uint<8> m_byte_offset; + basisu::packed_uint<8> m_byte_length; + basisu::packed_uint<8> m_uncompressed_byte_length; + }; + + struct ktx2_etc1s_global_data_header + { + basisu::packed_uint<2> m_endpoint_count; + basisu::packed_uint<2> m_selector_count; + basisu::packed_uint<4> m_endpoints_byte_length; + basisu::packed_uint<4> m_selectors_byte_length; + basisu::packed_uint<4> m_tables_byte_length; + basisu::packed_uint<4> m_extended_byte_length; + }; + + struct ktx2_etc1s_image_desc + { + basisu::packed_uint<4> m_image_flags; + basisu::packed_uint<4> m_rgb_slice_byte_offset; + basisu::packed_uint<4> m_rgb_slice_byte_length; + basisu::packed_uint<4> m_alpha_slice_byte_offset; + basisu::packed_uint<4> m_alpha_slice_byte_length; + }; + + struct ktx2_animdata + { + basisu::packed_uint<4> m_duration; + basisu::packed_uint<4> m_timescale; + basisu::packed_uint<4> m_loopcount; + }; +#pragma pack(pop) + + const uint32_t KTX2_VK_FORMAT_UNDEFINED = 0; + const uint32_t KTX2_KDF_DF_MODEL_UASTC = 166; + const uint32_t KTX2_KDF_DF_MODEL_ETC1S = 163; + const uint32_t KTX2_IMAGE_IS_P_FRAME = 2; + const uint32_t KTX2_UASTC_BLOCK_SIZE = 16; + const uint32_t KTX2_MAX_SUPPORTED_LEVEL_COUNT = 16; // this is an implementation specific constraint and can be increased + + // The KTX2 transfer functions supported by KTX2 + const uint32_t KTX2_KHR_DF_TRANSFER_LINEAR = 1; + const uint32_t KTX2_KHR_DF_TRANSFER_SRGB = 2; + + enum ktx2_supercompression + { + KTX2_SS_NONE = 0, + KTX2_SS_BASISLZ = 1, + KTX2_SS_ZSTANDARD = 2 + }; + + extern const uint8_t g_ktx2_file_identifier[12]; + + enum ktx2_df_channel_id + { + KTX2_DF_CHANNEL_ETC1S_RGB = 0U, + KTX2_DF_CHANNEL_ETC1S_RRR = 3U, + KTX2_DF_CHANNEL_ETC1S_GGG = 4U, + KTX2_DF_CHANNEL_ETC1S_AAA = 15U, + + KTX2_DF_CHANNEL_UASTC_DATA = 0U, + KTX2_DF_CHANNEL_UASTC_RGB = 0U, + KTX2_DF_CHANNEL_UASTC_RGBA = 3U, + KTX2_DF_CHANNEL_UASTC_RRR = 4U, + KTX2_DF_CHANNEL_UASTC_RRRG = 5U, + KTX2_DF_CHANNEL_UASTC_RG = 6U, + }; + + inline const char* ktx2_get_etc1s_df_channel_id_str(ktx2_df_channel_id id) + { + switch (id) + { + case KTX2_DF_CHANNEL_ETC1S_RGB: return "RGB"; + case KTX2_DF_CHANNEL_ETC1S_RRR: return "RRR"; + case KTX2_DF_CHANNEL_ETC1S_GGG: return "GGG"; + case KTX2_DF_CHANNEL_ETC1S_AAA: return "AAA"; + default: break; + } + return "?"; + } + + inline const char* ktx2_get_uastc_df_channel_id_str(ktx2_df_channel_id id) + { + switch (id) + { + case KTX2_DF_CHANNEL_UASTC_RGB: return "RGB"; + case KTX2_DF_CHANNEL_UASTC_RGBA: return "RGBA"; + case KTX2_DF_CHANNEL_UASTC_RRR: return "RRR"; + case KTX2_DF_CHANNEL_UASTC_RRRG: return "RRRG"; + case KTX2_DF_CHANNEL_UASTC_RG: return "RG"; + default: break; + } + return "?"; + } + + enum ktx2_df_color_primaries + { + KTX2_DF_PRIMARIES_UNSPECIFIED = 0, + KTX2_DF_PRIMARIES_BT709 = 1, + KTX2_DF_PRIMARIES_SRGB = 1, + KTX2_DF_PRIMARIES_BT601_EBU = 2, + KTX2_DF_PRIMARIES_BT601_SMPTE = 3, + KTX2_DF_PRIMARIES_BT2020 = 4, + KTX2_DF_PRIMARIES_CIEXYZ = 5, + KTX2_DF_PRIMARIES_ACES = 6, + KTX2_DF_PRIMARIES_ACESCC = 7, + KTX2_DF_PRIMARIES_NTSC1953 = 8, + KTX2_DF_PRIMARIES_PAL525 = 9, + KTX2_DF_PRIMARIES_DISPLAYP3 = 10, + KTX2_DF_PRIMARIES_ADOBERGB = 11 + }; + + inline const char* ktx2_get_df_color_primaries_str(ktx2_df_color_primaries p) + { + switch (p) + { + case KTX2_DF_PRIMARIES_UNSPECIFIED: return "UNSPECIFIED"; + case KTX2_DF_PRIMARIES_BT709: return "BT709"; + case KTX2_DF_PRIMARIES_BT601_EBU: return "EBU"; + case KTX2_DF_PRIMARIES_BT601_SMPTE: return "SMPTE"; + case KTX2_DF_PRIMARIES_BT2020: return "BT2020"; + case KTX2_DF_PRIMARIES_CIEXYZ: return "CIEXYZ"; + case KTX2_DF_PRIMARIES_ACES: return "ACES"; + case KTX2_DF_PRIMARIES_ACESCC: return "ACESCC"; + case KTX2_DF_PRIMARIES_NTSC1953: return "NTSC1953"; + case KTX2_DF_PRIMARIES_PAL525: return "PAL525"; + case KTX2_DF_PRIMARIES_DISPLAYP3: return "DISPLAYP3"; + case KTX2_DF_PRIMARIES_ADOBERGB: return "ADOBERGB"; + default: break; + } + return "?"; + } + + // Information about a single 2D texture "image" in a KTX2 file. + struct ktx2_image_level_info + { + // The mipmap level index (0=largest), texture array layer index, and cubemap face index of the image. + uint32_t m_level_index; + uint32_t m_layer_index; + uint32_t m_face_index; + + // The image's actual (or the original source image's) width/height in pixels, which may not be divisible by 4 pixels. + uint32_t m_orig_width; + uint32_t m_orig_height; + + // The image's physical width/height, which will always be divisible by 4 pixels. + uint32_t m_width; + uint32_t m_height; + + // The texture's dimensions in 4x4 texel blocks. + uint32_t m_num_blocks_x; + uint32_t m_num_blocks_y; + + // The total number of blocks + uint32_t m_total_blocks; + + // true if the image has alpha data + bool m_alpha_flag; + + // true if the image is an I-Frame. Currently, for ETC1S textures, the first frame will always be an I-Frame, and subsequent frames will always be P-Frames. + bool m_iframe_flag; + }; + + // Thread-specific ETC1S/supercompressed UASTC transcoder state. (If you're not doing multithreading transcoding you can ignore this.) + struct ktx2_transcoder_state + { + basist::basisu_transcoder_state m_transcoder_state; + basisu::uint8_vec m_level_uncomp_data; + int m_uncomp_data_level_index; + + void clear() + { + m_transcoder_state.clear(); + m_level_uncomp_data.clear(); + m_uncomp_data_level_index = -1; + } + }; + + // This class is quite similar to basisu_transcoder. It treats KTX2 files as a simple container for ETC1S/UASTC texture data. + // It does not support 1D or 3D textures. + // It only supports 2D and cubemap textures, with or without mipmaps, texture arrays of 2D/cubemap textures, and texture video files. + // It only supports raw non-supercompressed UASTC, ETC1S, UASTC+Zstd, or UASTC+zlib compressed files. + // DFD (Data Format Descriptor) parsing is purposely as simple as possible. + // If you need to know how to interpret the texture channels you'll need to parse the DFD yourself after calling get_dfd(). + class ktx2_transcoder + { + public: + ktx2_transcoder(); + + // Frees all allocations, resets object. + void clear(); + + // init() parses the KTX2 header, level index array, DFD, and key values, but nothing else. + // Importantly, it does not parse or decompress the ETC1S global supercompressed data, so some things (like which frames are I/P-Frames) won't be available until start_transcoding() is called. + // This method holds a pointer to the file data until clear() is called. + bool init(const void* pData, uint32_t data_size); + + // Returns the data/size passed to init(). + const uint8_t* get_data() const { return m_pData; } + uint32_t get_data_size() const { return m_data_size; } + + // Returns the KTX2 header. Valid after init(). + const ktx2_header& get_header() const { return m_header; } + + // Returns the KTX2 level index array. There will be one entry for each mipmap level. Valid after init(). + const basisu::vector& get_level_index() const { return m_levels; } + + // Returns the texture's width in texels. Always non-zero, might not be divisible by 4. Valid after init(). + uint32_t get_width() const { return m_header.m_pixel_width; } + + // Returns the texture's height in texels. Always non-zero, might not be divisible by 4. Valid after init(). + uint32_t get_height() const { return m_header.m_pixel_height; } + + // Returns the texture's number of mipmap levels. Always returns 1 or higher. Valid after init(). + uint32_t get_levels() const { return m_header.m_level_count; } + + // Returns the number of faces. Returns 1 for 2D textures and or 6 for cubemaps. Valid after init(). + uint32_t get_faces() const { return m_header.m_face_count; } + + // Returns 0 or the number of layers in the texture array or texture video. Valid after init(). + uint32_t get_layers() const { return m_header.m_layer_count; } + + // Returns cETC1S or cUASTC4x4. Valid after init(). + basist::basis_tex_format get_format() const { return m_format; } + + bool is_etc1s() const { return get_format() == basist::basis_tex_format::cETC1S; } + + bool is_uastc() const { return get_format() == basist::basis_tex_format::cUASTC4x4; } + + // Returns true if the ETC1S file has two planes (typically RGBA, or RRRG), or true if the UASTC file has alpha data. Valid after init(). + uint32_t get_has_alpha() const { return m_has_alpha; } + + // Returns the entire Data Format Descriptor (DFD) from the KTX2 file. Valid after init(). + // See https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#_the_khronos_data_format_descriptor_overview + const basisu::uint8_vec& get_dfd() const { return m_dfd; } + + // Some basic DFD accessors. Valid after init(). + uint32_t get_dfd_color_model() const { return m_dfd_color_model; } + + // Returns the DFD color primary. + // We do not validate the color primaries, so the returned value may not be in the ktx2_df_color_primaries enum. + ktx2_df_color_primaries get_dfd_color_primaries() const { return m_dfd_color_prims; } + + // Returns KTX2_KHR_DF_TRANSFER_LINEAR or KTX2_KHR_DF_TRANSFER_SRGB. + uint32_t get_dfd_transfer_func() const { return m_dfd_transfer_func; } + + uint32_t get_dfd_flags() const { return m_dfd_flags; } + + // Returns 1 (ETC1S/UASTC) or 2 (ETC1S with an internal alpha channel). + uint32_t get_dfd_total_samples() const { return m_dfd_samples; } + + // Returns the channel mapping for each DFD "sample". UASTC always has 1 sample, ETC1S can have one or two. + // Note the returned value SHOULD be one of the ktx2_df_channel_id enums, but we don't validate that. + // It's up to the caller to decide what to do if the value isn't in the enum. + ktx2_df_channel_id get_dfd_channel_id0() const { return m_dfd_chan0; } + ktx2_df_channel_id get_dfd_channel_id1() const { return m_dfd_chan1; } + + // Key value field data. + struct key_value + { + // The key field is UTF8 and always zero terminated. + basisu::uint8_vec m_key; + + // The value may be empty. It consists of raw bytes which may or may not be zero terminated. + basisu::uint8_vec m_value; + + bool operator< (const key_value& rhs) const { return strcmp((const char*)m_key.data(), (const char *)rhs.m_key.data()) < 0; } + }; + typedef basisu::vector key_value_vec; + + // Returns the array of key-value entries. This may be empty. Valid after init(). + // The order of key values fields in this array exactly matches the order they were stored in the file. The keys are supposed to be sorted by their Unicode code points. + const key_value_vec& get_key_values() const { return m_key_values; } + + const basisu::uint8_vec *find_key(const std::string& key_name) const; + + // Low-level ETC1S specific accessors + + // Returns the ETC1S global supercompression data header, which is only valid after start_transcoding() is called. + const ktx2_etc1s_global_data_header& get_etc1s_header() const { return m_etc1s_header; } + + // Returns the array of ETC1S image descriptors, which is only valid after get_etc1s_image_descs() is called. + const basisu::vector& get_etc1s_image_descs() const { return m_etc1s_image_descs; } + + // Must have called startTranscoding() first + uint32_t get_etc1s_image_descs_image_flags(uint32_t level_index, uint32_t layer_index, uint32_t face_index) const; + + // is_video() is only valid after start_transcoding() is called. + // For ETC1S data, if this returns true you must currently transcode the file from first to last frame, in order, without skipping any frames. + bool is_video() const { return m_is_video; } + + // start_transcoding() MUST be called before calling transcode_image(). + // This method decompresses the ETC1S global endpoint/selector codebooks, which is not free, so try to avoid calling it excessively. + bool start_transcoding(); + + // get_image_level_info() be called after init(), but the m_iframe_flag's won't be valid until start_transcoding() is called. + // You can call this method before calling transcode_image_level() to retrieve basic information about the mipmap level's dimensions, etc. + bool get_image_level_info(ktx2_image_level_info& level_info, uint32_t level_index, uint32_t layer_index, uint32_t face_index) const; + + // transcode_image_level() transcodes a single 2D texture or cubemap face from the KTX2 file. + // Internally it uses the same low-level transcode API's as basisu_transcoder::transcode_image_level(). + // If the file is UASTC and is supercompressed with Zstandard, and the file is a texture array or cubemap, it's highly recommended that each mipmap level is + // completely transcoded before switching to another level. Every time the mipmap level is changed all supercompressed level data must be decompressed using Zstandard as a single unit. + // Currently ETC1S videos must always be transcoded from first to last frame (or KTX2 "layer"), in order, with no skipping of frames. + // By default this method is not thread safe unless you specify a pointer to a user allocated thread-specific transcoder_state struct. + bool transcode_image_level( + uint32_t level_index, uint32_t layer_index, uint32_t face_index, + void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels, + basist::transcoder_texture_format fmt, + uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, + ktx2_transcoder_state *pState = nullptr); + + private: + const uint8_t* m_pData; + uint32_t m_data_size; + + ktx2_header m_header; + basisu::vector m_levels; + basisu::uint8_vec m_dfd; + key_value_vec m_key_values; + + ktx2_etc1s_global_data_header m_etc1s_header; + basisu::vector m_etc1s_image_descs; + + basist::basis_tex_format m_format; + + uint32_t m_dfd_color_model; + ktx2_df_color_primaries m_dfd_color_prims; + uint32_t m_dfd_transfer_func; + uint32_t m_dfd_flags; + uint32_t m_dfd_samples; + ktx2_df_channel_id m_dfd_chan0, m_dfd_chan1; + + basist::basisu_lowlevel_etc1s_transcoder m_etc1s_transcoder; + basist::basisu_lowlevel_uastc_transcoder m_uastc_transcoder; + + ktx2_transcoder_state m_def_transcoder_state; + + bool m_has_alpha; + bool m_is_video; + + bool decompress_level_data(uint32_t level_index, basisu::uint8_vec& uncomp_data); + bool decompress_etc1s_global_data(); + bool read_key_values(); + }; + +#endif // BASISD_SUPPORT_KTX2 + + // Returns true if the transcoder was compiled with KTX2 support. + bool basisu_transcoder_supports_ktx2(); + + // Returns true if the transcoder was compiled with Zstandard support. + bool basisu_transcoder_supports_ktx2_zstd(); + +} // namespace basisu + diff --git a/ext/basis_universal/basisu_transcoder_internal.h b/ext/basis_universal/basisu_transcoder_internal.h new file mode 100644 index 0000000000..0505df6ea6 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_internal.h @@ -0,0 +1,796 @@ +// basisu_transcoder_internal.h - Universal texture format transcoder library. +// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved. +// +// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#pragma once + +#ifdef _MSC_VER +#pragma warning (disable: 4127) // conditional expression is constant +#endif + +#define BASISD_LIB_VERSION 116 +#define BASISD_VERSION_STRING "01.16" + +#ifdef _DEBUG +#define BASISD_BUILD_DEBUG +#else +#define BASISD_BUILD_RELEASE +#endif + +#include "basisu.h" + +#define BASISD_znew (z = 36969 * (z & 65535) + (z >> 16)) + +namespace basisu +{ + extern bool g_debug_printf; +} + +namespace basist +{ + // Low-level formats directly supported by the transcoder (other supported texture formats are combinations of these low-level block formats). + // You probably don't care about these enum's unless you are going pretty low-level and calling the transcoder to decode individual slices. + enum class block_format + { + cETC1, // ETC1S RGB + cETC2_RGBA, // full ETC2 EAC RGBA8 block + cBC1, // DXT1 RGB + cBC3, // BC4 block followed by a four color BC1 block + cBC4, // DXT5A (alpha block only) + cBC5, // two BC4 blocks + cPVRTC1_4_RGB, // opaque-only PVRTC1 4bpp + cPVRTC1_4_RGBA, // PVRTC1 4bpp RGBA + cBC7, // Full BC7 block, any mode + cBC7_M5_COLOR, // RGB BC7 mode 5 color (writes an opaque mode 5 block) + cBC7_M5_ALPHA, // alpha portion of BC7 mode 5 (cBC7_M5_COLOR output data must have been written to the output buffer first to set the mode/rot fields etc.) + cETC2_EAC_A8, // alpha block of ETC2 EAC (first 8 bytes of the 16-bit ETC2 EAC RGBA format) + cASTC_4x4, // ASTC 4x4 (either color-only or color+alpha). Note that the transcoder always currently assumes sRGB is not enabled when outputting ASTC + // data. If you use a sRGB ASTC format you'll get ~1 LSB of additional error, because of the different way ASTC decoders scale 8-bit endpoints to 16-bits during unpacking. + + cATC_RGB, + cATC_RGBA_INTERPOLATED_ALPHA, + cFXT1_RGB, // Opaque-only, has oddball 8x4 pixel block size + + cPVRTC2_4_RGB, + cPVRTC2_4_RGBA, + + cETC2_EAC_R11, + cETC2_EAC_RG11, + + cIndices, // Used internally: Write 16-bit endpoint and selector indices directly to output (output block must be at least 32-bits) + + cRGB32, // Writes RGB components to 32bpp output pixels + cRGBA32, // Writes RGB255 components to 32bpp output pixels + cA32, // Writes alpha component to 32bpp output pixels + + cRGB565, + cBGR565, + + cRGBA4444_COLOR, + cRGBA4444_ALPHA, + cRGBA4444_COLOR_OPAQUE, + cRGBA4444, + + cUASTC_4x4, + + cTotalBlockFormats + }; + + const int COLOR5_PAL0_PREV_HI = 9, COLOR5_PAL0_DELTA_LO = -9, COLOR5_PAL0_DELTA_HI = 31; + const int COLOR5_PAL1_PREV_HI = 21, COLOR5_PAL1_DELTA_LO = -21, COLOR5_PAL1_DELTA_HI = 21; + const int COLOR5_PAL2_PREV_HI = 31, COLOR5_PAL2_DELTA_LO = -31, COLOR5_PAL2_DELTA_HI = 9; + const int COLOR5_PAL_MIN_DELTA_B_RUNLEN = 3, COLOR5_PAL_DELTA_5_RUNLEN_VLC_BITS = 3; + + const uint32_t ENDPOINT_PRED_TOTAL_SYMBOLS = (4 * 4 * 4 * 4) + 1; + const uint32_t ENDPOINT_PRED_REPEAT_LAST_SYMBOL = ENDPOINT_PRED_TOTAL_SYMBOLS - 1; + const uint32_t ENDPOINT_PRED_MIN_REPEAT_COUNT = 3; + const uint32_t ENDPOINT_PRED_COUNT_VLC_BITS = 4; + + const uint32_t NUM_ENDPOINT_PREDS = 3;// BASISU_ARRAY_SIZE(g_endpoint_preds); + const uint32_t CR_ENDPOINT_PRED_INDEX = NUM_ENDPOINT_PREDS - 1; + const uint32_t NO_ENDPOINT_PRED_INDEX = 3;//NUM_ENDPOINT_PREDS; + const uint32_t MAX_SELECTOR_HISTORY_BUF_SIZE = 64; + const uint32_t SELECTOR_HISTORY_BUF_RLE_COUNT_THRESH = 3; + const uint32_t SELECTOR_HISTORY_BUF_RLE_COUNT_BITS = 6; + const uint32_t SELECTOR_HISTORY_BUF_RLE_COUNT_TOTAL = (1 << SELECTOR_HISTORY_BUF_RLE_COUNT_BITS); + + uint16_t crc16(const void *r, size_t size, uint16_t crc); + + class huffman_decoding_table + { + friend class bitwise_decoder; + + public: + huffman_decoding_table() + { + } + + void clear() + { + basisu::clear_vector(m_code_sizes); + basisu::clear_vector(m_lookup); + basisu::clear_vector(m_tree); + } + + bool init(uint32_t total_syms, const uint8_t *pCode_sizes, uint32_t fast_lookup_bits = basisu::cHuffmanFastLookupBits) + { + if (!total_syms) + { + clear(); + return true; + } + + m_code_sizes.resize(total_syms); + memcpy(&m_code_sizes[0], pCode_sizes, total_syms); + + const uint32_t huffman_fast_lookup_size = 1 << fast_lookup_bits; + + m_lookup.resize(0); + m_lookup.resize(huffman_fast_lookup_size); + + m_tree.resize(0); + m_tree.resize(total_syms * 2); + + uint32_t syms_using_codesize[basisu::cHuffmanMaxSupportedInternalCodeSize + 1]; + basisu::clear_obj(syms_using_codesize); + for (uint32_t i = 0; i < total_syms; i++) + { + if (pCode_sizes[i] > basisu::cHuffmanMaxSupportedInternalCodeSize) + return false; + syms_using_codesize[pCode_sizes[i]]++; + } + + uint32_t next_code[basisu::cHuffmanMaxSupportedInternalCodeSize + 1]; + next_code[0] = next_code[1] = 0; + + uint32_t used_syms = 0, total = 0; + for (uint32_t i = 1; i < basisu::cHuffmanMaxSupportedInternalCodeSize; i++) + { + used_syms += syms_using_codesize[i]; + next_code[i + 1] = (total = ((total + syms_using_codesize[i]) << 1)); + } + + if (((1U << basisu::cHuffmanMaxSupportedInternalCodeSize) != total) && (used_syms != 1U)) + return false; + + for (int tree_next = -1, sym_index = 0; sym_index < (int)total_syms; ++sym_index) + { + uint32_t rev_code = 0, l, cur_code, code_size = pCode_sizes[sym_index]; + if (!code_size) + continue; + + cur_code = next_code[code_size]++; + + for (l = code_size; l > 0; l--, cur_code >>= 1) + rev_code = (rev_code << 1) | (cur_code & 1); + + if (code_size <= fast_lookup_bits) + { + uint32_t k = (code_size << 16) | sym_index; + while (rev_code < huffman_fast_lookup_size) + { + if (m_lookup[rev_code] != 0) + { + // Supplied codesizes can't create a valid prefix code. + return false; + } + + m_lookup[rev_code] = k; + rev_code += (1 << code_size); + } + continue; + } + + int tree_cur; + if (0 == (tree_cur = m_lookup[rev_code & (huffman_fast_lookup_size - 1)])) + { + const uint32_t idx = rev_code & (huffman_fast_lookup_size - 1); + if (m_lookup[idx] != 0) + { + // Supplied codesizes can't create a valid prefix code. + return false; + } + + m_lookup[idx] = tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + + if (tree_cur >= 0) + { + // Supplied codesizes can't create a valid prefix code. + return false; + } + + rev_code >>= (fast_lookup_bits - 1); + + for (int j = code_size; j > ((int)fast_lookup_bits + 1); j--) + { + tree_cur -= ((rev_code >>= 1) & 1); + + const int idx = -tree_cur - 1; + if (idx < 0) + return false; + else if (idx >= (int)m_tree.size()) + m_tree.resize(idx + 1); + + if (!m_tree[idx]) + { + m_tree[idx] = (int16_t)tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + else + { + tree_cur = m_tree[idx]; + if (tree_cur >= 0) + { + // Supplied codesizes can't create a valid prefix code. + return false; + } + } + } + + tree_cur -= ((rev_code >>= 1) & 1); + + const int idx = -tree_cur - 1; + if (idx < 0) + return false; + else if (idx >= (int)m_tree.size()) + m_tree.resize(idx + 1); + + if (m_tree[idx] != 0) + { + // Supplied codesizes can't create a valid prefix code. + return false; + } + + m_tree[idx] = (int16_t)sym_index; + } + + return true; + } + + const basisu::uint8_vec &get_code_sizes() const { return m_code_sizes; } + const basisu::int_vec get_lookup() const { return m_lookup; } + const basisu::int16_vec get_tree() const { return m_tree; } + + bool is_valid() const { return m_code_sizes.size() > 0; } + + private: + basisu::uint8_vec m_code_sizes; + basisu::int_vec m_lookup; + basisu::int16_vec m_tree; + }; + + class bitwise_decoder + { + public: + bitwise_decoder() : + m_buf_size(0), + m_pBuf(nullptr), + m_pBuf_start(nullptr), + m_pBuf_end(nullptr), + m_bit_buf(0), + m_bit_buf_size(0) + { + } + + void clear() + { + m_buf_size = 0; + m_pBuf = nullptr; + m_pBuf_start = nullptr; + m_pBuf_end = nullptr; + m_bit_buf = 0; + m_bit_buf_size = 0; + } + + bool init(const uint8_t *pBuf, uint32_t buf_size) + { + if ((!pBuf) && (buf_size)) + return false; + + m_buf_size = buf_size; + m_pBuf = pBuf; + m_pBuf_start = pBuf; + m_pBuf_end = pBuf + buf_size; + m_bit_buf = 0; + m_bit_buf_size = 0; + return true; + } + + void stop() + { + } + + inline uint32_t peek_bits(uint32_t num_bits) + { + if (!num_bits) + return 0; + + assert(num_bits <= 25); + + while (m_bit_buf_size < num_bits) + { + uint32_t c = 0; + if (m_pBuf < m_pBuf_end) + c = *m_pBuf++; + + m_bit_buf |= (c << m_bit_buf_size); + m_bit_buf_size += 8; + assert(m_bit_buf_size <= 32); + } + + return m_bit_buf & ((1 << num_bits) - 1); + } + + void remove_bits(uint32_t num_bits) + { + assert(m_bit_buf_size >= num_bits); + + m_bit_buf >>= num_bits; + m_bit_buf_size -= num_bits; + } + + uint32_t get_bits(uint32_t num_bits) + { + if (num_bits > 25) + { + assert(num_bits <= 32); + + const uint32_t bits0 = peek_bits(25); + m_bit_buf >>= 25; + m_bit_buf_size -= 25; + num_bits -= 25; + + const uint32_t bits = peek_bits(num_bits); + m_bit_buf >>= num_bits; + m_bit_buf_size -= num_bits; + + return bits0 | (bits << 25); + } + + const uint32_t bits = peek_bits(num_bits); + + m_bit_buf >>= num_bits; + m_bit_buf_size -= num_bits; + + return bits; + } + + uint32_t decode_truncated_binary(uint32_t n) + { + assert(n >= 2); + + const uint32_t k = basisu::floor_log2i(n); + const uint32_t u = (1 << (k + 1)) - n; + + uint32_t result = get_bits(k); + + if (result >= u) + result = ((result << 1) | get_bits(1)) - u; + + return result; + } + + uint32_t decode_rice(uint32_t m) + { + assert(m); + + uint32_t q = 0; + for (;;) + { + uint32_t k = peek_bits(16); + + uint32_t l = 0; + while (k & 1) + { + l++; + k >>= 1; + } + + q += l; + + remove_bits(l); + + if (l < 16) + break; + } + + return (q << m) + (get_bits(m + 1) >> 1); + } + + inline uint32_t decode_vlc(uint32_t chunk_bits) + { + assert(chunk_bits); + + const uint32_t chunk_size = 1 << chunk_bits; + const uint32_t chunk_mask = chunk_size - 1; + + uint32_t v = 0; + uint32_t ofs = 0; + + for ( ; ; ) + { + uint32_t s = get_bits(chunk_bits + 1); + v |= ((s & chunk_mask) << ofs); + ofs += chunk_bits; + + if ((s & chunk_size) == 0) + break; + + if (ofs >= 32) + { + assert(0); + break; + } + } + + return v; + } + + inline uint32_t decode_huffman(const huffman_decoding_table &ct, int fast_lookup_bits = basisu::cHuffmanFastLookupBits) + { + assert(ct.m_code_sizes.size()); + + const uint32_t huffman_fast_lookup_size = 1 << fast_lookup_bits; + + while (m_bit_buf_size < 16) + { + uint32_t c = 0; + if (m_pBuf < m_pBuf_end) + c = *m_pBuf++; + + m_bit_buf |= (c << m_bit_buf_size); + m_bit_buf_size += 8; + assert(m_bit_buf_size <= 32); + } + + int code_len; + + int sym; + if ((sym = ct.m_lookup[m_bit_buf & (huffman_fast_lookup_size - 1)]) >= 0) + { + code_len = sym >> 16; + sym &= 0xFFFF; + } + else + { + code_len = fast_lookup_bits; + do + { + sym = ct.m_tree[~sym + ((m_bit_buf >> code_len++) & 1)]; // ~sym = -sym - 1 + } while (sym < 0); + } + + m_bit_buf >>= code_len; + m_bit_buf_size -= code_len; + + return sym; + } + + bool read_huffman_table(huffman_decoding_table &ct) + { + ct.clear(); + + const uint32_t total_used_syms = get_bits(basisu::cHuffmanMaxSymsLog2); + + if (!total_used_syms) + return true; + if (total_used_syms > basisu::cHuffmanMaxSyms) + return false; + + uint8_t code_length_code_sizes[basisu::cHuffmanTotalCodelengthCodes]; + basisu::clear_obj(code_length_code_sizes); + + const uint32_t num_codelength_codes = get_bits(5); + if ((num_codelength_codes < 1) || (num_codelength_codes > basisu::cHuffmanTotalCodelengthCodes)) + return false; + + for (uint32_t i = 0; i < num_codelength_codes; i++) + code_length_code_sizes[basisu::g_huffman_sorted_codelength_codes[i]] = static_cast(get_bits(3)); + + huffman_decoding_table code_length_table; + if (!code_length_table.init(basisu::cHuffmanTotalCodelengthCodes, code_length_code_sizes)) + return false; + + if (!code_length_table.is_valid()) + return false; + + basisu::uint8_vec code_sizes(total_used_syms); + + uint32_t cur = 0; + while (cur < total_used_syms) + { + int c = decode_huffman(code_length_table); + + if (c <= 16) + code_sizes[cur++] = static_cast(c); + else if (c == basisu::cHuffmanSmallZeroRunCode) + cur += get_bits(basisu::cHuffmanSmallZeroRunExtraBits) + basisu::cHuffmanSmallZeroRunSizeMin; + else if (c == basisu::cHuffmanBigZeroRunCode) + cur += get_bits(basisu::cHuffmanBigZeroRunExtraBits) + basisu::cHuffmanBigZeroRunSizeMin; + else + { + if (!cur) + return false; + + uint32_t l; + if (c == basisu::cHuffmanSmallRepeatCode) + l = get_bits(basisu::cHuffmanSmallRepeatExtraBits) + basisu::cHuffmanSmallRepeatSizeMin; + else + l = get_bits(basisu::cHuffmanBigRepeatExtraBits) + basisu::cHuffmanBigRepeatSizeMin; + + const uint8_t prev = code_sizes[cur - 1]; + if (prev == 0) + return false; + do + { + if (cur >= total_used_syms) + return false; + code_sizes[cur++] = prev; + } while (--l > 0); + } + } + + if (cur != total_used_syms) + return false; + + return ct.init(total_used_syms, &code_sizes[0]); + } + + private: + uint32_t m_buf_size; + const uint8_t *m_pBuf; + const uint8_t *m_pBuf_start; + const uint8_t *m_pBuf_end; + + uint32_t m_bit_buf; + uint32_t m_bit_buf_size; + }; + + inline uint32_t basisd_rand(uint32_t seed) + { + if (!seed) + seed++; + uint32_t z = seed; + BASISD_znew; + return z; + } + + // Returns random number in [0,limit). Max limit is 0xFFFF. + inline uint32_t basisd_urand(uint32_t& seed, uint32_t limit) + { + seed = basisd_rand(seed); + return (((seed ^ (seed >> 16)) & 0xFFFF) * limit) >> 16; + } + + class approx_move_to_front + { + public: + approx_move_to_front(uint32_t n) + { + init(n); + } + + void init(uint32_t n) + { + m_values.resize(n); + m_rover = n / 2; + } + + const basisu::int_vec& get_values() const { return m_values; } + basisu::int_vec& get_values() { return m_values; } + + uint32_t size() const { return (uint32_t)m_values.size(); } + + const int& operator[] (uint32_t index) const { return m_values[index]; } + int operator[] (uint32_t index) { return m_values[index]; } + + void add(int new_value) + { + m_values[m_rover++] = new_value; + if (m_rover == m_values.size()) + m_rover = (uint32_t)m_values.size() / 2; + } + + void use(uint32_t index) + { + if (index) + { + //std::swap(m_values[index / 2], m_values[index]); + int x = m_values[index / 2]; + int y = m_values[index]; + m_values[index / 2] = y; + m_values[index] = x; + } + } + + // returns -1 if not found + int find(int value) const + { + for (uint32_t i = 0; i < m_values.size(); i++) + if (m_values[i] == value) + return i; + return -1; + } + + void reset() + { + const uint32_t n = (uint32_t)m_values.size(); + + m_values.clear(); + + init(n); + } + + private: + basisu::int_vec m_values; + uint32_t m_rover; + }; + + struct decoder_etc_block; + + inline uint8_t clamp255(int32_t i) + { + return (uint8_t)((i & 0xFFFFFF00U) ? (~(i >> 31)) : i); + } + + enum eNoClamp + { + cNoClamp = 0 + }; + + struct color32 + { + union + { + struct + { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + }; + + uint8_t c[4]; + + uint32_t m; + }; + + color32() { } + + color32(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { set(vr, vg, vb, va); } + color32(eNoClamp unused, uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { (void)unused; set_noclamp_rgba(vr, vg, vb, va); } + + void set(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { c[0] = static_cast(vr); c[1] = static_cast(vg); c[2] = static_cast(vb); c[3] = static_cast(va); } + + void set_noclamp_rgb(uint32_t vr, uint32_t vg, uint32_t vb) { c[0] = static_cast(vr); c[1] = static_cast(vg); c[2] = static_cast(vb); } + void set_noclamp_rgba(uint32_t vr, uint32_t vg, uint32_t vb, uint32_t va) { set(vr, vg, vb, va); } + + void set_clamped(int vr, int vg, int vb, int va) { c[0] = clamp255(vr); c[1] = clamp255(vg); c[2] = clamp255(vb); c[3] = clamp255(va); } + + uint8_t operator[] (uint32_t idx) const { assert(idx < 4); return c[idx]; } + uint8_t &operator[] (uint32_t idx) { assert(idx < 4); return c[idx]; } + + bool operator== (const color32&rhs) const { return m == rhs.m; } + + static color32 comp_min(const color32& a, const color32& b) { return color32(cNoClamp, basisu::minimum(a[0], b[0]), basisu::minimum(a[1], b[1]), basisu::minimum(a[2], b[2]), basisu::minimum(a[3], b[3])); } + static color32 comp_max(const color32& a, const color32& b) { return color32(cNoClamp, basisu::maximum(a[0], b[0]), basisu::maximum(a[1], b[1]), basisu::maximum(a[2], b[2]), basisu::maximum(a[3], b[3])); } + }; + + struct endpoint + { + color32 m_color5; + uint8_t m_inten5; + bool operator== (const endpoint& rhs) const + { + return (m_color5.r == rhs.m_color5.r) && (m_color5.g == rhs.m_color5.g) && (m_color5.b == rhs.m_color5.b) && (m_inten5 == rhs.m_inten5); + } + bool operator!= (const endpoint& rhs) const { return !(*this == rhs); } + }; + + struct selector + { + // Plain selectors (2-bits per value) + uint8_t m_selectors[4]; + + // ETC1 selectors + uint8_t m_bytes[4]; + + uint8_t m_lo_selector, m_hi_selector; + uint8_t m_num_unique_selectors; + bool operator== (const selector& rhs) const + { + return (m_selectors[0] == rhs.m_selectors[0]) && + (m_selectors[1] == rhs.m_selectors[1]) && + (m_selectors[2] == rhs.m_selectors[2]) && + (m_selectors[3] == rhs.m_selectors[3]); + } + bool operator!= (const selector& rhs) const + { + return !(*this == rhs); + } + + void init_flags() + { + uint32_t hist[4] = { 0, 0, 0, 0 }; + for (uint32_t y = 0; y < 4; y++) + { + for (uint32_t x = 0; x < 4; x++) + { + uint32_t s = get_selector(x, y); + hist[s]++; + } + } + + m_lo_selector = 3; + m_hi_selector = 0; + m_num_unique_selectors = 0; + + for (uint32_t i = 0; i < 4; i++) + { + if (hist[i]) + { + m_num_unique_selectors++; + if (i < m_lo_selector) m_lo_selector = static_cast(i); + if (i > m_hi_selector) m_hi_selector = static_cast(i); + } + } + } + + // Returned selector value ranges from 0-3 and is a direct index into g_etc1_inten_tables. + inline uint32_t get_selector(uint32_t x, uint32_t y) const + { + assert((x < 4) && (y < 4)); + return (m_selectors[y] >> (x * 2)) & 3; + } + + void set_selector(uint32_t x, uint32_t y, uint32_t val) + { + static const uint8_t s_selector_index_to_etc1[4] = { 3, 2, 0, 1 }; + + assert((x | y | val) < 4); + + m_selectors[y] &= ~(3 << (x * 2)); + m_selectors[y] |= (val << (x * 2)); + + const uint32_t etc1_bit_index = x * 4 + y; + + uint8_t *p = &m_bytes[3 - (etc1_bit_index >> 3)]; + + const uint32_t byte_bit_ofs = etc1_bit_index & 7; + const uint32_t mask = 1 << byte_bit_ofs; + + const uint32_t etc1_val = s_selector_index_to_etc1[val]; + + const uint32_t lsb = etc1_val & 1; + const uint32_t msb = etc1_val >> 1; + + p[0] &= ~mask; + p[0] |= (lsb << byte_bit_ofs); + + p[-2] &= ~mask; + p[-2] |= (msb << byte_bit_ofs); + } + }; + + bool basis_block_format_is_uncompressed(block_format tex_type); + +} // namespace basist + + + diff --git a/ext/basis_universal/basisu_transcoder_tables_astc.inc b/ext/basis_universal/basisu_transcoder_tables_astc.inc new file mode 100644 index 0000000000..cd634c0df5 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_astc.inc @@ -0,0 +1,481 @@ +{0,2,18},{0,32,2},{0,16,10},{0,16,10},{0,32,35},{0,16,27},{0,16,11},{0,16,27},{0,16,36},{0,16,28},{0,2,18},{0,32,2},{0,16,10},{0,16,10},{16,0,35},{0,16,27},{0,16,11},{0,16,27},{32,0,35},{0,16,27},{0,16,1},{0,16,1},{0,16,1},{0,16,1},{0,16,2},{0,16,2},{0,16,2},{0,0,4},{0,0,4},{0,0,4},{0,16,1}, +{0,16,1},{0,16,1},{0,16,1},{0,16,2},{0,16,2},{0,16,2},{0,0,4},{16,0,2},{0,0,4},{0,2,18},{0,32,2},{0,16,10},{0,16,10},{0,2,18},{2,0,18},{0,16,10},{0,16,18},{2,0,18},{0,16,18},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,4,44},{16,18,27},{16,2,30}, +{16,2,30},{0,4,52},{0,18,20},{0,2,1},{0,32,27},{0,2,77},{0,32,36},{16,4,19},{16,18,2},{16,2,5},{16,2,5},{32,32,51},{0,18,20},{0,2,1},{0,32,27},{32,32,51},{0,32,27},{16,18,26},{16,18,26},{16,18,26},{16,32,27},{0,34,8},{0,2,1},{0,2,1},{0,32,2},{0,32,19},{0,32,11},{16,18,1},{16,18,1},{16,18,1},{16,32,2},{16,2,8}, +{0,2,1},{0,2,1},{0,32,2},{34,0,8},{0,32,2},{16,4,18},{16,18,1},{16,2,4},{0,2,0},{16,4,18},{4,16,18},{0,2,0},{0,32,26},{4,16,18},{0,32,26},{16,0,26},{16,0,26},{16,0,26},{16,0,26},{0,18,0},{0,18,0},{0,18,0},{0,32,1},{0,16,10},{0,16,10},{32,36,36},{32,4,20},{32,34,31},{32,18,28},{16,6,60},{32,34,31},{32,18,19}, +{16,18,28},{0,34,52},{0,18,22},{2,4,22},{2,34,6},{2,18,14},{2,18,14},{18,2,51},{32,34,22},{32,18,10},{0,18,18},{38,0,51},{0,18,18},{32,4,19},{32,4,19},{32,4,19},{32,18,19},{32,34,17},{32,18,10},{32,18,10},{32,2,13},{16,18,14},{16,2,8},{2,18,5},{2,18,5},{2,18,5},{2,18,5},{2,2,8},{32,18,1},{32,18,1},{32,2,4},{2,2,8}, +{32,2,4},{4,0,18},{32,4,2},{2,18,10},{0,34,9},{4,0,18},{8,0,18},{0,34,9},{0,18,18},{8,0,18},{0,18,18},{32,0,18},{32,0,18},{32,0,18},{32,0,18},{32,18,9},{32,18,9},{32,18,9},{32,2,9},{16,2,4},{16,2,4},{18,6,44},{18,20,26},{18,4,30},{18,4,30},{2,6,52},{2,20,21},{2,4,1},{2,34,27},{16,20,52},{32,34,27},{18,6,19}, +{18,20,1},{18,4,5},{18,4,5},{20,16,51},{2,20,21},{2,4,1},{2,34,27},{16,20,51},{2,34,27},{18,20,26},{18,20,26},{18,20,26},{18,34,27},{2,36,8},{2,4,1},{2,4,1},{2,34,2},{32,4,11},{32,34,2},{18,20,1},{18,20,1},{18,20,1},{18,34,2},{18,4,8},{2,4,1},{2,4,1},{2,34,2},{36,2,8},{2,34,2},{36,0,18},{18,20,0},{18,4,4}, +{2,4,0},{36,0,18},{6,18,18},{2,4,0},{0,34,26},{6,18,18},{0,34,26},{18,0,26},{18,0,26},{18,0,26},{18,0,26},{2,4,1},{2,4,1},{2,4,1},{2,34,1},{32,34,1},{32,34,1},{34,8,40},{34,6,21},{34,36,33},{34,36,28},{34,22,55},{34,36,25},{34,36,13},{34,20,31},{32,6,55},{18,20,20},{4,6,21},{4,36,5},{4,36,5},{4,20,11},{22,0,51}, +{34,36,21},{34,36,9},{2,20,19},{32,6,51},{2,20,19},{34,6,21},{34,6,21},{34,6,21},{34,20,21},{34,6,14},{34,20,6},{34,20,6},{34,4,14},{18,20,11},{18,20,11},{4,36,1},{4,36,1},{4,36,1},{4,20,2},{2,24,8},{34,20,2},{34,20,2},{4,4,10},{28,0,8},{4,4,10},{22,16,18},{34,6,1},{4,36,4},{18,36,4},{22,16,18},{44,16,18},{18,36,4}, +{0,20,18},{44,16,18},{0,20,18},{34,0,20},{34,0,20},{34,0,20},{34,0,20},{34,20,5},{34,20,5},{34,20,5},{34,4,5},{18,20,2},{18,20,2},{20,8,46},{20,22,27},{20,6,31},{20,6,28},{4,24,52},{4,22,19},{4,6,7},{4,6,36},{18,22,56},{34,6,31},{20,8,21},{20,22,2},{20,6,6},{20,6,3},{36,6,51},{4,22,18},{4,6,6},{18,6,26},{31,0,51}, +{18,6,26},{20,22,26},{20,22,26},{20,22,26},{20,6,27},{4,38,9},{4,6,6},{4,6,6},{4,36,1},{34,6,9},{4,36,4},{20,22,1},{20,22,1},{20,22,1},{20,6,2},{22,2,8},{20,36,4},{20,36,4},{4,36,0},{42,2,8},{4,36,0},{22,4,18},{20,22,1},{36,6,2},{4,6,2},{22,4,18},{15,0,18},{4,6,2},{0,6,26},{15,0,18},{0,6,26},{20,0,26}, +{20,0,26},{20,0,26},{20,0,26},{4,22,1},{4,22,1},{4,22,1},{4,36,1},{4,36,4},{4,36,4},{36,40,38},{36,8,22},{36,38,33},{36,38,28},{36,24,55},{36,38,25},{36,38,13},{20,22,28},{34,8,55},{4,22,23},{6,8,21},{6,38,5},{6,38,5},{6,22,11},{24,2,51},{36,38,21},{20,38,9},{4,22,19},{13,0,51},{4,22,19},{36,8,21},{36,8,21},{36,8,21}, +{36,22,21},{36,8,14},{36,22,6},{36,22,6},{36,6,14},{4,38,10},{4,22,14},{6,38,1},{6,38,1},{6,38,1},{6,22,2},{8,2,8},{36,22,2},{36,22,2},{6,6,10},{30,2,8},{6,6,10},{10,0,18},{36,8,2},{6,38,4},{4,38,5},{10,0,18},{4,8,18},{4,38,5},{0,22,18},{4,8,18},{0,22,18},{36,0,20},{36,0,20},{36,0,20},{36,0,20},{36,22,5}, +{36,22,5},{36,22,5},{36,6,5},{4,22,5},{4,22,5},{22,10,46},{22,24,26},{22,8,30},{22,8,30},{6,26,52},{6,24,21},{6,8,5},{6,38,37},{20,24,53},{6,38,40},{22,10,21},{22,24,1},{22,8,5},{22,8,5},{16,11,51},{6,24,20},{6,8,4},{6,38,36},{25,0,51},{6,38,36},{22,24,26},{22,24,26},{22,24,26},{22,8,30},{6,40,9},{6,8,5},{6,8,5}, +{6,38,1},{36,8,11},{6,38,4},{22,24,1},{22,24,1},{22,24,1},{22,8,5},{24,4,8},{6,8,4},{6,8,4},{6,38,0},{11,0,8},{6,38,0},{42,0,18},{22,24,0},{22,8,4},{6,8,0},{42,0,18},{9,0,18},{6,8,0},{0,8,36},{9,0,18},{0,8,36},{22,0,26},{22,0,26},{22,0,26},{22,0,26},{6,24,1},{6,24,1},{6,24,1},{6,38,1},{6,38,4}, +{6,38,4},{38,12,44},{38,10,30},{38,40,46},{38,40,34},{38,26,53},{38,40,21},{38,40,9},{38,24,25},{6,10,57},{22,24,22},{8,10,21},{8,40,5},{8,40,5},{8,24,17},{28,0,51},{38,40,20},{38,40,8},{6,24,21},{37,0,51},{6,24,21},{38,26,26},{38,26,26},{38,26,26},{38,24,30},{38,10,9},{38,40,5},{38,40,5},{38,24,9},{22,24,11},{22,24,6},{8,40,1}, +{8,40,1},{8,40,1},{8,24,1},{38,10,8},{8,24,4},{8,24,4},{6,24,5},{23,0,8},{6,24,5},{16,7,18},{38,10,4},{8,40,4},{6,40,5},{16,7,18},{21,0,18},{6,40,5},{0,24,20},{21,0,18},{0,24,20},{38,0,26},{38,0,26},{38,0,26},{38,0,26},{38,40,1},{38,40,1},{38,40,1},{38,8,2},{22,24,2},{22,24,2},{24,12,38},{24,26,22},{24,10,30}, +{24,10,22},{8,28,52},{8,26,19},{8,10,6},{8,40,37},{38,26,55},{38,10,30},{24,12,22},{24,26,6},{24,10,14},{24,10,6},{42,6,51},{8,26,18},{24,10,3},{22,10,26},{19,0,51},{22,10,26},{24,26,21},{24,26,21},{24,26,21},{24,10,21},{8,42,9},{8,10,5},{8,10,5},{8,40,1},{38,10,8},{8,40,4},{24,26,5},{24,26,5},{24,26,5},{24,10,5},{28,2,8}, +{24,10,2},{24,10,2},{8,40,0},{42,8,8},{8,40,0},{26,8,18},{24,26,2},{40,10,2},{8,10,1},{26,8,18},{15,6,18},{8,10,1},{0,10,26},{15,6,18},{0,10,26},{24,0,20},{24,0,20},{24,0,20},{24,0,20},{8,26,1},{8,26,1},{8,26,1},{8,40,1},{38,10,4},{38,10,4},{40,14,40},{40,12,21},{40,42,33},{40,42,33},{40,28,55},{40,42,23},{40,42,18}, +{40,26,33},{8,12,57},{24,26,22},{10,12,21},{10,42,5},{10,42,5},{10,26,17},{30,2,51},{40,42,19},{24,42,14},{8,26,21},{35,2,51},{8,26,21},{40,12,21},{40,12,21},{40,12,21},{40,26,21},{40,12,14},{40,26,6},{40,26,6},{40,10,14},{8,42,10},{24,26,6},{10,42,1},{10,42,1},{10,42,1},{10,26,1},{16,3,8},{40,26,2},{40,26,2},{8,26,5},{17,0,8}, +{8,26,5},{16,1,18},{40,12,1},{10,42,4},{8,42,5},{16,1,18},{19,2,18},{8,42,5},{0,26,20},{19,2,18},{0,26,20},{40,0,20},{40,0,20},{40,0,20},{40,0,20},{40,26,5},{40,26,5},{40,26,5},{40,10,5},{24,26,2},{24,26,2},{26,14,38},{26,28,22},{26,12,30},{26,12,22},{10,30,52},{10,28,21},{10,12,6},{10,42,37},{24,28,53},{40,12,31},{26,14,22}, +{26,28,6},{26,12,14},{26,12,6},{47,2,51},{10,28,20},{26,12,3},{24,12,26},{17,2,51},{24,12,26},{26,28,21},{26,28,21},{26,28,21},{26,12,21},{10,44,9},{10,12,5},{10,12,5},{10,42,1},{40,12,9},{40,42,2},{26,28,5},{26,28,5},{26,28,5},{26,12,5},{30,4,8},{26,12,2},{26,12,2},{10,42,0},{15,8,8},{10,42,0},{15,0,18},{26,28,2},{42,12,5}, +{10,12,1},{15,0,18},{5,4,18},{10,12,1},{0,12,26},{5,4,18},{0,12,26},{26,0,20},{26,0,20},{26,0,20},{26,0,20},{10,28,1},{10,28,1},{10,28,1},{10,42,1},{40,42,2},{40,42,2},{42,47,46},{42,14,31},{12,44,37},{42,44,31},{42,46,52},{42,44,21},{42,44,6},{42,28,25},{10,14,51},{26,28,20},{12,30,18},{12,14,2},{12,44,1},{12,44,10},{29,0,51}, +{42,44,20},{42,44,5},{26,28,20},{37,6,51},{26,28,20},{42,30,26},{42,30,26},{42,30,26},{42,28,30},{42,14,9},{42,44,5},{42,44,5},{42,28,9},{10,44,9},{26,28,4},{12,44,0},{12,44,0},{12,44,0},{12,28,0},{45,0,8},{12,28,4},{12,28,4},{26,28,4},{27,8,8},{26,28,4},{45,2,18},{12,14,2},{12,44,1},{26,44,1},{45,2,18},{25,8,18},{26,44,1}, +{0,28,20},{25,8,18},{0,28,20},{42,0,26},{42,0,26},{42,0,26},{42,0,26},{42,44,1},{42,44,1},{42,44,1},{42,12,5},{26,28,0},{26,28,0},{28,47,38},{28,30,22},{28,14,33},{28,14,25},{12,31,55},{12,30,23},{12,14,18},{12,14,33},{42,30,55},{42,14,21},{28,47,22},{28,30,6},{44,14,14},{28,14,9},{46,10,51},{12,30,19},{28,14,6},{26,14,21},{23,8,51}, +{26,14,21},{28,30,21},{28,30,21},{28,30,21},{28,14,21},{12,46,14},{12,14,14},{12,14,14},{12,44,6},{42,14,10},{12,44,6},{28,30,5},{28,30,5},{28,30,5},{28,14,5},{29,2,8},{28,14,2},{28,14,2},{12,44,2},{35,6,8},{12,44,2},{8,7,18},{28,30,2},{44,14,5},{12,14,5},{8,7,18},{33,6,18},{12,14,5},{0,14,20},{33,6,18},{0,14,20},{28,0,20}, +{28,0,20},{28,0,20},{28,0,20},{12,30,5},{12,30,5},{12,30,5},{12,44,5},{42,14,1},{42,14,1},{44,15,46},{44,47,27},{14,46,37},{44,46,31},{44,31,53},{44,46,21},{44,46,6},{44,30,25},{42,47,55},{28,30,22},{14,31,20},{14,47,8},{14,46,1},{14,46,10},{38,3,51},{44,46,20},{44,46,5},{12,30,21},{35,8,51},{12,30,21},{44,31,26},{44,31,26},{44,31,26}, +{44,30,30},{44,47,11},{44,46,5},{44,46,5},{44,30,9},{12,46,9},{28,30,6},{14,46,0},{14,46,0},{14,46,0},{14,30,0},{43,2,8},{14,30,4},{14,30,4},{12,30,5},{21,8,8},{12,30,5},{41,0,18},{44,47,1},{14,46,1},{28,46,1},{41,0,18},{19,8,18},{28,46,1},{0,30,20},{19,8,18},{0,30,20},{44,0,26},{44,0,26},{44,0,26},{44,0,26},{44,46,1}, +{44,46,1},{44,46,1},{44,14,5},{28,30,2},{28,30,2},{30,45,38},{30,31,21},{30,47,24},{30,47,24},{14,29,55},{14,31,22},{14,47,8},{14,46,55},{28,31,53},{44,47,41},{30,45,22},{30,31,5},{30,47,8},{30,47,8},{41,2,51},{14,31,18},{14,47,4},{12,47,37},{17,8,51},{12,47,37},{30,31,20},{30,31,20},{30,31,20},{30,47,24},{14,15,14},{14,47,8},{14,47,8}, +{14,46,6},{44,47,9},{14,46,6},{30,31,4},{30,31,4},{30,31,4},{30,47,8},{38,1,8},{14,47,4},{14,47,4},{14,46,2},{43,28,8},{14,46,2},{9,0,18},{30,31,1},{46,47,1},{14,47,0},{9,0,18},{0,9,18},{14,47,0},{0,47,36},{0,9,18},{0,47,36},{30,0,20},{30,0,20},{30,0,20},{30,0,20},{14,31,4},{14,31,4},{14,31,4},{14,46,5},{14,46,5}, +{14,46,5},{46,43,54},{46,45,41},{47,15,55},{46,15,44},{46,13,51},{46,15,20},{46,15,8},{46,31,24},{14,45,56},{30,31,21},{47,29,21},{47,15,6},{47,15,6},{47,31,17},{23,0,51},{46,15,20},{46,15,8},{30,31,20},{18,9,51},{30,31,20},{46,13,37},{46,13,37},{46,13,37},{46,15,40},{46,45,8},{46,15,4},{46,15,4},{46,31,8},{14,15,14},{30,31,5},{47,15,2}, +{47,15,2},{47,15,2},{47,31,1},{39,0,8},{46,15,4},{46,15,4},{30,31,4},{9,28,8},{30,31,4},{39,2,18},{47,15,5},{47,15,5},{30,15,4},{39,2,18},{34,9,18},{30,15,4},{0,31,20},{34,9,18},{0,31,20},{46,0,36},{46,0,36},{46,0,36},{46,0,36},{46,15,0},{46,15,0},{46,15,0},{46,47,1},{30,31,1},{30,31,1},{31,43,38},{31,29,22},{31,45,25}, +{31,45,22},{47,43,53},{47,29,19},{47,45,6},{47,15,37},{46,29,52},{46,45,27},{31,43,22},{31,29,6},{31,45,9},{31,45,6},{9,6,51},{47,29,18},{47,45,5},{30,45,26},{32,7,51},{30,45,26},{31,13,21},{31,13,21},{31,13,21},{31,45,21},{47,13,9},{47,45,5},{47,45,5},{47,15,1},{46,45,10},{46,15,8},{31,13,5},{31,13,5},{31,13,5},{31,45,5},{23,2,8}, +{31,15,4},{31,15,4},{47,15,0},{20,9,8},{47,15,0},{47,11,18},{31,29,2},{15,45,5},{47,45,1},{47,11,18},{22,9,18},{47,45,1},{0,45,26},{22,9,18},{0,45,26},{31,0,20},{31,0,20},{31,0,20},{31,0,20},{47,29,1},{47,29,1},{47,29,1},{47,15,1},{46,45,1},{46,45,1},{15,11,38},{15,43,21},{15,13,33},{15,13,33},{15,27,55},{15,13,23},{15,13,18}, +{15,29,33},{47,13,59},{31,29,22},{45,27,21},{45,13,6},{45,13,6},{45,29,17},{21,2,51},{15,13,19},{15,13,14},{31,29,21},{24,9,51},{31,29,21},{15,27,21},{15,27,21},{15,27,21},{15,29,21},{15,13,14},{15,29,6},{15,29,6},{15,45,14},{47,13,10},{31,29,6},{45,13,2},{45,13,2},{45,13,2},{45,29,1},{37,2,8},{15,29,2},{15,29,2},{31,29,5},{34,7,8}, +{31,29,5},{35,0,18},{15,43,1},{45,13,5},{31,13,5},{35,0,18},{36,7,18},{31,13,5},{0,29,20},{36,7,18},{0,29,20},{15,0,20},{15,0,20},{15,0,20},{15,0,20},{15,13,5},{15,13,5},{15,13,5},{15,45,5},{31,29,2},{31,29,2},{29,41,38},{29,27,20},{29,43,25},{29,43,25},{45,41,53},{45,27,21},{45,43,6},{45,13,37},{31,27,53},{15,43,31},{29,41,22}, +{29,27,4},{29,43,9},{29,43,9},{35,2,51},{45,27,20},{45,43,5},{31,43,26},{34,5,51},{31,43,26},{29,27,20},{29,27,20},{29,27,20},{29,13,24},{45,11,9},{45,43,5},{45,43,5},{45,13,1},{15,43,9},{15,13,2},{29,27,4},{29,27,4},{29,27,4},{29,13,8},{44,1,8},{29,13,4},{29,13,4},{45,13,0},{26,9,8},{45,13,0},{3,0,18},{29,27,0},{13,43,5}, +{45,43,1},{3,0,18},{0,3,18},{45,43,1},{0,43,26},{0,3,18},{0,43,26},{29,0,20},{29,0,20},{29,0,20},{29,0,20},{45,27,1},{45,27,1},{45,27,1},{45,13,1},{15,13,2},{15,13,2},{13,9,46},{13,41,31},{43,11,37},{13,11,31},{13,25,53},{13,11,21},{13,11,6},{13,27,30},{29,11,56},{29,27,22},{43,25,18},{43,41,2},{43,11,1},{43,27,16},{17,0,51}, +{13,11,20},{13,11,5},{29,27,21},{18,3,51},{29,27,21},{13,25,26},{13,25,26},{13,25,26},{13,27,27},{13,41,9},{13,27,3},{13,27,3},{13,27,14},{45,11,9},{29,27,6},{43,11,0},{43,11,0},{43,11,0},{43,27,0},{31,5,8},{13,27,2},{13,27,2},{29,27,5},{14,9,8},{29,27,5},{31,3,18},{43,41,2},{43,11,1},{29,11,1},{31,3,18},{34,3,18},{29,11,1}, +{0,27,20},{34,3,18},{0,27,20},{13,0,26},{13,0,26},{13,0,26},{13,0,26},{13,11,1},{13,11,1},{13,11,1},{13,43,5},{29,27,2},{29,27,2},{27,39,38},{27,25,22},{27,41,33},{27,41,25},{43,23,55},{43,25,23},{43,41,18},{43,41,33},{13,25,55},{13,41,21},{27,39,22},{27,25,6},{11,41,14},{27,41,9},{27,9,51},{43,25,19},{27,41,6},{13,41,21},{14,7,51}, +{13,41,21},{27,9,21},{27,9,21},{27,9,21},{27,41,21},{43,9,14},{43,25,14},{43,25,14},{43,11,5},{13,41,10},{43,11,5},{27,9,5},{27,9,5},{27,9,5},{27,41,5},{17,2,8},{27,41,2},{27,41,2},{43,11,1},{16,1,8},{43,11,1},{43,7,18},{27,25,2},{11,41,5},{27,41,5},{43,7,18},{18,1,18},{27,41,5},{0,41,20},{18,1,18},{0,41,20},{27,0,20}, +{27,0,20},{27,0,20},{27,0,20},{43,9,5},{43,9,5},{43,9,5},{43,11,4},{13,41,1},{13,41,1},{11,7,46},{11,39,30},{41,9,37},{11,9,31},{11,23,53},{11,9,21},{11,9,6},{11,25,30},{13,39,55},{27,25,22},{41,23,18},{41,9,4},{41,9,1},{41,25,16},{17,6,51},{11,9,20},{11,9,5},{27,25,21},{20,1,51},{27,25,21},{11,23,26},{11,23,26},{11,23,26}, +{11,25,27},{11,39,9},{11,25,3},{11,25,3},{11,25,14},{43,9,9},{27,25,6},{41,9,0},{41,9,0},{41,9,0},{41,25,0},{29,3,8},{11,25,2},{11,25,2},{27,25,5},{43,9,8},{27,25,5},{29,1,18},{41,9,4},{41,9,1},{27,9,1},{29,1,18},{36,1,18},{27,9,1},{0,25,20},{36,1,18},{0,25,20},{11,0,26},{11,0,26},{11,0,26},{11,0,26},{11,9,1}, +{11,9,1},{11,9,1},{11,41,2},{27,25,2},{27,25,2},{25,37,38},{25,23,22},{25,39,25},{25,39,25},{41,21,55},{41,23,23},{41,39,9},{41,39,46},{27,23,53},{11,39,30},{25,37,22},{25,23,6},{25,39,9},{25,39,9},{27,3,51},{41,23,19},{41,39,5},{27,39,26},{39,9,51},{27,39,26},{25,7,21},{25,7,21},{25,7,21},{25,9,24},{41,7,14},{41,39,8},{41,39,8}, +{41,9,5},{11,39,8},{41,9,5},{25,7,5},{25,7,5},{25,7,5},{25,9,8},{39,11,8},{25,9,4},{25,9,4},{41,9,1},{22,1,8},{41,9,1},{41,5,18},{25,23,2},{9,39,2},{41,39,1},{41,5,18},{23,9,18},{41,39,1},{0,39,26},{23,9,18},{0,39,26},{25,0,20},{25,0,20},{25,0,20},{25,0,20},{41,7,5},{41,7,5},{41,7,5},{41,9,4},{41,9,4}, +{41,9,4},{39,21,54},{39,7,40},{39,7,37},{9,7,41},{9,5,51},{9,7,20},{9,7,5},{9,23,30},{41,37,51},{25,23,26},{39,21,18},{39,7,4},{39,7,1},{39,7,17},{11,1,51},{9,7,20},{9,7,5},{25,23,26},{5,9,51},{25,23,26},{39,7,36},{39,7,36},{39,7,36},{39,23,36},{9,21,10},{9,7,4},{9,7,4},{9,23,5},{41,7,12},{25,23,1},{39,7,0}, +{39,7,0},{39,7,0},{39,23,0},{25,5,8},{9,7,4},{9,7,4},{25,23,1},{10,1,8},{25,23,1},{25,3,18},{39,7,4},{39,7,1},{25,7,1},{25,3,18},{12,1,18},{25,7,1},{0,23,26},{12,1,18},{0,23,26},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,7,0},{9,7,0},{9,7,0},{9,23,4},{25,23,0},{25,23,0},{23,19,38},{23,5,23},{23,21,28}, +{23,37,23},{39,19,55},{39,21,25},{39,37,13},{39,37,33},{9,21,53},{9,37,22},{7,21,27},{23,5,14},{7,37,14},{23,37,14},{23,5,51},{39,21,21},{23,37,6},{9,37,21},{14,1,51},{9,37,21},{23,5,19},{23,5,19},{23,5,19},{23,37,19},{39,5,14},{39,21,9},{39,21,9},{39,7,5},{9,37,11},{39,7,5},{23,5,10},{23,5,10},{23,5,10},{7,7,10},{9,3,8}, +{23,37,2},{23,37,2},{39,7,1},{31,3,8},{39,7,1},{37,7,18},{23,5,5},{7,37,5},{23,37,5},{37,7,18},{30,1,18},{23,37,5},{0,37,20},{30,1,18},{0,37,20},{23,0,18},{23,0,18},{23,0,18},{23,0,18},{39,5,5},{39,5,5},{39,5,5},{39,7,4},{9,37,2},{9,37,2},{7,33,44},{7,35,31},{7,5,36},{7,5,31},{7,19,53},{7,5,22},{7,5,7}, +{7,21,31},{39,35,57},{23,21,27},{37,19,20},{37,5,4},{37,5,1},{37,5,17},{23,17,51},{7,5,21},{7,5,6},{23,21,26},{45,17,51},{23,21,26},{7,19,26},{7,19,26},{7,19,26},{7,5,30},{7,35,9},{7,5,6},{7,5,6},{7,21,6},{39,5,9},{23,21,2},{37,5,0},{37,5,0},{37,5,0},{37,21,0},{23,3,8},{37,21,4},{37,21,4},{23,21,1},{43,3,8}, +{23,21,1},{23,1,18},{37,5,4},{37,5,1},{23,5,1},{23,1,18},{33,7,18},{23,5,1},{0,21,26},{33,7,18},{0,21,26},{7,0,26},{7,0,26},{7,0,26},{7,0,26},{7,5,2},{7,5,2},{7,5,2},{7,37,2},{23,21,1},{23,21,1},{21,17,38},{21,19,20},{21,35,31},{21,35,23},{37,17,55},{37,19,22},{37,35,13},{37,35,33},{23,19,56},{7,35,21},{5,19,27}, +{21,19,11},{5,35,14},{21,35,14},{21,3,51},{37,19,18},{21,35,6},{7,35,21},{43,1,51},{7,35,21},{21,3,19},{21,3,19},{21,3,19},{21,35,19},{37,3,14},{37,35,9},{37,35,9},{37,5,5},{7,35,10},{37,5,5},{21,3,10},{21,3,10},{21,3,10},{5,5,10},{3,25,8},{21,35,2},{21,35,2},{37,5,1},{29,1,8},{37,5,1},{35,5,18},{21,19,2},{5,35,5}, +{21,35,5},{35,5,18},{27,1,18},{21,35,5},{0,35,20},{27,1,18},{0,35,20},{21,0,18},{21,0,18},{21,0,18},{21,0,18},{37,19,4},{37,19,4},{37,19,4},{37,5,4},{7,35,1},{7,35,1},{35,17,44},{35,33,27},{35,3,27},{35,3,35},{5,1,51},{5,3,26},{5,3,1},{5,19,30},{37,33,51},{21,19,26},{35,17,19},{35,33,2},{35,3,2},{35,3,10},{5,1,51}, +{5,3,26},{5,3,1},{21,19,26},{9,1,51},{21,19,26},{35,3,27},{35,3,27},{35,3,27},{35,19,27},{5,17,10},{5,3,1},{5,3,1},{5,19,5},{37,3,12},{21,19,1},{35,3,2},{35,3,2},{35,3,2},{35,19,2},{19,5,8},{5,3,1},{5,3,1},{21,19,1},{37,3,8},{21,19,1},{19,3,18},{35,33,1},{35,3,1},{5,3,1},{19,3,18},{39,1,18},{5,3,1}, +{0,19,26},{39,1,18},{0,19,26},{35,0,26},{35,0,26},{35,0,26},{35,0,26},{5,3,0},{5,3,0},{5,3,0},{5,19,4},{21,19,0},{21,19,0},{19,1,54},{19,1,22},{19,17,28},{19,33,27},{19,1,61},{35,17,30},{19,33,19},{35,33,31},{5,17,52},{5,33,20},{3,1,24},{3,17,8},{3,33,13},{3,33,17},{17,5,51},{35,17,21},{19,33,10},{5,33,19},{5,17,51}, +{5,33,19},{19,1,18},{19,1,18},{19,1,18},{19,33,18},{19,17,19},{19,33,10},{19,33,10},{19,3,14},{5,33,11},{35,3,6},{3,33,4},{3,33,4},{3,33,4},{3,3,8},{3,3,8},{19,33,1},{19,33,1},{19,3,5},{3,3,8},{19,3,5},{33,33,18},{19,1,4},{3,33,9},{19,33,9},{33,33,18},{33,33,18},{19,33,9},{0,33,18},{33,33,18},{0,33,18},{19,0,18}, +{19,0,18},{19,0,18},{19,0,18},{35,1,9},{35,1,9},{35,1,9},{19,3,10},{35,3,2},{35,3,2},{33,1,76},{33,1,36},{33,1,27},{33,1,35},{33,1,84},{3,1,26},{3,1,1},{3,17,30},{19,1,56},{19,17,27},{17,1,43},{33,1,11},{33,1,2},{33,1,10},{1,3,51},{3,1,26},{3,1,1},{19,17,26},{3,1,51},{19,17,26},{33,1,27},{33,1,27},{33,1,27}, +{33,17,26},{3,1,16},{3,1,1},{3,1,1},{3,17,5},{35,1,12},{19,17,2},{33,1,2},{33,1,2},{33,1,2},{33,17,1},{17,3,8},{3,1,1},{3,1,1},{19,17,1},{35,1,8},{19,17,1},{17,1,18},{17,1,10},{33,1,1},{19,1,0},{17,1,18},{33,1,18},{19,1,0},{0,17,26},{33,1,18},{0,17,26},{33,0,26},{33,0,26},{33,0,26},{33,0,26},{3,1,0}, +{3,1,0},{3,1,0},{3,17,4},{19,17,1},{19,17,1},{17,1,36},{17,1,28},{17,1,27},{17,1,19},{17,1,28},{17,1,12},{17,1,11},{17,1,10},{33,1,20},{33,1,2},{1,1,4},{1,1,4},{1,1,4},{1,1,4},{1,17,3},{17,1,3},{17,1,2},{17,1,1},{17,1,3},{17,1,1},{17,1,27},{17,1,27},{17,1,27},{17,1,19},{17,1,19},{17,1,11},{17,1,11}, +{17,1,10},{33,1,11},{33,1,2},{1,1,4},{1,1,4},{1,1,4},{1,1,4},{1,17,2},{17,1,2},{17,1,2},{17,1,1},{17,1,2},{17,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{17,0,18},{17,0,18},{17,0,18},{17,0,18},{17,1,10},{17,1,10},{17,1,10},{17,1,10},{33,1,2}, +{33,1,2},{0,4,74},{0,18,10},{0,2,1},{0,2,26},{0,34,154},{0,2,99},{0,32,49},{0,32,121},{0,32,162},{0,32,130},{0,4,74},{0,18,10},{0,2,1},{0,2,26},{32,0,153},{0,2,99},{0,32,49},{0,32,121},{0,32,153},{0,32,121},{0,2,0},{0,2,0},{0,2,0},{0,16,4},{0,32,13},{0,16,5},{0,16,5},{0,16,9},{0,16,14},{0,16,10},{0,2,0}, +{0,2,0},{0,2,0},{0,16,4},{16,0,13},{0,16,5},{0,16,5},{0,16,9},{32,0,13},{0,16,9},{32,32,72},{0,18,10},{0,2,1},{0,2,26},{32,32,72},{32,32,72},{0,2,26},{0,32,72},{32,32,72},{0,32,72},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,38,81},{0,20,10},{16,34,34}, +{0,18,26},{0,36,243},{0,34,99},{0,18,26},{0,2,139},{0,18,279},{0,2,164},{16,6,76},{16,4,8},{16,34,9},{16,18,24},{18,0,243},{0,34,99},{0,18,26},{0,2,139},{36,0,243},{0,2,139},{0,20,10},{0,20,10},{0,20,10},{0,18,10},{0,34,50},{0,18,10},{0,18,10},{0,32,20},{0,32,61},{0,32,29},{16,4,4},{16,4,4},{16,4,4},{16,2,5},{16,2,50}, +{0,18,10},{0,18,10},{0,32,20},{34,0,50},{0,32,20},{18,2,72},{0,20,1},{16,34,5},{0,18,17},{18,2,72},{38,0,72},{0,18,17},{0,18,80},{38,0,72},{0,18,80},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,32,0},{0,32,0},{0,32,0},{0,16,0},{0,16,1},{0,16,1},{16,24,135},{16,6,66},{16,20,122},{16,4,66},{0,8,244},{0,20,81},{0,4,2}, +{0,34,121},{0,4,344},{0,34,185},{32,8,74},{32,36,1},{32,4,17},{32,4,17},{16,38,243},{0,20,81},{0,4,2},{0,34,121},{38,16,243},{0,34,121},{16,22,61},{16,22,61},{16,22,61},{16,4,65},{0,6,52},{0,4,1},{0,4,1},{0,18,9},{0,18,94},{0,18,45},{32,36,0},{32,36,0},{32,36,0},{32,34,0},{2,2,50},{0,4,1},{0,4,1},{0,18,9},{2,2,50}, +{0,18,9},{20,16,72},{32,36,1},{2,4,1},{0,4,1},{20,16,72},{16,20,72},{0,4,1},{0,34,72},{16,20,72},{0,34,72},{16,0,61},{16,0,61},{16,0,61},{16,0,61},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,32,25},{0,32,25},{32,26,152},{2,22,91},{2,36,119},{32,20,89},{16,10,247},{16,6,78},{16,36,13},{16,4,110},{0,36,293},{0,4,103},{18,8,76}, +{18,6,8},{18,36,9},{2,20,19},{20,2,243},{16,6,74},{32,20,9},{0,4,94},{42,0,243},{0,4,94},{32,8,81},{32,8,81},{32,8,81},{32,20,80},{16,8,54},{16,36,9},{16,36,9},{16,34,8},{0,4,77},{0,34,6},{18,6,4},{18,6,4},{18,6,4},{18,4,5},{18,4,50},{32,20,0},{32,20,0},{16,34,4},{36,2,50},{16,34,4},{18,8,72},{2,22,1},{18,36,5}, +{0,36,4},{18,8,72},{44,0,72},{0,36,4},{0,4,90},{44,0,72},{0,4,90},{32,0,80},{32,0,80},{32,0,80},{32,0,80},{16,6,4},{16,6,4},{16,6,4},{16,34,4},{0,34,2},{0,34,2},{18,42,146},{18,8,83},{18,22,139},{18,6,79},{2,26,243},{2,38,78},{2,6,9},{2,36,110},{0,38,252},{0,36,79},{34,10,73},{34,8,6},{4,6,21},{34,6,14},{38,0,243}, +{2,38,78},{18,6,6},{0,36,75},{30,0,243},{0,36,75},{18,24,75},{18,24,75},{18,24,75},{18,6,75},{2,24,50},{2,6,5},{2,6,5},{2,20,4},{0,6,53},{16,20,2},{34,8,2},{34,8,2},{34,8,2},{34,36,2},{2,24,50},{18,6,2},{18,6,2},{16,20,1},{28,0,50},{16,20,1},{36,6,72},{34,8,5},{4,6,5},{2,6,5},{36,6,72},{31,0,72},{2,6,5}, +{0,36,74},{31,0,72},{0,36,74},{18,0,74},{18,0,74},{18,0,74},{18,0,74},{2,22,0},{2,22,0},{2,22,0},{2,4,4},{16,20,2},{16,20,2},{4,12,154},{4,24,85},{4,38,106},{34,38,95},{18,12,253},{18,8,90},{34,38,15},{18,6,122},{0,24,244},{16,22,93},{20,10,76},{20,8,9},{20,38,6},{20,22,24},{24,0,243},{18,8,81},{34,38,6},{0,22,80},{32,8,243}, +{0,22,80},{4,40,80},{4,40,80},{4,40,80},{4,22,80},{34,24,59},{34,22,10},{34,22,10},{18,36,19},{32,22,53},{32,6,5},{20,8,5},{20,8,5},{20,8,5},{20,6,8},{22,2,50},{34,22,1},{34,22,1},{32,6,4},{42,2,50},{32,6,4},{24,2,72},{20,8,5},{20,38,2},{18,38,1},{24,2,72},{13,0,72},{18,38,1},{0,22,80},{13,0,72},{0,22,80},{4,0,80}, +{4,0,80},{4,0,80},{4,0,80},{34,22,9},{34,22,9},{34,22,9},{18,36,10},{32,6,1},{32,6,1},{20,28,146},{20,10,77},{20,8,122},{20,8,77},{4,28,243},{4,40,78},{4,8,5},{4,38,110},{32,40,244},{2,38,79},{36,12,73},{36,40,2},{6,8,18},{36,8,18},{38,6,243},{34,40,73},{4,8,5},{2,38,75},{27,0,243},{2,38,75},{20,26,73},{20,26,73},{20,26,73}, +{20,8,76},{4,26,50},{4,8,4},{4,8,4},{4,22,4},{2,8,50},{18,22,2},{36,40,1},{36,40,1},{36,40,1},{36,38,2},{8,2,50},{4,8,4},{4,8,4},{18,22,1},{30,2,50},{18,22,1},{16,11,72},{36,40,1},{6,8,2},{4,8,1},{16,11,72},{25,0,72},{4,8,1},{0,38,74},{25,0,72},{0,38,74},{20,0,72},{20,0,72},{20,0,72},{20,0,72},{4,24,0}, +{4,24,0},{4,24,0},{4,6,4},{18,22,2},{18,22,2},{6,14,154},{6,26,85},{6,40,109},{6,24,97},{20,14,248},{20,10,78},{20,40,13},{20,8,110},{2,26,244},{34,8,91},{22,12,76},{22,10,9},{22,40,9},{22,24,29},{26,2,243},{20,10,74},{20,40,9},{2,24,80},{38,8,243},{2,24,80},{6,42,80},{6,42,80},{6,42,80},{6,24,81},{20,12,54},{20,40,9},{20,40,9}, +{20,38,13},{34,24,53},{34,8,10},{22,10,5},{22,10,5},{22,10,5},{22,8,5},{24,4,50},{36,24,1},{36,24,1},{34,8,9},{11,0,50},{34,8,9},{26,4,72},{22,10,5},{22,40,5},{4,40,5},{26,4,72},{7,0,72},{4,40,5},{0,24,80},{7,0,72},{0,24,80},{6,0,80},{6,0,80},{6,0,80},{6,0,80},{20,10,4},{20,10,4},{20,10,4},{20,38,4},{34,8,1}, +{34,8,1},{22,46,146},{22,12,83},{38,26,122},{22,10,79},{6,30,245},{6,42,74},{6,10,10},{6,40,111},{4,42,247},{20,40,79},{38,14,76},{38,12,5},{8,10,21},{38,10,17},{44,0,243},{6,42,73},{6,10,9},{4,40,74},{26,8,243},{4,40,74},{22,28,75},{22,28,75},{22,28,75},{22,10,75},{6,28,51},{6,10,6},{6,10,6},{6,24,6},{4,10,53},{20,24,6},{38,12,4}, +{38,12,4},{38,12,4},{38,40,5},{38,10,50},{22,40,4},{22,40,4},{36,24,1},{23,0,50},{36,24,1},{42,6,72},{38,12,1},{8,10,5},{6,10,5},{42,6,72},{19,0,72},{6,10,5},{0,40,74},{19,0,72},{0,40,74},{22,0,74},{22,0,74},{22,0,74},{22,0,74},{6,26,2},{6,26,2},{6,26,2},{6,8,5},{20,24,5},{20,24,5},{8,46,154},{8,28,85},{8,42,106}, +{8,42,97},{38,46,247},{38,12,82},{38,42,10},{22,26,119},{4,28,247},{36,26,83},{24,14,75},{24,28,6},{24,42,6},{24,26,30},{30,0,243},{38,12,78},{38,42,6},{4,26,75},{33,0,243},{4,26,75},{8,44,80},{8,44,80},{8,44,80},{8,26,80},{38,28,56},{38,26,9},{38,26,9},{38,40,14},{20,42,54},{6,10,9},{24,12,1},{24,12,1},{24,12,1},{24,10,5},{28,2,50}, +{38,26,5},{38,26,5},{6,10,5},{42,8,50},{6,10,5},{30,2,72},{8,28,5},{24,42,5},{22,42,1},{30,2,72},{35,2,72},{22,42,1},{0,26,74},{35,2,72},{0,26,74},{8,0,80},{8,0,80},{8,0,80},{8,0,80},{38,26,5},{38,26,5},{38,26,5},{38,40,5},{6,40,4},{6,40,4},{24,15,146},{24,14,83},{24,28,126},{24,12,79},{8,31,243},{8,44,78},{8,12,9}, +{8,42,110},{36,44,245},{22,42,79},{40,46,75},{40,14,6},{10,12,21},{40,12,14},{47,0,243},{8,44,78},{8,12,9},{6,42,74},{27,6,243},{6,42,74},{24,30,75},{24,30,75},{24,30,75},{24,12,75},{8,14,52},{8,12,5},{8,12,5},{8,26,5},{6,12,53},{22,26,6},{40,14,2},{40,14,2},{40,14,2},{40,42,1},{16,3,50},{24,42,4},{24,42,4},{38,26,1},{17,0,50}, +{38,26,1},{47,2,72},{40,14,5},{10,12,5},{8,12,5},{47,2,72},{17,2,72},{8,12,5},{0,42,74},{17,2,72},{0,42,74},{24,0,74},{24,0,74},{24,0,74},{24,0,74},{8,28,0},{8,28,0},{8,28,0},{8,10,1},{22,26,5},{22,26,5},{10,15,152},{10,30,85},{10,44,106},{40,44,95},{40,31,252},{24,14,90},{40,44,15},{24,12,122},{6,30,247},{38,28,89},{26,47,73}, +{26,30,6},{26,44,6},{26,28,21},{34,3,243},{8,30,76},{40,44,6},{6,28,80},{35,4,243},{6,28,80},{10,46,80},{10,46,80},{10,46,80},{10,28,81},{40,30,59},{40,28,10},{40,28,10},{24,42,18},{22,44,51},{8,12,9},{26,14,1},{26,14,1},{26,14,1},{26,12,5},{30,4,50},{40,28,1},{40,28,1},{8,12,5},{15,8,50},{8,12,5},{15,2,72},{10,30,5},{26,44,5}, +{24,44,1},{15,2,72},{33,4,72},{24,44,1},{0,28,80},{33,4,72},{0,28,80},{10,0,80},{10,0,80},{10,0,80},{10,0,80},{40,28,9},{40,28,9},{40,28,9},{24,42,9},{8,12,5},{8,12,5},{26,13,152},{26,47,89},{42,30,122},{26,14,89},{10,29,245},{10,46,74},{10,30,15},{10,44,106},{8,46,247},{24,44,81},{42,45,76},{42,47,9},{12,30,18},{42,14,17},{4,1,243}, +{10,46,73},{26,14,10},{8,44,80},{1,4,243},{8,44,80},{26,15,80},{26,15,80},{26,15,80},{26,14,80},{10,31,51},{10,30,6},{10,30,6},{10,28,6},{24,14,54},{24,28,6},{42,47,5},{42,47,5},{42,47,5},{42,44,5},{45,0,50},{26,14,1},{26,14,1},{40,28,1},{27,8,50},{40,28,1},{46,10,72},{12,46,5},{12,30,9},{26,14,9},{46,10,72},{23,8,72},{26,14,9}, +{0,44,80},{23,8,72},{0,44,80},{26,0,80},{26,0,80},{26,0,80},{26,0,80},{10,30,2},{10,30,2},{10,30,2},{10,12,5},{24,44,1},{24,44,1},{12,13,148},{12,31,79},{12,46,110},{12,46,83},{42,29,248},{42,47,85},{42,46,5},{26,30,126},{8,31,247},{40,30,83},{28,29,75},{28,47,5},{28,46,5},{28,46,26},{27,0,243},{26,31,80},{42,46,1},{8,30,75},{37,8,243}, +{8,30,75},{12,15,74},{12,15,74},{12,15,74},{12,30,74},{42,15,56},{42,46,5},{42,46,5},{26,14,21},{24,46,56},{10,14,2},{28,47,1},{28,47,1},{28,47,1},{28,14,5},{29,2,50},{42,46,1},{42,46,1},{10,14,1},{35,6,50},{10,14,1},{38,3,72},{28,47,4},{44,46,1},{26,46,1},{38,3,72},{35,8,72},{26,46,1},{0,30,74},{35,8,72},{0,30,74},{12,0,74}, +{12,0,74},{12,0,74},{12,0,74},{42,46,4},{42,46,4},{42,46,4},{42,44,5},{10,14,1},{10,14,1},{28,11,146},{28,45,84},{44,47,121},{28,47,79},{12,27,244},{12,15,79},{12,47,6},{12,46,106},{40,15,244},{26,46,81},{44,43,76},{44,15,6},{14,47,11},{44,47,14},{28,13,243},{42,15,76},{12,47,5},{10,46,80},{27,12,243},{10,46,80},{28,13,75},{28,13,75},{28,13,75}, +{28,47,78},{12,29,51},{12,47,5},{12,47,5},{12,30,6},{10,47,51},{26,30,6},{44,15,5},{44,15,5},{44,15,5},{44,46,5},{43,2,50},{12,47,4},{12,47,4},{42,30,1},{21,8,50},{42,30,1},{41,2,72},{44,15,2},{14,47,2},{12,47,1},{41,2,72},{17,8,72},{12,47,1},{0,46,80},{17,8,72},{0,46,80},{28,0,74},{28,0,74},{28,0,74},{28,0,74},{12,31,1}, +{12,31,1},{12,31,1},{12,14,5},{26,46,1},{26,46,1},{14,11,148},{14,29,79},{14,15,114},{14,31,90},{44,27,248},{28,45,84},{28,15,18},{28,47,115},{10,29,247},{42,47,91},{30,27,75},{30,45,5},{30,15,6},{30,31,21},{40,3,243},{28,45,75},{28,15,9},{10,31,80},{16,9,243},{10,31,80},{14,13,74},{14,13,74},{14,13,74},{14,31,74},{44,13,56},{44,31,6},{44,31,6}, +{44,46,21},{42,31,52},{42,47,10},{30,45,1},{30,45,1},{30,45,1},{30,47,2},{38,1,50},{44,31,2},{44,31,2},{42,47,9},{43,28,50},{42,47,9},{29,12,72},{30,45,4},{30,15,5},{12,15,5},{29,12,72},{26,13,72},{12,15,5},{0,31,80},{26,13,72},{0,31,80},{14,0,74},{14,0,74},{14,0,74},{14,0,74},{44,15,5},{44,15,5},{44,15,5},{44,46,5},{42,47,1}, +{42,47,1},{30,9,154},{46,43,91},{46,29,115},{30,45,85},{14,9,247},{14,13,77},{14,29,18},{14,15,114},{12,13,247},{28,15,79},{46,25,83},{46,43,10},{47,45,21},{46,45,17},{10,1,243},{14,13,73},{30,45,6},{12,15,74},{4,9,243},{12,15,74},{30,11,80},{30,11,80},{30,11,80},{30,45,81},{14,11,56},{14,29,9},{14,29,9},{14,31,6},{12,45,56},{44,31,5},{46,43,9}, +{46,43,9},{46,43,9},{46,15,10},{39,0,50},{30,45,2},{30,45,2},{44,31,1},{9,28,50},{44,31,1},{9,6,72},{46,43,1},{47,45,5},{14,45,5},{9,6,72},{32,7,72},{14,45,5},{0,15,74},{32,7,72},{0,15,74},{30,0,80},{30,0,80},{30,0,80},{30,0,80},{14,13,5},{14,13,5},{14,13,5},{14,31,5},{44,31,4},{44,31,4},{47,9,154},{47,27,81},{47,13,106}, +{47,13,97},{46,9,244},{46,43,79},{46,13,6},{46,45,121},{12,27,248},{44,29,84},{31,25,75},{31,27,6},{31,13,6},{31,29,30},{21,0,243},{46,43,78},{46,13,5},{12,29,75},{18,7,243},{12,29,75},{47,11,80},{47,11,80},{47,11,80},{47,29,80},{46,11,51},{46,13,5},{46,13,5},{46,15,11},{28,13,54},{14,45,6},{31,43,1},{31,43,1},{31,43,1},{31,29,5},{23,2,50}, +{46,13,4},{46,13,4},{14,45,5},{20,9,50},{14,45,5},{21,2,72},{47,27,1},{15,13,5},{30,13,1},{21,2,72},{24,9,72},{30,13,1},{0,29,74},{24,9,72},{0,29,74},{47,0,80},{47,0,80},{47,0,80},{47,0,80},{46,13,1},{46,13,1},{46,13,1},{46,15,2},{14,45,2},{14,45,2},{31,7,146},{31,41,83},{31,27,126},{31,43,79},{47,23,243},{47,11,78},{47,43,5}, +{47,13,110},{14,11,247},{30,13,79},{15,9,75},{15,11,2},{15,27,21},{15,43,14},{14,3,243},{47,11,78},{47,43,5},{14,13,74},{32,5,243},{14,13,74},{31,9,75},{31,9,75},{31,9,75},{31,43,75},{47,25,52},{47,43,1},{47,43,1},{47,29,5},{14,43,56},{46,29,5},{15,11,1},{15,11,1},{15,11,1},{15,13,1},{37,2,50},{47,43,1},{47,43,1},{46,29,1},{34,7,50}, +{46,29,1},{35,2,72},{15,11,1},{45,43,5},{47,43,4},{35,2,72},{34,5,72},{47,43,4},{0,13,74},{34,5,72},{0,13,74},{31,0,74},{31,0,74},{31,0,74},{31,0,74},{47,27,1},{47,27,1},{47,27,1},{47,45,1},{46,29,4},{46,29,4},{45,7,152},{45,25,81},{45,11,106},{45,11,97},{15,23,253},{31,25,90},{31,11,15},{31,43,122},{14,25,247},{46,27,89},{29,39,73}, +{29,25,6},{29,11,6},{29,27,26},{46,3,243},{47,25,76},{31,11,6},{14,27,80},{16,3,243},{14,27,80},{45,9,80},{45,9,80},{45,9,80},{45,27,81},{15,25,59},{15,27,10},{15,27,10},{31,13,18},{30,11,54},{46,43,9},{29,41,1},{29,41,1},{29,41,1},{29,43,2},{44,1,50},{15,27,1},{15,27,1},{46,43,5},{26,9,50},{46,43,5},{46,1,72},{45,25,1},{13,11,5}, +{31,11,2},{46,1,72},{26,7,72},{31,11,2},{0,27,80},{26,7,72},{0,27,80},{45,0,80},{45,0,80},{45,0,80},{45,0,80},{15,27,9},{15,27,9},{15,27,9},{31,13,9},{47,13,5},{47,13,5},{29,5,154},{29,39,89},{13,25,122},{29,41,89},{45,21,245},{45,9,74},{45,41,15},{45,11,106},{47,9,247},{31,11,85},{13,37,76},{13,9,9},{43,25,18},{13,41,17},{1,0,243}, +{45,9,73},{29,41,10},{47,11,80},{0,1,243},{47,11,80},{29,7,80},{29,7,80},{29,7,80},{29,41,80},{45,23,51},{45,41,6},{45,41,6},{45,27,6},{31,41,54},{31,27,6},{13,9,5},{13,9,5},{13,9,5},{13,11,5},{31,5,50},{29,41,1},{29,41,1},{15,27,1},{14,9,50},{15,27,1},{27,9,72},{13,9,5},{43,25,9},{29,41,9},{27,9,72},{14,7,72},{29,41,9}, +{0,11,80},{14,7,72},{0,11,80},{29,0,80},{29,0,80},{29,0,80},{29,0,80},{45,25,1},{45,25,1},{45,25,1},{45,27,5},{31,11,5},{31,11,5},{43,5,148},{43,23,79},{43,9,110},{43,9,83},{13,21,248},{13,39,85},{13,9,9},{29,25,126},{47,23,248},{15,25,83},{27,21,75},{27,23,6},{27,9,5},{27,9,26},{15,1,243},{29,23,74},{13,9,5},{31,25,75},{9,11,243}, +{31,25,75},{43,7,74},{43,7,74},{43,7,74},{43,25,74},{13,7,56},{13,9,9},{13,9,9},{13,11,21},{15,9,56},{15,41,6},{27,39,1},{27,39,1},{27,39,1},{27,25,5},{17,2,50},{43,25,4},{43,25,4},{15,41,2},{16,1,50},{15,41,2},{17,6,72},{27,23,5},{11,9,1},{29,9,0},{17,6,72},{20,1,72},{29,9,0},{0,25,74},{20,1,72},{0,25,74},{43,0,74}, +{43,0,74},{43,0,74},{43,0,74},{13,9,5},{13,9,5},{13,9,5},{13,11,5},{15,41,5},{15,41,5},{27,3,146},{27,37,83},{27,23,119},{27,39,79},{43,19,244},{43,7,79},{43,39,10},{43,9,106},{15,7,245},{29,9,85},{11,35,76},{11,7,9},{41,39,14},{11,39,17},{27,5,243},{13,7,78},{27,39,9},{45,9,80},{6,1,243},{45,9,80},{27,5,75},{27,5,75},{27,5,75}, +{27,39,75},{43,21,51},{43,39,6},{43,39,6},{43,25,6},{45,39,53},{29,25,6},{11,7,5},{11,7,5},{11,7,5},{11,9,5},{29,3,50},{27,39,5},{27,39,5},{13,25,1},{43,9,50},{13,25,1},{27,3,72},{41,7,4},{41,39,5},{27,39,5},{27,3,72},{39,9,72},{27,39,5},{0,9,80},{39,9,72},{0,9,80},{27,0,74},{27,0,74},{27,0,74},{27,0,74},{43,23,1}, +{43,23,1},{43,23,1},{43,25,5},{29,9,5},{29,9,5},{41,3,148},{41,21,79},{41,7,111},{41,7,91},{11,19,248},{11,37,85},{11,7,10},{27,39,122},{45,21,248},{13,23,83},{25,19,75},{25,21,6},{25,7,6},{25,23,30},{17,10,243},{27,21,81},{11,7,6},{29,23,75},{24,1,243},{29,23,75},{41,5,74},{41,5,74},{41,5,74},{41,23,74},{11,5,56},{11,7,9},{11,7,9}, +{11,9,21},{29,7,54},{13,39,5},{25,37,1},{25,37,1},{25,37,1},{25,39,2},{39,11,50},{41,23,4},{41,23,4},{13,39,4},{22,1,50},{13,39,4},{39,7,72},{25,21,5},{9,7,5},{27,7,2},{39,7,72},{26,1,72},{27,7,2},{0,23,74},{26,1,72},{0,23,74},{41,0,74},{41,0,74},{41,0,74},{41,0,74},{11,7,5},{11,7,5},{11,7,5},{11,9,5},{13,39,1}, +{13,39,1},{25,1,154},{9,35,91},{9,21,110},{25,37,89},{41,1,247},{41,5,77},{41,21,13},{41,7,109},{43,5,247},{27,7,85},{39,19,81},{9,35,10},{39,21,13},{9,37,22},{41,1,243},{41,5,73},{41,21,9},{43,7,80},{47,3,243},{43,7,80},{25,3,80},{25,3,80},{25,3,80},{25,37,80},{41,3,56},{41,21,9},{41,21,9},{41,23,9},{27,37,54},{11,23,9},{39,21,9}, +{39,21,9},{39,21,9},{9,7,10},{25,5,50},{25,37,1},{25,37,1},{11,23,5},{10,1,50},{11,23,5},{23,5,72},{9,35,1},{39,21,4},{11,21,4},{23,5,72},{14,1,72},{11,21,4},{0,7,80},{14,1,72},{0,7,80},{25,0,80},{25,0,80},{25,0,80},{25,0,80},{41,5,5},{41,5,5},{41,5,5},{41,23,5},{27,7,5},{27,7,5},{39,1,148},{39,3,79},{39,5,110}, +{39,5,83},{9,1,244},{9,35,79},{9,5,5},{9,21,122},{43,19,248},{11,21,77},{23,17,72},{23,19,2},{23,5,4},{23,5,25},{9,1,243},{25,19,74},{9,5,4},{27,21,73},{46,1,243},{27,21,73},{39,3,75},{39,3,75},{39,3,75},{39,21,75},{9,3,51},{9,5,5},{9,5,5},{9,7,18},{11,5,53},{41,37,2},{23,19,1},{23,19,1},{23,19,1},{23,21,1},{9,3,50}, +{9,5,4},{9,5,4},{41,37,1},{31,3,50},{41,37,1},{23,17,72},{23,19,2},{7,5,4},{25,5,0},{23,17,72},{45,17,72},{25,5,0},{0,21,72},{45,17,72},{0,21,72},{39,0,74},{39,0,74},{39,0,74},{39,0,74},{9,5,1},{9,5,1},{9,5,1},{9,7,2},{41,37,1},{41,37,1},{7,1,184},{23,17,93},{7,19,122},{23,35,89},{23,1,260},{39,3,74},{39,35,15}, +{39,5,106},{41,3,247},{25,5,85},{37,17,81},{7,33,5},{37,19,19},{7,35,17},{19,9,243},{39,3,73},{23,35,10},{41,5,80},{45,1,243},{41,5,80},{23,1,80},{23,1,80},{23,1,80},{23,35,80},{39,17,51},{39,35,6},{39,35,6},{39,21,6},{25,35,54},{9,21,9},{7,33,4},{7,33,4},{7,33,4},{7,5,5},{23,3,50},{23,35,1},{23,35,1},{9,21,5},{43,3,50}, +{9,21,5},{21,3,72},{7,33,1},{37,19,10},{23,35,9},{21,3,72},{43,1,72},{23,35,9},{0,5,80},{43,1,72},{0,5,80},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{39,19,1},{39,19,1},{39,19,1},{39,21,2},{25,5,5},{25,5,5},{21,1,234},{37,1,79},{37,3,110},{37,3,90},{37,1,300},{7,33,82},{7,3,9},{23,19,139},{41,17,248},{9,19,83},{21,1,90}, +{21,17,2},{21,3,4},{21,3,25},{21,17,243},{23,17,74},{7,3,5},{25,19,75},{17,21,243},{25,19,75},{37,1,75},{37,1,75},{37,1,75},{37,19,74},{7,1,56},{7,19,6},{7,19,6},{7,5,21},{9,3,53},{9,35,6},{21,17,1},{21,17,1},{21,17,1},{21,19,4},{3,25,50},{7,19,2},{7,19,2},{9,35,2},{29,1,50},{9,35,2},{17,39,72},{21,17,2},{5,3,4}, +{23,3,0},{17,39,72},{39,17,72},{23,3,0},{0,19,74},{39,17,72},{0,19,74},{37,0,74},{37,0,74},{37,0,74},{37,0,74},{7,3,5},{7,3,5},{7,3,5},{7,5,5},{9,35,5},{9,35,5},{5,1,290},{5,1,103},{5,17,110},{21,33,106},{5,1,345},{37,1,78},{37,17,13},{37,3,119},{39,1,248},{23,3,91},{35,1,126},{35,1,6},{35,17,8},{5,33,29},{35,1,243}, +{37,1,74},{37,17,9},{9,33,81},{1,35,243},{9,33,81},{5,1,94},{5,1,94},{5,1,94},{21,33,90},{21,1,61},{37,17,9},{37,17,9},{37,19,9},{23,33,53},{7,19,8},{35,17,4},{35,17,4},{35,17,4},{35,3,4},{19,5,50},{21,33,0},{21,33,0},{7,19,4},{37,3,50},{7,19,4},{17,5,72},{35,1,2},{35,17,4},{7,17,4},{17,5,72},{5,17,72},{7,17,4}, +{0,33,80},{5,17,72},{0,33,80},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{37,1,4},{37,1,4},{37,1,4},{37,19,5},{23,3,1},{23,3,1},{19,1,349},{35,1,185},{35,1,121},{35,1,81},{19,1,398},{5,1,102},{5,1,2},{21,17,122},{37,1,270},{7,17,66},{3,1,126},{19,1,45},{19,1,9},{19,1,25},{33,33,221},{35,1,82},{5,1,1},{23,17,61},{33,33,221}, +{23,17,61},{35,1,121},{35,1,121},{35,1,121},{35,17,73},{35,1,94},{5,1,2},{5,1,2},{5,33,17},{7,1,53},{37,33,1},{19,1,9},{19,1,9},{19,1,9},{19,17,1},{3,3,50},{5,1,1},{5,1,1},{37,33,0},{3,3,50},{37,33,0},{1,3,61},{33,1,25},{3,1,1},{5,1,1},{1,3,61},{3,1,61},{5,1,1},{0,17,61},{3,1,61},{0,17,61},{35,0,72}, +{35,0,72},{35,0,72},{35,0,72},{5,1,1},{5,1,1},{5,1,1},{5,3,1},{37,33,1},{37,33,1},{3,1,239},{3,1,164},{3,1,139},{19,1,89},{3,1,239},{19,1,62},{19,1,26},{35,17,34},{35,1,163},{21,1,10},{33,1,69},{33,1,29},{33,1,20},{33,1,4},{1,3,93},{3,1,38},{19,1,10},{21,1,10},{3,1,93},{21,1,10},{3,1,139},{3,1,139},{3,1,139}, +{19,1,89},{19,1,138},{19,1,26},{19,1,26},{35,17,9},{5,1,74},{5,17,8},{33,1,20},{33,1,20},{33,1,20},{33,1,4},{17,3,50},{19,1,10},{19,1,10},{5,17,4},{35,1,50},{5,17,4},{1,17,5},{17,1,1},{17,1,0},{33,1,0},{1,17,5},{17,1,5},{33,1,0},{0,1,9},{17,1,5},{0,1,9},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{19,1,17}, +{19,1,17},{19,1,17},{35,17,5},{21,1,1},{21,1,1},{17,1,162},{33,1,130},{33,1,121},{33,1,81},{33,1,138},{33,1,58},{33,1,49},{3,1,1},{19,1,82},{19,1,10},{17,1,18},{17,1,10},{17,1,9},{17,1,1},{1,17,18},{17,1,6},{17,1,5},{3,1,0},{17,1,18},{3,1,0},{33,1,121},{33,1,121},{33,1,121},{33,1,81},{33,1,89},{33,1,49},{33,1,49}, +{3,1,1},{19,1,46},{19,1,10},{17,1,9},{17,1,9},{17,1,9},{17,1,1},{17,1,13},{17,1,5},{17,1,5},{3,1,0},{33,1,13},{3,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{33,0,72},{33,0,72},{33,0,72},{33,0,72},{3,1,26},{3,1,26},{3,1,26},{3,1,1},{19,1,10}, +{19,1,10},{0,38,200},{0,20,25},{0,34,5},{0,34,85},{0,20,442},{0,34,266},{0,18,125},{0,2,318},{0,18,482},{0,2,343},{0,38,200},{0,20,25},{0,34,5},{0,34,85},{16,4,441},{0,34,266},{0,18,125},{0,2,318},{4,16,441},{0,2,318},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,41},{0,32,13},{0,32,13},{0,16,25},{0,16,46},{0,16,26},{0,4,1}, +{0,4,1},{0,4,1},{0,2,1},{0,2,41},{0,32,13},{0,32,13},{0,16,25},{2,0,41},{0,16,25},{18,2,200},{0,20,25},{0,34,5},{0,34,85},{18,2,200},{38,0,200},{0,34,85},{0,18,208},{38,0,200},{0,18,208},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,10,202},{0,22,1},{0,20,26}, +{0,4,41},{0,22,689},{0,20,352},{0,4,141},{0,18,468},{0,34,750},{0,18,504},{0,10,202},{0,22,1},{0,20,26},{0,4,41},{34,0,686},{0,20,352},{0,4,141},{0,18,468},{0,34,686},{0,18,468},{0,22,0},{0,22,0},{0,22,0},{0,34,1},{0,34,145},{0,18,45},{0,18,45},{0,32,85},{0,32,158},{0,32,94},{0,22,0},{0,22,0},{0,22,0},{0,34,1},{16,2,145}, +{0,18,45},{0,18,45},{0,32,85},{34,0,145},{0,32,85},{20,16,200},{0,22,1},{16,20,5},{0,4,41},{20,16,200},{16,20,200},{0,4,41},{0,34,200},{16,20,200},{0,34,200},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,12,229},{16,8,30},{16,6,74},{16,36,58},{0,10,723},{0,6,282},{0,36,69}, +{0,4,414},{0,20,868},{0,34,513},{16,12,204},{16,8,5},{32,6,29},{16,36,33},{4,2,723},{0,6,282},{0,36,69},{0,4,414},{10,0,723},{0,4,414},{16,8,30},{16,8,30},{16,8,30},{16,4,33},{0,6,164},{0,4,25},{0,4,25},{0,18,65},{0,18,206},{0,18,101},{16,8,5},{16,8,5},{16,8,5},{16,4,8},{2,2,162},{0,4,25},{0,4,25},{0,18,65},{2,2,162}, +{0,18,65},{18,8,200},{16,8,1},{2,36,5},{0,36,20},{18,8,200},{44,0,200},{0,36,20},{0,4,218},{44,0,200},{0,4,218},{16,0,29},{16,0,29},{16,0,29},{16,0,29},{0,18,1},{0,18,1},{0,18,1},{0,32,0},{0,32,9},{0,32,9},{16,30,327},{32,40,139},{32,22,202},{16,6,151},{0,28,724},{0,8,236},{0,22,14},{0,20,350},{0,6,956},{0,20,494},{2,12,203}, +{2,24,2},{2,22,27},{2,6,42},{36,2,723},{0,8,236},{0,22,14},{0,20,350},{20,4,723},{0,20,350},{16,42,125},{16,42,125},{16,42,125},{16,6,126},{0,24,164},{0,6,1},{0,6,1},{0,4,37},{0,4,280},{0,34,109},{2,24,1},{2,24,1},{2,24,1},{2,36,2},{18,4,162},{0,6,1},{0,6,1},{0,4,37},{36,2,162},{0,4,37},{8,0,200},{2,24,1},{18,22,5}, +{0,22,10},{8,0,200},{47,0,200},{0,22,10},{0,36,200},{47,0,200},{0,36,200},{16,0,125},{16,0,125},{16,0,125},{16,0,125},{0,6,0},{0,6,0},{0,6,0},{0,18,1},{0,18,37},{0,18,37},{2,46,410},{2,26,218},{2,8,317},{2,38,226},{16,30,725},{16,40,217},{16,38,15},{0,6,312},{0,38,988},{0,6,417},{34,28,209},{18,26,13},{34,8,27},{18,38,34},{8,0,723}, +{0,40,203},{16,38,14},{0,6,296},{47,0,723},{0,6,296},{2,12,208},{2,12,208},{2,12,208},{2,22,209},{16,42,163},{16,38,6},{16,38,6},{16,20,26},{0,6,285},{0,20,81},{18,26,9},{18,26,9},{18,26,9},{34,6,10},{2,24,162},{32,22,5},{32,22,5},{0,20,17},{28,0,162},{0,20,17},{24,2,200},{18,26,4},{4,8,9},{0,8,10},{24,2,200},{13,0,200},{0,8,10}, +{0,22,208},{13,0,200},{0,22,208},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{16,8,1},{16,8,1},{16,8,1},{16,4,2},{0,4,45},{0,4,45},{18,15,402},{18,12,222},{34,24,331},{18,24,218},{32,47,725},{32,26,212},{32,24,5},{32,38,324},{0,24,884},{0,38,300},{4,30,200},{4,26,5},{4,24,36},{4,8,41},{40,0,723},{16,26,203},{32,24,4},{0,38,251},{46,2,723}, +{0,38,251},{18,14,203},{18,14,203},{18,14,203},{18,8,202},{32,28,163},{32,24,5},{32,24,5},{32,6,21},{0,38,219},{0,6,13},{4,26,1},{4,26,1},{4,26,1},{4,38,0},{22,2,162},{2,8,1},{2,8,1},{0,6,4},{42,2,162},{0,6,4},{16,11,200},{34,42,4},{20,24,4},{32,24,0},{16,11,200},{25,0,200},{32,24,0},{0,38,202},{25,0,200},{0,38,202},{18,0,202}, +{18,0,202},{18,0,202},{18,0,202},{32,40,1},{32,40,1},{32,40,1},{32,36,1},{0,6,9},{0,6,9},{4,15,408},{4,28,221},{4,10,317},{4,40,221},{18,31,725},{18,42,217},{18,40,6},{2,8,315},{0,26,788},{0,8,228},{20,47,204},{20,12,6},{36,10,27},{20,40,33},{10,2,723},{32,12,203},{18,40,5},{0,8,227},{45,2,723},{0,8,227},{4,14,208},{4,14,208},{4,14,208}, +{4,24,209},{18,44,163},{18,40,2},{18,40,2},{18,22,26},{0,24,179},{0,38,3},{20,12,5},{20,12,5},{20,12,5},{20,24,5},{8,2,162},{18,40,1},{18,40,1},{0,38,2},{30,2,162},{0,38,2},{26,4,200},{20,12,2},{6,40,5},{18,40,4},{26,4,200},{7,0,200},{18,40,4},{0,24,208},{7,0,200},{0,24,208},{4,0,208},{4,0,208},{4,0,208},{4,0,208},{18,10,1}, +{18,10,1},{18,10,1},{18,6,2},{0,38,2},{0,38,2},{20,13,402},{20,14,220},{36,26,331},{20,26,216},{34,45,725},{34,12,213},{34,26,5},{34,24,337},{0,12,740},{16,40,216},{6,31,202},{6,28,1},{6,26,36},{6,10,41},{42,2,723},{18,28,200},{34,26,4},{0,40,209},{44,6,723},{0,40,209},{20,46,200},{20,46,200},{20,46,200},{20,10,201},{34,30,163},{34,26,5},{34,26,5}, +{34,8,18},{0,26,164},{32,8,2},{6,28,0},{6,28,0},{6,28,0},{6,40,1},{24,4,162},{4,10,1},{4,10,1},{2,8,2},{11,0,162},{2,8,2},{14,0,200},{6,28,1},{22,26,4},{34,26,0},{14,0,200},{8,10,200},{34,26,0},{0,40,200},{8,10,200},{0,40,200},{20,0,200},{20,0,200},{20,0,200},{20,0,200},{34,42,1},{34,42,1},{34,42,1},{34,38,1},{32,8,1}, +{32,8,1},{6,13,404},{6,30,219},{6,12,327},{6,42,215},{20,29,725},{20,44,217},{20,12,9},{4,10,321},{0,14,723},{32,26,222},{38,15,206},{38,14,8},{38,12,24},{22,42,34},{14,0,723},{4,14,203},{20,12,8},{0,26,203},{8,10,723},{0,26,203},{6,47,202},{6,47,202},{6,47,202},{6,26,206},{20,46,163},{20,12,5},{20,12,5},{20,24,30},{32,42,164},{2,40,6},{38,44,4}, +{38,44,4},{38,44,4},{38,10,5},{38,10,162},{20,12,4},{20,12,4},{2,40,2},{23,0,162},{2,40,2},{30,2,200},{38,14,4},{8,12,4},{4,12,4},{30,2,200},{35,2,200},{4,12,4},{0,26,202},{35,2,200},{0,26,202},{6,0,202},{6,0,202},{6,0,202},{6,0,202},{20,12,1},{20,12,1},{20,12,1},{20,8,2},{2,10,4},{2,10,4},{22,11,402},{22,47,227},{38,44,321}, +{22,28,218},{36,27,727},{36,30,215},{36,28,13},{36,42,327},{32,30,725},{18,42,212},{8,29,200},{8,30,4},{24,28,29},{8,12,45},{0,1,723},{20,30,203},{6,28,5},{32,42,202},{1,0,723},{32,42,202},{22,15,202},{22,15,202},{22,15,202},{22,12,202},{36,15,168},{36,28,13},{36,28,13},{36,10,17},{2,28,163},{34,10,9},{8,30,0},{8,30,0},{8,30,0},{8,42,0},{28,2,162}, +{6,12,5},{6,12,5},{4,10,4},{42,8,162},{4,10,4},{47,2,200},{8,30,4},{24,28,4},{36,28,0},{47,2,200},{17,2,200},{36,28,0},{0,42,202},{17,2,200},{0,42,202},{22,0,202},{22,0,202},{22,0,202},{22,0,202},{36,14,5},{36,14,5},{36,14,5},{36,40,4},{34,26,2},{34,26,2},{8,11,408},{8,31,221},{8,14,312},{8,44,226},{22,27,724},{22,46,217},{22,44,12}, +{6,12,321},{2,47,728},{34,28,234},{40,29,209},{24,47,10},{40,14,22},{24,44,34},{18,3,723},{36,47,203},{22,44,11},{32,28,208},{45,8,723},{32,28,208},{8,15,209},{8,15,209},{8,15,209},{8,28,209},{22,15,165},{22,44,3},{22,44,3},{22,26,30},{34,44,164},{4,42,6},{40,30,10},{40,30,10},{40,30,10},{40,12,10},{16,3,162},{22,44,2},{22,44,2},{4,42,2},{17,0,162}, +{4,42,2},{15,2,200},{24,47,1},{10,14,4},{6,14,5},{15,2,200},{33,4,200},{6,14,5},{0,28,208},{33,4,200},{0,28,208},{8,0,208},{8,0,208},{8,0,208},{8,0,208},{22,14,1},{22,14,1},{22,14,1},{22,10,2},{4,12,4},{4,12,4},{24,9,402},{24,45,227},{40,46,324},{24,30,218},{38,25,727},{38,47,213},{38,30,13},{38,28,325},{34,31,727},{20,44,218},{10,27,202}, +{10,31,1},{26,30,29},{10,14,45},{4,3,723},{22,31,200},{8,30,8},{34,44,202},{3,4,723},{34,44,202},{24,13,202},{24,13,202},{24,13,202},{24,14,202},{38,13,168},{38,30,13},{38,30,13},{38,12,17},{4,30,163},{36,12,9},{10,31,0},{10,31,0},{10,31,0},{10,44,0},{30,4,162},{8,14,4},{8,14,4},{6,12,4},{15,8,162},{6,12,4},{43,0,200},{10,31,1},{26,30,4}, +{38,30,0},{43,0,200},{19,6,200},{38,30,0},{0,44,202},{19,6,200},{0,44,202},{24,0,202},{24,0,202},{24,0,202},{24,0,202},{38,46,5},{38,46,5},{38,46,5},{38,42,4},{20,28,4},{20,28,4},{10,9,404},{10,29,219},{26,47,330},{10,46,222},{24,9,723},{24,15,209},{24,47,18},{8,14,324},{4,45,723},{36,30,222},{42,11,206},{42,15,8},{42,47,22},{26,46,41},{43,0,723}, +{8,15,202},{24,47,18},{4,30,202},{19,6,723},{4,30,202},{10,43,202},{10,43,202},{10,43,202},{10,30,206},{24,13,162},{24,46,8},{24,46,8},{24,44,25},{20,47,168},{22,44,4},{42,15,4},{42,15,4},{42,15,4},{42,14,8},{45,0,162},{40,46,4},{40,46,4},{22,44,0},{27,8,162},{22,44,0},{38,3,200},{42,15,4},{12,47,9},{8,47,10},{38,3,200},{35,8,200},{8,47,10}, +{0,30,202},{35,8,200},{0,30,202},{10,0,202},{10,0,202},{10,0,202},{10,0,202},{24,47,0},{24,47,0},{24,47,0},{24,12,4},{22,44,4},{22,44,4},{26,7,408},{42,13,236},{42,15,332},{26,31,224},{40,23,727},{40,45,213},{40,31,8},{40,46,312},{36,29,725},{22,46,218},{12,25,201},{12,13,6},{28,31,29},{12,47,42},{11,0,723},{24,29,203},{40,31,4},{6,46,209},{5,8,723}, +{6,46,209},{26,41,208},{26,41,208},{26,41,208},{26,47,208},{40,11,168},{40,31,8},{40,31,8},{40,14,22},{6,31,163},{38,30,10},{12,13,2},{12,13,2},{12,13,2},{12,46,2},{29,2,162},{10,47,2},{10,47,2},{22,30,9},{35,6,162},{22,30,9},{41,2,200},{42,13,4},{44,31,1},{40,31,0},{41,2,200},{17,8,200},{40,31,0},{0,46,208},{17,8,200},{0,46,208},{26,0,208}, +{26,0,208},{26,0,208},{26,0,208},{40,15,4},{40,15,4},{40,15,4},{40,44,5},{38,30,1},{38,30,1},{12,7,404},{12,27,212},{12,45,332},{12,15,215},{26,23,724},{26,13,216},{26,15,8},{26,47,318},{6,43,723},{8,47,227},{44,9,206},{44,13,8},{44,45,22},{28,15,38},{24,3,723},{10,13,202},{26,15,8},{6,31,209},{3,24,723},{6,31,209},{12,41,202},{12,41,202},{12,41,202}, +{12,31,203},{26,11,162},{26,15,4},{26,15,4},{26,46,25},{38,15,162},{24,46,4},{44,13,4},{44,13,4},{44,13,4},{44,47,5},{43,2,162},{26,15,4},{26,15,4},{24,46,0},{21,8,162},{24,46,0},{29,12,200},{28,43,2},{14,15,8},{26,15,4},{29,12,200},{26,13,200},{26,15,4},{0,31,208},{26,13,200},{0,31,208},{12,0,202},{12,0,202},{12,0,202},{12,0,202},{26,45,0}, +{26,45,0},{26,45,0},{26,14,4},{24,46,4},{24,46,4},{28,5,402},{28,41,222},{44,13,332},{28,29,218},{42,21,727},{42,43,213},{42,29,8},{42,31,340},{38,27,724},{24,15,217},{14,23,201},{14,27,3},{30,29,29},{14,45,42},{9,2,723},{26,27,201},{42,29,4},{22,15,201},{2,9,723},{22,15,201},{28,9,202},{28,9,202},{28,9,202},{28,45,203},{42,9,168},{42,29,8},{42,29,8}, +{42,47,21},{8,29,163},{40,47,2},{14,11,2},{14,11,2},{14,11,2},{14,15,2},{38,1,162},{12,45,2},{12,45,2},{10,47,2},{43,28,162},{10,47,2},{37,0,200},{14,27,2},{46,29,1},{42,29,0},{37,0,200},{36,9,200},{42,29,0},{0,15,200},{36,9,200},{0,15,200},{28,0,202},{28,0,202},{28,0,202},{28,0,202},{42,13,4},{42,13,4},{42,13,4},{42,46,5},{40,47,1}, +{40,47,1},{14,35,400},{14,25,217},{30,43,340},{14,13,213},{28,5,723},{28,11,209},{28,43,8},{12,45,332},{8,41,724},{40,29,222},{46,7,201},{46,41,2},{46,43,21},{30,13,41},{37,0,723},{12,41,203},{28,43,8},{8,29,202},{36,9,723},{8,29,202},{14,23,201},{14,23,201},{14,23,201},{14,13,204},{28,9,162},{28,43,4},{28,43,4},{28,31,29},{40,13,164},{26,15,3},{46,11,2}, +{46,11,2},{46,11,2},{46,29,5},{39,0,162},{44,13,2},{44,13,2},{10,15,2},{9,28,162},{10,15,2},{21,2,200},{46,41,1},{47,43,5},{12,43,4},{21,2,200},{24,9,200},{12,43,4},{0,29,202},{24,9,200},{0,29,202},{14,0,200},{14,0,200},{14,0,200},{14,0,200},{28,43,0},{28,43,0},{28,43,0},{28,47,1},{26,15,2},{26,15,2},{30,3,410},{46,9,227},{46,27,318}, +{30,27,224},{14,5,728},{44,25,215},{14,27,8},{44,13,332},{40,25,725},{26,13,212},{47,21,200},{47,25,4},{47,27,25},{47,43,52},{5,0,723},{28,25,203},{14,27,4},{40,13,202},{0,5,723},{40,13,202},{30,7,209},{30,7,209},{30,7,209},{30,43,208},{14,39,166},{14,27,8},{14,27,8},{44,45,22},{10,27,163},{12,45,8},{47,25,0},{47,25,0},{47,25,0},{47,13,0},{23,2,162}, +{14,27,4},{14,27,4},{12,45,4},{20,9,162},{12,45,4},{35,2,200},{47,25,4},{15,27,4},{44,27,0},{35,2,200},{34,5,200},{44,27,0},{0,13,202},{34,5,200},{0,13,202},{30,0,208},{30,0,208},{30,0,208},{30,0,208},{14,27,4},{14,27,4},{14,27,4},{14,15,8},{42,29,2},{42,29,2},{47,3,408},{47,23,218},{47,41,312},{47,11,226},{30,3,723},{30,9,209},{30,41,8}, +{14,43,332},{10,39,723},{12,43,236},{15,21,209},{31,39,10},{15,41,22},{31,11,43},{30,3,723},{44,39,204},{30,41,8},{40,27,208},{42,9,723},{40,27,208},{47,7,209},{47,7,209},{47,7,209},{47,27,208},{30,7,162},{30,41,4},{30,41,4},{30,29,29},{42,11,164},{12,13,6},{31,23,9},{31,23,9},{31,23,9},{31,27,10},{37,2,162},{46,11,2},{46,11,2},{12,13,2},{34,7,162}, +{12,13,2},{46,1,200},{31,39,1},{45,41,5},{14,41,4},{46,1,200},{26,7,200},{14,41,4},{0,27,208},{26,7,200},{0,27,208},{47,0,208},{47,0,208},{47,0,208},{47,0,208},{30,41,0},{30,41,0},{30,41,0},{30,45,1},{12,43,4},{12,43,4},{31,1,402},{31,37,222},{15,9,324},{31,25,218},{46,17,733},{46,23,215},{46,25,18},{46,27,330},{42,23,725},{28,11,219},{45,19,202}, +{45,23,4},{45,25,25},{45,41,52},{3,2,723},{30,23,203},{47,25,8},{42,11,202},{2,3,723},{42,11,202},{31,5,202},{31,5,202},{31,5,202},{31,41,202},{46,5,173},{46,25,18},{46,25,18},{46,43,22},{12,25,163},{14,43,8},{45,23,0},{45,23,0},{45,23,0},{45,11,0},{44,1,162},{47,41,4},{47,41,4},{14,43,4},{26,9,162},{14,43,4},{31,1,200},{45,23,4},{13,25,4}, +{46,25,0},{31,1,200},{32,1,200},{46,25,0},{0,11,202},{32,1,200},{0,11,202},{31,0,202},{31,0,202},{31,0,202},{31,0,202},{46,9,10},{46,9,10},{46,9,10},{46,13,9},{28,27,4},{28,27,4},{45,1,404},{45,21,218},{29,39,325},{45,9,222},{31,1,723},{31,7,209},{31,39,13},{47,41,324},{12,37,725},{44,25,227},{13,3,206},{13,37,9},{13,39,17},{29,9,48},{31,1,723}, +{47,7,208},{31,39,13},{12,25,202},{32,1,723},{12,25,202},{45,35,202},{45,35,202},{45,35,202},{45,25,203},{31,5,162},{31,9,8},{31,9,8},{31,27,29},{14,9,166},{30,11,1},{13,7,4},{13,7,4},{13,7,4},{13,25,8},{31,5,162},{15,9,4},{15,9,4},{30,11,0},{14,9,162},{30,11,0},{17,6,200},{29,21,4},{43,39,4},{46,39,5},{17,6,200},{20,1,200},{46,39,5}, +{0,25,202},{20,1,200},{0,25,202},{45,0,202},{45,0,202},{45,0,202},{45,0,202},{31,39,0},{31,39,0},{31,39,0},{31,27,4},{30,11,1},{30,11,1},{13,1,440},{29,35,234},{13,7,321},{29,23,218},{45,1,732},{15,21,215},{45,23,12},{15,9,312},{44,21,731},{30,9,221},{43,17,201},{43,5,6},{27,23,30},{43,39,46},{45,1,723},{31,21,203},{45,23,3},{14,9,209},{27,9,723}, +{14,9,209},{29,33,208},{29,33,208},{29,33,208},{29,39,208},{15,3,168},{45,23,11},{45,23,11},{15,41,22},{14,23,168},{46,25,10},{43,5,2},{43,5,2},{43,5,2},{43,9,2},{17,2,162},{45,23,2},{45,23,2},{30,25,10},{16,1,162},{30,25,10},{27,3,200},{13,5,4},{11,23,2},{15,23,1},{27,3,200},{39,9,200},{15,23,1},{0,9,208},{39,9,200},{0,9,208},{29,0,208}, +{29,0,208},{29,0,208},{29,0,208},{15,7,5},{15,7,5},{15,7,5},{15,11,4},{46,25,1},{46,25,1},{43,1,500},{43,19,212},{43,37,327},{43,7,220},{13,1,760},{29,5,209},{29,37,13},{45,39,321},{14,35,724},{46,23,227},{11,1,206},{11,35,9},{11,37,17},{27,7,43},{33,10,723},{15,35,204},{29,37,13},{14,23,202},{38,1,723},{14,23,202},{43,33,202},{43,33,202},{43,33,202}, +{43,23,203},{29,3,162},{29,7,5},{29,7,5},{29,25,29},{46,7,165},{31,9,4},{11,5,4},{11,5,4},{11,5,4},{11,39,5},{29,3,162},{13,7,5},{13,7,5},{31,9,0},{43,9,162},{31,9,0},{39,7,200},{27,35,2},{41,37,4},{15,37,5},{39,7,200},{26,1,200},{15,37,5},{0,23,202},{26,1,200},{0,23,202},{43,0,202},{43,0,202},{43,0,202},{43,0,202},{29,37,0}, +{29,37,0},{29,37,0},{29,25,4},{31,9,4},{31,9,4},{11,1,530},{27,33,222},{11,5,321},{27,21,219},{27,1,812},{13,19,215},{13,21,9},{13,7,327},{46,19,724},{31,7,219},{25,1,225},{41,3,6},{25,21,30},{41,37,46},{41,3,723},{29,19,203},{13,21,5},{46,7,202},{21,9,723},{46,7,202},{27,1,203},{27,1,203},{27,1,203},{27,37,202},{13,1,168},{13,21,8},{13,21,8}, +{13,39,24},{47,21,163},{15,39,8},{41,3,2},{41,3,2},{41,3,2},{41,7,1},{39,11,162},{13,21,4},{13,21,4},{45,39,4},{22,1,162},{45,39,4},{25,1,200},{11,3,4},{9,21,2},{13,21,1},{25,1,200},{33,9,200},{13,21,1},{0,7,202},{33,9,200},{0,7,202},{27,0,202},{27,0,202},{27,0,202},{27,0,202},{13,5,4},{13,5,4},{13,5,4},{13,9,4},{15,39,4}, +{15,39,4},{25,1,634},{41,17,216},{25,35,337},{41,5,220},{41,1,863},{27,3,211},{27,35,5},{27,37,331},{47,33,725},{15,21,220},{9,1,251},{9,33,2},{9,35,18},{25,5,48},{25,1,723},{43,33,203},{27,35,5},{47,21,200},{33,9,723},{47,21,200},{41,1,209},{41,1,209},{41,1,209},{41,5,204},{27,1,164},{27,35,4},{27,35,4},{27,7,36},{15,5,164},{29,7,1},{9,3,2}, +{9,3,2},{9,3,2},{9,21,2},{25,5,162},{11,5,1},{11,5,1},{29,7,0},{10,1,162},{29,7,0},{23,17,200},{9,33,1},{39,35,1},{43,35,1},{23,17,200},{45,17,200},{43,35,1},{0,21,200},{45,17,200},{0,21,200},{41,0,200},{41,0,200},{41,0,200},{41,0,200},{27,35,0},{27,35,0},{27,35,0},{27,23,4},{29,7,1},{29,7,1},{39,1,724},{9,1,228},{9,3,315}, +{25,19,218},{9,1,932},{11,17,213},{41,19,6},{11,5,317},{15,17,725},{29,5,221},{23,1,288},{39,1,3},{23,19,26},{39,19,51},{39,1,723},{27,17,203},{41,19,2},{15,5,208},{31,1,723},{15,5,208},{9,1,227},{9,1,227},{9,1,227},{25,35,209},{41,1,174},{41,19,5},{41,19,5},{11,37,27},{45,19,163},{13,21,6},{39,1,2},{39,1,2},{39,1,2},{39,5,2},{9,3,162}, +{41,19,1},{41,19,1},{13,21,5},{31,3,162},{13,21,5},{21,3,200},{39,1,2},{7,19,2},{11,19,1},{21,3,200},{43,1,200},{11,19,1},{0,5,208},{43,1,200},{0,5,208},{25,0,208},{25,0,208},{25,0,208},{25,0,208},{41,19,4},{41,19,4},{41,19,4},{41,7,5},{13,21,2},{13,21,2},{23,1,864},{39,1,300},{39,33,324},{39,3,222},{39,1,1020},{25,1,211},{25,33,5}, +{25,35,331},{29,1,732},{13,19,222},{37,1,347},{7,1,13},{7,33,21},{23,3,48},{1,13,723},{25,1,211},{25,33,5},{15,19,203},{13,1,723},{15,19,203},{39,1,251},{39,1,251},{39,1,251},{39,19,203},{9,1,195},{25,33,4},{25,33,4},{25,5,36},{13,3,164},{27,5,5},{7,1,4},{7,1,4},{7,1,4},{7,35,8},{23,3,162},{9,3,1},{9,3,1},{27,5,1},{43,3,162}, +{27,5,1},{17,39,200},{7,1,9},{37,33,1},{41,33,1},{17,39,200},{39,17,200},{41,33,1},{0,19,202},{39,17,200},{0,19,202},{39,0,202},{39,0,202},{39,0,202},{39,0,202},{25,33,0},{25,33,0},{25,33,0},{25,21,4},{43,35,4},{43,35,4},{37,1,1012},{7,1,417},{7,1,312},{23,17,218},{7,1,1144},{39,1,268},{39,17,15},{9,3,317},{27,1,804},{27,3,218},{5,1,398}, +{21,1,81},{21,17,26},{37,17,51},{35,3,723},{23,1,254},{39,17,6},{13,3,208},{25,1,723},{13,3,208},{7,1,296},{7,1,296},{7,1,296},{23,33,209},{39,1,243},{39,17,14},{39,17,14},{9,35,27},{43,17,163},{27,19,13},{21,1,17},{21,1,17},{21,1,17},{37,3,1},{3,25,162},{39,17,5},{39,17,5},{27,19,9},{29,1,162},{27,19,9},{19,1,200},{5,1,45},{5,17,2}, +{9,17,1},{19,1,200},{37,1,200},{9,17,1},{0,3,208},{37,1,200},{0,3,208},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{9,1,10},{9,1,10},{9,1,10},{9,5,9},{27,19,4},{27,19,4},{5,1,919},{21,1,494},{21,1,350},{37,1,201},{21,1,1014},{7,1,251},{23,1,14},{23,33,202},{9,1,721},{41,33,139},{19,1,341},{35,1,109},{5,1,37},{5,1,26},{3,3,546}, +{37,1,213},{7,1,1},{43,17,125},{3,3,546},{43,17,125},{21,1,350},{21,1,350},{21,1,350},{37,1,201},{37,1,312},{23,1,14},{23,1,14},{23,3,27},{41,1,168},{25,3,2},{5,1,37},{5,1,37},{5,1,37},{5,17,5},{19,5,162},{7,1,1},{7,1,1},{25,3,1},{37,3,162},{25,3,1},{33,1,113},{19,1,37},{19,1,1},{7,1,0},{33,1,113},{35,1,113},{7,1,0}, +{0,17,125},{35,1,113},{0,17,125},{37,0,200},{37,0,200},{37,0,200},{37,0,200},{23,1,10},{23,1,10},{23,1,10},{23,19,5},{25,3,1},{25,3,1},{35,1,773},{35,1,513},{5,1,414},{5,1,227},{35,1,818},{21,1,218},{37,1,69},{7,17,74},{23,1,534},{9,17,30},{3,1,190},{19,1,101},{19,1,65},{35,1,5},{33,33,333},{35,1,114},{5,1,25},{9,17,30},{33,33,333}, +{9,17,30},{5,1,414},{5,1,414},{5,1,414},{5,1,227},{21,1,373},{37,1,69},{37,1,69},{7,33,29},{9,1,216},{9,17,5},{19,1,65},{19,1,65},{19,1,65},{35,1,5},{3,3,162},{5,1,25},{5,1,25},{9,17,5},{3,3,162},{9,17,5},{17,1,25},{33,1,9},{33,1,0},{19,1,1},{17,1,25},{33,1,25},{19,1,1},{0,17,29},{33,1,25},{0,17,29},{5,0,218}, +{5,0,218},{5,0,218},{5,0,218},{37,1,20},{37,1,20},{37,1,20},{37,3,5},{9,17,1},{9,17,1},{3,1,642},{19,1,504},{19,1,468},{35,1,264},{19,1,657},{35,1,229},{5,1,141},{21,1,26},{21,1,457},{23,1,1},{33,1,134},{33,1,94},{33,1,85},{3,1,26},{1,19,193},{19,1,81},{19,1,45},{23,1,0},{19,1,193},{23,1,0},{19,1,468},{19,1,468},{19,1,468}, +{35,1,264},{35,1,425},{5,1,141},{5,1,141},{21,1,26},{7,1,254},{23,1,1},{33,1,85},{33,1,85},{33,1,85},{3,1,26},{17,3,145},{19,1,45},{19,1,45},{23,1,0},{35,1,145},{23,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{35,0,200},{35,0,200},{35,0,200},{35,0,200},{5,1,41}, +{5,1,41},{5,1,41},{21,17,5},{23,1,1},{23,1,1},{3,1,418},{3,1,343},{3,1,318},{3,1,243},{3,1,370},{19,1,161},{19,1,125},{35,1,5},{35,1,250},{21,1,25},{17,1,34},{17,1,26},{17,1,25},{33,1,13},{17,1,54},{33,1,22},{33,1,13},{5,1,1},{33,1,54},{5,1,1},{3,1,318},{3,1,318},{3,1,318},{3,1,243},{3,1,270},{19,1,125},{19,1,125}, +{35,1,5},{5,1,165},{21,1,25},{17,1,25},{17,1,25},{17,1,25},{33,1,13},{1,3,41},{33,1,13},{33,1,13},{5,1,1},{3,1,41},{5,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{19,0,208},{19,0,208},{19,0,208},{19,0,208},{35,1,85},{35,1,85},{35,1,85},{35,1,5},{21,1,25}, +{21,1,25},{0,26,421},{0,38,45},{0,36,2},{0,20,160},{0,38,926},{0,20,577},{0,4,264},{0,18,701},{0,34,989},{0,18,737},{0,26,421},{0,38,45},{0,36,2},{0,20,160},{34,0,925},{0,20,577},{0,4,264},{0,18,701},{0,34,925},{0,18,701},{0,20,1},{0,20,1},{0,20,1},{0,18,1},{0,18,85},{0,2,34},{0,2,34},{0,32,53},{0,32,94},{0,32,62},{0,20,1}, +{0,20,1},{0,20,1},{0,18,1},{32,0,85},{0,2,34},{0,2,34},{0,32,53},{18,0,85},{0,32,53},{34,4,421},{0,38,45},{0,36,2},{0,20,160},{34,4,421},{26,0,421},{0,20,160},{0,34,421},{26,0,421},{0,34,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,44,421},{0,24,13},{0,22,32}, +{0,36,113},{0,24,1262},{0,6,670},{0,20,304},{0,4,886},{0,4,1382},{0,34,953},{0,44,421},{0,24,13},{0,22,32},{0,36,113},{18,4,1261},{0,6,670},{0,20,304},{0,4,886},{36,2,1261},{0,4,886},{0,8,0},{0,8,0},{0,8,0},{0,4,0},{0,4,221},{0,34,73},{0,34,73},{0,2,125},{0,2,246},{0,2,150},{0,8,0},{0,8,0},{0,8,0},{0,4,0},{2,0,221}, +{0,34,73},{0,34,73},{0,2,125},{4,0,221},{0,2,125},{22,0,421},{0,24,13},{16,6,8},{0,36,113},{22,0,421},{44,0,421},{0,36,113},{0,20,433},{44,0,421},{0,20,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,430},{0,26,10},{16,38,79},{0,22,74},{0,42,1514},{0,38,717},{0,6,253}, +{0,20,965},{0,36,1713},{0,4,1109},{16,46,425},{16,10,9},{16,38,54},{0,22,74},{20,2,1514},{0,38,717},{0,6,253},{0,20,965},{42,0,1514},{0,20,965},{0,26,10},{0,26,10},{0,26,10},{0,36,9},{0,6,340},{0,20,97},{0,20,97},{0,18,185},{0,18,382},{0,18,221},{16,10,5},{16,10,5},{16,10,5},{16,36,5},{2,2,338},{0,20,97},{0,20,97},{0,18,185},{2,2,338}, +{0,18,185},{8,0,421},{0,26,1},{2,38,2},{0,22,65},{8,0,421},{31,0,421},{0,22,65},{0,36,421},{31,0,421},{0,36,421},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,32,0},{0,32,0},{0,32,0},{0,16,0},{0,16,1},{0,16,1},{16,45,482},{16,12,66},{32,24,186},{16,8,126},{0,14,1517},{0,24,605},{0,38,117},{0,6,886},{0,22,1815},{0,36,1085},{32,31,421}, +{32,42,1},{2,8,51},{32,38,85},{22,16,1514},{0,24,605},{0,38,117},{0,6,886},{44,16,1514},{0,6,886},{16,28,61},{16,28,61},{16,28,61},{16,22,62},{0,24,340},{0,22,37},{0,22,37},{0,4,125},{0,4,456},{0,34,213},{32,42,0},{32,42,0},{32,42,0},{32,6,1},{18,4,338},{0,22,37},{0,22,37},{0,4,125},{36,2,338},{0,4,125},{40,0,421},{32,42,1},{18,8,5}, +{0,8,37},{40,0,421},{13,0,421},{0,8,37},{0,22,433},{13,0,421},{0,22,433},{16,0,61},{16,0,61},{16,0,61},{16,0,61},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,32,25},{0,32,25},{32,43,623},{32,44,219},{32,10,382},{32,24,243},{0,15,1517},{0,26,497},{0,24,35},{0,22,761},{0,8,2003},{0,22,1050},{18,15,422},{18,28,6},{18,40,51},{2,24,77},{24,0,1514}, +{0,26,497},{0,24,35},{0,22,761},{32,8,1514},{0,22,761},{32,30,202},{32,30,202},{32,30,202},{32,8,203},{0,28,338},{0,8,10},{0,8,10},{0,20,89},{0,6,565},{0,20,233},{18,12,1},{18,12,1},{18,12,1},{18,38,1},{2,24,338},{0,8,10},{0,8,10},{0,20,89},{28,0,338},{0,20,89},{40,4,421},{2,28,5},{4,40,1},{0,24,26},{40,4,421},{25,0,421},{0,24,26}, +{0,38,425},{25,0,421},{0,38,425},{32,0,202},{32,0,202},{32,0,202},{32,0,202},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,34,68},{0,34,68},{2,11,821},{2,30,429},{2,26,634},{2,10,429},{0,27,1514},{0,28,446},{0,10,8},{0,8,670},{0,40,2187},{0,38,1083},{34,29,422},{34,14,6},{4,26,50},{34,10,86},{38,6,1514},{0,28,446},{0,10,8},{0,8,670},{27,0,1514}, +{0,8,670},{2,31,401},{2,31,401},{2,31,401},{2,24,404},{0,46,340},{0,10,4},{0,10,4},{0,6,52},{0,22,677},{0,6,277},{34,14,2},{34,14,2},{34,14,2},{34,8,5},{22,2,338},{0,10,4},{0,10,4},{0,6,52},{42,2,338},{0,6,52},{28,0,421},{34,14,5},{36,10,5},{0,10,4},{28,0,421},{7,0,421},{0,10,4},{0,24,425},{7,0,421},{0,24,425},{2,0,400}, +{2,0,400},{2,0,400},{2,0,400},{0,26,0},{0,26,0},{0,26,0},{0,36,1},{0,4,149},{0,4,149},{18,9,842},{18,47,462},{34,12,661},{18,26,450},{16,25,1521},{16,14,441},{16,42,15},{16,24,653},{0,26,2030},{0,24,882},{20,13,425},{20,30,9},{20,42,54},{4,26,77},{26,2,1514},{0,14,422},{16,42,11},{0,24,626},{38,8,1514},{0,24,626},{18,45,421},{18,45,421},{18,45,421}, +{18,10,422},{16,15,344},{16,42,14},{16,42,14},{16,38,38},{0,24,602},{0,38,162},{20,14,4},{20,14,4},{20,14,4},{20,40,5},{8,2,338},{32,26,2},{32,26,2},{0,38,18},{30,2,338},{0,38,18},{14,0,421},{4,30,5},{6,42,1},{0,42,1},{14,0,421},{19,0,421},{0,42,1},{0,40,421},{19,0,421},{0,40,421},{18,0,421},{18,0,421},{18,0,421},{18,0,421},{16,12,5}, +{16,12,5},{16,12,5},{16,6,8},{0,6,80},{0,6,80},{4,9,854},{4,31,458},{4,28,674},{34,12,453},{2,25,1515},{32,30,445},{2,12,9},{32,10,657},{0,28,1850},{0,10,666},{36,27,422},{36,46,6},{6,28,48},{36,12,86},{16,7,1514},{16,46,421},{2,12,8},{0,10,545},{21,0,1514},{0,10,545},{34,13,433},{34,13,433},{34,13,433},{34,42,433},{2,15,339},{2,12,5},{2,12,5}, +{32,8,50},{0,10,477},{0,8,62},{36,46,2},{36,46,2},{36,46,2},{36,10,5},{24,4,338},{2,12,4},{2,12,4},{0,24,9},{11,0,338},{0,24,9},{0,1,421},{36,46,5},{38,12,5},{2,12,4},{0,1,421},{1,0,421},{2,12,4},{0,26,425},{1,0,421},{0,26,425},{4,0,433},{4,0,433},{4,0,433},{4,0,433},{2,28,1},{2,28,1},{2,28,1},{2,38,2},{0,8,37}, +{0,8,37},{20,7,842},{20,45,455},{36,14,655},{20,28,450},{34,9,1523},{18,47,450},{34,44,13},{18,42,659},{0,14,1731},{0,42,542},{22,11,422},{22,47,5},{22,44,50},{6,28,86},{30,0,1514},{2,47,421},{34,44,4},{0,42,506},{33,0,1514},{0,42,506},{20,43,421},{20,43,421},{20,43,421},{20,12,425},{18,13,347},{34,28,11},{34,28,11},{18,40,43},{0,12,389},{0,10,9},{22,47,1}, +{22,47,1},{22,47,1},{22,42,1},{38,10,338},{34,28,2},{34,28,2},{0,10,5},{23,0,338},{0,10,5},{2,1,421},{22,47,4},{8,44,0},{18,44,0},{2,1,421},{1,2,421},{18,44,0},{0,42,425},{1,2,421},{0,42,425},{20,0,421},{20,0,421},{20,0,421},{20,0,421},{18,30,9},{18,30,9},{18,30,9},{34,8,10},{0,10,5},{0,10,5},{6,37,846},{6,29,454},{6,46,685}, +{6,14,459},{4,7,1517},{4,31,446},{4,14,19},{34,12,655},{0,47,1635},{0,12,478},{38,9,425},{38,15,6},{8,30,41},{38,14,77},{47,0,1514},{18,15,422},{20,14,11},{0,12,477},{27,6,1514},{0,12,477},{6,27,426},{6,27,426},{6,27,426},{6,44,426},{4,13,340},{4,14,10},{4,14,10},{4,26,50},{0,44,355},{16,26,6},{38,15,5},{38,15,5},{38,15,5},{38,28,5},{28,2,338}, +{20,14,2},{20,14,2},{32,26,1},{42,8,338},{32,26,1},{29,0,421},{38,15,2},{40,14,10},{18,30,9},{29,0,421},{33,4,421},{18,30,9},{0,28,425},{33,4,421},{0,28,425},{6,0,425},{6,0,425},{6,0,425},{6,0,425},{4,30,1},{4,30,1},{4,30,1},{4,40,0},{16,26,5},{16,26,5},{22,5,842},{22,43,455},{38,47,679},{22,30,455},{20,21,1521},{20,15,438},{36,46,13}, +{20,28,653},{0,15,1553},{16,44,454},{24,9,422},{24,45,5},{24,46,50},{8,30,77},{34,3,1514},{4,45,422},{36,46,4},{0,44,434},{35,4,1514},{0,44,434},{22,41,421},{22,41,421},{22,41,421},{22,14,422},{20,11,342},{36,30,11},{36,30,11},{20,42,38},{0,46,340},{32,12,5},{24,45,1},{24,45,1},{24,45,1},{24,44,1},{16,3,338},{36,30,2},{36,30,2},{32,12,4},{17,0,338}, +{32,12,4},{43,0,421},{24,45,4},{10,46,0},{4,46,1},{43,0,421},{19,6,421},{4,46,1},{0,44,425},{19,6,421},{0,44,425},{22,0,421},{22,0,421},{22,0,421},{22,0,421},{20,31,5},{20,31,5},{20,31,5},{20,26,5},{32,12,1},{32,12,1},{8,5,854},{8,27,458},{24,31,670},{38,47,462},{6,5,1517},{6,29,446},{6,47,6},{36,14,655},{0,29,1530},{32,30,465},{40,23,422}, +{40,13,2},{10,31,48},{40,46,90},{45,2,1514},{20,13,425},{6,47,6},{0,30,434},{25,8,1514},{0,30,434},{8,25,434},{8,25,434},{8,25,434},{8,30,437},{6,11,340},{6,47,5},{6,47,5},{6,12,52},{16,47,342},{18,28,1},{40,13,1},{40,13,1},{40,13,1},{40,14,5},{30,4,338},{22,46,4},{22,46,4},{18,28,1},{15,8,338},{18,28,1},{11,0,421},{40,13,1},{26,47,5}, +{6,47,2},{11,0,421},{5,8,421},{6,47,2},{0,30,425},{5,8,421},{0,30,425},{8,0,433},{8,0,433},{8,0,433},{8,0,433},{6,31,0},{6,31,0},{6,31,0},{6,42,0},{18,28,1},{18,28,1},{24,33,846},{24,41,465},{40,15,658},{24,31,454},{38,5,1518},{22,13,446},{38,15,14},{22,46,667},{0,27,1518},{18,46,453},{26,7,421},{26,27,2},{42,15,53},{10,31,86},{27,0,1514}, +{6,43,425},{38,15,10},{16,46,434},{37,8,1514},{16,46,434},{24,23,426},{24,23,426},{24,23,426},{24,47,426},{38,25,344},{38,31,9},{38,31,9},{22,44,41},{18,31,341},{4,14,2},{26,27,1},{26,27,1},{26,27,1},{26,46,1},{45,0,338},{8,31,5},{8,31,5},{4,14,1},{27,8,338},{4,14,1},{8,1,421},{26,27,2},{12,15,1},{6,15,2},{8,1,421},{1,8,421},{6,15,2}, +{0,46,433},{1,8,421},{0,46,433},{24,0,425},{24,0,425},{24,0,425},{24,0,425},{38,15,4},{38,15,4},{38,15,4},{38,12,8},{4,14,1},{4,14,1},{10,33,846},{10,25,454},{26,29,658},{10,45,454},{8,3,1517},{8,27,446},{8,45,8},{38,47,650},{32,11,1518},{4,47,462},{42,5,425},{42,11,9},{12,29,43},{42,15,89},{28,13,1514},{22,11,422},{8,45,8},{16,31,426},{27,12,1514}, +{16,31,426},{10,23,425},{10,23,425},{10,23,425},{10,15,429},{8,9,340},{8,45,4},{8,45,4},{8,30,50},{34,45,341},{20,30,6},{42,11,5},{42,11,5},{42,11,5},{42,31,8},{29,2,338},{8,45,4},{8,45,4},{36,30,1},{35,6,338},{36,30,1},{23,0,421},{12,11,4},{44,45,5},{8,45,4},{23,0,421},{18,9,421},{8,45,4},{0,31,425},{18,9,421},{0,31,425},{10,0,425}, +{10,0,425},{10,0,425},{10,0,425},{8,13,1},{8,13,1},{8,13,1},{8,44,0},{20,30,5},{20,30,5},{26,1,846},{26,39,470},{42,13,658},{26,29,454},{40,3,1523},{24,11,446},{24,13,20},{24,31,658},{2,25,1521},{20,15,458},{28,5,422},{28,25,6},{28,13,51},{12,29,86},{40,3,1514},{8,41,421},{24,13,11},{18,15,421},{16,9,1514},{18,15,421},{26,21,426},{26,21,426},{26,21,426}, +{26,45,426},{24,7,347},{40,29,11},{40,29,11},{24,46,41},{20,29,342},{36,47,10},{28,41,1},{28,41,1},{28,41,1},{28,15,2},{43,2,338},{40,29,2},{40,29,2},{36,47,9},{21,8,338},{36,47,9},{37,0,421},{12,25,5},{14,13,1},{8,13,2},{37,0,421},{32,7,421},{8,13,2},{0,15,421},{32,7,421},{0,15,421},{26,0,425},{26,0,425},{26,0,425},{26,0,425},{24,27,9}, +{24,27,9},{24,27,9},{40,14,10},{36,47,1},{36,47,1},{12,1,850},{12,23,454},{12,27,666},{12,43,454},{10,1,1517},{10,25,446},{10,43,8},{40,45,666},{34,9,1515},{6,45,462},{44,3,425},{44,9,9},{14,27,50},{44,13,89},{39,2,1514},{24,9,422},{10,43,8},{18,29,426},{34,9,1514},{18,29,426},{12,21,425},{12,21,425},{12,21,425},{12,13,429},{10,7,340},{10,43,4},{10,43,4}, +{10,47,50},{36,43,341},{22,31,1},{44,9,5},{44,9,5},{44,9,5},{44,29,8},{38,1,338},{26,13,4},{26,13,4},{22,31,1},{43,28,338},{22,31,1},{5,0,421},{14,9,4},{46,43,5},{10,43,4},{5,0,421},{0,5,421},{10,43,4},{0,29,425},{0,5,421},{0,29,425},{12,0,425},{12,0,425},{12,0,425},{12,0,425},{10,27,0},{10,27,0},{10,27,0},{10,46,0},{22,31,1}, +{22,31,1},{44,1,890},{44,7,462},{44,41,666},{28,27,454},{42,1,1518},{26,39,446},{42,11,8},{26,13,666},{4,23,1523},{22,13,454},{30,33,421},{30,23,1},{46,11,50},{30,27,89},{21,0,1514},{40,23,425},{42,11,4},{20,13,425},{18,7,1514},{20,13,425},{28,19,426},{28,19,426},{28,19,426},{28,27,429},{42,21,344},{42,11,8},{42,11,8},{26,15,50},{6,11,341},{8,45,9},{30,23,1}, +{30,23,1},{30,23,1},{30,13,0},{39,0,338},{42,11,4},{42,11,4},{8,45,5},{9,28,338},{8,45,5},{14,1,421},{30,23,1},{47,11,0},{26,11,0},{14,1,421},{4,5,421},{26,11,0},{0,13,425},{4,5,421},{0,13,425},{28,0,425},{28,0,425},{28,0,425},{28,0,425},{42,11,4},{42,11,4},{42,11,4},{42,47,5},{8,15,4},{8,15,4},{30,1,950},{14,21,458},{30,25,658}, +{14,41,446},{28,1,1542},{12,23,438},{12,25,20},{12,43,658},{36,7,1518},{38,27,470},{46,1,430},{46,37,10},{47,25,41},{46,41,82},{14,3,1514},{26,7,422},{28,41,11},{20,27,426},{32,5,1514},{20,27,426},{14,19,421},{14,19,421},{14,19,421},{14,11,422},{12,35,339},{12,25,11},{12,25,11},{12,29,51},{38,41,338},{24,29,6},{46,37,9},{46,37,9},{46,37,9},{46,27,10},{23,2,338}, +{28,41,2},{28,41,2},{40,29,1},{20,9,338},{40,29,1},{17,0,421},{46,37,1},{31,25,10},{26,25,9},{17,0,421},{18,3,421},{26,25,9},{0,27,425},{18,3,421},{0,27,425},{14,0,421},{14,0,421},{14,0,421},{14,0,421},{12,9,2},{12,9,2},{12,9,2},{12,15,1},{24,13,5},{24,13,5},{46,1,1010},{46,5,462},{46,39,650},{30,25,454},{14,1,1575},{28,7,446},{44,9,8}, +{28,27,658},{6,21,1523},{24,11,454},{31,1,422},{31,21,6},{31,9,50},{47,25,77},{46,3,1514},{42,21,425},{44,9,4},{22,11,425},{16,3,1514},{22,11,425},{30,17,426},{30,17,426},{30,17,426},{30,25,429},{44,19,344},{44,9,8},{44,9,8},{28,13,43},{8,9,340},{10,43,9},{31,37,1},{31,37,1},{31,37,1},{31,11,2},{37,2,338},{44,9,4},{44,9,4},{10,43,5},{34,7,338}, +{10,43,5},{31,1,421},{31,21,5},{45,9,0},{12,9,1},{31,1,421},{32,1,421},{12,9,1},{0,11,425},{32,1,421},{0,11,425},{30,0,425},{30,0,425},{30,0,425},{30,0,425},{44,9,4},{44,9,4},{44,9,4},{44,45,5},{10,13,4},{10,13,4},{31,1,1098},{47,19,453},{47,23,667},{47,39,473},{46,1,1641},{14,21,438},{14,39,14},{14,41,658},{38,5,1518},{40,25,465},{45,1,437}, +{15,5,2},{45,23,41},{15,39,86},{31,3,1514},{28,5,422},{30,39,9},{22,25,426},{34,3,1514},{22,25,426},{47,17,434},{47,17,434},{47,17,434},{47,9,437},{14,33,339},{14,39,10},{14,39,10},{14,43,53},{40,39,341},{26,27,2},{15,5,1},{15,5,1},{15,5,1},{15,25,5},{44,1,338},{30,9,5},{30,9,5},{26,27,1},{26,9,338},{26,27,1},{45,1,421},{15,5,1},{13,39,8}, +{14,39,4},{45,1,421},{20,1,421},{14,39,4},{0,25,425},{20,1,421},{0,25,425},{47,0,433},{47,0,433},{47,0,433},{47,0,433},{14,7,2},{14,7,2},{14,7,2},{14,13,1},{26,27,2},{26,27,2},{45,1,1202},{31,33,465},{15,37,655},{31,7,461},{47,1,1725},{30,35,446},{46,7,6},{30,25,670},{24,19,1518},{26,9,458},{13,1,469},{29,19,1},{13,7,52},{29,23,85},{15,1,1514}, +{14,35,426},{46,7,5},{24,9,434},{9,11,1514},{24,9,434},{31,1,434},{31,1,434},{31,1,434},{31,39,426},{46,17,339},{46,7,6},{46,7,6},{30,11,48},{10,7,341},{12,41,2},{29,19,1},{29,19,1},{29,19,1},{29,9,0},{31,5,338},{47,23,4},{47,23,4},{12,41,1},{14,9,338},{12,41,1},{43,1,421},{29,19,1},{43,7,0},{30,7,0},{43,1,421},{8,1,421},{30,7,0}, +{0,9,433},{8,1,421},{0,9,433},{31,0,425},{31,0,425},{31,0,425},{31,0,425},{46,7,2},{46,7,2},{46,7,2},{46,27,5},{12,41,1},{12,41,1},{29,1,1346},{45,17,454},{29,21,653},{45,37,459},{45,1,1818},{47,19,446},{47,37,13},{46,39,679},{10,3,1518},{42,23,455},{27,1,526},{13,33,5},{43,21,38},{13,7,93},{27,5,1514},{30,3,425},{31,37,11},{40,23,421},{6,1,1514}, +{40,23,421},{45,1,434},{45,1,434},{45,1,434},{45,7,429},{47,1,340},{47,37,4},{47,37,4},{47,25,50},{42,37,338},{44,25,5},{13,33,4},{13,33,4},{13,33,4},{13,23,5},{17,2,338},{31,37,2},{31,37,2},{44,25,1},{16,1,338},{44,25,1},{11,1,421},{13,33,1},{27,21,5},{30,21,5},{11,1,421},{26,1,421},{30,21,5},{0,23,421},{26,1,421},{0,23,421},{45,0,425}, +{45,0,425},{45,0,425},{45,0,425},{47,5,1},{47,5,1},{47,5,1},{47,11,0},{44,25,4},{44,25,4},{43,1,1502},{13,1,478},{13,35,655},{29,5,461},{29,1,1926},{31,3,446},{15,5,19},{47,7,685},{26,17,1518},{28,7,454},{11,1,569},{27,17,6},{27,5,50},{43,21,97},{17,10,1514},{47,33,425},{15,5,10},{26,7,426},{24,1,1514},{26,7,426},{13,1,477},{13,1,477},{13,1,477}, +{29,37,426},{15,1,355},{15,21,11},{15,21,11},{31,9,41},{12,5,341},{14,39,6},{27,33,1},{27,33,1},{27,33,1},{27,7,2},{29,3,338},{15,21,2},{15,21,2},{14,39,5},{43,9,338},{14,39,5},{25,1,421},{43,1,5},{41,5,0},{31,5,1},{25,1,421},{14,1,421},{31,5,1},{0,7,425},{14,1,421},{0,7,425},{29,0,425},{29,0,425},{29,0,425},{29,0,425},{31,19,9}, +{31,19,9},{31,19,9},{31,25,10},{14,39,2},{14,39,2},{11,1,1634},{43,1,542},{43,19,659},{43,35,459},{43,1,2070},{45,17,446},{45,35,13},{15,37,655},{12,1,1518},{44,21,455},{25,1,646},{11,1,9},{41,19,43},{11,5,93},{25,3,1514},{31,1,422},{29,35,11},{42,21,421},{12,1,1514},{42,21,421},{43,1,506},{43,1,506},{43,1,506},{43,5,429},{29,1,381},{45,35,4},{45,35,4}, +{45,23,50},{44,35,338},{46,23,5},{11,1,5},{11,1,5},{11,1,5},{11,21,5},{39,11,338},{29,35,2},{29,35,2},{46,23,1},{22,1,338},{46,23,1},{39,1,421},{11,1,5},{25,19,10},{31,19,9},{39,1,421},{31,1,421},{31,19,9},{0,21,421},{31,1,421},{0,21,421},{43,0,425},{43,0,425},{43,0,425},{43,0,425},{45,19,0},{45,19,0},{45,19,0},{45,9,0},{46,23,4}, +{46,23,4},{25,1,1874},{11,1,666},{11,33,657},{27,3,451},{11,1,2201},{13,1,454},{13,3,9},{29,5,674},{14,1,1557},{30,5,458},{39,1,722},{9,1,62},{9,33,50},{25,19,85},{9,1,1514},{29,1,446},{13,3,5},{44,5,433},{46,1,1514},{44,5,433},{11,1,545},{11,1,545},{11,1,545},{27,19,429},{43,1,437},{13,3,8},{13,3,8},{29,7,48},{30,19,341},{47,37,6},{25,1,9}, +{25,1,9},{25,1,9},{25,5,0},{25,5,338},{13,3,4},{13,3,4},{47,37,2},{10,1,338},{47,37,2},{37,1,421},{9,1,37},{39,3,2},{29,3,1},{37,1,421},{43,1,421},{29,3,1},{0,5,433},{43,1,421},{0,5,433},{27,0,425},{27,0,425},{27,0,425},{27,0,425},{13,3,4},{13,3,4},{13,3,4},{13,39,5},{46,21,5},{46,21,5},{9,1,2030},{25,1,882},{25,17,653}, +{41,33,453},{9,1,2382},{27,1,546},{43,17,15},{13,35,661},{47,1,1653},{46,19,462},{7,1,837},{39,1,162},{39,17,38},{9,33,89},{19,9,1514},{27,1,521},{43,17,14},{44,19,421},{45,1,1514},{44,19,421},{25,1,626},{25,1,626},{25,1,626},{41,3,422},{11,1,488},{43,17,11},{43,17,11},{43,21,54},{46,33,340},{31,21,9},{39,1,18},{39,1,18},{39,1,18},{9,19,10},{9,3,338}, +{27,33,2},{27,33,2},{15,21,4},{31,3,338},{15,21,4},{5,1,421},{7,1,80},{7,17,8},{13,17,5},{5,1,421},{9,1,421},{13,17,5},{0,19,421},{9,1,421},{0,19,421},{41,0,421},{41,0,421},{41,0,421},{41,0,421},{43,1,1},{43,1,1},{43,1,1},{43,7,1},{31,5,5},{31,5,5},{23,1,2201},{39,1,1083},{9,1,670},{25,1,450},{39,1,2443},{11,1,684},{11,1,8}, +{27,3,634},{29,1,1751},{31,3,429},{21,1,890},{7,1,277},{7,1,52},{23,17,74},{21,17,1459},{25,1,603},{11,1,4},{30,3,401},{17,21,1459},{30,3,401},{9,1,670},{9,1,670},{9,1,670},{25,17,429},{25,1,579},{11,1,8},{11,1,8},{27,5,50},{47,1,340},{15,35,6},{7,1,52},{7,1,52},{7,1,52},{23,3,0},{23,3,338},{11,1,4},{11,1,4},{15,35,2},{43,3,338}, +{15,35,2},{19,1,392},{5,1,149},{37,1,1},{27,1,0},{19,1,392},{37,1,392},{27,1,0},{0,3,400},{37,1,392},{0,3,400},{25,0,425},{25,0,425},{25,0,425},{25,0,425},{11,1,4},{11,1,4},{11,1,4},{11,37,5},{15,35,5},{15,35,5},{7,1,1901},{23,1,1050},{23,1,761},{39,1,426},{7,1,2093},{9,1,551},{25,1,35},{11,33,382},{13,1,1407},{45,33,219},{5,1,638}, +{21,1,233},{21,1,89},{7,1,29},{17,39,1064},{23,1,398},{9,1,10},{31,33,202},{39,17,1064},{31,33,202},{23,1,761},{23,1,761},{23,1,761},{39,1,426},{9,1,638},{25,1,35},{25,1,35},{41,19,51},{45,1,355},{29,19,6},{21,1,89},{21,1,89},{21,1,89},{7,17,5},{3,25,338},{9,1,10},{9,1,10},{13,19,1},{29,1,338},{13,19,1},{3,1,200},{35,1,68},{5,1,1}, +{9,1,1},{3,1,200},{5,1,200},{9,1,1},{0,33,202},{5,1,200},{0,33,202},{39,0,425},{39,0,425},{39,0,425},{39,0,425},{25,1,26},{25,1,26},{25,1,26},{41,5,1},{29,3,5},{29,3,5},{21,1,1606},{37,1,1085},{7,1,886},{7,1,461},{21,1,1749},{23,1,470},{39,1,117},{25,33,186},{11,1,1166},{13,17,66},{19,1,461},{35,1,213},{5,1,125},{21,1,2},{3,3,722}, +{7,1,266},{23,1,37},{29,17,61},{3,3,722},{29,17,61},{7,1,886},{7,1,886},{7,1,886},{7,1,461},{23,1,770},{39,1,117},{39,1,117},{9,3,51},{43,1,426},{43,33,1},{5,1,125},{5,1,125},{5,1,125},{21,1,2},{19,5,338},{23,1,37},{23,1,37},{43,33,0},{37,3,338},{43,33,0},{1,3,61},{33,1,25},{3,1,1},{5,1,1},{1,3,61},{3,1,61},{5,1,1}, +{0,17,61},{3,1,61},{0,17,61},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{9,1,37},{9,1,37},{9,1,37},{9,19,5},{43,33,1},{43,33,1},{5,1,1450},{5,1,1109},{21,1,965},{37,1,542},{5,1,1505},{7,1,478},{7,1,253},{39,17,79},{9,1,1054},{27,1,10},{3,1,318},{19,1,221},{19,1,185},{35,1,29},{33,33,509},{35,1,210},{21,1,97},{27,1,10},{33,33,509}, +{27,1,10},{21,1,965},{21,1,965},{21,1,965},{37,1,542},{21,1,900},{7,1,253},{7,1,253},{39,17,54},{41,1,549},{11,17,9},{19,1,185},{19,1,185},{19,1,185},{35,1,29},{3,3,338},{21,1,97},{21,1,97},{11,17,5},{3,3,338},{11,17,5},{1,17,5},{17,1,1},{17,1,0},{33,1,0},{1,17,5},{17,1,5},{33,1,0},{0,1,9},{17,1,5},{0,1,9},{37,0,421}, +{37,0,421},{37,0,421},{37,0,421},{23,1,65},{23,1,65},{23,1,65},{39,3,2},{27,1,1},{27,1,1},{35,1,1213},{35,1,953},{5,1,886},{5,1,545},{35,1,1186},{21,1,448},{21,1,304},{23,1,32},{23,1,790},{25,1,13},{33,1,198},{3,1,150},{3,1,125},{19,1,36},{33,1,294},{19,1,121},{35,1,73},{9,1,0},{1,33,294},{9,1,0},{5,1,886},{5,1,886},{5,1,886}, +{5,1,545},{5,1,765},{21,1,304},{21,1,304},{23,1,32},{39,1,486},{25,1,13},{3,1,125},{3,1,125},{3,1,125},{19,1,36},{3,1,221},{35,1,73},{35,1,73},{9,1,0},{5,1,221},{9,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{37,1,113}, +{37,1,113},{37,1,113},{7,17,8},{25,1,13},{25,1,13},{3,1,885},{19,1,737},{19,1,701},{35,1,485},{19,1,834},{5,1,364},{5,1,264},{37,1,2},{7,1,554},{39,1,45},{17,1,82},{33,1,62},{33,1,53},{33,1,13},{1,3,114},{33,1,54},{3,1,34},{21,1,1},{3,1,114},{21,1,1},{19,1,701},{19,1,701},{19,1,701},{35,1,485},{35,1,574},{5,1,264},{5,1,264}, +{37,1,2},{7,1,329},{39,1,45},{33,1,53},{33,1,53},{33,1,53},{33,1,13},{33,1,85},{3,1,34},{3,1,34},{21,1,1},{19,1,85},{21,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{35,0,421},{35,0,421},{35,0,421},{35,0,421},{21,1,160},{21,1,160},{21,1,160},{37,1,2},{39,1,45}, +{39,1,45},{0,30,882},{0,10,100},{0,38,2},{0,6,340},{0,10,1896},{0,22,1189},{0,6,565},{0,4,1421},{0,20,2043},{0,4,1521},{0,30,882},{0,10,100},{0,38,2},{0,6,340},{4,2,1896},{0,22,1189},{0,6,565},{0,4,1421},{10,0,1896},{0,4,1421},{0,22,1},{0,22,1},{0,22,1},{0,34,0},{0,4,164},{0,18,52},{0,18,52},{0,32,98},{0,32,179},{0,32,107},{0,22,1}, +{0,22,1},{0,22,1},{0,34,0},{32,16,162},{0,18,52},{0,18,52},{0,32,98},{16,32,162},{0,32,98},{38,0,882},{0,10,100},{0,38,2},{0,6,340},{38,0,882},{30,0,882},{0,6,340},{0,20,884},{30,0,882},{0,20,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,15,884},{0,12,34},{0,24,13}, +{0,38,250},{0,12,2355},{0,8,1355},{0,22,585},{0,20,1669},{0,36,2567},{0,20,1813},{0,15,884},{0,12,34},{0,24,13},{0,38,250},{0,12,2355},{0,8,1355},{0,22,585},{0,20,1669},{12,0,2355},{0,20,1669},{0,10,0},{0,10,0},{0,10,0},{0,20,1},{0,20,340},{0,4,125},{0,4,125},{0,2,200},{0,18,376},{0,2,225},{0,10,0},{0,10,0},{0,10,0},{0,20,1},{16,4,338}, +{0,4,125},{0,4,125},{0,2,200},{4,16,338},{0,2,200},{24,0,882},{0,12,34},{16,24,4},{0,38,250},{24,0,882},{32,8,882},{0,38,250},{0,6,884},{32,8,882},{0,6,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,27,882},{0,14,9},{0,40,81},{0,8,202},{0,14,2899},{0,24,1539},{0,8,643}, +{0,6,2004},{0,6,3189},{0,36,2207},{0,27,882},{0,14,9},{16,40,61},{0,8,202},{6,2,2899},{0,24,1539},{0,8,643},{0,6,2004},{14,0,2899},{0,6,2004},{0,28,1},{0,28,1},{0,28,1},{0,6,4},{0,22,578},{0,36,221},{0,36,221},{0,18,365},{0,18,632},{0,18,401},{0,28,1},{0,28,1},{0,28,1},{0,6,4},{32,4,578},{0,36,221},{0,36,221},{0,18,365},{22,0,578}, +{0,18,365},{38,6,882},{0,14,9},{2,40,1},{0,8,202},{38,6,882},{27,0,882},{0,8,202},{0,22,884},{27,0,882},{0,22,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,25,910},{16,46,31},{16,26,151},{0,40,181},{0,31,3048},{0,26,1416},{0,40,506},{0,22,1944},{0,38,3484},{0,6,2233},{16,25,885}, +{16,46,6},{32,26,78},{16,40,165},{36,6,3048},{0,26,1416},{0,40,506},{0,22,1944},{31,0,3048},{0,22,1944},{16,30,26},{16,30,26},{16,30,26},{16,38,27},{0,24,650},{0,22,157},{0,22,157},{0,4,325},{0,4,766},{0,4,425},{16,30,1},{16,30,1},{16,30,1},{16,38,2},{18,4,648},{0,22,157},{0,22,157},{0,4,325},{36,2,648},{0,4,325},{26,2,882},{0,46,5},{18,26,4}, +{0,40,145},{26,2,882},{38,8,882},{0,40,145},{0,8,890},{38,8,882},{0,8,890},{16,0,26},{16,0,26},{16,0,26},{16,0,26},{0,18,0},{0,18,0},{0,18,0},{0,32,1},{0,16,10},{0,16,10},{16,7,1009},{16,31,134},{32,12,297},{16,26,238},{0,43,3048},{0,28,1224},{0,26,267},{0,8,1764},{0,24,3685},{0,38,2157},{2,9,885},{2,47,5},{18,12,77},{32,26,165},{6,8,3048}, +{0,28,1224},{0,26,267},{0,8,1764},{43,0,3048},{0,8,1764},{16,45,125},{16,45,125},{16,45,125},{16,40,126},{0,28,648},{0,24,80},{0,24,80},{0,36,260},{0,6,875},{0,20,413},{2,46,1},{2,46,1},{2,46,1},{2,24,2},{2,24,648},{0,24,80},{0,24,80},{0,36,260},{28,0,648},{0,36,260},{44,0,882},{2,47,4},{4,42,1},{0,26,98},{44,0,882},{26,8,882},{0,26,98}, +{0,24,890},{26,8,882},{0,24,890},{16,0,125},{16,0,125},{16,0,125},{16,0,125},{0,6,0},{0,6,0},{0,6,0},{0,18,1},{0,18,37},{0,18,37},{32,5,1147},{32,45,282},{2,44,523},{32,12,381},{0,9,3051},{0,14,1110},{0,12,116},{0,24,1658},{0,26,3859},{0,8,2173},{18,23,886},{18,15,6},{34,28,69},{18,42,166},{40,4,3048},{0,14,1110},{0,12,116},{0,24,1658},{22,8,3048}, +{0,24,1658},{32,13,265},{32,13,265},{32,13,265},{32,10,266},{0,46,650},{0,26,26},{0,26,26},{0,22,194},{0,22,987},{0,6,427},{18,15,5},{18,15,5},{18,15,5},{18,40,5},{22,2,648},{0,26,26},{0,26,26},{0,22,194},{42,2,648},{0,22,194},{30,0,882},{18,15,2},{20,28,4},{0,12,52},{30,0,882},{33,0,882},{0,12,52},{0,10,884},{33,0,882},{0,10,884},{32,0,265}, +{32,0,265},{32,0,265},{32,0,265},{0,24,0},{0,24,0},{0,24,0},{0,4,4},{0,34,89},{0,34,89},{2,3,1365},{2,13,510},{18,14,813},{2,28,566},{0,37,3048},{0,46,1013},{0,44,42},{0,10,1509},{0,12,4057},{0,10,2185},{4,7,885},{4,45,10},{20,44,86},{34,28,173},{28,0,3048},{0,46,1013},{0,44,42},{0,10,1509},{37,0,3048},{0,10,1509},{2,11,482},{2,11,482},{2,11,482}, +{2,42,481},{0,29,650},{0,12,4},{0,12,4},{0,38,128},{0,8,1161},{0,22,483},{4,15,2},{4,15,2},{4,15,2},{4,26,2},{8,2,648},{0,12,4},{0,12,4},{0,38,128},{30,2,648},{0,38,128},{47,0,882},{34,45,2},{6,44,1},{0,44,26},{47,0,882},{27,6,882},{0,44,26},{0,26,890},{27,6,882},{0,26,890},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,12,0}, +{0,12,0},{0,12,0},{0,6,1},{0,20,180},{0,20,180},{18,17,1647},{18,27,810},{34,46,1178},{2,14,837},{0,19,3048},{0,15,933},{0,14,21},{0,26,1443},{0,28,4329},{0,26,2227},{20,21,885},{20,29,5},{36,30,69},{20,44,182},{42,6,3048},{0,15,933},{0,14,21},{0,26,1443},{19,0,3048},{0,26,1443},{18,25,765},{18,25,765},{18,25,765},{18,28,766},{0,11,648},{0,14,5},{0,14,5}, +{0,24,89},{0,10,1342},{0,8,557},{20,29,1},{20,29,1},{20,29,1},{20,42,2},{24,4,648},{16,44,2},{16,44,2},{0,24,89},{11,0,648},{0,24,89},{34,3,882},{4,13,4},{22,30,4},{0,14,17},{34,3,882},{35,4,882},{0,14,17},{0,12,884},{35,4,882},{0,12,884},{18,0,765},{18,0,765},{18,0,765},{18,0,765},{0,30,0},{0,30,0},{0,30,0},{0,38,0},{0,6,274}, +{0,6,274},{34,1,1782},{34,41,940},{4,31,1356},{34,46,950},{16,1,3052},{16,29,910},{16,46,22},{0,12,1335},{0,46,4231},{0,12,1924},{6,5,882},{6,43,5},{22,47,86},{36,30,174},{32,3,3048},{0,13,900},{32,46,13},{0,12,1299},{39,4,3048},{0,12,1299},{34,23,882},{34,23,882},{34,23,882},{34,14,883},{16,9,651},{16,46,18},{16,46,18},{16,10,74},{0,42,1256},{0,40,434},{6,13,0}, +{6,13,0},{6,13,0},{6,28,1},{38,10,648},{2,30,2},{2,30,2},{0,10,45},{23,0,648},{0,10,45},{4,1,882},{36,27,4},{8,46,4},{0,46,5},{4,1,882},{1,4,882},{0,46,5},{0,28,890},{1,4,882},{0,28,890},{34,0,882},{34,0,882},{34,0,882},{34,0,882},{16,31,1},{16,31,1},{16,31,1},{16,24,1},{0,8,250},{0,8,250},{20,1,1814},{20,25,945},{36,15,1363}, +{4,47,945},{2,1,3052},{32,43,916},{2,47,23},{16,44,1337},{0,31,3975},{0,28,1612},{22,19,886},{22,11,6},{38,31,77},{22,46,185},{2,1,3048},{0,27,883},{2,47,19},{0,44,1188},{1,2,3048},{0,44,1188},{20,7,901},{20,7,901},{20,7,901},{20,30,900},{2,9,654},{2,47,14},{2,47,14},{32,26,70},{0,28,1059},{0,26,236},{22,27,4},{22,27,4},{22,27,4},{22,14,8},{28,2,648}, +{18,46,5},{18,46,5},{0,42,36},{42,8,648},{0,42,36},{27,0,882},{22,11,2},{24,31,4},{0,31,5},{27,0,882},{37,8,882},{0,31,5},{0,14,882},{37,8,882},{0,14,882},{4,0,900},{4,0,900},{4,0,900},{4,0,900},{2,15,5},{2,15,5},{2,15,5},{2,40,4},{0,40,146},{0,40,146},{6,1,1864},{36,39,947},{6,29,1356},{36,31,943},{34,1,3073},{18,27,910},{18,15,21}, +{2,14,1335},{0,45,3751},{0,14,1379},{8,3,885},{8,41,5},{24,15,85},{38,31,182},{29,0,3048},{32,11,884},{34,15,16},{0,30,1146},{37,6,3048},{0,30,1146},{36,21,882},{36,21,882},{36,21,882},{36,47,886},{18,7,649},{18,15,21},{18,15,21},{18,12,74},{0,14,945},{0,12,91},{8,11,2},{8,11,2},{8,11,2},{8,30,2},{16,3,648},{34,31,1},{34,31,1},{0,12,10},{17,0,648}, +{0,12,10},{28,13,882},{38,25,4},{10,15,1},{2,15,1},{28,13,882},{27,12,882},{2,15,1},{0,30,890},{27,12,882},{0,30,890},{36,0,882},{36,0,882},{36,0,882},{36,0,882},{18,29,1},{18,29,1},{18,29,1},{18,26,1},{0,42,68},{0,42,68},{22,1,1944},{22,23,945},{38,13,1363},{6,45,945},{20,1,3115},{34,41,916},{4,45,18},{18,46,1337},{0,13,3580},{0,46,1153},{24,17,886}, +{24,9,6},{40,29,69},{24,15,168},{46,10,3048},{2,25,885},{4,45,14},{0,46,1053},{23,8,3048},{0,46,1053},{22,5,901},{22,5,901},{22,5,901},{6,31,901},{4,7,654},{4,45,9},{4,45,9},{34,28,70},{0,47,825},{0,44,25},{24,25,4},{24,25,4},{24,25,4},{24,46,8},{30,4,648},{20,15,0},{20,15,0},{0,44,0},{15,8,648},{0,44,0},{40,3,882},{24,9,2},{26,29,4}, +{2,29,5},{40,3,882},{16,9,882},{2,29,5},{0,47,890},{16,9,882},{0,47,890},{6,0,900},{6,0,900},{6,0,900},{6,0,900},{4,13,5},{4,13,5},{4,13,5},{4,42,4},{0,28,18},{0,28,18},{8,1,2056},{38,21,956},{8,43,1348},{38,29,949},{6,1,3156},{20,25,910},{20,13,22},{4,47,1318},{0,11,3384},{0,31,1015},{10,1,882},{10,39,5},{26,13,75},{40,29,174},{27,2,3048}, +{34,9,885},{36,13,10},{0,31,990},{39,10,3048},{0,31,990},{38,3,885},{38,3,885},{38,3,885},{38,45,885},{20,5,649},{20,13,21},{20,13,21},{20,14,66},{0,15,729},{0,30,5},{10,9,0},{10,9,0},{10,9,0},{10,31,1},{45,0,648},{6,29,2},{6,29,2},{16,30,4},{27,8,648},{16,30,4},{10,1,882},{40,23,1},{12,13,1},{4,13,1},{10,1,882},{4,9,882},{4,13,1}, +{0,31,890},{4,9,882},{0,31,890},{38,0,884},{38,0,884},{38,0,884},{38,0,884},{20,27,1},{20,27,1},{20,27,1},{20,28,1},{0,30,1},{0,30,1},{40,1,2134},{24,21,943},{40,11,1348},{8,43,952},{38,1,3240},{36,39,914},{6,27,22},{36,15,1330},{0,25,3244},{0,15,951},{42,1,891},{26,7,10},{42,27,77},{26,13,171},{8,1,3048},{4,23,886},{6,27,21},{0,15,950},{1,8,3048}, +{0,15,950},{24,3,890},{24,3,890},{24,3,890},{24,29,890},{6,35,649},{6,43,10},{6,43,10},{36,30,77},{0,13,675},{32,46,6},{26,7,10},{26,7,10},{26,7,10},{26,15,10},{29,2,648},{22,13,2},{22,13,2},{2,46,2},{35,6,648},{2,46,2},{21,0,882},{26,7,1},{28,27,4},{4,27,5},{21,0,882},{18,7,882},{4,27,5},{0,45,884},{18,7,882},{0,45,884},{24,0,890}, +{24,0,890},{24,0,890},{24,0,890},{6,11,1},{6,11,1},{6,11,1},{6,44,2},{16,47,2},{16,47,2},{26,1,2252},{40,35,940},{10,41,1348},{40,27,954},{24,1,3321},{22,23,910},{22,11,22},{6,45,1318},{0,39,3156},{0,29,940},{28,1,920},{12,37,5},{28,41,77},{12,27,180},{23,0,3048},{36,7,884},{38,11,10},{0,29,915},{18,9,3048},{0,29,915},{40,17,882},{40,17,882},{40,17,882}, +{40,43,883},{22,3,649},{38,27,20},{38,27,20},{22,47,86},{0,27,656},{2,31,9},{12,7,0},{12,7,0},{12,7,0},{12,29,1},{43,2,648},{38,27,4},{38,27,4},{34,47,4},{21,8,648},{34,47,4},{14,3,882},{42,21,1},{14,11,1},{6,11,1},{14,3,882},{32,5,882},{6,11,1},{0,29,890},{32,5,882},{0,29,890},{40,0,882},{40,0,882},{40,0,882},{40,0,882},{22,25,1}, +{22,25,1},{22,25,1},{22,30,2},{2,31,0},{2,31,0},{42,1,2404},{26,19,935},{42,9,1348},{10,41,952},{40,1,3409},{38,37,914},{8,41,30},{38,29,1354},{0,37,3087},{2,13,951},{14,1,954},{28,5,6},{44,25,77},{28,11,185},{9,6,3048},{6,21,886},{24,41,21},{0,43,900},{32,7,3048},{0,43,900},{26,1,891},{26,1,891},{26,1,891},{26,27,891},{8,3,654},{8,41,14},{8,41,14}, +{38,31,77},{16,41,651},{34,15,3},{28,5,5},{28,5,5},{28,5,5},{28,13,5},{38,1,648},{24,11,2},{24,11,2},{4,15,2},{43,28,648},{4,15,2},{46,3,882},{28,5,2},{30,25,4},{6,25,5},{46,3,882},{16,3,882},{6,25,5},{0,43,884},{16,3,882},{0,43,884},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{8,9,5},{8,9,5},{8,9,5},{8,46,4},{34,15,2}, +{34,15,2},{28,1,2612},{12,3,951},{28,39,1354},{42,9,952},{26,1,3544},{24,21,910},{40,9,30},{8,43,1348},{0,35,3060},{18,27,935},{30,1,1005},{14,35,3},{30,39,77},{44,25,185},{41,12,3048},{38,35,890},{40,9,14},{0,27,891},{16,5,3048},{0,27,891},{42,1,900},{42,1,900},{42,1,900},{42,41,885},{24,1,654},{40,25,21},{40,25,21},{24,45,77},{2,9,651},{4,29,6},{14,5,2}, +{14,5,2},{14,5,2},{14,27,2},{39,0,648},{10,25,2},{10,25,2},{4,29,5},{9,28,648},{4,29,5},{1,0,882},{44,19,2},{47,9,4},{8,9,5},{1,0,882},{0,1,882},{8,9,5},{0,27,890},{0,1,882},{0,27,890},{42,0,884},{42,0,884},{42,0,884},{42,0,884},{24,7,5},{24,7,5},{24,7,5},{24,31,4},{4,29,2},{4,29,2},{14,1,2774},{28,1,940},{44,7,1318}, +{12,39,966},{12,1,3700},{40,35,916},{10,23,22},{40,11,1348},{16,19,3051},{34,41,940},{47,1,1061},{30,3,9},{46,23,86},{30,9,190},{14,1,3048},{8,19,886},{26,39,20},{16,41,882},{4,5,3048},{16,41,882},{28,1,915},{28,1,915},{28,1,915},{28,25,890},{10,1,657},{10,39,10},{10,39,10},{40,29,77},{18,39,654},{36,13,5},{46,35,4},{46,35,4},{46,35,4},{46,11,4},{23,2,648}, +{42,9,4},{42,9,4},{6,13,0},{20,9,648},{6,13,0},{15,1,882},{30,3,0},{31,23,2},{24,23,1},{15,1,882},{9,11,882},{24,23,1},{0,41,882},{9,11,882},{0,41,882},{28,0,890},{28,0,890},{28,0,890},{28,0,890},{10,7,1},{10,7,1},{10,7,1},{10,15,1},{20,43,1},{20,43,1},{46,1,3014},{14,1,951},{14,37,1330},{44,23,958},{14,1,3865},{26,19,913},{26,7,22}, +{10,41,1348},{32,33,3049},{20,25,943},{15,1,1154},{47,33,6},{31,37,77},{46,23,185},{17,0,3048},{40,3,885},{42,7,10},{2,25,890},{18,3,3048},{2,25,890},{14,1,950},{14,1,950},{14,1,950},{44,39,885},{42,1,672},{26,7,21},{26,7,21},{26,43,77},{34,7,652},{6,27,10},{47,3,2},{47,3,2},{47,3,2},{47,25,2},{37,2,648},{12,23,2},{12,23,2},{6,27,10},{34,7,648}, +{6,27,10},{27,5,882},{46,17,2},{45,7,2},{10,7,1},{27,5,882},{6,1,882},{10,7,1},{0,25,890},{6,1,882},{0,25,890},{44,0,884},{44,0,884},{44,0,884},{44,0,884},{26,5,5},{26,5,5},{26,5,5},{26,29,4},{6,27,1},{6,27,1},{47,1,3214},{30,1,1015},{46,5,1318},{14,37,966},{30,1,4009},{42,33,916},{12,21,22},{42,9,1348},{18,17,3051},{20,39,956},{29,1,1240}, +{31,1,5},{15,21,66},{31,7,185},{27,9,3048},{10,17,886},{12,21,21},{2,39,885},{14,7,3048},{2,39,885},{30,1,990},{30,1,990},{30,1,990},{30,23,890},{28,1,715},{12,37,10},{12,37,10},{12,27,75},{20,37,651},{38,11,5},{31,17,4},{31,17,4},{31,17,4},{31,9,8},{44,1,648},{28,7,2},{28,7,2},{8,11,0},{26,9,648},{8,11,0},{17,10,882},{31,1,1},{29,21,1}, +{26,21,1},{17,10,882},{24,1,882},{26,21,1},{0,39,884},{24,1,882},{0,39,884},{30,0,890},{30,0,890},{30,0,890},{30,0,890},{12,5,1},{12,5,1},{12,5,1},{12,13,1},{22,41,1},{22,41,1},{15,1,3526},{47,1,1153},{47,19,1337},{46,5,958},{47,1,4231},{28,17,910},{44,5,18},{12,39,1363},{20,1,3067},{22,23,945},{43,1,1380},{45,1,25},{29,35,70},{45,21,185},{13,3,3048}, +{12,1,888},{44,5,9},{18,7,901},{44,5,3048},{18,7,901},{47,1,1053},{47,1,1053},{47,1,1053},{46,37,890},{14,1,762},{44,5,14},{44,5,14},{28,41,69},{6,5,650},{8,25,6},{45,1,0},{45,1,0},{45,1,0},{45,23,0},{31,5,648},{14,21,0},{14,21,0},{24,25,4},{14,9,648},{24,25,4},{41,1,882},{29,1,18},{43,5,4},{12,5,5},{41,1,882},{47,3,882},{12,5,5}, +{0,7,900},{47,3,882},{0,7,900},{46,0,890},{46,0,890},{46,0,890},{46,0,890},{28,3,5},{28,3,5},{28,3,5},{28,27,4},{8,25,2},{8,25,2},{29,1,3764},{15,1,1379},{15,3,1335},{47,35,950},{15,1,4477},{14,1,925},{14,19,21},{28,7,1356},{22,1,3145},{38,37,947},{11,1,1485},{13,1,91},{13,19,74},{29,35,178},{43,1,3048},{14,1,925},{14,19,21},{20,37,882},{8,1,3048}, +{20,37,882},{31,1,1146},{31,1,1146},{31,1,1146},{31,21,890},{46,1,841},{14,35,16},{14,35,16},{14,25,85},{38,35,649},{40,9,5},{13,1,10},{13,1,10},{13,1,10},{13,7,9},{17,2,648},{30,35,1},{30,35,1},{10,9,2},{16,1,648},{10,9,2},{9,1,882},{43,1,68},{27,19,1},{28,19,1},{9,1,882},{46,1,882},{28,19,1},{0,37,882},{46,1,882},{0,37,882},{31,0,890}, +{31,0,890},{31,0,890},{31,0,890},{14,3,1},{14,3,1},{14,3,1},{14,11,1},{40,9,4},{40,9,4},{13,1,4076},{29,1,1612},{45,17,1337},{15,3,950},{29,1,4684},{46,1,1035},{46,3,23},{14,37,1363},{24,1,3256},{24,21,945},{41,1,1650},{27,1,236},{27,33,70},{13,19,174},{11,1,3048},{47,1,1013},{46,3,14},{20,5,901},{5,9,3048},{20,5,901},{45,1,1188},{45,1,1188},{45,1,1188}, +{15,35,883},{47,1,910},{46,3,19},{46,3,19},{30,39,77},{8,3,651},{10,23,6},{43,1,36},{43,1,36},{43,1,36},{43,21,1},{29,3,648},{47,19,5},{47,19,5},{26,23,4},{43,9,648},{26,23,4},{19,9,882},{41,1,146},{41,3,4},{14,3,5},{19,9,882},{45,1,882},{14,3,5},{0,5,900},{45,1,882},{0,5,900},{15,0,882},{15,0,882},{15,0,882},{15,0,882},{30,1,5}, +{30,1,5},{30,1,5},{30,25,4},{10,23,2},{10,23,2},{11,1,4374},{13,1,1924},{13,1,1335},{45,33,961},{13,1,4972},{47,1,1225},{47,17,22},{30,5,1356},{26,1,3460},{40,35,940},{9,1,1755},{41,1,434},{11,17,74},{27,3,185},{23,5,3048},{15,1,1146},{47,17,18},{22,35,882},{14,1,3048},{22,35,882},{13,1,1299},{13,1,1299},{13,1,1299},{29,19,890},{15,1,1017},{47,33,13},{47,33,13}, +{46,23,86},{40,33,652},{42,7,5},{11,1,45},{11,1,45},{11,1,45},{27,5,5},{39,11,648},{31,3,2},{31,3,2},{12,7,0},{22,1,648},{12,7,0},{21,17,882},{9,1,250},{25,17,1},{30,17,1},{21,17,882},{17,21,882},{30,17,1},{0,35,882},{17,21,882},{0,35,882},{29,0,890},{29,0,890},{29,0,890},{29,0,890},{47,1,5},{47,1,5},{47,1,5},{47,9,4},{26,37,4}, +{26,37,4},{41,1,4427},{27,1,2227},{27,1,1443},{13,17,925},{11,1,4878},{45,1,1331},{15,1,21},{47,35,1178},{44,1,3438},{26,19,810},{23,1,1746},{9,1,557},{25,1,89},{11,17,142},{23,17,2814},{13,1,1125},{15,1,5},{24,19,765},{45,17,2814},{24,19,765},{27,1,1443},{27,1,1443},{27,1,1443},{13,33,884},{29,1,1132},{15,1,21},{15,1,21},{31,37,69},{10,1,648},{28,21,5},{25,1,89}, +{25,1,89},{25,1,89},{41,19,1},{25,5,648},{45,17,2},{45,17,2},{28,21,1},{10,1,648},{28,21,1},{19,3,761},{7,1,274},{39,1,0},{31,1,0},{19,3,761},{39,1,761},{31,1,0},{0,19,765},{39,1,761},{0,19,765},{13,0,884},{13,0,884},{13,0,884},{13,0,884},{15,1,17},{15,1,17},{15,1,17},{31,23,4},{12,5,4},{12,5,4},{9,1,3933},{11,1,2185},{11,1,1509}, +{27,1,899},{41,1,4346},{13,1,1109},{45,1,42},{15,19,813},{30,1,2958},{12,3,510},{7,1,1386},{23,1,483},{39,1,128},{25,17,59},{3,25,2249},{11,1,870},{13,1,4},{10,3,482},{29,1,2249},{10,3,482},{11,1,1509},{11,1,1509},{11,1,1509},{27,17,890},{43,1,1275},{45,1,42},{45,1,42},{45,21,86},{12,1,675},{44,5,10},{39,1,128},{39,1,128},{39,1,128},{9,3,5},{9,3,648}, +{13,1,4},{13,1,4},{14,5,2},{31,3,648},{14,5,2},{3,3,481},{21,1,180},{7,1,1},{13,1,0},{3,3,481},{7,1,481},{13,1,0},{0,3,481},{7,1,481},{0,3,481},{27,0,890},{27,0,890},{27,0,890},{27,0,890},{45,1,26},{45,1,26},{45,1,26},{45,7,1},{44,35,2},{44,35,2},{39,1,3541},{9,1,2173},{25,1,1658},{11,1,893},{9,1,3801},{27,1,1035},{13,1,116}, +{45,3,523},{47,1,2574},{44,33,282},{21,1,1070},{7,1,427},{23,1,194},{39,1,16},{21,17,1769},{25,1,673},{27,1,26},{12,33,265},{17,21,1769},{12,33,265},{25,1,1658},{25,1,1658},{25,1,1658},{11,1,893},{11,1,1386},{13,1,116},{13,1,116},{29,35,69},{14,1,734},{14,19,6},{23,1,194},{23,1,194},{23,1,194},{39,17,1},{23,3,648},{27,1,26},{27,1,26},{14,19,5},{43,3,648}, +{14,19,5},{33,3,265},{35,1,89},{5,1,4},{25,1,0},{33,3,265},{21,1,265},{25,1,0},{0,33,265},{21,1,265},{0,33,265},{11,0,884},{11,0,884},{11,0,884},{11,0,884},{13,1,52},{13,1,52},{13,1,52},{29,21,4},{14,19,2},{14,19,2},{23,1,3267},{39,1,2157},{9,1,1764},{25,1,954},{39,1,3397},{11,1,950},{27,1,267},{13,33,297},{29,1,2313},{30,17,134},{5,1,838}, +{21,1,413},{37,1,260},{7,1,9},{17,39,1374},{23,1,518},{25,1,80},{44,17,125},{39,17,1374},{44,17,125},{9,1,1764},{9,1,1764},{9,1,1764},{25,1,954},{25,1,1569},{27,1,267},{27,1,267},{13,19,77},{47,1,846},{46,3,5},{37,1,260},{37,1,260},{37,1,260},{7,1,9},{3,25,648},{25,1,80},{25,1,80},{47,3,1},{29,1,648},{47,3,1},{33,1,113},{19,1,37},{19,1,1}, +{7,1,0},{33,1,113},{35,1,113},{7,1,0},{0,17,125},{35,1,113},{0,17,125},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{27,1,98},{27,1,98},{27,1,98},{43,5,1},{46,3,4},{46,3,4},{7,1,3032},{7,1,2233},{23,1,1944},{39,1,1083},{7,1,3096},{9,1,1028},{41,1,506},{27,17,151},{13,1,2068},{47,17,31},{35,1,693},{5,1,425},{5,1,325},{21,1,52},{3,3,1032}, +{7,1,406},{23,1,157},{31,17,26},{3,3,1032},{31,17,26},{23,1,1944},{23,1,1944},{23,1,1944},{39,1,1083},{39,1,1723},{41,1,506},{41,1,506},{27,33,78},{45,1,1034},{47,17,6},{5,1,325},{5,1,325},{5,1,325},{21,1,52},{19,5,648},{23,1,157},{23,1,157},{31,17,1},{37,3,648},{31,17,1},{17,1,18},{17,1,10},{33,1,1},{19,1,0},{17,1,18},{33,1,18},{19,1,0}, +{0,17,26},{33,1,18},{0,17,26},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{41,1,145},{41,1,145},{41,1,145},{27,19,4},{47,1,5},{47,1,5},{21,1,2710},{37,1,2207},{7,1,2004},{23,1,1173},{21,1,2775},{39,1,1036},{9,1,643},{41,1,81},{11,1,1900},{15,1,9},{3,1,524},{19,1,401},{19,1,365},{5,1,104},{33,33,771},{5,1,369},{37,1,221},{29,1,1},{33,33,771}, +{29,1,1},{7,1,2004},{7,1,2004},{7,1,2004},{23,1,1173},{23,1,1784},{9,1,643},{9,1,643},{41,17,61},{13,1,1091},{15,1,9},{19,1,365},{19,1,365},{19,1,365},{5,1,104},{33,5,578},{37,1,221},{37,1,221},{29,1,1},{23,1,578},{29,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{23,0,884}, +{23,0,884},{23,0,884},{23,0,884},{9,1,202},{9,1,202},{9,1,202},{41,3,1},{15,1,9},{15,1,9},{5,1,2214},{21,1,1813},{21,1,1669},{7,1,1109},{21,1,2151},{23,1,874},{23,1,585},{25,1,13},{25,1,1508},{13,1,34},{3,1,300},{3,1,225},{3,1,200},{19,1,61},{33,17,451},{35,1,192},{5,1,125},{11,1,0},{17,33,451},{11,1,0},{21,1,1669},{21,1,1669},{21,1,1669}, +{7,1,1109},{7,1,1460},{23,1,585},{23,1,585},{25,1,13},{11,1,872},{13,1,34},{3,1,200},{3,1,200},{3,1,200},{19,1,61},{17,5,338},{5,1,125},{5,1,125},{11,1,0},{5,17,338},{11,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{7,0,884},{7,0,884},{7,0,884},{7,0,884},{39,1,250}, +{39,1,250},{39,1,250},{25,17,4},{13,1,34},{13,1,34},{35,1,1818},{5,1,1521},{5,1,1421},{21,1,1028},{5,1,1675},{7,1,790},{7,1,565},{39,1,2},{23,1,1155},{11,1,100},{33,1,147},{33,1,107},{33,1,98},{3,1,29},{1,19,216},{19,1,88},{19,1,52},{23,1,1},{19,1,216},{23,1,1},{5,1,1421},{5,1,1421},{5,1,1421},{21,1,1028},{21,1,1158},{7,1,565},{7,1,565}, +{39,1,2},{25,1,723},{11,1,100},{33,1,98},{33,1,98},{33,1,98},{3,1,29},{33,17,162},{19,1,52},{19,1,52},{23,1,1},{17,33,162},{23,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{21,0,884},{21,0,884},{21,0,884},{21,0,884},{7,1,340},{7,1,340},{7,1,340},{39,1,2},{11,1,100}, +{11,1,100},{0,13,1568},{0,14,185},{0,10,5},{0,8,586},{0,44,3371},{0,24,2147},{0,8,1027},{0,36,2571},{0,6,3617},{0,20,2729},{0,13,1568},{0,14,185},{0,10,5},{0,8,586},{18,8,3371},{0,24,2147},{0,8,1027},{0,36,2571},{44,0,3371},{0,36,2571},{0,24,1},{0,24,1},{0,24,1},{0,20,1},{0,20,288},{0,34,100},{0,34,100},{0,2,164},{0,2,321},{0,2,189},{0,24,1}, +{0,24,1},{0,24,1},{0,20,1},{32,2,288},{0,34,100},{0,34,100},{0,2,164},{20,0,288},{0,2,164},{24,2,1568},{0,14,185},{0,10,5},{0,8,586},{24,2,1568},{13,0,1568},{0,8,586},{0,22,1576},{13,0,1568},{0,22,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1568},{0,46,89},{0,26,20}, +{0,40,505},{0,46,3968},{0,10,2316},{0,24,1078},{0,6,2880},{0,22,4305},{0,6,3105},{0,25,1568},{0,46,89},{0,26,20},{0,40,505},{18,10,3968},{0,10,2316},{0,24,1078},{0,6,2880},{46,0,3968},{0,6,2880},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{0,6,514},{0,20,193},{0,20,193},{0,18,317},{0,18,556},{0,18,353},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{2,2,512}, +{0,20,193},{0,20,193},{0,18,317},{2,2,512},{0,18,317},{16,11,1568},{0,46,89},{16,26,5},{0,40,505},{16,11,1568},{25,0,1568},{0,40,505},{0,38,1570},{25,0,1568},{0,38,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,7,1568},{0,15,37},{16,12,76},{0,10,421},{0,15,4652},{0,42,2540},{0,10,1097}, +{0,38,3251},{0,8,5108},{0,22,3545},{0,7,1568},{0,15,37},{16,12,51},{0,10,421},{38,2,4651},{0,42,2540},{0,10,1097},{0,38,3251},{16,8,4651},{0,38,3251},{0,46,0},{0,46,0},{0,46,0},{0,38,1},{0,8,802},{0,6,289},{0,6,289},{0,34,493},{0,34,872},{0,34,557},{0,46,0},{0,46,0},{0,46,0},{0,38,1},{4,0,802},{0,6,289},{0,6,289},{0,34,493},{8,0,802}, +{0,34,493},{26,4,1568},{0,15,37},{32,12,2},{0,10,421},{26,4,1568},{7,0,1568},{0,10,421},{0,24,1576},{7,0,1568},{0,24,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,19,1570},{0,29,8},{16,44,166},{0,12,338},{0,29,5420},{0,28,2755},{0,26,1208},{0,8,3659},{0,24,5988},{0,38,4028},{0,19,1570}, +{0,29,8},{16,44,141},{0,12,338},{40,0,5419},{0,28,2755},{0,26,1208},{0,8,3659},{46,2,5419},{0,8,3659},{0,45,0},{0,45,0},{0,45,0},{0,24,1},{0,24,1154},{0,22,433},{0,22,433},{0,4,697},{0,4,1270},{0,4,797},{0,45,0},{0,45,0},{0,45,0},{0,24,1},{18,4,1152},{0,22,433},{0,22,433},{0,4,697},{36,2,1152},{0,4,697},{14,0,1568},{0,29,8},{18,28,1}, +{0,12,338},{14,0,1568},{8,10,1568},{0,12,338},{0,40,1568},{8,10,1568},{0,40,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,17,1609},{16,43,45},{32,30,282},{0,28,325},{0,25,5419},{0,14,2514},{0,12,804},{0,24,3462},{0,10,6191},{0,8,3965},{32,3,1574},{32,13,17},{2,14,130},{16,28,312},{16,11,5419}, +{0,14,2514},{0,12,804},{0,24,3462},{25,0,5419},{0,24,3462},{16,43,41},{16,43,41},{16,43,41},{16,10,42},{0,28,1152},{0,40,292},{0,40,292},{0,36,596},{0,6,1379},{0,20,761},{32,29,4},{32,29,4},{32,29,4},{32,10,5},{2,24,1152},{0,40,292},{0,40,292},{0,36,596},{28,0,1152},{0,36,596},{30,2,1568},{0,27,4},{4,14,1},{0,28,244},{30,2,1568},{35,2,1568},{0,28,244}, +{0,26,1570},{35,2,1568},{0,26,1570},{16,0,41},{16,0,41},{16,0,41},{16,0,41},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,32,13},{0,32,13},{32,1,1733},{32,11,159},{32,46,455},{16,14,377},{0,7,5419},{0,47,2294},{0,44,542},{0,10,3225},{0,12,6401},{0,10,3901},{2,17,1569},{2,27,6},{18,46,125},{32,14,296},{26,4,5419},{0,47,2294},{0,44,542},{0,10,3225},{7,0,5419}, +{0,10,3225},{32,11,158},{32,11,158},{32,11,158},{32,42,157},{0,46,1154},{0,26,170},{0,26,170},{0,22,482},{0,22,1491},{0,6,739},{2,27,2},{2,27,2},{2,27,2},{2,26,5},{22,2,1152},{0,26,170},{0,26,170},{0,22,482},{42,2,1152},{0,22,482},{47,2,1568},{32,11,2},{20,30,5},{0,14,185},{47,2,1568},{17,2,1568},{0,14,185},{0,42,1570},{17,2,1568},{0,42,1570},{32,0,157}, +{32,0,157},{32,0,157},{32,0,157},{0,22,0},{0,22,0},{0,22,0},{0,34,1},{0,18,45},{0,18,45},{2,1,2003},{32,9,330},{2,31,710},{32,30,517},{0,35,5420},{0,15,2081},{0,30,345},{0,42,3099},{0,28,6641},{0,10,3885},{34,1,1574},{34,11,17},{4,47,134},{18,30,312},{14,0,5419},{0,15,2081},{0,30,345},{0,42,3099},{8,10,5419},{0,42,3099},{32,23,317},{32,23,317},{32,23,317}, +{32,28,317},{0,29,1154},{0,28,80},{0,28,80},{0,8,388},{0,8,1665},{0,38,753},{34,27,4},{34,27,4},{34,27,4},{34,12,5},{8,2,1152},{0,28,80},{0,28,80},{0,8,388},{30,2,1152},{0,8,388},{15,2,1568},{18,41,4},{36,47,5},{0,46,125},{15,2,1568},{33,4,1568},{0,46,125},{0,28,1576},{33,4,1568},{0,28,1576},{32,0,317},{32,0,317},{32,0,317},{32,0,317},{0,40,0}, +{0,40,0},{0,40,0},{0,20,0},{0,34,113},{0,34,113},{18,1,2395},{2,23,570},{18,45,1046},{2,47,725},{0,1,5419},{0,13,1947},{0,47,185},{0,12,2880},{0,14,6964},{0,12,3841},{20,1,1593},{4,25,6},{20,15,131},{34,46,326},{0,1,5419},{0,13,1947},{0,47,185},{0,12,2880},{1,0,5419},{0,12,2880},{2,21,546},{2,21,546},{2,21,546},{2,14,545},{0,11,1152},{0,30,37},{0,30,37}, +{0,24,317},{0,10,1846},{0,8,797},{4,25,2},{4,25,2},{4,25,2},{4,28,2},{24,4,1152},{0,30,37},{0,30,37},{0,24,317},{11,0,1152},{0,24,317},{43,0,1568},{34,9,1},{22,31,1},{0,47,85},{43,0,1568},{19,6,1568},{0,47,85},{0,44,1570},{19,6,1568},{0,44,1570},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,28,0},{0,28,0},{0,28,0},{0,6,1},{0,20,208}, +{0,20,208},{4,1,3030},{18,37,927},{34,29,1474},{18,15,1042},{16,1,5540},{0,27,1787},{0,15,57},{0,44,2668},{0,46,7299},{0,28,3836},{6,1,1612},{36,39,10},{6,29,136},{20,31,312},{47,2,5419},{0,27,1787},{0,15,57},{0,44,2668},{17,2,5419},{0,44,2668},{18,19,883},{18,19,883},{18,19,883},{18,46,882},{0,23,1152},{0,31,5},{0,31,5},{0,10,225},{0,26,2064},{0,10,901},{36,9,2}, +{36,9,2},{36,9,2},{36,14,1},{38,10,1152},{0,31,5},{0,31,5},{0,10,225},{23,0,1152},{0,10,225},{38,3,1568},{20,39,4},{8,45,5},{0,15,41},{38,3,1568},{35,8,1568},{0,15,41},{0,30,1570},{35,8,1568},{0,30,1570},{18,0,882},{18,0,882},{18,0,882},{18,0,882},{0,47,1},{0,47,1},{0,47,1},{0,8,1},{0,6,325},{0,6,325},{20,1,3734},{34,5,1332},{4,43,1958}, +{18,45,1395},{2,1,5808},{0,25,1676},{0,29,20},{0,30,2566},{0,15,7631},{0,44,3925},{22,1,1656},{6,7,9},{22,13,132},{6,45,309},{15,2,5419},{0,25,1676},{0,29,20},{0,30,2566},{33,4,5419},{0,30,2566},{34,33,1258},{34,33,1258},{34,33,1258},{34,47,1259},{0,5,1154},{0,45,5},{0,45,5},{0,42,180},{0,12,2275},{0,10,981},{6,23,4},{6,23,4},{6,23,4},{6,46,5},{28,2,1152}, +{16,15,1},{16,15,1},{0,42,180},{42,8,1152},{0,42,180},{41,2,1568},{36,7,2},{24,29,5},{0,29,20},{41,2,1568},{17,8,1568},{0,29,20},{0,46,1576},{17,8,1568},{0,46,1576},{34,0,1258},{34,0,1258},{34,0,1258},{34,0,1258},{0,29,0},{0,29,0},{0,29,0},{0,40,1},{0,38,482},{0,38,482},{36,1,4356},{4,19,1676},{20,27,2370},{34,13,1683},{18,1,6121},{0,39,1616},{16,43,36}, +{0,46,2397},{0,45,7815},{0,46,3837},{8,1,1715},{38,37,10},{8,43,131},{22,29,312},{43,0,5419},{0,39,1612},{16,43,27},{0,46,2393},{19,6,5419},{0,46,2393},{4,1,1577},{4,1,1577},{4,1,1577},{4,15,1576},{0,17,1156},{16,13,22},{16,13,22},{0,12,134},{0,44,2441},{0,12,971},{38,23,1},{38,23,1},{38,23,1},{38,47,2},{16,3,1152},{32,29,1},{32,29,1},{0,12,130},{17,0,1152}, +{0,12,130},{29,12,1568},{22,37,4},{10,43,5},{0,43,10},{29,12,1568},{26,13,1568},{0,43,10},{0,31,1576},{26,13,1568},{0,31,1576},{4,0,1576},{4,0,1576},{4,0,1576},{4,0,1576},{0,41,4},{0,41,4},{0,41,4},{0,26,4},{0,24,562},{0,24,562},{22,1,4616},{20,3,1677},{6,41,2378},{20,43,1681},{4,1,6311},{16,7,1620},{32,27,20},{0,31,2365},{0,43,7444},{0,47,3383},{40,1,1766}, +{8,5,11},{24,11,132},{8,13,314},{11,0,5419},{0,37,1577},{32,27,19},{0,31,2265},{5,8,5419},{0,31,2265},{20,1,1593},{20,1,1593},{20,1,1593},{20,29,1569},{32,1,1155},{32,27,19},{32,27,19},{16,44,125},{0,46,2150},{0,28,659},{8,21,2},{8,21,2},{8,21,2},{8,31,2},{30,4,1152},{18,13,1},{18,13,1},{0,44,72},{15,8,1152},{0,44,72},{37,0,1568},{38,5,2},{26,27,2}, +{0,27,2},{37,0,1568},{36,9,1568},{0,27,2},{0,15,1568},{36,9,1568},{0,15,1568},{20,0,1568},{20,0,1568},{20,0,1568},{20,0,1568},{32,41,1},{32,41,1},{32,41,1},{32,42,2},{0,26,388},{0,26,388},{8,1,4936},{6,17,1676},{22,9,2363},{36,11,1689},{36,1,6476},{2,37,1620},{18,41,24},{32,15,2370},{0,41,7036},{0,15,2859},{26,1,1851},{40,35,11},{10,25,136},{24,27,321},{41,2,5419}, +{16,5,1571},{18,41,20},{0,15,2130},{17,8,5419},{0,15,2130},{6,1,1619},{6,1,1619},{6,1,1619},{6,13,1571},{18,1,1158},{18,11,21},{18,11,21},{2,30,125},{0,31,1905},{0,14,425},{40,5,2},{40,5,2},{40,5,2},{40,45,2},{45,0,1152},{4,27,5},{4,27,5},{0,30,41},{27,8,1152},{0,30,41},{21,2,1568},{24,19,2},{12,41,1},{16,41,1},{21,2,1568},{24,9,1568},{16,41,1}, +{0,29,1570},{24,9,1568},{0,29,1570},{6,0,1570},{6,0,1570},{6,0,1570},{6,0,1570},{18,25,4},{18,25,4},{18,25,4},{18,28,5},{0,28,232},{0,28,232},{24,1,5154},{38,1,1680},{8,39,2378},{22,41,1683},{22,1,6708},{18,5,1628},{34,25,24},{2,29,2363},{0,9,6740},{0,45,2553},{12,1,1964},{10,3,8},{26,9,139},{40,41,309},{29,12,5419},{2,35,1572},{4,25,21},{0,29,2027},{26,13,5419}, +{0,29,2027},{38,1,1664},{38,1,1664},{38,1,1664},{22,27,1570},{4,1,1185},{34,25,20},{34,25,20},{34,46,130},{0,45,1721},{0,46,218},{10,19,4},{10,19,4},{10,19,4},{10,13,8},{29,2,1152},{20,11,5},{20,11,5},{0,47,25},{35,6,1152},{0,47,25},{35,2,1568},{10,3,4},{28,25,5},{18,25,4},{35,2,1568},{34,5,1568},{18,25,4},{0,13,1570},{34,5,1568},{0,13,1570},{22,0,1570}, +{22,0,1570},{22,0,1570},{22,0,1570},{34,23,1},{34,23,1},{34,23,1},{34,14,4},{0,14,149},{0,14,149},{26,1,5444},{8,1,1724},{24,23,2378},{38,9,1689},{8,1,6964},{4,35,1620},{20,39,36},{34,13,2370},{0,23,6513},{0,13,2244},{44,1,2099},{42,33,11},{12,23,136},{26,25,321},{37,0,5419},{18,3,1571},{20,39,27},{0,43,1924},{36,9,5419},{0,43,1924},{8,1,1720},{8,1,1720},{8,1,1720}, +{8,11,1577},{36,1,1224},{20,9,19},{20,9,19},{4,47,122},{0,43,1548},{0,31,90},{42,19,1},{42,19,1},{42,19,1},{42,43,2},{43,2,1152},{6,25,5},{6,25,5},{0,31,9},{21,8,1152},{0,31,9},{46,1,1568},{26,17,2},{14,39,2},{18,39,1},{46,1,1568},{26,7,1568},{18,39,1},{0,27,1576},{26,7,1568},{0,27,1576},{8,0,1576},{8,0,1576},{8,0,1576},{8,0,1576},{20,23,9}, +{20,23,9},{20,23,9},{4,30,10},{0,47,73},{0,47,73},{42,1,5700},{40,1,1798},{40,37,2375},{24,39,1683},{40,1,7153},{20,3,1626},{36,23,24},{4,27,2386},{0,21,6243},{0,27,1980},{30,1,2210},{12,1,8},{28,7,132},{42,39,323},{5,0,5419},{4,33,1572},{6,23,21},{0,27,1836},{0,5,5419},{0,27,1836},{40,1,1762},{40,1,1762},{40,1,1762},{24,25,1570},{6,1,1275},{36,23,20},{36,23,20}, +{36,15,125},{0,41,1395},{0,45,25},{12,17,4},{12,17,4},{12,17,4},{12,11,8},{38,1,1152},{22,9,4},{22,9,4},{0,45,0},{43,28,1152},{0,45,0},{31,1,1568},{42,1,2},{30,23,5},{4,23,5},{31,1,1568},{32,1,1568},{4,23,5},{0,11,1570},{32,1,1568},{0,11,1570},{24,0,1570},{24,0,1570},{24,0,1570},{24,0,1570},{36,21,1},{36,21,1},{36,21,1},{36,46,4},{0,15,25}, +{0,15,25},{28,1,6116},{26,1,1980},{26,5,2386},{40,7,1689},{26,1,7408},{6,17,1620},{22,37,24},{36,41,2375},{0,35,6044},{0,41,1798},{47,1,2385},{44,1,25},{14,37,125},{28,23,315},{35,2,5419},{20,1,1569},{22,37,20},{0,41,1762},{34,5,5419},{0,41,1762},{26,1,1836},{26,1,1836},{26,1,1836},{10,9,1574},{38,1,1363},{22,7,21},{22,7,21},{6,29,132},{0,9,1284},{0,13,8},{44,1,0}, +{44,1,0},{44,1,0},{44,41,0},{39,0,1152},{8,23,4},{8,23,4},{16,13,4},{9,28,1152},{16,13,4},{17,6,1568},{14,1,25},{47,37,4},{20,37,1},{17,6,1568},{20,1,1568},{20,37,1},{0,25,1570},{20,1,1568},{0,25,1570},{10,0,1570},{10,0,1570},{10,0,1570},{10,0,1570},{22,5,5},{22,5,5},{22,5,5},{22,31,5},{0,43,2},{0,43,2},{14,1,6434},{12,1,2244},{12,35,2370}, +{26,21,1685},{12,1,7724},{38,1,1620},{38,21,36},{22,25,2378},{0,3,5839},{0,9,1724},{31,1,2546},{30,1,90},{46,5,122},{14,7,322},{46,1,5419},{22,1,1602},{8,21,19},{0,9,1720},{26,7,5419},{0,9,1720},{42,1,1924},{42,1,1924},{42,1,1924},{26,23,1577},{24,1,1414},{38,21,27},{38,21,27},{22,13,136},{0,7,1218},{32,43,11},{30,1,9},{30,1,9},{30,1,9},{14,9,10},{23,2,1152}, +{24,7,5},{24,7,5},{18,43,1},{20,9,1152},{18,43,1},{27,3,1568},{46,1,73},{31,5,10},{36,5,9},{27,3,1568},{39,9,1568},{36,5,9},{0,9,1576},{39,9,1568},{0,9,1576},{26,0,1576},{26,0,1576},{26,0,1576},{26,0,1576},{38,19,1},{38,19,1},{38,19,1},{38,15,2},{16,27,2},{16,27,2},{30,1,6786},{44,1,2553},{28,3,2363},{42,5,1689},{28,1,8052},{24,1,1671},{24,35,24}, +{38,9,2378},{0,1,5715},{0,39,1680},{45,1,2675},{47,1,218},{47,35,130},{30,21,315},{31,1,5419},{24,1,1667},{24,35,20},{0,39,1664},{32,1,5419},{0,39,1664},{28,1,2027},{28,1,2027},{28,1,2027},{12,7,1571},{10,1,1521},{24,5,21},{24,5,21},{8,27,139},{0,21,1169},{2,11,8},{46,1,25},{46,1,25},{46,1,25},{46,39,1},{37,2,1152},{10,21,5},{10,21,5},{18,11,4},{34,7,1152}, +{18,11,4},{39,7,1568},{15,1,149},{15,35,4},{22,35,1},{39,7,1568},{26,1,1568},{22,35,1},{0,23,1570},{26,1,1568},{0,23,1570},{12,0,1570},{12,0,1570},{12,0,1570},{12,0,1570},{24,19,4},{24,19,4},{24,19,4},{24,29,5},{2,11,4},{2,11,4},{47,1,7186},{14,1,2859},{14,33,2370},{28,35,1683},{30,1,8313},{40,1,1819},{40,19,24},{8,23,2363},{16,1,5820},{16,7,1676},{13,1,2892}, +{15,1,425},{31,3,125},{47,35,321},{45,1,5419},{26,1,1796},{10,19,21},{0,7,1619},{27,9,5419},{0,7,1619},{14,1,2130},{14,1,2130},{14,1,2130},{28,21,1570},{42,1,1608},{40,19,20},{40,19,20},{24,11,136},{0,19,1155},{34,41,11},{31,1,41},{31,1,41},{31,1,41},{47,7,5},{44,1,1152},{26,5,5},{26,5,5},{4,41,2},{26,9,1152},{4,41,2},{25,1,1568},{29,1,232},{29,19,5}, +{24,19,4},{25,1,1568},{33,9,1568},{24,19,4},{0,7,1570},{33,9,1568},{0,7,1570},{28,0,1570},{28,0,1570},{28,0,1570},{28,0,1570},{40,17,1},{40,17,1},{40,17,1},{40,13,1},{18,25,2},{18,25,2},{15,1,7706},{46,1,3383},{30,1,2365},{14,3,1685},{47,1,8695},{42,1,2092},{26,33,20},{40,7,2378},{4,1,6099},{2,21,1677},{27,1,3152},{29,1,659},{45,17,125},{31,19,315},{27,3,5419}, +{44,1,1993},{26,33,19},{0,21,1593},{39,9,5419},{0,21,1593},{30,1,2265},{30,1,2265},{30,1,2265},{14,5,1572},{28,1,1764},{26,33,19},{26,33,19},{10,25,132},{32,3,1155},{4,9,11},{45,1,72},{45,1,72},{45,1,72},{15,37,1},{31,5,1152},{12,19,1},{12,19,1},{20,9,2},{14,9,1152},{20,9,2},{23,17,1568},{27,1,388},{43,33,2},{40,33,1},{23,17,1568},{45,17,1568},{40,33,1}, +{0,21,1568},{45,17,1568},{0,21,1568},{14,0,1568},{14,0,1568},{14,0,1568},{14,0,1568},{26,1,2},{26,1,2},{26,1,2},{26,27,2},{4,39,2},{4,39,2},{45,1,8016},{47,1,3837},{47,1,2397},{30,17,1685},{31,1,9093},{28,1,2484},{42,17,36},{26,21,2370},{36,1,6379},{18,5,1676},{11,1,3345},{13,1,971},{13,1,134},{15,33,326},{39,7,5419},{30,1,2185},{12,17,22},{0,5,1577},{26,1,5419}, +{0,5,1577},{47,1,2393},{47,1,2393},{47,1,2393},{30,19,1576},{14,1,1890},{42,17,27},{42,17,27},{42,9,131},{2,17,1152},{36,39,10},{13,1,130},{13,1,130},{13,1,130},{45,5,5},{17,2,1152},{28,33,1},{28,33,1},{22,39,1},{16,1,1152},{22,39,1},{21,3,1568},{25,1,562},{27,1,4},{40,1,4},{21,3,1568},{43,1,1568},{40,1,4},{0,5,1576},{43,1,1568},{0,5,1576},{30,0,1576}, +{30,0,1576},{30,0,1576},{30,0,1576},{42,1,10},{42,1,10},{42,1,10},{42,11,5},{36,23,4},{36,23,4},{13,1,7700},{45,1,3925},{31,1,2566},{47,17,1637},{45,1,8460},{14,1,2285},{28,1,20},{42,5,1958},{38,1,5932},{4,35,1332},{9,1,2987},{11,1,981},{43,1,180},{29,17,219},{9,3,4803},{47,1,1925},{44,1,5},{32,35,1258},{31,3,4803},{32,35,1258},{31,1,2566},{31,1,2566},{31,1,2566}, +{47,3,1577},{30,1,2054},{28,1,20},{28,1,20},{12,23,132},{34,1,1155},{6,7,9},{43,1,180},{43,1,180},{43,1,180},{13,35,1},{29,3,1152},{14,17,1},{14,17,1},{22,7,4},{43,9,1152},{22,7,4},{21,1,1250},{39,1,482},{41,1,1},{28,1,0},{21,1,1250},{41,1,1250},{28,1,0},{0,35,1258},{41,1,1250},{0,35,1258},{47,0,1576},{47,0,1576},{47,0,1576},{47,0,1576},{28,1,20}, +{28,1,20},{28,1,20},{28,25,5},{6,37,2},{6,37,2},{43,1,7164},{29,1,3836},{45,1,2668},{31,1,1579},{13,1,7780},{30,1,2041},{14,1,57},{28,35,1474},{24,1,5308},{36,19,927},{9,1,2475},{11,1,901},{11,1,225},{43,17,110},{37,7,4056},{15,1,1590},{30,1,5},{18,19,883},{30,1,4056},{18,19,883},{45,1,2668},{45,1,2668},{45,1,2668},{31,17,1570},{47,1,2214},{14,1,57},{14,1,57}, +{28,7,136},{36,1,1186},{38,37,10},{11,1,225},{11,1,225},{11,1,225},{43,3,5},{39,11,1152},{30,1,5},{30,1,5},{8,37,2},{22,1,1152},{8,37,2},{5,1,882},{7,1,325},{9,1,1},{46,1,1},{5,1,882},{9,1,882},{46,1,1},{0,19,882},{9,1,882},{0,19,882},{31,0,1570},{31,0,1570},{31,0,1570},{31,0,1570},{14,1,41},{14,1,41},{14,1,41},{44,9,5},{38,21,4}, +{38,21,4},{11,1,6493},{13,1,3841},{13,1,2880},{45,1,1574},{43,1,7071},{47,1,1822},{46,1,185},{44,19,1046},{26,1,4761},{22,3,570},{23,1,2034},{9,1,797},{25,1,317},{11,17,34},{23,17,3318},{13,1,1221},{31,1,37},{20,3,546},{45,17,3318},{20,3,546},{13,1,2880},{13,1,2880},{13,1,2880},{45,1,1574},{45,1,2443},{46,1,185},{46,1,185},{14,21,131},{38,1,1275},{24,5,6},{25,1,317}, +{25,1,317},{25,1,317},{11,33,1},{25,5,1152},{31,1,37},{31,1,37},{24,5,2},{10,1,1152},{24,5,2},{3,3,545},{21,1,208},{7,1,1},{29,1,0},{3,3,545},{23,1,545},{29,1,0},{0,3,545},{23,1,545},{0,3,545},{45,0,1570},{45,0,1570},{45,0,1570},{45,0,1570},{46,1,85},{46,1,85},{46,1,85},{30,23,1},{8,35,1},{8,35,1},{41,1,6095},{11,1,3885},{43,1,3099}, +{13,1,1636},{11,1,6422},{45,1,1767},{31,1,345},{30,3,710},{44,1,4358},{8,33,330},{7,1,1698},{39,1,753},{9,1,388},{41,1,9},{3,25,2753},{27,1,1018},{29,1,80},{22,33,317},{29,1,2753},{22,33,317},{43,1,3099},{43,1,3099},{43,1,3099},{13,1,1636},{29,1,2628},{31,1,345},{31,1,345},{46,5,134},{40,1,1395},{10,35,17},{9,1,388},{9,1,388},{9,1,388},{41,1,9},{9,3,1152}, +{29,1,80},{29,1,80},{26,35,4},{31,3,1152},{26,35,4},{33,3,313},{35,1,113},{21,1,0},{41,1,0},{33,3,313},{21,1,313},{41,1,0},{0,33,317},{21,1,313},{0,33,317},{29,0,1576},{29,0,1576},{29,0,1576},{29,0,1576},{47,1,125},{47,1,125},{47,1,125},{46,37,5},{40,19,4},{40,19,4},{9,1,5661},{11,1,3901},{11,1,3225},{43,1,1739},{41,1,5978},{29,1,1685},{45,1,542}, +{47,33,455},{14,1,3994},{10,33,159},{21,1,1418},{7,1,739},{23,1,482},{9,1,16},{21,17,2273},{11,1,878},{27,1,170},{10,33,158},{17,21,2273},{10,33,158},{11,1,3225},{11,1,3225},{11,1,3225},{43,1,1739},{43,1,2875},{45,1,542},{45,1,542},{47,19,125},{42,1,1584},{26,3,6},{23,1,482},{23,1,482},{23,1,482},{9,1,16},{23,3,1152},{27,1,170},{27,1,170},{26,3,2},{43,3,1152}, +{26,3,2},{17,3,145},{19,1,45},{35,1,1},{23,1,0},{17,3,145},{35,1,145},{23,1,0},{0,33,157},{35,1,145},{0,33,157},{43,0,1570},{43,0,1570},{43,0,1570},{43,0,1570},{15,1,185},{15,1,185},{15,1,185},{31,21,5},{10,33,2},{10,33,2},{39,1,5341},{9,1,3965},{25,1,3462},{11,1,1889},{9,1,5505},{13,1,1765},{13,1,804},{31,33,282},{47,1,3750},{42,17,45},{5,1,1210}, +{21,1,761},{37,1,596},{23,1,73},{17,39,1878},{9,1,781},{41,1,292},{42,17,41},{39,17,1878},{42,17,41},{25,1,3462},{25,1,3462},{25,1,3462},{11,1,1889},{11,1,3058},{13,1,804},{13,1,804},{15,3,130},{44,1,1798},{12,33,17},{37,1,596},{37,1,596},{37,1,596},{23,1,73},{3,25,1152},{41,1,292},{41,1,292},{28,33,4},{29,1,1152},{28,33,4},{1,3,41},{33,1,13},{3,1,1}, +{5,1,1},{1,3,41},{3,1,41},{5,1,1},{0,17,41},{3,1,41},{0,17,41},{27,0,1570},{27,0,1570},{27,0,1570},{27,0,1570},{29,1,244},{29,1,244},{29,1,244},{15,5,1},{26,1,4},{26,1,4},{23,1,5128},{39,1,4028},{9,1,3659},{25,1,2169},{39,1,5148},{11,1,1917},{27,1,1208},{45,17,166},{29,1,3628},{28,1,8},{35,1,1089},{5,1,797},{5,1,697},{37,1,221},{3,3,1536}, +{7,1,706},{23,1,433},{44,1,0},{3,3,1536},{44,1,0},{9,1,3659},{9,1,3659},{9,1,3659},{25,1,2169},{25,1,3366},{27,1,1208},{27,1,1208},{45,17,141},{47,1,2105},{28,1,8},{5,1,697},{5,1,697},{5,1,697},{37,1,221},{19,5,1152},{23,1,433},{23,1,433},{44,1,0},{37,3,1152},{44,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0}, +{0,1,0},{1,1,0},{0,1,0},{41,0,1568},{41,0,1568},{41,0,1568},{41,0,1568},{13,1,338},{13,1,338},{13,1,338},{29,19,1},{28,1,8},{28,1,8},{7,1,4416},{23,1,3545},{39,1,3251},{9,1,2027},{23,1,4372},{41,1,1771},{11,1,1097},{13,17,76},{29,1,2956},{14,1,37},{19,1,753},{35,1,557},{35,1,493},{21,1,148},{17,5,1067},{21,1,513},{7,1,289},{47,1,0},{5,17,1067}, +{47,1,0},{39,1,3251},{39,1,3251},{39,1,3251},{9,1,2027},{9,1,2819},{11,1,1097},{11,1,1097},{13,17,51},{47,1,1769},{14,1,37},{35,1,493},{35,1,493},{35,1,493},{21,1,148},{5,1,802},{7,1,289},{7,1,289},{47,1,0},{9,1,802},{47,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{25,0,1576}, +{25,0,1576},{25,0,1576},{25,0,1576},{11,1,421},{11,1,421},{11,1,421},{13,33,2},{14,1,37},{14,1,37},{21,1,3786},{7,1,3105},{7,1,2880},{23,1,1929},{7,1,3648},{9,1,1532},{25,1,1078},{27,1,20},{13,1,2452},{47,1,89},{3,1,456},{19,1,353},{19,1,317},{35,1,89},{33,33,683},{5,1,321},{21,1,193},{13,1,1},{33,33,683},{13,1,1},{7,1,2880},{7,1,2880},{7,1,2880}, +{23,1,1929},{39,1,2411},{25,1,1078},{25,1,1078},{27,1,20},{29,1,1451},{47,1,89},{19,1,317},{19,1,317},{19,1,317},{35,1,89},{3,3,512},{21,1,193},{21,1,193},{13,1,1},{3,3,512},{13,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{39,0,1570},{39,0,1570},{39,0,1570},{39,0,1570},{41,1,505}, +{41,1,505},{41,1,505},{27,17,5},{47,1,89},{47,1,89},{21,1,3210},{21,1,2729},{37,1,2571},{7,1,1825},{21,1,3015},{39,1,1388},{9,1,1027},{11,1,5},{11,1,2032},{15,1,185},{3,1,264},{3,1,189},{3,1,164},{19,1,45},{17,3,384},{35,1,164},{35,1,100},{25,1,1},{35,1,384},{25,1,1},{37,1,2571},{37,1,2571},{37,1,2571},{7,1,1825},{7,1,2112},{9,1,1027},{9,1,1027}, +{11,1,5},{13,1,1235},{15,1,185},{3,1,164},{3,1,164},{3,1,164},{19,1,45},{33,3,288},{35,1,100},{35,1,100},{25,1,1},{21,1,288},{25,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{23,0,1576},{23,0,1576},{23,0,1576},{23,0,1576},{9,1,586},{9,1,586},{9,1,586},{11,1,5},{15,1,185}, +{15,1,185},{0,37,2665},{0,45,274},{0,44,8},{0,26,1025},{0,15,5885},{0,12,3666},{0,10,1742},{0,38,4406},{0,8,6359},{0,22,4730},{0,37,2665},{0,45,274},{0,44,8},{0,26,1025},{22,4,5885},{0,12,3666},{0,10,1742},{0,38,4406},{15,0,5885},{0,38,4406},{0,28,0},{0,28,0},{0,28,0},{0,6,1},{0,22,545},{0,20,208},{0,20,208},{0,18,340},{0,18,593},{0,18,376},{0,28,0}, +{0,28,0},{0,28,0},{0,6,1},{2,2,545},{0,20,208},{0,20,208},{0,18,340},{22,0,545},{0,18,340},{28,0,2665},{0,45,274},{0,44,8},{0,26,1025},{28,0,2665},{37,0,2665},{0,26,1025},{0,24,2665},{37,0,2665},{0,24,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,3,2665},{0,43,169},{0,14,17}, +{0,12,865},{0,13,6669},{0,28,3898},{0,42,1825},{0,8,4826},{0,24,7263},{0,38,5231},{0,3,2665},{0,43,169},{0,14,17},{0,12,865},{24,2,6669},{0,28,3898},{0,42,1825},{0,8,4826},{13,0,6669},{0,8,4826},{0,46,1},{0,46,1},{0,46,1},{0,8,4},{0,8,841},{0,6,306},{0,6,306},{0,34,520},{0,34,917},{0,34,584},{0,46,1},{0,46,1},{0,46,1},{0,8,4},{4,0,841}, +{0,6,306},{0,6,306},{0,34,520},{8,0,841},{0,34,520},{44,2,2665},{0,43,169},{16,14,2},{0,12,865},{44,2,2665},{3,0,2665},{0,12,865},{0,40,2669},{3,0,2665},{0,40,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,1,2669},{0,41,85},{16,46,79},{0,44,725},{0,11,7538},{0,14,4214},{0,12,1842}, +{0,8,5354},{0,10,8241},{0,8,5795},{0,1,2669},{0,41,85},{16,46,54},{0,44,725},{24,4,7538},{0,14,4214},{0,12,1842},{0,8,5354},{11,0,7538},{0,8,5354},{0,29,1},{0,29,1},{0,29,1},{0,24,4},{0,40,1201},{0,22,458},{0,22,458},{0,4,730},{0,4,1325},{0,4,830},{0,29,1},{0,29,1},{0,29,1},{0,24,4},{20,0,1201},{0,22,458},{0,22,458},{0,4,730},{40,0,1201}, +{0,4,730},{30,2,2665},{0,41,85},{32,46,5},{0,44,725},{30,2,2665},{35,2,2665},{0,44,725},{0,26,2665},{35,2,2665},{0,26,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{16,1,2799},{0,9,29},{16,31,167},{0,14,650},{0,9,8493},{0,46,4485},{0,44,1934},{0,40,5878},{0,26,9333},{0,40,6503},{16,1,2774}, +{0,9,29},{16,31,142},{0,14,650},{42,0,8493},{0,46,4485},{0,44,1934},{0,40,5878},{9,0,8493},{0,40,5878},{0,11,0},{0,11,0},{0,11,0},{0,26,1},{0,26,1625},{0,24,629},{0,24,629},{0,20,986},{0,20,1793},{0,20,1130},{0,11,0},{0,11,0},{0,11,0},{0,26,1},{36,0,1625},{0,24,629},{0,24,629},{0,20,986},{26,0,1625},{0,20,986},{2,1,2665},{0,9,29},{18,47,1}, +{0,14,650},{2,1,2665},{1,2,2665},{0,14,650},{0,42,2669},{1,2,2665},{0,42,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{32,1,3171},{0,7,4},{16,15,315},{0,46,514},{0,7,9669},{0,31,4865},{0,46,2114},{0,10,6505},{0,12,10663},{0,10,7181},{32,1,3050},{0,7,4},{32,15,274},{0,46,514},{26,4,9669}, +{0,31,4865},{0,46,2114},{0,10,6505},{7,0,9669},{0,10,6505},{0,23,0},{0,23,0},{0,23,0},{0,12,1},{0,28,2178},{0,10,820},{0,10,820},{0,6,1348},{0,6,2405},{0,20,1553},{0,23,0},{0,23,0},{0,23,0},{0,12,1},{2,24,2178},{0,10,820},{0,10,820},{0,6,1348},{28,0,2178},{0,6,1348},{29,0,2665},{0,7,4},{4,31,9},{0,46,514},{29,0,2665},{17,4,2665},{0,46,514}, +{0,28,2665},{17,4,2665},{0,28,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,1,3529},{16,21,35},{32,29,444},{0,31,474},{0,19,9670},{0,45,4529},{0,46,1634},{0,42,6265},{0,28,10919},{0,26,7149},{18,1,3146},{16,21,10},{2,29,285},{0,31,474},{14,0,9669},{0,45,4529},{0,46,1634},{0,42,6265},{8,10,9669}, +{0,42,6265},{16,21,34},{16,21,34},{16,21,34},{16,44,34},{0,46,2180},{0,12,610},{0,12,610},{0,22,1184},{0,22,2517},{0,22,1473},{16,21,9},{16,21,9},{16,21,9},{16,44,9},{22,2,2178},{0,12,610},{0,12,610},{0,22,1184},{42,2,2178},{0,22,1184},{13,2,2665},{16,21,1},{20,45,0},{0,31,410},{13,2,2665},{3,6,2665},{0,31,410},{0,14,2677},{3,6,2665},{0,14,2677},{16,0,34}, +{16,0,34},{16,0,34},{16,0,34},{0,34,0},{0,34,0},{0,34,0},{0,32,1},{0,32,10},{0,32,10},{18,1,3971},{32,35,150},{2,43,644},{16,45,534},{0,1,9669},{0,43,4214},{0,31,1226},{0,28,5954},{0,14,11246},{0,12,6951},{4,1,3285},{2,5,4},{34,13,274},{32,15,483},{0,1,9669},{0,43,4214},{0,31,1226},{0,28,5954},{1,0,9669},{0,28,5954},{16,3,146},{16,3,146},{16,3,146}, +{16,30,147},{0,29,2180},{0,28,458},{0,28,458},{0,8,1018},{0,8,2691},{0,38,1419},{2,21,0},{2,21,0},{2,21,0},{2,14,1},{8,2,2178},{0,28,458},{0,28,458},{0,8,1018},{30,2,2178},{0,8,1018},{27,2,2665},{2,5,4},{6,29,9},{0,15,338},{27,2,2665},{35,8,2665},{0,15,338},{0,30,2665},{35,8,2665},{0,30,2665},{16,0,146},{16,0,146},{16,0,146},{16,0,146},{0,6,1}, +{0,6,1},{0,6,1},{0,18,4},{0,18,40},{0,18,40},{34,1,4603},{32,3,307},{2,11,925},{32,29,667},{16,1,9779},{0,41,3905},{0,45,913},{0,44,5653},{0,46,11530},{0,44,6878},{36,1,3390},{18,19,11},{4,27,269},{2,29,474},{18,3,9669},{0,41,3905},{0,45,913},{0,44,5653},{45,8,9669},{0,44,5653},{32,1,291},{32,1,291},{32,1,291},{32,47,291},{0,11,2178},{0,46,305},{0,46,305}, +{0,40,925},{0,10,2872},{0,8,1427},{34,5,10},{34,5,10},{34,5,10},{18,46,9},{24,4,2178},{0,46,305},{0,46,305},{0,40,925},{11,0,2178},{0,40,925},{8,1,2665},{18,19,2},{22,43,0},{0,29,265},{8,1,2665},{1,8,2665},{0,29,265},{0,46,2677},{1,8,2665},{0,46,2677},{32,0,290},{32,0,290},{32,0,290},{32,0,290},{0,24,1},{0,24,1},{0,24,1},{0,20,1},{0,34,100}, +{0,34,100},{20,1,5538},{2,17,582},{34,41,1298},{2,43,882},{2,1,10086},{0,9,3618},{0,43,581},{0,30,5418},{0,15,11905},{0,14,6895},{22,1,3586},{4,3,3},{36,11,273},{34,43,478},{15,2,9669},{0,9,3618},{0,43,581},{0,30,5418},{33,4,9669},{0,30,5418},{2,1,570},{2,1,570},{2,1,570},{2,15,549},{0,23,2178},{0,15,185},{0,15,185},{0,10,765},{0,26,3090},{0,10,1441},{4,3,2}, +{4,3,2},{4,3,2},{4,47,2},{38,10,2178},{0,15,185},{0,15,185},{0,10,765},{23,0,2178},{0,10,765},{23,0,2665},{4,3,2},{8,11,8},{0,43,181},{23,0,2665},{18,9,2665},{0,43,181},{0,31,2665},{18,9,2665},{0,31,2665},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,28,0},{0,28,0},{0,28,0},{0,6,1},{0,20,208},{0,20,208},{36,1,6378},{18,1,926},{4,9,1734}, +{18,27,1131},{18,1,10495},{0,7,3434},{0,27,353},{0,47,5186},{0,45,12293},{0,46,6789},{8,1,3785},{20,17,10},{6,25,270},{4,27,491},{43,0,9669},{0,7,3434},{0,27,353},{0,47,5186},{19,6,9669},{0,47,5186},{18,1,922},{18,1,922},{18,1,922},{18,45,842},{0,5,2180},{0,29,106},{0,29,106},{0,42,666},{0,12,3301},{0,26,1514},{36,3,4},{36,3,4},{36,3,4},{36,15,8},{28,2,2178}, +{0,29,106},{0,29,106},{0,42,666},{42,8,2178},{0,42,666},{7,2,2665},{20,17,1},{24,41,2},{0,11,136},{7,2,2665},{2,7,2665},{0,11,136},{0,15,2669},{2,7,2665},{0,15,2669},{18,0,841},{18,0,841},{18,0,841},{18,0,841},{0,46,1},{0,46,1},{0,46,1},{0,8,4},{0,6,306},{0,6,306},{6,1,7490},{34,1,1446},{4,39,2218},{18,41,1450},{34,1,11103},{0,21,3209},{0,41,187}, +{0,31,4909},{0,43,12686},{0,31,6845},{40,1,3938},{6,1,3},{38,9,273},{36,41,478},{11,0,9669},{0,21,3209},{0,41,187},{0,31,4909},{5,8,9669},{0,31,4909},{34,1,1382},{34,1,1382},{34,1,1382},{34,13,1213},{0,17,2178},{0,27,40},{0,27,40},{0,28,544},{0,44,3603},{0,12,1541},{6,1,2},{6,1,2},{6,1,2},{6,45,2},{16,3,2178},{0,27,40},{0,27,40},{0,28,544},{17,0,2178}, +{0,28,544},{21,2,2665},{6,1,2},{10,9,8},{0,25,90},{21,2,2665},{16,5,2665},{0,25,90},{0,29,2665},{16,5,2665},{0,29,2665},{34,0,1213},{34,0,1213},{34,0,1213},{34,0,1213},{0,29,1},{0,29,1},{0,29,1},{0,24,4},{0,22,458},{0,22,458},{22,1,8710},{20,1,2145},{20,7,2826},{34,25,1850},{20,1,11913},{0,35,3073},{0,9,86},{0,15,4721},{0,41,13118},{0,15,6837},{26,1,4118}, +{38,1,29},{8,23,258},{6,25,491},{24,3,9669},{0,35,3073},{0,9,86},{0,15,4721},{3,24,9669},{0,15,4721},{4,1,1973},{4,1,1973},{4,1,1973},{34,27,1630},{16,1,2221},{0,25,10},{0,25,10},{0,44,450},{0,46,3876},{0,28,1633},{38,1,4},{38,1,4},{38,1,4},{38,29,8},{30,4,2178},{0,25,10},{0,25,10},{0,44,450},{15,8,2178},{0,44,450},{14,1,2665},{8,1,25},{26,39,1}, +{0,9,61},{14,1,2665},{4,5,2665},{0,9,61},{0,13,2669},{4,5,2665},{0,13,2669},{34,0,1629},{34,0,1629},{34,0,1629},{34,0,1629},{0,11,0},{0,11,0},{0,11,0},{0,26,1},{0,24,629},{0,24,629},{8,1,10335},{36,1,3100},{36,21,3546},{4,39,2361},{36,1,12883},{0,33,2901},{0,23,25},{0,13,4485},{0,25,13589},{0,45,6982},{42,1,4353},{24,1,117},{40,37,270},{38,39,491},{29,12,9669}, +{0,33,2901},{0,23,25},{0,13,4485},{26,13,9669},{0,13,4485},{36,1,2739},{36,1,2739},{36,1,2739},{4,41,2181},{32,1,2427},{0,39,4},{0,39,4},{0,46,353},{0,31,4242},{0,14,1830},{24,1,17},{24,1,17},{24,1,17},{8,43,2},{45,0,2178},{16,39,2},{16,39,2},{0,46,353},{27,8,2178},{0,46,353},{17,0,2665},{40,1,73},{12,7,5},{0,23,25},{17,0,2665},{18,3,2665},{0,23,25}, +{0,27,2665},{18,3,2665},{0,27,2665},{4,0,2180},{4,0,2180},{4,0,2180},{4,0,2180},{0,23,0},{0,23,0},{0,23,0},{0,12,1},{0,10,820},{0,10,820},{24,1,11582},{6,1,4137},{6,35,4199},{20,7,2845},{6,1,13958},{0,1,2826},{0,37,31},{0,43,4255},{0,39,13958},{0,43,6958},{28,1,4610},{10,1,278},{10,21,261},{8,23,481},{37,0,9669},{0,1,2825},{16,37,18},{0,43,4254},{36,9,9669}, +{0,43,4254},{36,1,3454},{36,1,3454},{36,1,3454},{20,9,2665},{18,1,2740},{16,7,26},{16,7,26},{0,47,278},{0,15,4491},{0,46,1858},{40,1,29},{40,1,29},{40,1,29},{40,27,5},{29,2,2178},{32,23,2},{32,23,2},{0,47,277},{35,6,2178},{0,47,277},{1,2,2665},{42,1,157},{28,37,2},{0,37,5},{1,2,2665},{2,1,2665},{0,37,5},{0,11,2677},{2,1,2665},{0,11,2677},{20,0,2665}, +{20,0,2665},{20,0,2665},{20,0,2665},{0,5,2},{0,5,2},{0,5,2},{0,14,5},{0,12,981},{0,12,981},{40,1,12090},{38,1,4554},{22,19,4203},{36,21,2837},{38,1,14410},{32,1,2930},{32,21,37},{0,27,4187},{0,37,13477},{0,27,6222},{14,1,4826},{42,1,465},{42,35,270},{40,7,488},{5,0,9669},{2,1,2921},{2,21,25},{0,27,4106},{0,5,9669},{0,27,4106},{22,1,3593},{22,1,3593},{22,1,3593}, +{6,39,2677},{34,1,2840},{32,21,21},{32,21,21},{16,15,277},{0,43,4186},{0,31,1450},{26,1,52},{26,1,52},{26,1,52},{10,41,2},{43,2,2178},{18,7,4},{18,7,4},{0,15,205},{21,8,2178},{0,15,205},{13,3,2665},{44,1,260},{14,5,5},{0,5,8},{13,3,2665},{20,1,2665},{0,5,8},{0,25,2665},{20,1,2665},{0,25,2665},{6,0,2677},{6,0,2677},{6,0,2677},{6,0,2677},{32,35,4}, +{32,35,4},{32,35,4},{32,30,5},{0,28,745},{0,28,745},{26,1,12542},{24,1,4990},{8,33,4178},{22,5,2845},{24,1,14719},{2,1,3162},{18,35,34},{16,41,4197},{0,5,13013},{0,41,5610},{46,1,5121},{28,1,754},{12,19,270},{26,21,484},{30,3,9669},{4,1,3110},{18,35,18},{0,41,3929},{42,9,9669},{0,41,3929},{8,1,3770},{8,1,3770},{8,1,3770},{22,7,2666},{20,1,3011},{18,5,26},{18,5,26}, +{32,45,261},{0,27,3822},{0,15,1062},{12,1,98},{12,1,98},{12,1,98},{42,25,5},{38,1,2178},{34,21,2},{34,21,2},{0,29,160},{43,28,2178},{0,29,160},{43,1,2665},{30,1,388},{30,35,2},{16,35,2},{43,1,2665},{8,1,2665},{16,35,2},{0,9,2677},{8,1,2665},{0,9,2677},{22,0,2665},{22,0,2665},{22,0,2665},{22,0,2665},{2,3,2},{2,3,2},{2,3,2},{2,46,5},{0,46,578}, +{0,46,578},{12,1,13222},{40,1,5610},{40,17,4197},{38,19,2849},{26,1,15194},{4,1,3497},{34,19,34},{32,9,4178},{0,3,12493},{0,25,4990},{47,1,5429},{14,1,1062},{44,33,261},{42,5,499},{46,1,9669},{36,1,3341},{4,19,26},{0,9,3770},{26,7,9669},{0,9,3770},{40,1,3929},{40,1,3929},{40,1,3929},{8,37,2678},{6,1,3174},{34,19,18},{34,19,18},{18,13,270},{0,25,3462},{0,29,754},{28,1,160}, +{28,1,160},{28,1,160},{12,39,5},{39,0,2178},{20,35,2},{20,35,2},{0,13,98},{9,28,2178},{0,13,98},{11,1,2665},{47,1,578},{47,3,5},{2,3,2},{11,1,2665},{42,1,2665},{2,3,2},{0,23,2665},{42,1,2665},{0,23,2665},{8,0,2677},{8,0,2677},{8,0,2677},{8,0,2677},{34,17,2},{34,17,2},{34,17,2},{34,31,2},{0,31,388},{0,31,388},{28,1,13826},{26,1,6222},{26,1,4187}, +{24,3,2835},{42,1,15614},{36,1,3886},{20,33,37},{18,23,4203},{0,17,12134},{0,39,4554},{45,1,5669},{30,1,1450},{14,17,277},{28,19,484},{31,1,9669},{38,1,3605},{20,33,21},{0,23,3593},{32,1,9669},{0,23,3593},{26,1,4106},{26,1,4106},{26,1,4106},{24,5,2665},{22,1,3378},{20,3,25},{20,3,25},{34,43,270},{0,39,3206},{0,43,465},{14,1,205},{14,1,205},{14,1,205},{44,7,5},{23,2,2178}, +{36,3,4},{36,3,4},{0,27,52},{20,9,2178},{0,27,52},{39,3,2665},{29,1,745},{31,33,5},{34,33,4},{39,3,2665},{14,1,2665},{34,33,4},{0,7,2677},{14,1,2665},{0,7,2677},{24,0,2665},{24,0,2665},{24,0,2665},{24,0,2665},{4,1,8},{4,1,8},{4,1,8},{4,15,5},{0,45,260},{0,45,260},{14,1,14322},{42,1,6958},{42,1,4255},{40,17,2837},{28,1,16150},{38,1,4422},{36,1,31}, +{34,7,4199},{0,1,11889},{0,7,4137},{29,1,6018},{47,1,1858},{46,1,278},{44,3,499},{45,1,9669},{40,1,3905},{6,17,26},{0,37,3454},{27,9,9669},{0,37,3454},{42,1,4254},{42,1,4254},{42,1,4254},{40,19,2678},{24,1,3540},{36,17,18},{36,17,18},{20,11,261},{0,37,2979},{0,11,278},{46,1,277},{46,1,277},{46,1,277},{14,37,5},{37,2,2178},{22,33,2},{22,33,2},{0,41,29},{34,7,2178}, +{0,41,29},{7,3,2665},{13,1,981},{15,1,5},{4,1,2},{7,3,2665},{15,1,2665},{4,1,2},{0,21,2665},{15,1,2665},{0,21,2665},{10,0,2677},{10,0,2677},{10,0,2677},{10,0,2677},{36,1,5},{36,1,5},{36,1,5},{36,29,2},{0,43,157},{0,43,157},{30,1,13683},{44,1,6982},{12,1,4485},{26,17,2739},{14,1,15204},{24,1,4100},{22,1,25},{20,37,3546},{0,1,10840},{0,37,3100},{13,1,5451}, +{15,1,1830},{47,1,353},{30,33,333},{39,11,8712},{26,1,3507},{38,1,4},{0,37,2739},{22,1,8712},{0,37,2739},{12,1,4485},{12,1,4485},{12,1,4485},{26,3,2665},{40,1,3736},{22,1,25},{22,1,25},{36,41,270},{0,5,2779},{0,25,117},{47,1,353},{47,1,353},{47,1,353},{46,5,5},{44,1,2178},{38,17,2},{38,17,2},{0,25,17},{26,9,2178},{0,25,17},{3,25,2178},{11,1,820},{13,1,1}, +{22,1,0},{3,25,2178},{29,1,2178},{22,1,0},{0,5,2180},{29,1,2178},{0,5,2180},{26,0,2665},{26,0,2665},{26,0,2665},{26,0,2665},{22,1,25},{22,1,25},{22,1,25},{6,13,5},{0,41,73},{0,41,73},{47,1,12750},{14,1,6837},{14,1,4721},{12,1,2694},{30,1,14061},{40,1,3663},{8,1,86},{6,21,2826},{2,1,9775},{0,21,2145},{11,1,4689},{29,1,1633},{45,1,450},{47,17,195},{17,10,7578}, +{44,1,2961},{24,1,10},{0,5,1973},{24,1,7578},{0,5,1973},{14,1,4721},{14,1,4721},{14,1,4721},{12,17,2673},{26,1,3965},{8,1,86},{8,1,86},{22,9,258},{0,3,2571},{0,39,29},{45,1,450},{45,1,450},{45,1,450},{47,19,5},{31,5,2178},{24,1,10},{24,1,10},{0,39,4},{14,9,2178},{0,39,4},{37,1,1625},{25,1,629},{27,1,1},{10,1,0},{37,1,1625},{27,1,1625},{10,1,0}, +{0,35,1629},{27,1,1625},{0,35,1629},{12,0,2669},{12,0,2669},{12,0,2669},{12,0,2669},{8,1,61},{8,1,61},{8,1,61},{38,27,1},{0,9,25},{0,9,25},{15,1,12134},{30,1,6845},{30,1,4909},{28,1,2666},{47,1,13165},{26,1,3426},{40,1,187},{38,5,2218},{2,1,9023},{0,35,1446},{11,1,4097},{13,1,1541},{29,1,544},{31,17,90},{39,7,6661},{14,1,2525},{26,1,40},{0,35,1382},{26,1,6661}, +{0,35,1382},{30,1,4909},{30,1,4909},{30,1,4909},{28,1,2666},{12,1,4230},{40,1,187},{40,1,187},{8,39,273},{0,17,2453},{0,7,3},{29,1,544},{29,1,544},{29,1,544},{15,3,5},{17,2,2178},{26,1,40},{26,1,40},{0,7,2},{16,1,2178},{0,7,2},{21,1,1201},{23,1,458},{25,1,4},{28,1,1},{21,1,1201},{41,1,1201},{28,1,1},{0,35,1213},{41,1,1201},{0,35,1213},{28,0,2665}, +{28,0,2665},{28,0,2665},{28,0,2665},{24,1,90},{24,1,90},{24,1,90},{8,11,8},{0,7,2},{0,7,2},{45,1,11330},{47,1,6789},{46,1,5186},{14,1,2694},{47,1,12365},{42,1,3246},{26,1,353},{8,5,1734},{20,1,8393},{0,19,926},{25,1,3614},{27,1,1514},{43,1,666},{45,17,35},{9,3,5829},{47,1,2177},{28,1,106},{0,19,922},{31,3,5829},{0,19,922},{46,1,5186},{46,1,5186},{46,1,5186}, +{14,1,2694},{14,1,4504},{26,1,353},{26,1,353},{24,7,270},{16,1,2450},{16,21,10},{43,1,666},{43,1,666},{43,1,666},{45,33,2},{29,3,2178},{28,1,106},{28,1,106},{2,37,4},{43,9,2178},{2,37,4},{5,1,841},{7,1,306},{9,1,4},{47,1,1},{5,1,841},{9,1,841},{47,1,1},{0,19,841},{9,1,841},{0,19,841},{14,0,2669},{14,0,2669},{14,0,2669},{14,0,2669},{10,1,136}, +{10,1,136},{10,1,136},{40,25,2},{16,21,1},{16,21,1},{29,1,10834},{15,1,6895},{31,1,5418},{30,1,2786},{45,1,11530},{44,1,3154},{42,1,581},{40,35,1298},{36,1,7857},{16,3,582},{9,1,3105},{11,1,1441},{11,1,765},{13,1,8},{37,7,5082},{47,1,1905},{14,1,185},{0,3,570},{30,1,5082},{0,3,570},{31,1,5418},{31,1,5418},{31,1,5418},{30,1,2786},{30,1,4724},{42,1,581},{42,1,581}, +{10,37,273},{2,1,2587},{2,5,3},{11,1,765},{11,1,765},{11,1,765},{13,1,8},{39,11,2178},{14,1,185},{14,1,185},{2,5,2},{22,1,2178},{2,5,2},{3,3,545},{21,1,208},{7,1,1},{29,1,0},{3,3,545},{23,1,545},{29,1,0},{0,3,545},{23,1,545},{0,3,545},{30,0,2665},{30,0,2665},{30,0,2665},{30,0,2665},{42,1,181},{42,1,181},{42,1,181},{10,9,8},{2,5,2}, +{2,5,2},{13,1,10311},{45,1,6878},{45,1,5653},{47,1,2933},{29,1,10827},{14,1,3066},{44,1,913},{10,3,925},{8,1,7297},{2,33,307},{39,1,2707},{9,1,1427},{41,1,925},{27,1,32},{23,17,4344},{29,1,1611},{47,1,305},{0,33,291},{45,17,4344},{0,33,291},{45,1,5653},{45,1,5653},{45,1,5653},{47,1,2933},{47,1,5051},{44,1,913},{44,1,913},{26,5,269},{4,1,2859},{18,19,11},{41,1,925}, +{41,1,925},{41,1,925},{27,1,32},{25,5,2178},{47,1,305},{47,1,305},{18,19,10},{10,1,2178},{18,19,10},{33,3,288},{35,1,100},{21,1,1},{25,1,1},{33,3,288},{21,1,288},{25,1,1},{0,33,290},{21,1,288},{0,33,290},{47,0,2677},{47,0,2677},{47,0,2677},{47,0,2677},{28,1,265},{28,1,265},{28,1,265},{42,23,0},{18,19,2},{18,19,2},{11,1,9837},{13,1,6951},{29,1,5954}, +{15,1,3166},{13,1,10279},{47,1,3138},{30,1,1226},{42,3,644},{40,1,6929},{34,33,150},{7,1,2436},{39,1,1419},{9,1,1018},{11,1,101},{3,25,3779},{13,1,1475},{29,1,458},{2,17,146},{29,1,3779},{2,17,146},{29,1,5954},{29,1,5954},{29,1,5954},{15,1,3166},{31,1,5396},{30,1,1226},{30,1,1226},{12,35,274},{36,1,3147},{4,3,4},{9,1,1018},{9,1,1018},{9,1,1018},{11,1,101},{9,3,2178}, +{29,1,458},{29,1,458},{20,3,0},{31,3,2178},{20,3,0},{17,3,128},{19,1,40},{19,1,4},{7,1,1},{17,3,128},{35,1,128},{7,1,1},{0,17,146},{35,1,128},{0,17,146},{31,0,2665},{31,0,2665},{31,0,2665},{31,0,2665},{14,1,338},{14,1,338},{14,1,338},{28,7,9},{4,3,4},{4,3,4},{11,1,9437},{27,1,7149},{43,1,6265},{29,1,3402},{11,1,9788},{47,1,3234},{47,1,1634}, +{28,33,444},{42,1,6719},{20,17,35},{21,1,2210},{23,1,1473},{23,1,1184},{25,1,241},{21,17,3299},{11,1,1400},{13,1,610},{20,17,34},{17,21,3299},{20,17,34},{43,1,6265},{43,1,6265},{43,1,6265},{29,1,3402},{45,1,5621},{47,1,1634},{47,1,1634},{28,3,285},{8,1,3421},{20,17,10},{23,1,1184},{23,1,1184},{23,1,1184},{25,1,241},{23,3,2178},{13,1,610},{13,1,610},{20,17,9},{43,3,2178}, +{20,17,9},{17,1,34},{33,1,10},{33,1,1},{35,1,0},{17,1,34},{3,1,34},{35,1,0},{0,17,34},{3,1,34},{0,17,34},{15,0,2677},{15,0,2677},{15,0,2677},{15,0,2677},{30,1,410},{30,1,410},{30,1,410},{44,21,0},{20,17,1},{20,17,1},{9,1,9175},{11,1,7181},{11,1,6505},{13,1,3686},{11,1,9340},{45,1,3447},{47,1,2114},{14,17,315},{44,1,6532},{6,1,4},{21,1,2034}, +{21,1,1553},{7,1,1348},{39,1,410},{17,39,2904},{9,1,1411},{11,1,820},{22,1,0},{39,17,2904},{22,1,0},{11,1,6505},{11,1,6505},{11,1,6505},{13,1,3686},{13,1,5990},{47,1,2114},{47,1,2114},{14,33,274},{40,1,3789},{6,1,4},{7,1,1348},{7,1,1348},{7,1,1348},{39,1,410},{3,25,2178},{11,1,820},{11,1,820},{22,1,0},{29,1,2178},{22,1,0},{1,1,0},{1,1,0},{1,1,0}, +{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{29,0,2665},{29,0,2665},{29,0,2665},{29,0,2665},{47,1,514},{47,1,514},{47,1,514},{30,5,9},{6,1,4},{6,1,4},{9,1,7987},{41,1,6503},{41,1,5878},{27,1,3561},{25,1,8118},{29,1,3051},{45,1,1934},{30,17,167},{30,1,5562},{8,1,29},{5,1,1507},{21,1,1130},{21,1,986},{23,1,298},{19,3,2166}, +{23,1,1019},{25,1,629},{10,1,0},{39,1,2166},{10,1,0},{41,1,5878},{41,1,5878},{41,1,5878},{27,1,3561},{27,1,5301},{45,1,1934},{45,1,1934},{30,17,142},{42,1,3266},{8,1,29},{21,1,986},{21,1,986},{21,1,986},{23,1,298},{37,1,1625},{25,1,629},{25,1,629},{10,1,0},{27,1,1625},{10,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0}, +{0,1,0},{1,1,0},{0,1,0},{43,0,2669},{43,0,2669},{43,0,2669},{43,0,2669},{15,1,650},{15,1,650},{15,1,650},{46,19,1},{8,1,29},{8,1,29},{39,1,7111},{9,1,5795},{9,1,5354},{11,1,3381},{9,1,6983},{13,1,2803},{13,1,1842},{47,17,79},{47,1,4802},{40,1,85},{35,1,1132},{5,1,830},{5,1,730},{7,1,226},{3,3,1601},{7,1,739},{23,1,458},{28,1,1},{3,3,1601}, +{28,1,1},{9,1,5354},{9,1,5354},{9,1,5354},{11,1,3381},{11,1,4622},{13,1,1842},{13,1,1842},{47,17,54},{44,1,2834},{40,1,85},{5,1,730},{5,1,730},{5,1,730},{7,1,226},{21,1,1201},{23,1,458},{23,1,458},{28,1,1},{41,1,1201},{28,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{27,0,2665}, +{27,0,2665},{27,0,2665},{27,0,2665},{45,1,725},{45,1,725},{45,1,725},{47,33,5},{40,1,85},{40,1,85},{23,1,6361},{39,1,5231},{9,1,4826},{41,1,3294},{39,1,6071},{11,1,2610},{43,1,1825},{15,1,17},{47,1,4162},{42,1,169},{19,1,792},{35,1,584},{35,1,520},{21,1,153},{19,1,1121},{7,1,531},{7,1,306},{47,1,1},{37,1,1121},{47,1,1},{9,1,4826},{9,1,4826},{9,1,4826}, +{41,1,3294},{41,1,4145},{43,1,1825},{43,1,1825},{15,1,17},{30,1,2474},{42,1,169},{35,1,520},{35,1,520},{35,1,520},{21,1,153},{5,1,841},{7,1,306},{7,1,306},{47,1,1},{9,1,841},{47,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{41,0,2669},{41,0,2669},{41,0,2669},{41,0,2669},{13,1,865}, +{13,1,865},{13,1,865},{15,17,2},{42,1,169},{42,1,169},{7,1,5637},{23,1,4730},{39,1,4406},{9,1,3146},{39,1,5287},{11,1,2418},{11,1,1742},{45,1,8},{29,1,3547},{44,1,274},{3,1,489},{19,1,376},{19,1,340},{35,1,100},{33,33,726},{5,1,344},{21,1,208},{29,1,0},{33,33,726},{29,1,0},{39,1,4406},{39,1,4406},{39,1,4406},{9,1,3146},{9,1,3630},{11,1,1742},{11,1,1742}, +{45,1,8},{47,1,2178},{44,1,274},{19,1,340},{19,1,340},{19,1,340},{35,1,100},{3,3,545},{21,1,208},{21,1,208},{29,1,0},{23,1,545},{29,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{25,0,2665},{25,0,2665},{25,0,2665},{25,0,2665},{27,1,1025},{27,1,1025},{27,1,1025},{45,1,8},{44,1,274}, +{44,1,274},{36,1,50644},{0,1,2121},{0,25,169},{0,41,4591},{20,1,59804},{0,3,19310},{0,11,7401},{0,43,24008},{0,9,65535},{0,15,40741},{18,1,10267},{0,3,1445},{0,41,137},{0,15,3985},{42,6,18065},{0,45,12064},{0,31,6081},{0,12,14121},{19,0,18065},{0,12,14121},{0,15,1},{0,15,1},{0,15,1},{0,24,0},{0,24,1105},{0,22,410},{0,22,410},{0,4,666},{0,4,1217},{0,4,766},{0,15,1}, +{0,15,1},{0,15,1},{0,24,0},{34,2,1105},{0,22,410},{0,22,410},{0,4,666},{24,0,1105},{0,4,666},{43,2,9248},{0,3,1445},{0,41,137},{0,15,3985},{43,2,9248},{21,8,9248},{0,15,3985},{0,14,9256},{21,8,9248},{0,14,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{36,1,53600},{16,1,2998},{0,9,44}, +{0,25,3941},{36,1,62123},{0,1,18506},{0,25,6750},{0,27,23131},{0,39,65535},{0,29,40569},{34,1,10859},{0,1,1241},{0,9,50},{0,13,3690},{16,3,19334},{0,43,12449},{0,15,6117},{0,28,14809},{17,0,19334},{0,28,14809},{0,27,0},{0,27,0},{0,27,0},{0,10,1},{0,26,1513},{0,8,585},{0,8,585},{0,20,914},{0,20,1669},{0,20,1058},{0,27,0},{0,27,0},{0,27,0},{0,10,1},{34,4,1513}, +{0,8,585},{0,8,585},{0,20,914},{26,0,1513},{0,20,914},{38,1,9248},{0,1,1241},{0,9,50},{0,13,3690},{38,1,9248},{43,28,9248},{0,13,3690},{0,46,9250},{43,28,9248},{0,46,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{36,1,56716},{16,1,4497},{0,23,30},{0,39,3500},{36,1,64625},{0,1,18101},{0,9,6313}, +{0,11,22459},{0,37,65535},{0,43,39632},{4,1,11624},{0,1,1225},{0,39,10},{0,27,3400},{16,1,20689},{0,41,12854},{0,43,6221},{0,44,15490},{19,2,20689},{0,44,15490},{0,9,1},{0,9,1},{0,9,1},{0,42,1},{0,12,1985},{0,10,757},{0,10,757},{0,36,1241},{0,36,2193},{0,20,1394},{0,9,1},{0,9,1},{0,9,1},{0,42,1},{6,0,1985},{0,10,757},{0,10,757},{0,36,1241},{12,0,1985}, +{0,36,1241},{24,1,9248},{0,1,1225},{0,39,10},{0,27,3400},{24,1,9248},{32,9,9248},{0,27,3400},{0,47,9248},{32,9,9248},{0,47,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,1,58324},{32,1,6344},{0,7,6},{0,23,2873},{36,1,65535},{16,1,17968},{0,23,5727},{0,25,21128},{0,21,63585},{0,27,38087},{36,1,12449}, +{16,1,1437},{0,7,9},{0,41,3185},{47,2,22129},{0,25,13298},{0,43,6189},{0,44,16354},{17,2,22129},{0,44,16354},{0,21,0},{0,21,0},{0,21,0},{0,44,1},{0,44,2521},{0,26,953},{0,26,953},{0,6,1553},{0,6,2770},{0,6,1778},{0,21,0},{0,21,0},{0,21,0},{0,44,1},{22,0,2521},{0,26,953},{0,26,953},{0,6,1553},{44,0,2521},{0,6,1553},{7,0,9248},{16,1,1412},{16,7,0}, +{0,41,3185},{7,0,9248},{0,7,9248},{0,41,3185},{0,15,9266},{0,7,9248},{0,15,9266},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{22,1,58878},{32,1,8497},{0,21,52},{0,37,2302},{22,1,65535},{16,1,18091},{0,37,5062},{0,9,19646},{0,5,60796},{0,41,35977},{36,1,13547},{16,1,1923},{16,21,62},{0,25,2897},{45,0,23851}, +{0,39,13856},{0,27,6323},{0,46,17289},{27,8,23851},{0,46,17289},{0,33,0},{0,33,0},{0,33,0},{0,30,0},{0,46,3200},{0,12,1186},{0,12,1186},{0,38,1962},{0,22,3521},{0,22,2261},{0,33,0},{0,33,0},{0,33,0},{0,30,0},{18,10,3200},{0,12,1186},{0,12,1186},{0,38,1962},{46,0,3200},{0,38,1962},{37,2,9248},{2,1,1717},{2,21,5},{0,25,2897},{37,2,9248},{34,7,9248},{0,25,2897}, +{0,45,9250},{34,7,9248},{0,45,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{22,1,59528},{2,1,10468},{0,5,122},{0,21,1965},{22,1,65535},{16,1,18728},{0,21,4602},{0,23,18427},{0,3,58418},{0,25,34396},{6,1,14752},{2,1,2501},{16,35,141},{0,39,2720},{45,2,25472},{0,37,14401},{0,41,6413},{0,46,18185},{25,8,25472}, +{0,46,18185},{0,1,16},{0,1,16},{0,1,16},{0,47,0},{0,31,3872},{0,28,1450},{0,28,1450},{0,38,2362},{0,38,4283},{0,38,2723},{0,1,16},{0,1,16},{0,1,16},{0,47,0},{36,6,3872},{0,28,1450},{0,28,1450},{0,38,2362},{31,0,3872},{0,38,2362},{44,1,9248},{20,1,2041},{18,5,2},{0,39,2720},{44,1,9248},{26,9,9248},{0,39,2720},{0,13,9256},{26,9,9248},{0,13,9256},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{24,1,60070},{2,1,12544},{0,19,188},{0,35,1604},{22,1,65535},{32,1,19503},{0,5,4081},{0,7,17117},{0,3,56204},{0,25,32856},{22,1,15824},{2,1,3225},{32,19,229},{0,7,2478},{46,10,26744},{0,21,14657},{0,25,6357},{0,31,18737},{23,8,26744},{0,31,18737},{16,1,115},{16,1,115},{16,1,115}, +{0,15,5},{0,29,4420},{0,46,1613},{0,46,1613},{0,8,2642},{0,8,4931},{0,8,3083},{16,1,90},{16,1,90},{16,1,90},{0,15,5},{8,2,4418},{0,46,1613},{0,46,1613},{0,8,2642},{30,2,4418},{0,8,2642},{33,0,9248},{36,1,2405},{34,19,5},{0,7,2474},{33,0,9248},{32,3,9248},{0,7,2474},{0,43,9250},{32,3,9248},{0,43,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,16,1}, +{0,16,1},{0,16,1},{0,16,1},{0,16,2},{0,16,2},{24,1,60699},{2,1,14864},{16,3,314},{0,19,1400},{24,1,65535},{2,1,20230},{0,19,3323},{0,37,15488},{0,17,54456},{0,39,31364},{24,1,16210},{4,1,3849},{2,33,221},{0,37,2328},{38,3,26744},{0,3,14114},{0,23,5618},{0,15,18273},{35,8,26744},{0,15,18273},{32,1,291},{32,1,291},{32,1,291},{16,29,50},{0,11,4418},{0,31,1325},{0,31,1325}, +{0,10,2465},{0,10,5112},{0,8,3051},{2,1,136},{2,1,136},{2,1,136},{32,29,5},{24,4,4418},{0,31,1325},{0,31,1325},{0,10,2465},{11,0,4418},{0,10,2465},{47,1,9248},{8,1,2738},{20,3,1},{0,37,2228},{47,1,9248},{31,9,9248},{0,37,2228},{0,11,9256},{31,9,9248},{0,11,9256},{16,0,50},{16,0,50},{16,0,50},{16,0,50},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,32,18}, +{0,32,18},{24,1,61549},{2,1,17597},{16,17,476},{0,33,1268},{24,1,65535},{2,1,21346},{0,33,2615},{0,5,13900},{0,17,52724},{0,37,29656},{40,1,16729},{36,1,4545},{34,1,221},{32,21,2384},{8,1,26744},{0,3,13529},{0,37,4710},{0,29,17819},{1,8,26744},{0,29,17819},{2,1,626},{2,1,626},{2,1,626},{32,43,185},{0,23,4418},{0,45,1037},{0,45,1037},{0,10,2249},{0,26,5330},{0,10,2925},{34,1,185}, +{34,1,185},{34,1,185},{18,13,4},{38,10,4418},{0,45,1037},{0,45,1037},{0,10,2249},{23,0,4418},{0,10,2249},{29,3,9248},{40,1,3188},{6,17,2},{0,35,2041},{29,3,9248},{43,9,9248},{0,35,2041},{0,41,9256},{43,9,9248},{0,41,9256},{32,0,185},{32,0,185},{32,0,185},{32,0,185},{0,38,0},{0,38,0},{0,38,0},{0,34,1},{0,18,61},{0,18,61},{40,1,62083},{4,1,19345},{16,1,697}, +{0,17,1188},{24,1,65535},{2,1,22086},{0,17,2057},{0,35,12551},{0,1,51532},{0,37,28158},{26,1,16691},{36,1,5081},{20,1,265},{32,35,2281},{29,12,26259},{0,17,12803},{0,5,3981},{0,43,16952},{26,13,26259},{0,43,16952},{18,1,1006},{18,1,1006},{18,1,1006},{2,11,378},{0,5,4420},{0,43,820},{0,43,820},{0,12,2020},{0,12,5541},{0,42,2966},{20,1,265},{20,1,265},{20,1,265},{34,27,1},{28,2,4418}, +{0,43,820},{0,43,820},{0,12,2020},{42,8,4418},{0,12,2020},{43,3,8978},{42,1,3434},{22,1,1},{0,19,1737},{43,3,8978},{45,7,8978},{0,19,1737},{0,9,8986},{45,7,8978},{0,9,8986},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,10,1},{0,10,1},{0,10,1},{0,20,4},{0,4,136},{0,4,136},{40,1,62361},{4,1,19653},{16,1,1095},{0,17,1126},{24,1,65535},{2,1,21601},{0,17,1502}, +{0,19,11253},{0,1,50904},{0,37,27226},{42,1,15419},{38,1,4708},{36,1,320},{18,19,1862},{23,2,24371},{0,1,11221},{0,35,2905},{0,27,15080},{20,9,24371},{0,27,15080},{34,1,1522},{34,1,1522},{34,1,1522},{2,25,618},{0,17,4418},{0,41,610},{0,41,610},{0,44,1810},{0,44,5843},{0,12,2885},{36,1,320},{36,1,320},{36,1,320},{20,11,9},{16,3,4418},{0,41,610},{0,41,610},{0,44,1810},{17,0,4418}, +{0,44,1810},{27,3,7938},{44,1,3033},{8,1,4},{0,19,1225},{27,3,7938},{39,9,7938},{0,19,1225},{0,9,7946},{39,9,7938},{0,9,7946},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,44,0},{0,44,0},{0,44,0},{0,22,1},{0,36,232},{0,36,232},{40,1,62690},{4,1,20049},{32,1,1585},{16,17,1131},{40,1,65535},{2,1,21187},{0,17,1035},{0,19,10004},{0,1,50320},{0,37,26351},{28,1,14260}, +{24,1,4365},{22,1,410},{4,19,1523},{47,11,22568},{0,1,9893},{0,19,1997},{0,27,13320},{22,9,22568},{0,27,13320},{4,1,2169},{4,1,2169},{4,1,2169},{18,9,929},{16,1,4461},{0,9,442},{0,9,442},{0,14,1665},{0,46,6116},{0,44,2907},{22,1,410},{22,1,410},{22,1,410},{36,25,1},{30,4,4418},{0,9,442},{0,9,442},{0,14,1665},{15,8,4418},{0,14,1665},{11,3,6962},{14,1,2645},{10,1,1}, +{0,3,832},{11,3,6962},{44,3,6962},{0,3,832},{0,39,6962},{44,3,6962},{0,39,6962},{18,0,925},{18,0,925},{18,0,925},{18,0,925},{0,47,0},{0,47,0},{0,47,0},{0,8,0},{0,22,338},{0,22,338},{40,1,63078},{4,1,20586},{32,1,2208},{16,1,1221},{40,1,65535},{2,1,20797},{0,17,616},{0,19,8676},{0,1,49684},{0,37,25424},{14,1,12942},{40,1,4061},{8,1,530},{36,19,1147},{21,2,20642}, +{16,1,8678},{0,3,1157},{0,41,11489},{24,9,20642},{0,41,11489},{20,1,3009},{20,1,3009},{20,1,3009},{34,7,1358},{32,1,4667},{0,7,305},{0,7,305},{0,46,1445},{0,31,6482},{0,14,3034},{8,1,530},{8,1,530},{8,1,530},{22,9,5},{45,0,4418},{0,7,305},{0,7,305},{0,46,1445},{27,8,4418},{0,46,1445},{11,1,5941},{30,1,2260},{42,1,0},{0,33,445},{11,1,5941},{26,1,5941},{0,33,445}, +{0,23,5941},{26,1,5941},{0,23,5941},{34,0,1354},{34,0,1354},{34,0,1354},{34,0,1354},{0,13,0},{0,13,0},{0,13,0},{0,40,1},{0,8,522},{0,8,522},{40,1,63433},{4,1,21145},{32,1,2873},{16,1,1404},{40,1,65535},{2,1,20517},{0,1,339},{0,19,7570},{0,1,49136},{0,37,24652},{30,1,11862},{26,1,3845},{40,1,617},{22,3,868},{44,1,19021},{2,1,7769},{0,33,621},{0,25,9957},{26,9,19021}, +{0,25,9957},{36,1,3819},{36,1,3819},{36,1,3819},{4,37,1809},{2,1,5012},{0,5,185},{0,5,185},{0,31,1285},{0,15,6822},{0,46,3029},{40,1,617},{40,1,617},{40,1,617},{38,23,2},{29,2,4418},{0,5,185},{0,5,185},{0,31,1285},{35,6,4418},{0,31,1285},{41,1,5101},{47,1,1924},{28,1,1},{0,17,221},{41,1,5101},{28,1,5101},{0,17,221},{0,7,5113},{28,1,5101},{0,7,5113},{4,0,1808}, +{4,0,1808},{4,0,1808},{4,0,1808},{0,25,0},{0,25,0},{0,25,0},{0,26,4},{0,24,698},{0,24,698},{26,1,63733},{4,1,21777},{32,1,3641},{16,1,1687},{40,1,65535},{2,1,20303},{0,1,133},{0,3,6539},{0,1,48607},{0,37,23935},{30,1,10886},{42,1,3641},{26,1,724},{8,33,659},{46,3,17485},{2,1,6985},{0,17,257},{0,25,8565},{16,3,17485},{0,25,8565},{6,1,4820},{6,1,4820},{6,1,4820}, +{4,5,2324},{18,1,5437},{0,3,101},{0,3,101},{0,15,1129},{0,45,7234},{0,31,3141},{26,1,724},{26,1,724},{26,1,724},{24,7,4},{43,2,4418},{0,3,101},{0,3,101},{0,15,1129},{21,8,4418},{0,15,1129},{25,1,4325},{15,1,1658},{14,1,4},{0,17,61},{25,1,4325},{14,1,4325},{0,17,61},{0,7,4329},{14,1,4325},{0,7,4329},{4,0,2320},{4,0,2320},{4,0,2320},{4,0,2320},{0,7,0}, +{0,7,0},{0,7,0},{0,28,1},{0,10,872},{0,10,872},{26,1,63992},{4,1,22482},{2,1,4507},{32,1,2059},{40,1,65535},{2,1,20157},{0,1,26},{0,3,5537},{0,1,48100},{0,21,23272},{47,1,9918},{28,1,3518},{42,1,832},{24,33,446},{46,1,16034},{4,1,6314},{0,1,65},{0,39,7293},{26,7,16034},{0,39,7293},{22,1,5900},{22,1,5900},{22,1,5900},{20,19,2888},{34,1,6029},{0,17,40},{0,17,40}, +{0,29,1000},{0,43,7619},{0,15,3261},{42,1,832},{42,1,832},{42,1,832},{40,21,1},{38,1,4418},{0,17,40},{0,17,40},{0,29,1000},{43,28,4418},{0,29,1000},{9,1,3613},{29,1,1345},{47,1,4},{0,1,1},{9,1,3613},{46,1,3613},{0,1,1},{0,37,3613},{46,1,3613},{0,37,3613},{20,0,2888},{20,0,2888},{20,0,2888},{20,0,2888},{0,19,1},{0,19,1},{0,19,1},{0,14,0},{0,12,1082}, +{0,12,1082},{26,1,64289},{20,1,23310},{2,1,5546},{32,1,2553},{40,1,65535},{2,1,20076},{0,1,26},{0,3,4514},{0,1,47560},{0,5,22518},{31,1,9017},{14,1,3261},{28,1,1000},{10,33,281},{17,2,14504},{36,1,5594},{16,1,40},{0,23,5900},{16,1,14504},{0,23,5900},{38,1,7293},{38,1,7293},{38,1,7293},{36,33,3614},{4,1,6900},{0,1,65},{0,1,65},{0,43,832},{0,41,8070},{0,29,3518},{28,1,1000}, +{28,1,1000},{28,1,1000},{26,5,2},{39,0,4418},{16,1,40},{16,1,40},{0,43,832},{9,28,4418},{0,43,832},{23,17,2888},{13,1,1082},{15,1,0},{18,1,1},{23,17,2888},{45,17,2888},{18,1,1},{0,21,2888},{45,17,2888},{0,21,2888},{36,0,3613},{36,0,3613},{36,0,3613},{36,0,3613},{0,1,1},{0,1,1},{0,1,1},{0,46,4},{0,28,1345},{0,28,1345},{26,1,64605},{36,1,24062},{2,1,6574}, +{32,1,3098},{26,1,65535},{2,1,20094},{0,1,133},{0,33,3661},{0,1,47145},{0,5,21893},{45,1,8116},{30,1,3141},{14,1,1129},{42,17,147},{43,7,13235},{38,1,5012},{2,1,101},{0,7,4820},{18,1,13235},{0,7,4820},{24,1,8565},{24,1,8565},{24,1,8565},{6,1,4329},{36,1,7725},{16,1,257},{16,1,257},{0,27,724},{0,25,8530},{0,43,3641},{14,1,1129},{14,1,1129},{14,1,1129},{42,19,2},{23,2,4418}, +{2,1,101},{2,1,101},{0,27,724},{20,9,4418},{0,27,724},{37,3,2312},{11,1,872},{29,1,1},{6,1,0},{37,3,2312},{21,5,2312},{6,1,0},{0,5,2320},{21,5,2312},{0,5,2320},{6,0,4329},{6,0,4329},{6,0,4329},{6,0,4329},{16,1,61},{16,1,61},{16,1,61},{0,15,4},{0,14,1658},{0,14,1658},{26,1,64960},{36,1,24888},{18,1,7643},{32,1,3742},{26,1,65535},{4,1,20161},{0,1,342}, +{0,33,2900},{0,1,46786},{0,5,21347},{29,1,7443},{47,1,3029},{30,1,1285},{12,17,66},{17,6,12051},{24,1,4500},{4,1,185},{0,37,3819},{20,1,12051},{0,37,3819},{24,1,9957},{24,1,9957},{24,1,9957},{22,1,5161},{36,1,8717},{32,1,621},{32,1,621},{0,41,617},{0,39,9026},{0,27,3845},{30,1,1285},{30,1,1285},{30,1,1285},{28,3,4},{37,2,4418},{4,1,185},{4,1,185},{0,41,617},{34,7,4418}, +{0,41,617},{21,3,1800},{25,1,698},{27,1,4},{24,1,0},{21,3,1800},{43,1,1800},{24,1,0},{0,5,1808},{43,1,1800},{0,5,1808},{6,0,5113},{6,0,5113},{6,0,5113},{6,0,5113},{16,1,221},{16,1,221},{16,1,221},{0,29,1},{0,46,1924},{0,46,1924},{26,1,65314},{36,1,25774},{18,1,8796},{32,1,4480},{26,1,65535},{4,1,20229},{16,1,625},{0,33,2238},{0,1,46456},{0,5,20870},{13,1,6795}, +{15,1,3034},{47,1,1445},{44,1,17},{39,11,10952},{40,1,4076},{6,1,305},{0,21,3009},{22,1,10952},{0,21,3009},{40,1,11489},{40,1,11489},{40,1,11489},{38,1,6125},{6,1,9922},{2,1,1157},{2,1,1157},{0,9,530},{0,37,9571},{0,41,4061},{47,1,1445},{47,1,1445},{47,1,1445},{44,17,2},{44,1,4418},{6,1,305},{6,1,305},{0,9,530},{26,9,4418},{0,9,530},{5,3,1352},{9,1,522},{41,1,1}, +{12,1,0},{5,3,1352},{11,1,1352},{12,1,0},{0,35,1354},{11,1,1352},{0,35,1354},{22,0,5941},{22,0,5941},{22,0,5941},{22,0,5941},{32,1,445},{32,1,445},{32,1,445},{0,43,0},{0,31,2260},{0,31,2260},{26,1,65535},{36,1,26766},{18,1,10162},{2,1,5359},{26,1,65359},{4,1,20334},{16,1,1051},{0,33,1610},{0,1,45998},{0,5,20364},{11,1,6173},{45,1,2907},{15,1,1665},{30,1,2},{17,10,9818}, +{42,1,3693},{8,1,442},{0,5,2169},{24,1,9818},{0,5,2169},{26,1,13320},{26,1,13320},{26,1,13320},{8,1,7395},{22,1,11384},{18,1,1997},{18,1,1997},{0,23,410},{0,21,10181},{0,25,4365},{15,1,1665},{15,1,1665},{15,1,1665},{30,1,2},{31,5,4418},{8,1,442},{8,1,442},{0,23,410},{14,9,4418},{0,23,410},{5,1,925},{23,1,338},{9,1,0},{46,1,0},{5,1,925},{9,1,925},{46,1,0}, +{0,19,925},{9,1,925},{0,19,925},{38,0,6962},{38,0,6962},{38,0,6962},{38,0,6962},{2,1,832},{2,1,832},{2,1,832},{0,11,1},{0,15,2645},{0,15,2645},{26,1,65535},{36,1,27616},{18,1,11415},{2,1,6203},{26,1,65014},{4,1,20439},{16,1,1524},{0,17,1111},{0,1,45494},{0,5,19935},{11,1,5581},{13,1,2885},{45,1,1810},{47,1,50},{39,7,8901},{44,1,3373},{40,1,610},{0,35,1522},{26,1,8901}, +{0,35,1522},{26,1,15080},{26,1,15080},{26,1,15080},{24,1,8661},{24,1,12846},{34,1,2905},{34,1,2905},{0,37,320},{0,3,10790},{0,39,4708},{45,1,1810},{45,1,1810},{45,1,1810},{47,1,50},{17,2,4418},{40,1,610},{40,1,610},{0,37,320},{16,1,4418},{0,37,320},{35,1,613},{37,1,232},{23,1,1},{45,1,0},{35,1,613},{23,1,613},{45,1,0},{0,3,617},{23,1,613},{0,3,617},{8,0,7946}, +{8,0,7946},{8,0,7946},{8,0,7946},{18,1,1225},{18,1,1225},{18,1,1225},{0,9,4},{0,45,3033},{0,45,3033},{26,1,65535},{36,1,28505},{34,1,12706},{2,1,7117},{26,1,64677},{4,1,20609},{16,1,2082},{0,17,705},{0,1,45031},{0,5,19583},{41,1,5202},{43,1,2966},{13,1,2020},{31,1,148},{9,3,8069},{30,1,3125},{42,1,820},{0,19,1006},{31,3,8069},{0,19,1006},{42,1,16952},{42,1,16952},{42,1,16952}, +{24,1,10085},{24,1,14318},{4,1,3981},{4,1,3981},{0,21,265},{0,3,11302},{0,37,5081},{13,1,2020},{13,1,2020},{13,1,2020},{31,1,148},{29,3,4418},{42,1,820},{42,1,820},{0,21,265},{43,9,4418},{0,21,265},{19,1,365},{5,1,136},{21,1,4},{11,1,1},{19,1,365},{37,1,365},{11,1,1},{0,3,377},{37,1,365},{0,3,377},{8,0,8986},{8,0,8986},{8,0,8986},{8,0,8986},{18,1,1737}, +{18,1,1737},{18,1,1737},{0,23,1},{0,43,3434},{0,43,3434},{42,1,65535},{36,1,29412},{4,1,13785},{18,1,7875},{26,1,64490},{20,1,20801},{32,1,2593},{16,17,472},{0,1,43813},{0,3,17452},{9,1,4729},{11,1,2925},{11,1,2249},{45,1,281},{37,7,7322},{47,1,2941},{44,1,1037},{0,3,626},{30,1,7322},{0,3,626},{28,1,17819},{28,1,17819},{28,1,17819},{40,1,10777},{40,1,15150},{36,1,4710},{36,1,4710}, +{0,35,221},{0,17,11076},{0,37,4545},{11,1,2249},{11,1,2249},{11,1,2249},{45,1,281},{39,11,4418},{44,1,1037},{44,1,1037},{0,35,185},{22,1,4418},{0,35,185},{3,1,181},{19,1,61},{35,1,1},{39,1,0},{3,1,181},{5,1,181},{39,1,0},{0,33,185},{5,1,181},{0,33,185},{40,0,9256},{40,0,9256},{40,0,9256},{40,0,9256},{34,1,2041},{34,1,2041},{34,1,2041},{16,7,2},{0,41,3188}, +{0,41,3188},{42,1,65535},{38,1,30127},{36,1,14877},{4,1,8601},{42,1,64081},{36,1,20736},{18,1,3192},{2,17,302},{0,1,42247},{0,3,14278},{39,1,4387},{9,1,3051},{11,1,2465},{13,1,490},{23,17,6584},{29,1,2843},{30,1,1325},{0,33,291},{45,17,6584},{0,33,291},{14,1,18273},{14,1,18273},{14,1,18273},{42,1,11259},{26,1,15731},{22,1,5618},{22,1,5618},{32,3,221},{0,1,10637},{0,5,3849},{11,1,2465}, +{11,1,2465},{11,1,2465},{13,1,490},{25,5,4418},{30,1,1325},{30,1,1325},{0,3,136},{10,1,4418},{0,3,136},{1,3,50},{33,1,18},{3,1,0},{5,1,0},{1,3,50},{3,1,50},{5,1,0},{0,17,50},{3,1,50},{0,17,50},{10,0,9256},{10,0,9256},{10,0,9256},{10,0,9256},{36,1,2228},{36,1,2228},{36,1,2228},{2,21,1},{0,9,2738},{0,9,2738},{28,1,65535},{24,1,30766},{6,1,16028}, +{36,1,9391},{28,1,64158},{36,1,21269},{4,1,3821},{18,1,176},{0,1,41339},{0,3,11746},{23,1,4216},{9,1,3083},{9,1,2642},{27,1,776},{3,25,6019},{13,1,2763},{47,1,1613},{0,17,115},{29,1,6019},{0,17,115},{30,1,18737},{30,1,18737},{30,1,18737},{12,1,11820},{42,1,16379},{24,1,6357},{24,1,6357},{18,33,229},{0,1,10589},{0,3,3225},{9,1,2642},{9,1,2642},{9,1,2642},{27,1,776},{9,3,4418}, +{47,1,1613},{47,1,1613},{0,17,90},{31,3,4418},{0,17,90},{1,17,2},{17,1,2},{17,1,1},{17,1,1},{1,17,2},{17,1,2},{17,1,1},{0,1,4},{17,1,2},{0,1,4},{42,0,9250},{42,0,9250},{42,0,9250},{42,0,9250},{6,1,2474},{6,1,2474},{6,1,2474},{18,35,5},{0,37,2405},{0,37,2405},{14,1,65535},{24,1,31241},{22,1,16737},{6,1,10024},{14,1,64173},{38,1,21415},{20,1,4180}, +{4,1,111},{16,1,40689},{0,3,9508},{7,1,3648},{39,1,2723},{39,1,2362},{11,1,725},{37,1,5163},{13,1,2451},{29,1,1450},{0,1,16},{7,19,5163},{0,1,16},{47,1,18185},{47,1,18185},{47,1,18185},{44,1,11714},{28,1,15784},{40,1,6413},{40,1,6413},{34,17,141},{0,1,9881},{0,3,2501},{39,1,2362},{39,1,2362},{39,1,2362},{11,1,725},{37,7,3872},{29,1,1450},{29,1,1450},{0,1,16},{30,1,3872}, +{0,1,16},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{12,0,9256},{12,0,9256},{12,0,9256},{12,0,9256},{38,1,2720},{38,1,2720},{38,1,2720},{4,19,2},{0,21,2041},{0,21,2041},{30,1,65535},{40,1,31563},{8,1,17236},{38,1,10554},{14,1,63701},{24,1,21372},{36,1,4441},{20,1,45},{16,1,40151},{0,33,7454},{21,1,3014}, +{23,1,2261},{39,1,1962},{25,1,629},{21,17,4267},{11,1,2028},{13,1,1186},{32,1,0},{17,21,4267},{32,1,0},{47,1,17289},{47,1,17289},{47,1,17289},{14,1,11436},{14,1,14726},{26,1,6323},{26,1,6323},{20,17,62},{16,1,9032},{0,17,1923},{39,1,1962},{39,1,1962},{39,1,1962},{25,1,629},{19,11,3200},{13,1,1186},{13,1,1186},{32,1,0},{47,1,3200},{32,1,0},{1,1,0},{1,1,0},{1,1,0}, +{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{44,0,9250},{44,0,9250},{44,0,9250},{44,0,9250},{24,1,2897},{24,1,2897},{24,1,2897},{20,3,5},{0,3,1717},{0,3,1717},{30,1,65535},{26,1,31988},{24,1,17745},{8,1,11181},{30,1,63430},{40,1,21435},{22,1,4810},{6,1,5},{2,1,39477},{0,33,5328},{21,1,2339},{7,1,1778},{7,1,1553},{9,1,477},{19,5,3361}, +{25,1,1634},{27,1,953},{20,1,0},{37,3,3361},{20,1,0},{45,1,16354},{45,1,16354},{45,1,16354},{30,1,11202},{30,1,13722},{42,1,6189},{42,1,6189},{6,1,9},{2,1,8249},{0,17,1437},{7,1,1553},{7,1,1553},{7,1,1553},{9,1,477},{23,1,2521},{27,1,953},{27,1,953},{20,1,0},{45,1,2521},{20,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0}, +{0,1,0},{1,1,0},{0,1,0},{14,0,9266},{14,0,9266},{14,0,9266},{14,0,9266},{40,1,3185},{40,1,3185},{40,1,3185},{6,17,0},{0,17,1412},{0,17,1412},{47,1,65535},{42,1,32389},{10,1,18354},{40,1,11850},{30,1,63370},{40,1,21737},{8,1,5159},{22,1,24},{2,1,39380},{0,17,3675},{5,1,1843},{21,1,1394},{37,1,1241},{23,1,370},{5,1,2646},{9,1,1282},{11,1,757},{8,1,1},{9,1,2646}, +{8,1,1},{45,1,15490},{45,1,15490},{45,1,15490},{47,1,10946},{47,1,12914},{42,1,6221},{42,1,6221},{38,1,10},{2,1,7753},{0,1,1225},{37,1,1241},{37,1,1241},{37,1,1241},{23,1,370},{7,1,1985},{11,1,757},{11,1,757},{8,1,1},{13,1,1985},{8,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{46,0,9248}, +{46,0,9248},{46,0,9248},{46,0,9248},{26,1,3400},{26,1,3400},{26,1,3400},{38,1,10},{0,1,1225},{0,1,1225},{47,1,65535},{28,1,33179},{26,1,18917},{10,1,12588},{47,1,62997},{26,1,21996},{24,1,5521},{8,1,36},{4,1,39403},{0,17,2452},{5,1,1411},{21,1,1058},{21,1,914},{7,1,274},{35,1,2017},{23,1,939},{9,1,585},{26,1,0},{1,35,2017},{26,1,0},{29,1,14809},{29,1,14809},{29,1,14809}, +{31,1,10801},{47,1,12162},{14,1,6117},{14,1,6117},{8,1,50},{20,1,7322},{0,1,1241},{21,1,914},{21,1,914},{21,1,914},{7,1,274},{35,5,1513},{9,1,585},{9,1,585},{26,1,0},{27,1,1513},{26,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{47,0,9250},{47,0,9250},{47,0,9250},{47,0,9250},{12,1,3690}, +{12,1,3690},{12,1,3690},{8,1,50},{0,1,1241},{0,1,1241},{45,1,65535},{14,1,33274},{42,1,19608},{42,1,13375},{47,1,62627},{42,1,22211},{10,1,6045},{24,1,138},{36,1,39015},{0,1,1732},{35,1,1048},{5,1,766},{5,1,666},{37,1,212},{3,3,1473},{7,1,675},{23,1,410},{14,1,1},{3,3,1473},{14,1,1},{13,1,14121},{13,1,14121},{13,1,14121},{45,1,10571},{45,1,11434},{30,1,6081},{30,1,6081}, +{40,1,137},{36,1,6926},{2,1,1445},{5,1,666},{5,1,666},{5,1,666},{37,1,212},{35,3,1105},{23,1,410},{23,1,410},{14,1,1},{25,1,1105},{14,1,1},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{1,1,0},{0,1,0},{1,1,0},{0,1,0},{15,0,9256},{15,0,9256},{15,0,9256},{15,0,9256},{14,1,3985},{14,1,3985},{14,1,3985},{40,1,137},{2,1,1445}, +{2,1,1445}, diff --git a/ext/basis_universal/basisu_transcoder_tables_astc_0_255.inc b/ext/basis_universal/basisu_transcoder_tables_astc_0_255.inc new file mode 100644 index 0000000000..da4e7fee98 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_astc_0_255.inc @@ -0,0 +1,481 @@ +{0,16,18},{0,12,1},{0,8,0},{0,7,5},{0,10,35},{0,6,21},{0,6,9},{0,4,24},{1,4,36},{0,4,25},{0,16,18},{0,12,1},{0,8,0},{0,7,5},{5,0,35},{0,6,21},{0,6,9},{0,4,24},{10,0,35},{0,4,24},{0,7,0},{0,7,0},{0,7,0},{0,3,0},{0,4,2},{0,3,0},{0,3,0},{0,1,1},{0,2,2},{0,1,1},{0,7,0}, +{0,7,0},{0,7,0},{0,3,0},{2,0,2},{0,3,0},{0,3,0},{0,1,1},{4,0,2},{0,1,1},{8,0,18},{0,12,1},{0,8,0},{0,7,5},{8,0,18},{16,0,18},{0,7,5},{0,5,18},{16,0,18},{0,5,18},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,34,36},{3,23,19},{4,17,25}, +{3,16,19},{0,34,51},{0,20,18},{0,16,1},{0,13,22},{0,15,68},{0,12,33},{6,28,18},{6,21,0},{6,16,1},{5,15,3},{17,0,51},{1,19,18},{2,15,1},{0,13,22},{34,0,51},{0,13,22},{3,25,18},{3,25,18},{3,25,18},{3,14,18},{0,25,8},{0,16,1},{0,16,1},{0,10,0},{0,12,17},{0,9,5},{6,19,0},{6,19,0},{6,19,0},{6,12,0},{12,0,8}, +{4,13,0},{4,13,0},{0,10,0},{25,0,8},{0,10,0},{20,0,18},{6,21,0},{8,16,0},{0,16,0},{20,0,18},{40,0,18},{0,16,0},{0,13,18},{40,0,18},{0,13,18},{3,0,18},{3,0,18},{3,0,18},{3,0,18},{0,19,0},{0,19,0},{0,19,0},{0,9,0},{0,9,4},{0,9,4},{11,42,36},{11,31,19},{12,24,24},{11,24,19},{8,42,51},{8,28,18},{8,24,1}, +{7,20,22},{0,27,52},{2,21,18},{14,36,18},{14,29,0},{14,24,1},{13,23,3},{29,0,51},{9,27,18},{10,23,1},{0,21,18},{58,0,51},{0,21,18},{11,33,18},{11,33,18},{11,33,18},{11,22,18},{8,33,8},{8,24,1},{8,24,1},{8,18,0},{2,23,8},{4,18,1},{14,26,0},{14,26,0},{14,26,0},{14,20,0},{24,0,8},{11,22,0},{11,22,0},{6,18,0},{49,0,8}, +{6,18,0},{32,0,18},{14,29,0},{15,24,0},{6,24,0},{32,0,18},{64,0,18},{6,24,0},{0,21,18},{64,0,18},{0,21,18},{11,0,18},{11,0,18},{11,0,18},{11,0,18},{8,27,0},{8,27,0},{8,27,0},{8,17,0},{4,19,0},{4,19,0},{19,50,36},{19,39,19},{20,32,24},{19,32,19},{16,50,51},{16,36,18},{16,32,1},{15,28,22},{7,37,51},{10,29,18},{22,43,18}, +{22,36,1},{22,32,1},{21,31,3},{41,0,51},{17,35,18},{18,31,1},{8,29,18},{82,0,51},{8,29,18},{19,41,18},{19,41,18},{19,41,18},{19,30,18},{16,41,8},{16,31,1},{16,31,1},{16,26,0},{10,31,8},{12,26,1},{22,34,0},{22,34,0},{22,34,0},{22,28,0},{36,0,8},{18,30,0},{18,30,0},{14,26,0},{73,0,8},{14,26,0},{43,0,18},{20,38,0},{23,32,0}, +{14,32,0},{43,0,18},{89,0,18},{14,32,0},{0,29,18},{89,0,18},{0,29,18},{19,0,18},{19,0,18},{19,0,18},{19,0,18},{16,35,0},{16,35,0},{16,35,0},{16,25,0},{12,27,0},{12,27,0},{28,59,36},{28,48,19},{29,41,24},{28,41,19},{25,59,51},{25,45,18},{25,41,1},{24,37,22},{16,46,51},{19,38,18},{31,52,18},{31,45,1},{31,41,1},{30,40,3},{54,0,51}, +{24,45,18},{27,40,1},{17,38,18},{110,0,51},{17,38,18},{28,49,18},{28,49,18},{28,49,18},{28,39,18},{25,49,8},{25,40,1},{25,40,1},{25,35,0},{19,40,8},{20,35,1},{31,43,0},{31,43,0},{31,43,0},{31,37,0},{49,0,8},{27,39,0},{27,39,0},{23,35,0},{101,0,8},{23,35,0},{57,0,18},{29,47,0},{32,41,0},{23,41,0},{57,0,18},{116,0,18},{23,41,0}, +{0,38,18},{116,0,18},{0,38,18},{28,0,18},{28,0,18},{28,0,18},{28,0,18},{25,43,0},{25,43,0},{25,43,0},{25,34,0},{19,37,0},{19,37,0},{36,66,36},{36,56,19},{37,49,24},{36,49,19},{33,66,51},{33,53,18},{33,49,1},{32,45,22},{23,54,51},{27,46,18},{39,60,18},{39,53,1},{39,49,1},{38,48,3},{66,0,51},{32,53,18},{35,48,1},{25,46,18},{134,0,51}, +{25,46,18},{36,57,18},{36,57,18},{36,57,18},{36,47,18},{33,57,8},{33,48,1},{33,48,1},{33,43,0},{25,49,8},{28,43,1},{39,51,0},{39,51,0},{39,51,0},{39,45,0},{61,0,8},{35,47,0},{35,47,0},{31,43,0},{125,0,8},{31,43,0},{69,0,18},{37,55,0},{40,49,0},{31,49,0},{69,0,18},{140,0,18},{31,49,0},{0,46,18},{140,0,18},{0,46,18},{36,0,18}, +{36,0,18},{36,0,18},{36,0,18},{33,51,0},{33,51,0},{33,51,0},{33,42,0},{27,45,0},{27,45,0},{44,74,36},{44,64,19},{45,57,24},{44,57,19},{41,74,51},{41,61,18},{41,57,1},{40,53,22},{31,62,51},{35,54,18},{47,68,18},{47,61,1},{47,57,1},{46,56,3},{78,0,51},{40,61,18},{43,56,1},{33,54,18},{158,0,51},{33,54,18},{44,65,18},{44,65,18},{44,65,18}, +{44,55,18},{41,65,8},{41,56,1},{41,56,1},{41,51,0},{33,57,8},{36,51,1},{47,59,0},{47,59,0},{47,59,0},{47,53,0},{73,0,8},{43,55,0},{43,55,0},{39,51,0},{149,0,8},{39,51,0},{81,0,18},{45,63,0},{48,57,0},{39,57,0},{81,0,18},{164,0,18},{39,57,0},{0,54,18},{164,0,18},{0,54,18},{44,0,18},{44,0,18},{44,0,18},{44,0,18},{41,59,0}, +{41,59,0},{41,59,0},{41,50,0},{35,53,0},{35,53,0},{52,82,36},{52,71,19},{53,65,24},{52,65,19},{49,82,51},{49,68,18},{49,65,1},{48,61,22},{39,70,51},{43,62,18},{55,76,18},{55,69,1},{55,65,1},{54,64,3},{89,0,51},{49,68,18},{51,64,1},{41,62,18},{183,0,51},{41,62,18},{52,73,18},{52,73,18},{52,73,18},{52,63,18},{49,73,8},{49,64,1},{49,64,1}, +{49,59,0},{42,64,8},{44,59,1},{55,67,0},{55,67,0},{55,67,0},{55,61,0},{85,0,8},{51,63,0},{51,63,0},{47,59,0},{174,0,8},{47,59,0},{92,0,18},{54,70,0},{56,65,0},{47,65,0},{92,0,18},{189,0,18},{47,65,0},{0,62,18},{189,0,18},{0,62,18},{52,0,18},{52,0,18},{52,0,18},{52,0,18},{49,67,0},{49,67,0},{49,67,0},{49,58,0},{43,61,0}, +{43,61,0},{61,91,36},{61,80,19},{62,74,24},{61,73,20},{58,91,51},{58,77,18},{58,73,2},{57,70,22},{48,79,51},{50,71,19},{64,85,18},{64,77,1},{64,74,1},{63,73,3},{103,0,51},{58,77,18},{59,74,1},{49,71,18},{210,0,51},{49,71,18},{61,82,18},{61,82,18},{61,82,18},{61,72,18},{58,82,8},{58,73,1},{58,73,1},{58,68,0},{51,73,8},{53,68,1},{64,76,0}, +{64,76,0},{64,76,0},{64,70,0},{98,0,8},{60,72,0},{60,72,0},{56,68,0},{201,0,8},{56,68,0},{106,0,18},{63,79,0},{65,74,0},{55,74,0},{106,0,18},{216,0,18},{55,74,0},{0,71,18},{216,0,18},{0,71,18},{61,0,18},{61,0,18},{61,0,18},{61,0,18},{58,76,0},{58,76,0},{58,76,0},{58,67,0},{53,69,0},{53,69,0},{69,99,36},{69,88,19},{70,82,24}, +{69,81,20},{66,99,51},{66,85,18},{66,81,2},{65,79,23},{56,87,51},{58,79,19},{72,93,18},{72,85,1},{72,82,1},{72,80,5},{115,0,51},{66,85,18},{67,82,1},{57,79,18},{234,0,51},{57,79,18},{69,90,18},{69,90,18},{69,90,18},{69,79,18},{66,90,8},{66,81,1},{66,81,1},{66,75,1},{59,81,8},{61,76,1},{72,84,0},{72,84,0},{72,84,0},{72,78,0},{110,0,8}, +{69,79,0},{69,79,0},{63,76,0},{225,0,8},{63,76,0},{118,0,18},{71,87,0},{73,82,0},{63,82,0},{118,0,18},{240,0,18},{63,82,0},{0,79,18},{240,0,18},{0,79,18},{69,0,18},{69,0,18},{69,0,18},{69,0,18},{66,84,0},{66,84,0},{66,84,0},{66,75,0},{61,77,0},{61,77,0},{77,107,36},{77,96,19},{78,90,24},{77,89,20},{74,107,51},{74,93,18},{74,89,2}, +{73,87,23},{64,95,51},{66,87,19},{80,101,18},{80,93,1},{80,90,1},{80,88,5},{127,0,51},{74,93,18},{75,90,1},{65,87,18},{254,2,51},{65,87,18},{77,98,18},{77,98,18},{77,98,18},{77,87,18},{74,98,8},{74,89,1},{74,89,1},{74,83,1},{67,89,8},{69,84,1},{80,92,0},{80,92,0},{80,92,0},{80,86,0},{122,0,8},{77,87,0},{77,87,0},{71,84,0},{249,0,8}, +{71,84,0},{129,0,18},{79,95,0},{81,90,0},{71,90,0},{129,0,18},{254,5,18},{71,90,0},{0,87,18},{254,5,18},{0,87,18},{77,0,18},{77,0,18},{77,0,18},{77,0,18},{74,92,0},{74,92,0},{74,92,0},{74,83,0},{69,85,0},{69,85,0},{85,115,36},{85,104,19},{86,98,24},{85,97,20},{82,115,51},{82,101,18},{82,97,2},{81,95,23},{72,103,51},{74,95,19},{88,109,18}, +{88,101,1},{88,98,1},{88,96,5},{138,0,51},{82,101,18},{83,98,1},{73,95,18},{254,14,51},{73,95,18},{85,106,18},{85,106,18},{85,106,18},{85,95,18},{82,106,8},{82,97,1},{82,97,1},{82,91,1},{75,97,8},{77,92,1},{88,100,0},{88,100,0},{88,100,0},{88,94,0},{134,0,8},{85,95,0},{85,95,0},{79,92,0},{255,9,8},{79,92,0},{141,0,18},{87,103,0},{89,98,0}, +{79,98,0},{141,0,18},{254,17,18},{79,98,0},{0,95,18},{254,17,18},{0,95,18},{85,0,18},{85,0,18},{85,0,18},{85,0,18},{82,100,0},{82,100,0},{82,100,0},{82,91,0},{77,93,0},{77,93,0},{94,124,36},{94,113,19},{95,107,24},{94,106,20},{91,124,51},{91,110,18},{91,106,2},{90,104,23},{81,112,51},{83,104,19},{97,118,18},{97,110,1},{97,107,1},{97,105,5},{152,0,51}, +{91,110,18},{92,107,1},{82,104,18},{255,27,51},{82,104,18},{94,115,18},{94,115,18},{94,115,18},{94,104,18},{91,115,8},{91,106,1},{91,106,1},{91,100,1},{84,106,8},{86,101,1},{97,108,0},{97,108,0},{97,108,0},{97,103,0},{147,0,8},{94,104,0},{94,104,0},{88,101,0},{254,23,8},{88,101,0},{155,0,18},{96,112,0},{98,107,0},{88,107,0},{155,0,18},{255,30,18},{88,107,0}, +{0,104,18},{255,30,18},{0,104,18},{94,0,18},{94,0,18},{94,0,18},{94,0,18},{91,109,0},{91,109,0},{91,109,0},{91,100,0},{86,102,0},{86,102,0},{102,132,36},{102,121,19},{102,116,23},{102,114,20},{99,132,51},{99,118,18},{99,114,2},{98,112,23},{89,120,51},{91,112,19},{105,125,18},{105,118,1},{105,115,1},{105,113,5},{164,0,51},{99,118,18},{100,114,1},{90,112,18},{255,39,51}, +{90,112,18},{102,123,18},{102,123,18},{102,123,18},{102,112,18},{99,123,8},{99,114,1},{99,114,1},{99,108,1},{92,114,8},{94,109,1},{105,116,0},{105,116,0},{105,116,0},{105,111,0},{159,0,8},{102,112,0},{102,112,0},{96,109,0},{254,35,8},{96,109,0},{167,0,18},{104,120,0},{106,115,0},{96,115,0},{167,0,18},{254,42,18},{96,115,0},{0,112,18},{254,42,18},{0,112,18},{102,0,18}, +{102,0,18},{102,0,18},{102,0,18},{99,117,0},{99,117,0},{99,117,0},{99,108,0},{94,110,0},{94,110,0},{110,140,36},{110,130,18},{110,124,23},{110,122,20},{107,140,51},{107,126,18},{107,122,2},{106,120,23},{97,128,51},{99,120,19},{113,133,18},{113,126,1},{113,123,1},{113,121,5},{175,0,51},{107,126,18},{108,122,1},{98,120,18},{254,51,51},{98,120,18},{110,130,18},{110,130,18},{110,130,18}, +{110,120,18},{107,131,8},{107,122,1},{107,122,1},{107,116,1},{100,122,8},{102,117,1},{113,124,0},{113,124,0},{113,124,0},{113,119,0},{171,0,8},{110,120,0},{110,120,0},{104,117,0},{255,46,8},{104,117,0},{178,0,18},{112,128,0},{114,123,0},{104,123,0},{178,0,18},{254,54,18},{104,123,0},{0,120,18},{254,54,18},{0,120,18},{110,0,18},{110,0,18},{110,0,18},{110,0,18},{107,124,0}, +{107,124,0},{107,124,0},{107,116,0},{102,118,0},{102,118,0},{118,147,36},{118,138,18},{118,132,23},{118,130,20},{115,148,51},{115,134,18},{115,130,2},{114,128,23},{105,136,51},{108,128,18},{121,141,18},{121,134,1},{121,131,1},{121,129,5},{187,0,51},{115,134,18},{116,130,1},{106,128,18},{254,63,51},{106,128,18},{118,138,18},{118,138,18},{118,138,18},{118,128,18},{115,138,8},{115,130,1},{115,130,1}, +{115,124,1},{108,130,8},{110,125,1},{121,132,0},{121,132,0},{121,132,0},{121,127,0},{183,0,8},{118,128,0},{118,128,0},{112,125,0},{255,58,8},{112,125,0},{190,0,18},{120,136,0},{122,131,0},{112,131,0},{190,0,18},{254,66,18},{112,131,0},{0,128,18},{254,66,18},{0,128,18},{118,0,18},{118,0,18},{118,0,18},{118,0,18},{115,132,0},{115,132,0},{115,132,0},{115,124,0},{110,126,0}, +{110,126,0},{127,156,36},{127,147,18},{127,141,23},{127,139,20},{124,156,51},{124,143,18},{124,139,2},{123,137,23},{114,145,51},{117,137,18},{130,150,18},{130,143,1},{130,140,1},{130,138,5},{201,0,51},{124,143,18},{125,139,1},{115,137,18},{255,76,51},{115,137,18},{127,147,18},{127,147,18},{127,147,18},{127,137,18},{124,147,8},{124,139,1},{124,139,1},{124,133,1},{117,139,8},{119,134,1},{130,141,0}, +{130,141,0},{130,141,0},{130,136,0},{196,0,8},{127,137,0},{127,137,0},{121,134,0},{254,72,8},{121,134,0},{204,0,18},{129,145,0},{131,140,0},{121,140,0},{204,0,18},{255,79,18},{121,140,0},{0,137,18},{255,79,18},{0,137,18},{127,0,18},{127,0,18},{127,0,18},{127,0,18},{124,141,0},{124,141,0},{124,141,0},{124,133,0},{119,135,0},{119,135,0},{135,164,36},{135,154,19},{135,149,23}, +{135,147,20},{132,164,51},{132,151,18},{132,147,2},{131,145,23},{121,153,51},{125,145,18},{138,158,18},{138,151,1},{138,148,1},{138,146,5},{213,0,51},{131,151,18},{133,147,1},{123,145,18},{254,88,51},{123,145,18},{135,155,18},{135,155,18},{135,155,18},{135,145,18},{132,155,8},{132,147,1},{132,147,1},{132,141,1},{125,147,8},{127,142,1},{138,149,0},{138,149,0},{138,149,0},{138,144,0},{208,0,8}, +{135,145,0},{135,145,0},{129,142,0},{254,84,8},{129,142,0},{215,0,18},{137,153,0},{139,148,0},{129,148,0},{215,0,18},{254,91,18},{129,148,0},{0,145,18},{254,91,18},{0,145,18},{135,0,18},{135,0,18},{135,0,18},{135,0,18},{132,149,0},{132,149,0},{132,149,0},{132,141,0},{127,143,0},{127,143,0},{143,172,36},{143,162,19},{143,157,23},{143,155,20},{140,172,51},{140,159,18},{140,155,2}, +{139,153,23},{129,161,51},{132,153,19},{146,166,18},{146,159,1},{146,156,1},{146,154,5},{224,0,51},{139,159,18},{141,155,1},{130,153,18},{254,100,51},{130,153,18},{143,163,18},{143,163,18},{143,163,18},{143,153,18},{140,163,8},{140,155,1},{140,155,1},{140,149,1},{132,155,8},{135,150,1},{146,157,0},{146,157,0},{146,157,0},{146,152,0},{220,0,8},{143,153,0},{143,153,0},{137,150,0},{255,95,8}, +{137,150,0},{227,0,18},{144,161,0},{147,156,0},{136,156,0},{227,0,18},{254,103,18},{136,156,0},{0,153,18},{254,103,18},{0,153,18},{143,0,18},{143,0,18},{143,0,18},{143,0,18},{140,157,0},{140,157,0},{140,157,0},{140,149,0},{135,151,0},{135,151,0},{151,180,36},{151,170,19},{151,165,23},{151,163,20},{148,180,51},{148,167,18},{148,163,2},{148,160,24},{137,169,51},{140,161,19},{154,174,18}, +{154,167,1},{154,164,1},{154,162,5},{236,0,51},{147,167,18},{149,164,1},{138,161,18},{254,112,51},{138,161,18},{151,171,18},{151,171,18},{151,171,18},{151,161,18},{148,171,8},{148,162,1},{148,162,1},{148,157,1},{140,163,8},{143,158,1},{154,165,0},{154,165,0},{154,165,0},{154,160,0},{232,0,8},{150,161,0},{150,161,0},{144,158,0},{255,107,8},{144,158,0},{239,0,18},{152,169,0},{155,164,0}, +{144,164,0},{239,0,18},{254,115,18},{144,164,0},{0,161,18},{254,115,18},{0,161,18},{151,0,18},{151,0,18},{151,0,18},{151,0,18},{148,165,0},{148,165,0},{148,165,0},{148,157,0},{142,159,0},{142,159,0},{160,189,36},{160,179,19},{160,174,23},{160,172,20},{157,189,51},{157,176,18},{157,172,2},{157,169,24},{146,178,51},{149,170,19},{163,183,18},{163,176,1},{163,173,1},{163,172,5},{250,0,51}, +{156,176,18},{158,173,1},{147,170,18},{255,125,51},{147,170,18},{160,180,18},{160,180,18},{160,180,18},{160,170,18},{157,180,8},{157,171,1},{157,171,1},{157,166,1},{149,172,8},{152,167,1},{163,174,0},{163,174,0},{163,174,0},{163,168,0},{245,0,8},{159,170,0},{159,170,0},{153,167,0},{254,121,8},{153,167,0},{253,0,18},{161,178,0},{164,173,0},{153,173,0},{253,0,18},{254,128,18},{153,173,0}, +{0,170,18},{254,128,18},{0,170,18},{160,0,18},{160,0,18},{160,0,18},{160,0,18},{157,174,0},{157,174,0},{157,174,0},{157,165,0},{151,168,0},{151,168,0},{168,197,36},{168,187,19},{168,182,23},{168,180,20},{165,197,51},{165,184,18},{165,180,2},{165,177,24},{154,186,51},{157,178,19},{171,191,18},{171,184,1},{171,181,1},{171,180,5},{255,13,51},{164,184,18},{166,181,1},{155,178,18},{254,137,51}, +{155,178,18},{168,188,18},{168,188,18},{168,188,18},{168,178,18},{165,188,8},{165,179,1},{165,179,1},{165,174,1},{157,180,8},{160,175,1},{171,182,0},{171,182,0},{171,182,0},{171,176,0},{255,4,8},{167,178,0},{167,178,0},{161,175,0},{255,132,8},{161,175,0},{255,19,18},{169,186,0},{172,181,0},{161,181,0},{255,19,18},{254,140,18},{161,181,0},{0,178,18},{254,140,18},{0,178,18},{168,0,18}, +{168,0,18},{168,0,18},{168,0,18},{165,182,0},{165,182,0},{165,182,0},{165,173,0},{159,176,0},{159,176,0},{176,205,36},{176,195,19},{176,190,23},{176,188,20},{173,205,51},{173,192,18},{173,188,2},{173,185,24},{162,194,51},{165,186,19},{179,199,18},{179,192,1},{179,189,1},{179,188,5},{255,37,51},{172,192,18},{174,189,1},{163,186,18},{254,149,51},{163,186,18},{176,196,18},{176,196,18},{176,196,18}, +{176,186,18},{173,196,8},{173,187,1},{173,187,1},{173,182,1},{165,188,8},{168,183,1},{179,190,0},{179,190,0},{179,190,0},{179,184,0},{255,28,8},{175,186,0},{175,186,0},{169,183,0},{255,144,8},{169,183,0},{255,43,18},{177,194,0},{180,189,0},{169,189,0},{255,43,18},{254,152,18},{169,189,0},{0,186,18},{254,152,18},{0,186,18},{176,0,18},{176,0,18},{176,0,18},{176,0,18},{173,190,0}, +{173,190,0},{173,190,0},{173,181,0},{167,184,0},{167,184,0},{184,213,36},{184,203,19},{184,197,22},{184,196,20},{181,213,51},{181,200,18},{181,196,2},{181,193,24},{170,202,51},{173,194,19},{187,207,18},{187,201,1},{187,197,0},{187,196,5},{255,61,51},{180,200,18},{182,197,1},{171,194,18},{254,161,51},{171,194,18},{184,204,18},{184,204,18},{184,204,18},{184,194,18},{181,204,8},{181,195,1},{181,195,1}, +{181,190,1},{173,196,8},{176,191,1},{187,197,0},{187,197,0},{187,197,0},{187,192,0},{255,52,8},{183,194,0},{183,194,0},{177,191,0},{255,156,8},{177,191,0},{255,67,18},{185,202,0},{187,197,0},{177,197,0},{255,67,18},{254,164,18},{177,197,0},{0,194,18},{254,164,18},{0,194,18},{184,0,18},{184,0,18},{184,0,18},{184,0,18},{181,198,0},{181,198,0},{181,198,0},{181,189,0},{175,192,0}, +{175,192,0},{193,222,36},{193,212,18},{193,206,22},{193,205,20},{190,222,51},{189,209,19},{190,206,1},{190,202,24},{179,211,51},{182,203,19},{196,215,18},{196,210,1},{196,206,0},{196,205,5},{255,89,51},{189,209,18},{190,206,1},{180,203,18},{254,174,51},{180,203,18},{193,212,18},{193,212,18},{193,212,18},{193,203,18},{190,213,8},{190,204,1},{190,204,1},{190,199,1},{182,205,8},{185,200,1},{196,206,0}, +{196,206,0},{196,206,0},{196,201,0},{255,79,8},{192,203,0},{192,203,0},{186,200,0},{253,170,8},{186,200,0},{255,95,18},{194,211,0},{196,206,0},{186,206,0},{255,95,18},{254,177,18},{186,206,0},{0,203,18},{254,177,18},{0,203,18},{193,0,18},{193,0,18},{193,0,18},{193,0,18},{190,206,0},{190,206,0},{190,206,0},{190,198,0},{184,201,0},{184,201,0},{201,229,36},{201,220,18},{201,214,22}, +{201,213,20},{198,230,51},{197,217,19},{198,214,1},{198,210,24},{187,219,51},{190,211,19},{204,223,18},{204,218,1},{204,214,0},{204,213,5},{255,113,51},{197,217,18},{198,214,1},{188,211,18},{254,186,51},{188,211,18},{201,220,18},{201,220,18},{201,220,18},{201,211,18},{198,220,8},{198,212,1},{198,212,1},{198,207,1},{190,213,8},{192,208,1},{204,214,0},{204,214,0},{204,214,0},{204,209,0},{255,104,8}, +{200,211,0},{200,211,0},{194,208,0},{255,181,8},{194,208,0},{255,119,18},{202,219,0},{204,214,0},{194,214,0},{255,119,18},{254,189,18},{194,214,0},{0,211,18},{254,189,18},{0,211,18},{201,0,18},{201,0,18},{201,0,18},{201,0,18},{198,214,0},{198,214,0},{198,214,0},{198,206,0},{192,209,0},{192,209,0},{209,237,36},{209,228,18},{209,222,22},{209,221,20},{206,237,51},{205,225,19},{206,222,1}, +{206,218,24},{196,226,51},{197,219,19},{212,231,18},{212,226,1},{212,222,0},{212,221,5},{255,137,51},{205,225,18},{206,222,1},{196,219,18},{254,198,51},{196,219,18},{209,228,18},{209,228,18},{209,228,18},{209,219,18},{206,228,8},{206,220,1},{206,220,1},{206,215,1},{198,221,8},{200,216,1},{212,222,0},{212,222,0},{212,222,0},{212,217,0},{255,128,8},{208,219,0},{208,219,0},{202,216,0},{255,193,8}, +{202,216,0},{255,143,18},{210,227,0},{212,222,0},{202,222,0},{255,143,18},{254,201,18},{202,222,0},{0,219,18},{254,201,18},{0,219,18},{209,0,18},{209,0,18},{209,0,18},{209,0,18},{206,222,0},{206,222,0},{206,222,0},{206,214,0},{200,217,0},{200,217,0},{217,245,36},{217,236,18},{217,230,22},{217,229,20},{214,245,51},{213,233,19},{214,230,1},{214,226,24},{204,234,51},{205,227,19},{220,239,18}, +{220,234,1},{220,230,0},{220,229,5},{255,161,51},{213,233,18},{214,230,1},{204,227,18},{254,210,51},{204,227,18},{217,236,18},{217,236,18},{217,236,18},{217,227,18},{214,236,8},{214,228,1},{214,228,1},{214,223,1},{206,229,8},{208,224,1},{220,230,0},{220,230,0},{220,230,0},{220,225,0},{255,152,8},{216,227,0},{216,227,0},{210,224,0},{255,205,8},{210,224,0},{255,167,18},{218,235,0},{220,230,0}, +{210,230,0},{255,167,18},{253,213,18},{210,230,0},{0,227,18},{253,213,18},{0,227,18},{217,0,18},{217,0,18},{217,0,18},{217,0,18},{214,230,0},{214,230,0},{214,230,0},{214,222,0},{208,225,0},{208,225,0},{226,254,36},{226,245,18},{226,239,22},{226,238,20},{223,254,51},{223,241,18},{223,239,1},{223,235,24},{213,243,51},{214,236,19},{229,248,18},{228,243,1},{229,239,0},{229,238,5},{255,189,51}, +{223,241,18},{223,239,1},{212,236,18},{254,223,51},{212,236,18},{226,245,18},{226,245,18},{226,245,18},{226,236,18},{223,245,8},{223,237,1},{223,237,1},{223,232,1},{216,237,8},{217,233,1},{229,239,0},{229,239,0},{229,239,0},{229,234,0},{255,180,8},{225,236,0},{225,236,0},{219,233,0},{255,218,8},{219,233,0},{255,195,18},{228,243,0},{229,239,0},{218,239,0},{255,195,18},{254,226,18},{218,239,0}, +{0,236,18},{254,226,18},{0,236,18},{226,0,18},{226,0,18},{226,0,18},{226,0,18},{223,239,0},{223,239,0},{223,239,0},{223,231,0},{217,234,0},{217,234,0},{235,254,46},{234,253,18},{234,247,22},{233,246,22},{233,255,56},{231,249,18},{231,247,1},{231,243,24},{221,251,51},{222,244,19},{238,254,19},{237,249,1},{237,247,0},{237,246,5},{255,213,51},{231,249,18},{231,247,1},{220,244,18},{254,235,51}, +{220,244,18},{234,253,18},{234,253,18},{234,253,18},{234,244,18},{231,253,8},{231,245,1},{231,245,1},{231,240,1},{224,245,8},{226,241,0},{237,247,0},{237,247,0},{237,247,0},{237,242,0},{255,204,8},{233,244,0},{233,244,0},{226,241,0},{255,230,8},{226,241,0},{255,219,18},{236,251,0},{237,247,0},{226,247,0},{255,219,18},{254,238,18},{226,247,0},{0,244,18},{254,238,18},{0,244,18},{234,0,18}, +{234,0,18},{234,0,18},{234,0,18},{231,247,0},{231,247,0},{231,247,0},{231,239,0},{226,241,0},{226,241,0},{245,255,72},{243,255,33},{242,255,22},{241,254,22},{242,255,81},{240,255,21},{239,255,1},{238,251,25},{234,255,56},{230,252,19},{248,255,29},{246,255,5},{245,255,0},{244,254,6},{255,237,51},{240,255,20},{239,255,1},{228,252,18},{254,247,51},{228,252,18},{242,255,22},{242,255,22},{242,255,22}, +{242,251,18},{241,254,14},{239,253,1},{239,253,1},{239,249,1},{232,253,8},{234,249,0},{245,255,0},{245,255,0},{245,255,0},{245,250,0},{255,228,8},{242,251,0},{242,251,0},{234,249,0},{255,242,8},{234,249,0},{255,243,18},{246,255,4},{245,255,0},{234,255,0},{255,243,18},{254,250,18},{234,255,0},{0,252,18},{254,250,18},{0,252,18},{242,0,18},{242,0,18},{242,0,18},{242,0,18},{239,255,0}, +{239,255,0},{239,255,0},{239,247,0},{234,249,0},{234,249,0},{251,255,28},{251,255,25},{251,255,24},{250,255,19},{251,255,24},{249,255,10},{248,255,9},{247,255,0},{246,255,12},{243,255,1},{254,255,1},{253,255,1},{253,255,1},{253,255,0},{255,249,3},{252,255,0},{252,255,0},{246,255,0},{254,253,3},{246,255,0},{251,255,24},{251,255,24},{251,255,24},{250,255,19},{250,254,19},{248,255,9},{248,255,9}, +{247,255,0},{246,255,8},{243,255,1},{253,254,1},{253,254,1},{253,254,1},{253,255,0},{255,249,2},{252,255,0},{252,255,0},{246,255,0},{254,253,2},{246,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{250,0,18},{250,0,18},{250,0,18},{250,0,18},{248,255,5},{248,255,5},{248,255,5},{247,255,0},{243,255,1}, +{243,255,1},{0,34,72},{0,24,5},{0,17,0},{0,13,25},{0,22,153},{0,15,90},{0,13,41},{0,10,110},{0,9,162},{0,8,119},{0,34,72},{0,24,5},{0,17,0},{0,13,25},{11,0,153},{0,15,90},{0,13,41},{0,10,110},{22,0,153},{0,10,110},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,7,13},{0,6,2},{0,6,2},{0,4,5},{0,3,13},{0,4,6},{0,16,0}, +{0,16,0},{0,16,0},{0,8,0},{3,0,13},{0,6,2},{0,6,2},{0,4,5},{7,0,13},{0,4,5},{17,0,72},{0,24,5},{0,17,0},{0,13,25},{17,0,72},{34,0,72},{0,13,25},{0,11,72},{34,0,72},{0,11,72},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,54,77},{2,37,5},{3,25,18}, +{1,23,13},{0,43,243},{0,27,99},{0,23,24},{0,16,139},{0,18,276},{0,16,164},{3,52,72},{3,36,0},{4,26,6},{2,24,11},{21,0,243},{0,27,99},{0,23,24},{0,16,139},{43,0,243},{0,16,139},{2,36,5},{2,36,5},{2,36,5},{1,19,5},{0,25,50},{0,18,5},{0,18,5},{0,10,18},{0,12,59},{0,10,27},{3,34,0},{3,34,0},{3,34,0},{3,18,0},{12,0,50}, +{0,18,5},{0,18,5},{0,10,18},{25,0,50},{0,10,18},{29,0,72},{3,36,0},{8,25,0},{0,23,8},{29,0,72},{58,0,72},{0,23,8},{0,19,72},{58,0,72},{0,19,72},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,3,1},{0,3,1},{6,70,133},{6,46,65},{7,35,94},{5,33,65},{0,67,243},{0,39,75},{0,32,2}, +{0,25,105},{0,30,332},{0,24,164},{11,60,72},{11,44,0},{12,34,6},{10,32,11},{33,0,243},{0,39,75},{1,32,1},{0,25,105},{67,0,243},{0,25,105},{6,52,61},{6,52,61},{6,52,61},{5,29,61},{0,49,50},{0,32,1},{0,32,1},{0,19,5},{0,21,94},{0,18,35},{11,42,0},{11,42,0},{11,42,0},{11,26,0},{24,0,50},{3,30,0},{3,30,0},{0,19,5},{49,0,50}, +{0,19,5},{41,0,72},{11,44,0},{16,33,0},{0,32,1},{41,0,72},{82,0,72},{0,32,1},{0,27,72},{82,0,72},{0,27,72},{5,0,61},{5,0,61},{5,0,61},{5,0,61},{0,34,0},{0,34,0},{0,34,0},{0,17,0},{0,15,17},{0,15,17},{13,80,144},{13,56,77},{15,43,109},{12,40,76},{7,77,243},{7,49,73},{7,41,1},{5,33,100},{0,42,287},{0,33,98},{19,68,72}, +{19,52,0},{20,42,6},{18,40,11},{45,0,243},{4,50,72},{9,40,1},{0,34,83},{92,0,243},{0,34,83},{13,62,72},{13,62,72},{13,62,72},{13,37,72},{7,59,50},{7,41,1},{7,41,1},{6,28,3},{0,36,66},{0,29,4},{19,50,0},{19,50,0},{19,50,0},{19,34,0},{36,0,50},{11,38,0},{11,38,0},{0,29,0},{73,0,50},{0,29,0},{52,0,72},{18,52,0},{23,41,0}, +{5,41,0},{52,0,72},{107,0,72},{5,41,0},{0,35,72},{107,0,72},{0,35,72},{13,0,72},{13,0,72},{13,0,72},{13,0,72},{7,44,0},{7,44,0},{7,44,0},{7,25,0},{0,27,2},{0,27,2},{22,89,144},{22,65,77},{24,52,109},{21,49,76},{16,86,243},{16,58,73},{16,50,1},{14,42,100},{0,57,248},{3,43,75},{28,77,72},{28,61,0},{29,50,5},{27,49,11},{58,0,243}, +{13,59,72},{18,49,1},{0,44,73},{119,0,243},{0,44,73},{22,71,72},{22,71,72},{22,71,72},{22,46,72},{16,68,50},{16,50,1},{16,50,1},{15,37,3},{0,49,50},{6,38,1},{28,59,0},{28,59,0},{28,59,0},{28,43,0},{49,0,50},{20,47,0},{20,47,0},{8,38,0},{101,0,50},{8,38,0},{66,0,72},{27,61,0},{32,50,0},{13,50,0},{66,0,72},{134,0,72},{13,50,0}, +{0,44,72},{134,0,72},{0,44,72},{22,0,72},{22,0,72},{22,0,72},{22,0,72},{16,53,0},{16,53,0},{16,53,0},{16,34,0},{6,39,0},{6,39,0},{30,97,144},{30,73,77},{32,59,106},{30,56,77},{24,94,243},{24,66,73},{24,58,2},{22,50,100},{2,69,243},{10,51,76},{36,85,72},{36,67,1},{37,58,5},{35,57,11},{70,0,243},{21,67,72},{26,58,1},{3,52,72},{143,0,243}, +{3,52,72},{30,79,72},{30,79,72},{30,79,72},{30,54,72},{24,76,50},{25,56,2},{25,56,2},{23,45,3},{8,57,50},{14,46,1},{36,66,0},{36,66,0},{36,66,0},{36,51,0},{61,0,50},{27,56,0},{27,56,0},{16,46,0},{125,0,50},{16,46,0},{78,0,72},{35,69,0},{40,58,0},{21,58,0},{78,0,72},{158,0,72},{21,58,0},{0,52,72},{158,0,72},{0,52,72},{30,0,72}, +{30,0,72},{30,0,72},{30,0,72},{24,61,0},{24,61,0},{24,61,0},{24,42,0},{14,47,0},{14,47,0},{38,105,144},{38,81,77},{40,67,106},{38,64,77},{32,102,243},{32,74,73},{32,66,2},{30,59,103},{10,77,243},{18,59,76},{44,93,72},{44,75,1},{45,66,5},{44,63,13},{82,0,243},{29,75,72},{33,66,1},{11,60,72},{167,0,243},{11,60,72},{38,87,72},{38,87,72},{38,87,72}, +{38,62,72},{32,84,50},{33,64,2},{33,64,2},{31,53,3},{16,65,50},{22,54,1},{44,74,0},{44,74,0},{44,74,0},{44,59,0},{73,0,50},{35,63,0},{35,63,0},{23,54,0},{149,0,50},{23,54,0},{89,0,72},{43,77,0},{48,66,0},{29,66,0},{89,0,72},{183,0,72},{29,66,0},{0,60,72},{183,0,72},{0,60,72},{38,0,72},{38,0,72},{38,0,72},{38,0,72},{32,69,0}, +{32,69,0},{32,69,0},{32,50,0},{21,55,0},{21,55,0},{46,113,144},{46,88,76},{48,75,106},{46,72,77},{40,110,243},{40,82,73},{40,73,2},{38,67,103},{18,85,243},{26,67,76},{52,100,72},{52,83,1},{53,74,5},{52,72,13},{94,0,243},{37,83,72},{41,74,1},{19,68,72},{192,0,243},{19,68,72},{46,95,72},{46,95,72},{46,95,72},{46,70,72},{40,92,50},{40,73,1},{40,73,1}, +{39,61,3},{24,73,50},{30,62,1},{52,82,0},{52,82,0},{52,82,0},{52,67,0},{85,0,50},{43,71,0},{43,71,0},{31,62,0},{174,0,50},{31,62,0},{101,0,72},{51,85,0},{56,74,0},{37,74,0},{101,0,72},{207,0,72},{37,74,0},{0,68,72},{207,0,72},{0,68,72},{46,0,72},{46,0,72},{46,0,72},{46,0,72},{40,76,0},{40,76,0},{40,76,0},{40,58,0},{29,63,0}, +{29,63,0},{55,122,144},{55,97,76},{57,84,106},{55,81,77},{49,119,243},{48,91,74},{49,82,2},{47,76,103},{27,94,243},{35,76,76},{61,109,72},{61,92,1},{62,83,5},{61,81,13},{107,0,243},{46,92,72},{50,83,1},{28,77,72},{219,0,243},{28,77,72},{55,103,72},{55,103,72},{55,103,72},{55,79,72},{49,101,50},{49,82,1},{49,82,1},{49,69,5},{33,82,50},{38,71,1},{61,91,0}, +{61,91,0},{61,91,0},{61,76,0},{98,0,50},{52,80,0},{52,80,0},{40,71,0},{201,0,50},{40,71,0},{115,0,72},{60,94,0},{65,83,0},{46,83,0},{115,0,72},{234,0,72},{46,83,0},{0,77,72},{234,0,72},{0,77,72},{55,0,72},{55,0,72},{55,0,72},{55,0,72},{49,85,0},{49,85,0},{49,85,0},{49,67,0},{38,72,0},{38,72,0},{63,130,144},{63,105,76},{65,92,106}, +{63,89,77},{57,127,243},{56,99,74},{57,90,2},{55,84,103},{35,102,243},{42,84,76},{69,117,72},{69,100,1},{70,91,5},{69,89,13},{119,0,243},{54,100,72},{58,91,1},{36,85,72},{243,0,243},{36,85,72},{63,111,72},{63,111,72},{63,111,72},{63,87,72},{57,108,50},{57,90,1},{57,90,1},{57,77,5},{41,90,50},{46,79,1},{69,99,0},{69,99,0},{69,99,0},{69,84,0},{110,0,50}, +{60,88,0},{60,88,0},{48,79,0},{225,0,50},{48,79,0},{127,0,72},{68,102,0},{73,91,0},{54,91,0},{127,0,72},{254,2,72},{54,91,0},{0,85,72},{254,2,72},{0,85,72},{63,0,72},{63,0,72},{63,0,72},{63,0,72},{57,93,0},{57,93,0},{57,93,0},{57,75,0},{46,80,0},{46,80,0},{71,137,144},{71,113,76},{73,100,106},{71,97,77},{65,135,243},{64,107,74},{65,98,2}, +{63,92,103},{44,109,243},{50,92,76},{77,125,72},{77,108,1},{78,99,5},{77,97,13},{131,0,243},{62,108,72},{66,99,1},{44,93,72},{255,6,243},{44,93,72},{71,119,72},{71,119,72},{71,119,72},{71,95,72},{65,116,50},{65,98,1},{65,98,1},{65,85,5},{49,98,50},{54,87,1},{77,107,0},{77,107,0},{77,107,0},{77,92,0},{122,0,50},{68,96,0},{68,96,0},{56,87,0},{249,0,50}, +{56,87,0},{138,0,72},{76,110,0},{81,99,0},{62,99,0},{138,0,72},{254,14,72},{62,99,0},{0,93,72},{254,14,72},{0,93,72},{71,0,72},{71,0,72},{71,0,72},{71,0,72},{65,101,0},{65,101,0},{65,101,0},{65,83,0},{54,88,0},{54,88,0},{79,145,144},{79,121,76},{81,108,106},{79,105,77},{73,142,243},{72,115,74},{73,106,2},{71,100,103},{52,117,243},{58,100,76},{85,133,72}, +{85,116,1},{86,107,5},{85,105,13},{143,0,243},{70,116,72},{74,107,1},{52,101,72},{255,18,243},{52,101,72},{79,127,72},{79,127,72},{79,127,72},{79,103,72},{73,124,50},{73,106,1},{73,106,1},{73,93,5},{57,106,50},{62,95,1},{85,115,0},{85,115,0},{85,115,0},{85,100,0},{134,0,50},{76,104,0},{76,104,0},{64,95,0},{255,9,50},{64,95,0},{150,0,72},{84,118,0},{89,107,0}, +{70,107,0},{150,0,72},{254,26,72},{70,107,0},{0,101,72},{254,26,72},{0,101,72},{79,0,72},{79,0,72},{79,0,72},{79,0,72},{73,109,0},{73,109,0},{73,109,0},{73,91,0},{62,96,0},{62,96,0},{88,154,144},{88,130,76},{90,117,106},{88,114,77},{82,151,243},{81,124,74},{82,115,2},{80,109,103},{61,126,243},{67,109,76},{94,142,72},{94,125,1},{95,116,5},{94,114,13},{156,0,243}, +{79,125,72},{83,116,1},{61,110,72},{254,32,243},{61,110,72},{88,136,72},{88,136,72},{88,136,72},{88,112,72},{82,133,50},{82,115,1},{82,115,1},{82,102,5},{66,115,50},{71,104,1},{94,124,0},{94,124,0},{94,124,0},{94,109,0},{147,0,50},{85,113,0},{85,113,0},{73,104,0},{254,23,50},{73,104,0},{164,0,72},{93,127,0},{98,116,0},{79,116,0},{164,0,72},{255,39,72},{79,116,0}, +{0,110,72},{255,39,72},{0,110,72},{88,0,72},{88,0,72},{88,0,72},{88,0,72},{82,118,0},{82,118,0},{82,118,0},{82,100,0},{71,105,0},{71,105,0},{96,162,144},{96,138,76},{98,125,106},{96,122,77},{90,159,243},{90,131,73},{90,123,2},{88,117,103},{69,134,243},{75,117,76},{102,150,72},{102,133,1},{103,124,5},{102,122,13},{168,0,243},{88,132,72},{91,124,1},{69,118,72},{255,43,243}, +{69,118,72},{96,144,72},{96,144,72},{96,144,72},{96,120,72},{90,141,50},{90,123,1},{90,123,1},{90,110,5},{74,123,50},{79,112,1},{102,132,0},{102,132,0},{102,132,0},{102,117,0},{159,0,50},{93,121,0},{93,121,0},{81,112,0},{254,35,50},{81,112,0},{175,0,72},{101,135,0},{106,124,0},{87,124,0},{175,0,72},{254,51,72},{87,124,0},{0,118,72},{254,51,72},{0,118,72},{96,0,72}, +{96,0,72},{96,0,72},{96,0,72},{90,126,0},{90,126,0},{90,126,0},{90,108,0},{79,113,0},{79,113,0},{104,170,144},{104,146,76},{106,133,106},{104,130,77},{98,167,243},{98,139,73},{98,131,2},{96,125,103},{77,142,243},{83,125,76},{110,158,72},{110,142,0},{111,132,5},{110,130,13},{180,0,243},{96,140,72},{99,132,1},{76,126,72},{255,55,243},{76,126,72},{104,152,72},{104,152,72},{104,152,72}, +{104,128,72},{98,149,50},{98,131,1},{98,131,1},{98,118,5},{83,130,50},{87,120,1},{110,140,0},{110,140,0},{110,140,0},{110,125,0},{171,0,50},{101,129,0},{101,129,0},{89,120,0},{255,46,50},{89,120,0},{187,0,72},{110,142,0},{114,132,0},{94,132,0},{187,0,72},{254,63,72},{94,132,0},{0,126,72},{254,63,72},{0,126,72},{104,0,72},{104,0,72},{104,0,72},{104,0,72},{98,134,0}, +{98,134,0},{98,134,0},{98,116,0},{87,121,0},{87,121,0},{112,178,144},{112,154,76},{114,140,105},{112,138,77},{106,175,243},{106,147,73},{106,139,2},{104,133,103},{85,150,243},{91,133,76},{118,166,72},{118,149,1},{119,140,5},{118,138,13},{192,0,243},{104,148,72},{107,140,1},{84,134,72},{255,67,243},{84,134,72},{112,160,72},{112,160,72},{112,160,72},{112,136,72},{106,157,50},{106,139,1},{106,139,1}, +{106,126,5},{91,138,50},{95,128,1},{118,147,0},{118,147,0},{118,147,0},{118,133,0},{183,0,50},{109,137,0},{109,137,0},{97,128,0},{255,58,50},{97,128,0},{199,0,72},{117,151,0},{122,140,0},{102,140,0},{199,0,72},{254,75,72},{102,140,0},{0,134,72},{254,75,72},{0,134,72},{112,0,72},{112,0,72},{112,0,72},{112,0,72},{106,142,0},{106,142,0},{106,142,0},{106,124,0},{95,129,0}, +{95,129,0},{121,187,144},{121,163,76},{122,151,103},{121,148,77},{115,184,243},{115,156,73},{115,148,2},{112,141,105},{94,159,243},{100,142,76},{127,175,72},{127,158,1},{128,149,5},{127,147,13},{205,0,243},{113,157,72},{116,149,1},{93,143,72},{254,81,243},{93,143,72},{121,169,72},{121,169,72},{121,169,72},{121,145,72},{115,166,50},{115,148,1},{115,148,1},{115,135,5},{100,147,50},{104,137,1},{127,156,0}, +{127,156,0},{127,156,0},{127,142,0},{196,0,50},{117,146,0},{117,146,0},{106,137,0},{254,72,50},{106,137,0},{213,0,72},{125,160,0},{131,149,0},{111,149,0},{213,0,72},{254,88,72},{111,149,0},{0,143,72},{254,88,72},{0,143,72},{121,0,72},{121,0,72},{121,0,72},{121,0,72},{115,151,0},{115,151,0},{115,151,0},{115,133,0},{104,138,0},{104,138,0},{129,195,144},{129,170,76},{130,159,103}, +{129,156,77},{123,192,243},{123,164,73},{123,156,2},{122,149,106},{102,167,243},{108,150,76},{135,182,72},{135,166,1},{136,157,5},{134,155,14},{217,0,243},{121,165,72},{124,157,1},{101,151,72},{255,92,243},{101,151,72},{129,177,72},{129,177,72},{129,177,72},{129,152,72},{123,174,50},{123,155,1},{123,155,1},{123,143,5},{108,155,50},{113,145,0},{135,164,0},{135,164,0},{135,164,0},{135,150,0},{208,0,50}, +{125,154,0},{125,154,0},{113,145,0},{254,84,50},{113,145,0},{224,0,72},{133,168,0},{139,157,0},{119,157,0},{224,0,72},{254,100,72},{119,157,0},{0,151,72},{254,100,72},{0,151,72},{129,0,72},{129,0,72},{129,0,72},{129,0,72},{123,158,0},{123,158,0},{123,158,0},{123,141,0},{113,145,0},{113,145,0},{137,203,144},{137,178,76},{138,167,103},{137,164,77},{131,200,243},{130,173,74},{131,164,2}, +{130,157,106},{110,175,243},{116,158,76},{143,190,72},{143,174,1},{144,165,5},{142,163,14},{229,0,243},{129,173,72},{132,165,1},{109,159,72},{255,104,243},{109,159,72},{137,184,72},{137,184,72},{137,184,72},{137,160,72},{131,182,50},{131,163,1},{131,163,1},{131,152,5},{116,163,50},{120,153,1},{143,172,0},{143,172,0},{143,172,0},{143,157,0},{220,0,50},{133,162,0},{133,162,0},{121,153,0},{255,95,50}, +{121,153,0},{236,0,72},{141,176,0},{147,165,0},{127,165,0},{236,0,72},{254,112,72},{127,165,0},{0,159,72},{254,112,72},{0,159,72},{137,0,72},{137,0,72},{137,0,72},{137,0,72},{131,166,0},{131,166,0},{131,166,0},{131,149,0},{120,154,0},{120,154,0},{145,211,144},{145,186,76},{146,175,103},{145,172,77},{139,208,243},{138,181,74},{139,172,2},{138,165,106},{118,183,243},{124,166,76},{151,198,72}, +{151,182,1},{152,173,5},{150,171,14},{241,0,243},{135,182,72},{140,173,1},{117,167,72},{255,116,243},{117,167,72},{145,192,72},{145,192,72},{145,192,72},{145,168,72},{139,189,50},{139,171,1},{139,171,1},{139,160,5},{124,171,50},{128,161,1},{151,180,0},{151,180,0},{151,180,0},{151,165,0},{232,0,50},{141,170,0},{141,170,0},{129,161,0},{255,107,50},{129,161,0},{248,0,72},{149,184,0},{155,173,0}, +{135,173,0},{248,0,72},{254,124,72},{135,173,0},{0,167,72},{254,124,72},{0,167,72},{145,0,72},{145,0,72},{145,0,72},{145,0,72},{139,174,0},{139,174,0},{139,174,0},{139,156,0},{127,162,0},{127,162,0},{154,219,144},{154,195,76},{155,184,103},{154,181,77},{148,217,243},{147,190,74},{148,181,2},{147,174,106},{126,192,243},{133,175,76},{160,207,72},{160,191,1},{161,182,5},{159,180,14},{254,0,243}, +{144,191,72},{149,182,1},{126,176,72},{255,129,243},{126,176,72},{154,201,72},{154,201,72},{154,201,72},{154,177,72},{148,198,50},{148,180,1},{148,180,1},{148,169,5},{132,181,50},{137,170,1},{160,189,0},{160,189,0},{160,189,0},{160,174,0},{245,0,50},{150,179,0},{150,179,0},{138,170,0},{254,121,50},{138,170,0},{255,13,72},{158,193,0},{164,182,0},{144,182,0},{255,13,72},{254,137,72},{144,182,0}, +{0,176,72},{254,137,72},{0,176,72},{154,0,72},{154,0,72},{154,0,72},{154,0,72},{148,183,0},{148,183,0},{148,183,0},{148,165,0},{136,171,0},{136,171,0},{162,227,144},{162,203,76},{163,192,103},{162,189,77},{156,224,243},{155,198,74},{156,189,2},{155,182,106},{134,200,243},{141,183,76},{168,215,72},{168,199,1},{169,190,5},{167,188,14},{255,22,243},{152,199,72},{157,190,1},{134,184,72},{255,141,243}, +{134,184,72},{162,209,72},{162,209,72},{162,209,72},{162,185,72},{156,206,50},{156,188,1},{156,188,1},{156,177,5},{139,189,50},{145,178,1},{168,197,0},{168,197,0},{168,197,0},{168,182,0},{255,4,50},{158,187,0},{158,187,0},{146,178,0},{255,132,50},{146,178,0},{255,37,72},{166,201,0},{172,190,0},{152,190,0},{255,37,72},{254,149,72},{152,190,0},{0,184,72},{254,149,72},{0,184,72},{162,0,72}, +{162,0,72},{162,0,72},{162,0,72},{156,191,0},{156,191,0},{156,191,0},{156,173,0},{144,179,0},{144,179,0},{170,235,144},{170,211,76},{171,200,103},{170,197,77},{164,232,243},{163,206,74},{164,197,2},{163,190,106},{142,208,243},{149,191,76},{176,223,72},{176,207,1},{177,198,5},{175,196,14},{255,46,243},{160,207,72},{165,198,1},{142,192,72},{255,153,243},{142,192,72},{170,217,72},{170,217,72},{170,217,72}, +{170,193,72},{164,214,50},{164,196,1},{164,196,1},{164,185,5},{147,197,50},{153,186,1},{176,205,0},{176,205,0},{176,205,0},{176,190,0},{255,28,50},{166,195,0},{166,195,0},{154,186,0},{255,144,50},{154,186,0},{255,61,72},{174,209,0},{180,198,0},{160,198,0},{255,61,72},{254,161,72},{160,198,0},{0,192,72},{254,161,72},{0,192,72},{170,0,72},{170,0,72},{170,0,72},{170,0,72},{164,199,0}, +{164,199,0},{164,199,0},{164,181,0},{152,187,0},{152,187,0},{178,243,144},{178,219,76},{179,208,103},{178,205,77},{172,240,243},{171,214,74},{172,205,2},{171,198,106},{150,216,243},{157,199,76},{184,231,72},{184,215,1},{185,206,5},{183,204,14},{255,70,243},{169,214,72},{173,206,1},{150,200,72},{255,165,243},{150,200,72},{178,225,72},{178,225,72},{178,225,72},{178,201,72},{172,222,50},{172,204,1},{172,204,1}, +{172,193,5},{155,205,50},{161,194,1},{184,213,0},{184,213,0},{184,213,0},{184,198,0},{255,52,50},{174,203,0},{174,203,0},{162,194,0},{255,156,50},{162,194,0},{255,86,72},{182,217,0},{188,206,0},{168,206,0},{255,86,72},{255,172,72},{168,206,0},{0,200,72},{255,172,72},{0,200,72},{178,0,72},{178,0,72},{178,0,72},{178,0,72},{172,207,0},{172,207,0},{172,207,0},{172,189,0},{160,195,0}, +{160,195,0},{187,252,144},{187,228,76},{188,217,103},{187,214,77},{181,249,243},{180,222,74},{181,214,2},{180,207,106},{159,225,243},{166,208,76},{193,240,72},{193,224,1},{194,216,3},{192,213,14},{255,98,243},{178,223,72},{182,215,1},{158,209,72},{255,178,243},{158,209,72},{187,234,72},{187,234,72},{187,234,72},{187,210,72},{181,231,50},{181,213,1},{181,213,1},{181,202,5},{165,213,50},{170,203,1},{193,222,0}, +{193,222,0},{193,222,0},{193,207,0},{255,79,50},{183,212,0},{183,212,0},{171,203,0},{253,170,50},{171,203,0},{255,113,72},{192,225,0},{196,215,0},{177,215,0},{255,113,72},{254,186,72},{177,215,0},{0,209,72},{254,186,72},{0,209,72},{187,0,72},{187,0,72},{187,0,72},{187,0,72},{181,216,0},{181,216,0},{181,216,0},{181,198,0},{169,204,0},{169,204,0},{196,255,148},{195,236,76},{196,225,103}, +{195,222,77},{189,254,244},{188,230,74},{189,222,2},{188,215,106},{167,233,243},{173,217,77},{201,248,72},{201,231,1},{202,224,3},{200,221,14},{255,122,243},{186,231,72},{189,222,2},{166,217,72},{255,190,243},{166,217,72},{195,242,72},{195,242,72},{195,242,72},{195,218,72},{189,239,50},{189,221,1},{189,221,1},{189,210,5},{173,221,50},{178,211,1},{201,229,0},{201,229,0},{201,229,0},{201,215,0},{255,104,50}, +{191,220,0},{191,220,0},{179,211,0},{255,181,50},{179,211,0},{255,137,72},{200,233,0},{204,223,0},{184,223,0},{255,137,72},{254,198,72},{184,223,0},{0,217,72},{254,198,72},{0,217,72},{195,0,72},{195,0,72},{195,0,72},{195,0,72},{189,224,0},{189,224,0},{189,224,0},{189,206,0},{177,212,0},{177,212,0},{205,255,170},{203,244,76},{204,232,100},{202,230,79},{199,255,255},{196,238,74},{197,231,2}, +{196,223,106},{175,241,243},{181,225,77},{210,254,73},{209,239,1},{210,232,3},{208,229,14},{255,146,243},{194,239,72},{198,230,2},{174,225,72},{255,202,243},{174,225,72},{203,250,72},{203,250,72},{203,250,72},{203,226,72},{197,247,50},{197,229,1},{197,229,1},{197,218,5},{181,229,50},{186,219,1},{209,237,0},{209,237,0},{209,237,0},{209,223,0},{255,128,50},{199,228,0},{199,228,0},{187,219,0},{255,193,50}, +{187,219,0},{255,161,72},{208,241,0},{212,231,0},{192,231,0},{255,161,72},{254,210,72},{192,231,0},{0,225,72},{254,210,72},{0,225,72},{203,0,72},{203,0,72},{203,0,72},{203,0,72},{197,232,0},{197,232,0},{197,232,0},{197,214,0},{185,220,0},{185,220,0},{215,255,208},{212,252,75},{212,240,100},{210,238,79},{211,255,287},{204,246,74},{205,239,1},{203,231,109},{183,249,243},{189,233,77},{218,255,81}, +{217,247,1},{218,240,3},{215,237,17},{255,171,243},{202,247,72},{205,239,1},{182,233,72},{254,214,243},{182,233,72},{211,255,73},{211,255,73},{211,255,73},{211,234,72},{205,255,50},{205,237,1},{205,237,1},{205,226,5},{189,237,50},{194,227,0},{217,245,0},{217,245,0},{217,245,0},{217,231,0},{255,152,50},{208,235,0},{208,235,0},{194,227,0},{255,205,50},{194,227,0},{255,186,72},{216,249,0},{220,239,0}, +{200,239,0},{255,186,72},{255,221,72},{200,239,0},{0,233,72},{255,221,72},{0,233,72},{211,0,72},{211,0,72},{211,0,72},{211,0,72},{205,239,0},{205,239,0},{205,239,0},{205,222,0},{194,227,0},{194,227,0},{224,255,274},{222,255,98},{221,249,100},{219,247,79},{221,255,332},{213,255,74},{214,248,1},{212,240,109},{195,255,245},{198,242,77},{230,255,106},{226,255,4},{227,249,3},{224,246,17},{255,198,243}, +{213,255,73},{214,248,1},{191,242,72},{255,227,243},{191,242,72},{221,255,83},{221,255,83},{221,255,83},{220,243,72},{215,255,59},{214,246,1},{214,246,1},{213,234,6},{198,246,50},{203,236,0},{226,254,0},{226,254,0},{226,254,0},{226,240,0},{255,180,50},{217,244,0},{217,244,0},{203,236,0},{255,218,50},{203,236,0},{255,213,72},{228,255,2},{229,248,0},{209,248,0},{255,213,72},{254,235,72},{209,248,0}, +{0,242,72},{254,235,72},{0,242,72},{220,0,72},{220,0,72},{220,0,72},{220,0,72},{214,248,0},{214,248,0},{214,248,0},{214,231,0},{203,236,0},{203,236,0},{233,255,327},{231,255,164},{230,255,105},{228,253,77},{230,255,370},{225,255,95},{222,254,2},{220,248,94},{213,255,262},{208,249,65},{239,255,126},{237,255,35},{235,255,5},{234,253,13},{255,219,221},{228,255,82},{223,254,1},{201,249,61},{254,238,221}, +{201,249,61},{230,255,105},{230,255,105},{230,255,105},{228,251,72},{227,255,83},{222,254,1},{222,254,1},{221,243,6},{206,254,50},{211,244,0},{235,254,5},{235,254,5},{235,254,5},{234,248,0},{255,204,50},{225,252,0},{225,252,0},{211,244,0},{255,230,50},{211,244,0},{255,234,61},{240,255,17},{238,255,0},{219,255,0},{255,234,61},{255,245,61},{219,255,0},{0,249,61},{255,245,61},{0,249,61},{228,0,72}, +{228,0,72},{228,0,72},{228,0,72},{222,253,1},{222,253,1},{222,253,1},{222,239,0},{211,244,0},{211,244,0},{242,255,233},{239,255,164},{239,255,139},{237,255,78},{239,255,239},{234,255,62},{232,255,24},{230,252,18},{225,255,158},{218,253,5},{248,255,53},{245,255,27},{245,255,18},{242,255,1},{255,237,93},{240,255,26},{237,255,5},{217,253,5},{254,247,93},{217,253,5},{239,255,139},{239,255,139},{239,255,139}, +{237,255,78},{236,255,118},{232,255,24},{232,255,24},{229,251,6},{222,255,67},{219,252,0},{245,255,18},{245,255,18},{245,255,18},{242,254,1},{255,228,50},{237,255,5},{237,255,5},{219,252,0},{255,242,50},{219,252,0},{255,246,5},{251,254,1},{250,255,0},{243,255,0},{255,246,5},{255,251,5},{243,255,0},{0,253,5},{255,251,5},{0,253,5},{236,0,72},{236,0,72},{236,0,72},{236,0,72},{232,254,8}, +{232,254,8},{232,254,8},{230,247,0},{219,252,0},{219,252,0},{248,255,136},{245,255,119},{245,255,110},{244,255,81},{245,255,122},{243,255,52},{241,255,41},{238,255,0},{237,255,75},{231,255,5},{251,255,9},{251,255,6},{251,255,5},{250,255,1},{255,246,17},{249,255,3},{249,255,2},{237,255,0},{255,251,17},{237,255,0},{245,255,110},{245,255,110},{245,255,110},{244,255,81},{245,255,86},{241,255,41},{241,255,41}, +{238,255,0},{234,255,46},{231,255,5},{251,255,5},{251,255,5},{251,255,5},{250,255,1},{255,243,13},{249,255,2},{249,255,2},{237,255,0},{254,250,13},{237,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{244,0,72},{244,0,72},{244,0,72},{244,0,72},{241,254,25},{241,254,25},{241,254,25},{238,255,0},{231,255,5}, +{231,255,5},{0,58,200},{0,42,17},{0,29,0},{0,25,65},{0,40,441},{0,27,266},{0,23,121},{0,16,318},{0,18,467},{0,16,343},{0,58,200},{0,42,17},{0,29,0},{0,25,65},{20,0,441},{0,27,266},{0,23,121},{0,16,318},{40,0,441},{0,16,318},{0,28,0},{0,28,0},{0,28,0},{0,14,0},{0,13,41},{0,12,10},{0,12,10},{0,7,20},{0,6,42},{0,7,24},{0,28,0}, +{0,28,0},{0,28,0},{0,14,0},{6,0,41},{0,12,10},{0,12,10},{0,7,20},{13,0,41},{0,7,20},{29,0,200},{0,42,17},{0,29,0},{0,25,65},{29,0,200},{58,0,200},{0,25,65},{0,19,200},{58,0,200},{0,19,200},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,82,200},{0,54,1},{1,38,19}, +{0,34,34},{0,55,686},{0,36,339},{0,30,139},{0,22,446},{0,24,747},{0,22,495},{0,82,200},{0,54,1},{2,39,17},{0,34,34},{27,0,686},{0,36,339},{0,30,139},{0,22,446},{55,0,686},{0,22,446},{0,52,0},{0,52,0},{0,52,0},{0,26,0},{0,25,145},{0,21,45},{0,21,45},{0,13,80},{0,12,154},{0,10,94},{0,52,0},{0,52,0},{0,52,0},{0,26,0},{12,0,145}, +{0,21,45},{0,21,45},{0,13,80},{25,0,145},{0,13,80},{41,0,200},{0,54,1},{8,37,0},{0,34,34},{41,0,200},{82,0,200},{0,34,34},{0,27,200},{82,0,200},{0,27,200},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,99,225},{4,65,26},{6,46,74},{3,43,45},{0,79,723},{0,48,282},{0,42,54}, +{0,31,401},{0,36,852},{0,29,497},{7,92,200},{7,64,0},{9,46,21},{5,42,29},{39,0,723},{0,48,282},{0,42,54},{0,31,401},{79,0,723},{0,31,401},{4,68,25},{4,68,25},{4,68,25},{3,36,25},{0,49,162},{0,36,17},{0,36,17},{0,22,58},{0,21,206},{0,19,97},{7,62,0},{7,62,0},{7,62,0},{7,34,0},{24,0,162},{0,36,17},{0,36,17},{0,22,58},{49,0,162}, +{0,22,58},{52,0,200},{6,64,0},{16,45,0},{0,44,17},{52,0,200},{107,0,200},{0,44,17},{0,35,200},{107,0,200},{0,35,200},{3,0,25},{3,0,25},{3,0,25},{3,0,25},{0,22,0},{0,22,0},{0,22,0},{0,11,0},{0,9,5},{0,9,5},{8,115,313},{8,78,121},{10,56,198},{7,51,126},{0,104,723},{0,63,227},{0,51,6},{0,40,339},{0,48,956},{0,38,494},{15,100,200}, +{15,72,0},{17,54,21},{15,49,32},{51,0,723},{0,63,227},{0,51,6},{0,40,339},{104,0,723},{0,40,339},{8,84,113},{8,84,113},{8,84,113},{7,46,113},{0,73,162},{0,48,1},{0,48,1},{0,31,29},{0,33,270},{0,27,109},{15,70,0},{15,70,0},{15,70,0},{15,42,0},{36,0,162},{0,48,1},{0,48,1},{0,31,29},{73,0,162},{0,31,29},{64,0,200},{14,72,0},{24,53,0}, +{0,53,4},{64,0,200},{131,0,200},{0,53,4},{0,43,200},{131,0,200},{0,43,200},{7,0,113},{7,0,113},{7,0,113},{7,0,113},{0,46,0},{0,46,0},{0,46,0},{0,23,0},{0,18,34},{0,18,34},{14,130,400},{15,88,215},{17,66,315},{13,60,210},{4,123,723},{3,75,207},{4,62,2},{2,49,303},{0,60,969},{0,48,417},{24,109,200},{24,81,0},{26,63,21},{23,58,33},{64,0,723}, +{0,78,201},{6,62,1},{0,50,289},{131,0,723},{0,50,289},{14,99,200},{14,99,200},{14,99,200},{14,56,200},{4,92,162},{5,60,2},{5,60,2},{3,40,14},{0,45,280},{0,39,77},{24,79,0},{24,79,0},{24,79,0},{24,51,0},{49,0,162},{7,59,0},{7,59,0},{0,40,8},{101,0,162},{0,40,8},{78,0,200},{23,81,0},{32,62,0},{1,62,0},{78,0,200},{158,0,200},{1,62,0}, +{0,52,200},{158,0,200},{0,52,200},{14,0,200},{14,0,200},{14,0,200},{14,0,200},{4,65,0},{4,65,0},{4,65,0},{4,34,0},{0,33,40},{0,33,40},{22,138,400},{23,96,215},{25,74,315},{21,68,210},{12,131,723},{11,83,207},{12,70,2},{10,57,303},{0,72,865},{0,57,290},{32,117,200},{32,89,0},{34,71,21},{31,66,33},{76,0,723},{5,87,200},{14,70,1},{0,59,251},{155,0,723}, +{0,59,251},{22,107,200},{22,107,200},{22,107,200},{22,64,200},{12,100,162},{13,68,2},{13,68,2},{10,47,17},{0,60,213},{0,48,13},{32,87,0},{32,87,0},{32,87,0},{32,59,0},{61,0,162},{15,67,0},{15,67,0},{0,50,1},{125,0,162},{0,50,1},{89,0,200},{31,89,0},{40,70,0},{9,70,0},{89,0,200},{183,0,200},{9,70,0},{0,60,200},{183,0,200},{0,60,200},{22,0,200}, +{22,0,200},{22,0,200},{22,0,200},{12,73,0},{12,73,0},{12,73,0},{12,42,0},{0,45,8},{0,45,8},{30,145,400},{31,104,215},{33,82,315},{29,76,210},{20,139,723},{19,91,207},{20,78,2},{18,65,303},{0,88,787},{0,66,225},{40,125,200},{40,97,0},{43,79,19},{39,74,33},{88,0,723},{14,94,200},{22,78,1},{0,66,224},{180,0,723},{0,66,224},{30,115,200},{30,115,200},{30,115,200}, +{30,72,200},{20,108,162},{21,76,2},{21,76,2},{18,56,17},{0,72,173},{2,58,1},{40,95,0},{40,95,0},{40,95,0},{40,67,0},{73,0,162},{23,75,0},{23,75,0},{3,58,0},{149,0,162},{3,58,0},{101,0,200},{39,97,0},{48,78,0},{17,78,0},{101,0,200},{207,0,200},{17,78,0},{0,68,200},{207,0,200},{0,68,200},{30,0,200},{30,0,200},{30,0,200},{30,0,200},{20,81,0}, +{20,81,0},{20,81,0},{20,50,0},{1,59,0},{1,59,0},{38,153,400},{39,112,215},{41,90,315},{37,84,210},{28,147,723},{27,99,207},{28,86,2},{26,73,303},{0,100,739},{4,75,212},{48,133,200},{48,105,0},{51,87,19},{47,82,33},{100,0,723},{22,102,200},{30,86,1},{0,75,206},{204,0,723},{0,75,206},{38,123,200},{38,123,200},{38,123,200},{38,80,200},{28,116,162},{29,84,2},{29,84,2}, +{26,64,17},{0,85,162},{10,66,1},{48,103,0},{48,103,0},{48,103,0},{48,75,0},{85,0,162},{31,83,0},{31,83,0},{11,66,0},{174,0,162},{11,66,0},{113,0,200},{47,105,0},{56,86,0},{25,86,0},{113,0,200},{231,0,200},{25,86,0},{0,76,200},{231,0,200},{0,76,200},{38,0,200},{38,0,200},{38,0,200},{38,0,200},{28,89,0},{28,89,0},{28,89,0},{28,58,0},{9,67,0}, +{9,67,0},{47,162,400},{48,121,215},{50,98,308},{46,93,210},{37,155,723},{36,107,207},{37,95,2},{35,82,303},{0,113,723},{13,84,212},{57,142,200},{57,112,1},{60,96,19},{56,91,33},{113,0,723},{31,111,200},{39,95,1},{0,85,200},{231,0,723},{0,85,200},{47,132,200},{47,132,200},{47,132,200},{47,89,200},{37,125,162},{38,93,2},{38,93,2},{35,73,17},{10,93,162},{19,75,1},{57,111,0}, +{57,111,0},{57,111,0},{57,84,0},{98,0,162},{40,92,0},{40,92,0},{20,75,0},{201,0,162},{20,75,0},{127,0,200},{56,114,0},{65,95,0},{34,95,0},{127,0,200},{254,2,200},{34,95,0},{0,85,200},{254,2,200},{0,85,200},{47,0,200},{47,0,200},{47,0,200},{47,0,200},{37,98,0},{37,98,0},{37,98,0},{37,67,0},{18,76,0},{18,76,0},{55,170,400},{56,129,215},{58,106,308}, +{54,101,210},{45,163,723},{44,115,207},{45,103,2},{43,90,303},{8,121,723},{21,92,212},{65,150,200},{65,121,0},{68,104,19},{64,99,33},{125,0,723},{39,119,200},{47,103,1},{7,93,200},{255,0,723},{7,93,200},{55,140,200},{55,140,200},{55,140,200},{55,97,200},{45,133,162},{46,101,2},{46,101,2},{43,81,17},{18,101,162},{27,83,1},{65,119,0},{65,119,0},{65,119,0},{65,92,0},{110,0,162}, +{48,100,0},{48,100,0},{28,83,0},{225,0,162},{28,83,0},{138,0,200},{65,121,0},{73,103,0},{42,103,0},{138,0,200},{254,14,200},{42,103,0},{0,93,200},{254,14,200},{0,93,200},{55,0,200},{55,0,200},{55,0,200},{55,0,200},{45,106,0},{45,106,0},{45,106,0},{45,75,0},{26,84,0},{26,84,0},{63,178,400},{64,137,215},{66,114,308},{62,109,210},{53,171,723},{52,123,207},{53,111,2}, +{51,98,303},{16,129,723},{27,100,215},{73,158,200},{73,129,0},{76,112,19},{72,107,33},{137,0,723},{47,127,200},{55,111,1},{15,101,200},{255,12,723},{15,101,200},{63,148,200},{63,148,200},{63,148,200},{63,105,200},{53,141,162},{54,109,2},{54,109,2},{51,89,17},{26,109,162},{35,91,1},{73,127,0},{73,127,0},{73,127,0},{73,100,0},{122,0,162},{56,108,0},{56,108,0},{36,91,0},{249,0,162}, +{36,91,0},{150,0,200},{73,129,0},{81,111,0},{49,111,0},{150,0,200},{254,26,200},{49,111,0},{0,101,200},{254,26,200},{0,101,200},{63,0,200},{63,0,200},{63,0,200},{63,0,200},{53,114,0},{53,114,0},{53,114,0},{53,83,0},{34,92,0},{34,92,0},{71,186,400},{72,144,212},{74,122,308},{70,117,210},{61,179,723},{60,131,207},{61,118,2},{59,106,303},{24,137,723},{35,108,215},{81,166,200}, +{81,137,0},{84,120,19},{80,115,33},{149,0,723},{55,135,200},{62,119,1},{23,109,200},{255,24,723},{23,109,200},{71,156,200},{71,156,200},{71,156,200},{71,113,200},{61,149,162},{61,118,1},{61,118,1},{59,97,17},{34,117,162},{43,99,1},{81,135,0},{81,135,0},{81,135,0},{81,108,0},{134,0,162},{64,116,0},{64,116,0},{44,99,0},{255,9,162},{44,99,0},{162,0,200},{81,137,0},{89,119,0}, +{57,119,0},{162,0,200},{254,38,200},{57,119,0},{0,109,200},{254,38,200},{0,109,200},{71,0,200},{71,0,200},{71,0,200},{71,0,200},{61,121,0},{61,121,0},{61,121,0},{61,91,0},{42,100,0},{42,100,0},{80,195,400},{81,153,212},{83,131,308},{79,127,212},{70,188,723},{69,140,207},{70,127,2},{68,115,303},{34,145,723},{44,117,215},{90,174,200},{90,146,0},{93,129,19},{89,124,33},{162,0,723}, +{64,144,200},{71,128,1},{32,118,200},{254,38,723},{32,118,200},{80,165,200},{80,165,200},{80,165,200},{80,122,200},{70,158,162},{70,127,1},{70,127,1},{68,106,17},{43,126,162},{52,108,1},{90,144,0},{90,144,0},{90,144,0},{90,117,0},{147,0,162},{74,124,0},{74,124,0},{53,108,0},{254,23,162},{53,108,0},{175,0,200},{90,146,0},{98,128,0},{66,128,0},{175,0,200},{254,51,200},{66,128,0}, +{0,118,200},{254,51,200},{0,118,200},{80,0,200},{80,0,200},{80,0,200},{80,0,200},{70,130,0},{70,130,0},{70,130,0},{70,100,0},{51,109,0},{51,109,0},{88,203,400},{89,161,212},{91,139,308},{87,135,212},{78,196,723},{77,148,207},{78,135,2},{75,122,305},{42,153,723},{52,125,215},{98,182,200},{98,154,0},{101,137,19},{97,132,33},{174,0,723},{72,152,200},{79,136,1},{40,126,200},{255,49,723}, +{40,126,200},{88,172,200},{88,172,200},{88,172,200},{88,129,200},{78,166,162},{78,135,1},{78,135,1},{76,114,17},{51,134,162},{60,116,0},{98,152,0},{98,152,0},{98,152,0},{98,125,0},{159,0,162},{82,132,0},{82,132,0},{60,116,0},{254,35,162},{60,116,0},{187,0,200},{98,154,0},{106,136,0},{74,136,0},{187,0,200},{254,63,200},{74,136,0},{0,126,200},{254,63,200},{0,126,200},{88,0,200}, +{88,0,200},{88,0,200},{88,0,200},{78,138,0},{78,138,0},{78,138,0},{78,108,0},{60,116,0},{60,116,0},{96,211,400},{97,169,212},{99,147,308},{95,143,212},{86,204,723},{85,156,207},{86,143,2},{83,131,308},{50,161,723},{60,133,215},{106,190,200},{106,162,0},{109,145,19},{105,141,35},{186,0,723},{80,160,200},{87,144,1},{48,134,200},{255,61,723},{48,134,200},{96,180,200},{96,180,200},{96,180,200}, +{96,137,200},{86,174,162},{86,143,1},{86,143,1},{84,122,17},{59,142,162},{68,124,0},{106,160,0},{106,160,0},{106,160,0},{106,133,0},{171,0,162},{90,140,0},{90,140,0},{68,124,0},{255,46,162},{68,124,0},{199,0,200},{106,162,0},{114,144,0},{82,144,0},{199,0,200},{254,75,200},{82,144,0},{0,134,200},{254,75,200},{0,134,200},{96,0,200},{96,0,200},{96,0,200},{96,0,200},{86,146,0}, +{86,146,0},{86,146,0},{86,116,0},{68,124,0},{68,124,0},{104,219,400},{105,177,212},{107,155,308},{103,151,212},{94,212,723},{93,164,207},{94,151,2},{91,139,308},{58,169,723},{68,141,215},{114,198,200},{114,170,0},{117,153,19},{113,149,35},{198,0,723},{88,168,200},{95,152,1},{56,142,200},{255,73,723},{56,142,200},{104,188,200},{104,188,200},{104,188,200},{104,145,200},{94,181,162},{94,151,1},{94,151,1}, +{92,130,17},{67,150,162},{76,132,0},{114,168,0},{114,168,0},{114,168,0},{114,141,0},{183,0,162},{98,148,0},{98,148,0},{76,132,0},{255,58,162},{76,132,0},{211,0,200},{114,170,0},{122,152,0},{90,152,0},{211,0,200},{255,86,200},{90,152,0},{0,142,200},{255,86,200},{0,142,200},{104,0,200},{104,0,200},{104,0,200},{104,0,200},{94,154,0},{94,154,0},{94,154,0},{94,124,0},{76,132,0}, +{76,132,0},{113,228,400},{114,186,215},{116,164,308},{112,160,212},{103,221,723},{102,173,207},{103,160,2},{100,148,308},{67,178,723},{78,150,212},{123,207,200},{123,179,0},{125,163,17},{122,158,35},{211,0,723},{96,177,200},{104,161,1},{65,151,200},{255,86,723},{65,151,200},{113,197,200},{113,197,200},{113,197,200},{113,154,200},{103,190,162},{103,160,1},{103,160,1},{102,138,19},{76,159,162},{85,141,0},{123,177,0}, +{123,177,0},{123,177,0},{123,149,0},{196,0,162},{107,157,0},{107,157,0},{85,141,0},{254,72,162},{85,141,0},{224,0,200},{123,179,0},{131,161,0},{99,161,0},{224,0,200},{254,100,200},{99,161,0},{0,151,200},{254,100,200},{0,151,200},{113,0,200},{113,0,200},{113,0,200},{113,0,200},{103,163,0},{103,163,0},{103,163,0},{103,133,0},{85,141,0},{85,141,0},{121,235,400},{122,194,215},{124,172,308}, +{120,168,212},{111,229,723},{110,181,207},{111,168,2},{108,156,308},{75,186,723},{86,158,212},{131,215,200},{131,187,0},{133,171,17},{130,166,35},{223,0,723},{104,185,200},{112,169,1},{73,159,200},{255,98,723},{73,159,200},{121,205,200},{121,205,200},{121,205,200},{121,162,200},{111,198,162},{111,168,1},{111,168,1},{110,146,19},{84,167,162},{93,149,0},{131,185,0},{131,185,0},{131,185,0},{131,157,0},{208,0,162}, +{115,165,0},{115,165,0},{93,149,0},{254,84,162},{93,149,0},{236,0,200},{131,187,0},{139,169,0},{107,169,0},{236,0,200},{254,112,200},{107,169,0},{0,159,200},{254,112,200},{0,159,200},{121,0,200},{121,0,200},{121,0,200},{121,0,200},{111,171,0},{111,171,0},{111,171,0},{111,141,0},{93,149,0},{93,149,0},{129,243,400},{130,202,215},{133,180,305},{128,176,212},{119,236,723},{118,189,207},{119,176,2}, +{116,164,308},{83,194,723},{94,166,212},{139,223,200},{139,195,0},{141,179,17},{138,174,35},{235,0,723},{112,193,200},{120,177,1},{81,167,200},{255,110,723},{81,167,200},{129,213,200},{129,213,200},{129,213,200},{129,170,200},{119,206,162},{119,176,1},{119,176,1},{118,154,19},{91,175,162},{101,157,0},{139,192,0},{139,192,0},{139,192,0},{139,165,0},{220,0,162},{123,173,0},{123,173,0},{101,157,0},{255,95,162}, +{101,157,0},{248,0,200},{139,195,0},{147,177,0},{115,177,0},{248,0,200},{254,124,200},{115,177,0},{0,167,200},{254,124,200},{0,167,200},{129,0,200},{129,0,200},{129,0,200},{129,0,200},{119,179,0},{119,179,0},{119,179,0},{119,148,0},{101,157,0},{101,157,0},{137,251,400},{138,210,215},{140,187,303},{136,184,212},{127,244,723},{126,197,207},{127,184,2},{124,172,308},{91,202,723},{102,174,212},{147,231,200}, +{147,202,1},{149,187,17},{146,182,35},{247,0,723},{120,201,200},{128,185,1},{88,175,200},{255,122,723},{88,175,200},{137,221,200},{137,221,200},{137,221,200},{137,178,200},{127,214,162},{127,184,1},{127,184,1},{126,162,19},{99,183,162},{109,165,0},{147,200,0},{147,200,0},{147,200,0},{147,173,0},{232,0,162},{131,181,0},{131,181,0},{109,165,0},{255,107,162},{109,165,0},{255,10,200},{146,203,0},{155,185,0}, +{123,185,0},{255,10,200},{255,135,200},{123,185,0},{0,175,200},{255,135,200},{0,175,200},{137,0,200},{137,0,200},{137,0,200},{137,0,200},{127,187,0},{127,187,0},{127,187,0},{127,156,0},{109,165,0},{109,165,0},{147,255,404},{147,219,215},{149,196,303},{145,193,212},{136,253,723},{135,206,207},{136,193,2},{133,181,308},{100,211,723},{111,183,212},{156,240,200},{156,210,1},{158,196,17},{155,191,35},{255,10,723}, +{129,210,200},{137,194,1},{97,184,200},{255,135,723},{97,184,200},{146,230,200},{146,230,200},{146,230,200},{146,187,200},{136,223,162},{136,193,1},{136,193,1},{135,171,19},{108,192,162},{118,174,0},{156,209,0},{156,209,0},{156,209,0},{156,182,0},{245,0,162},{139,191,0},{139,191,0},{118,174,0},{254,121,162},{118,174,0},{255,37,200},{155,212,0},{164,194,0},{131,194,0},{255,37,200},{254,149,200},{131,194,0}, +{0,184,200},{254,149,200},{0,184,200},{146,0,200},{146,0,200},{146,0,200},{146,0,200},{136,196,0},{136,196,0},{136,196,0},{136,165,0},{118,174,0},{118,174,0},{156,255,426},{155,227,215},{157,204,303},{153,201,212},{146,254,728},{143,214,207},{144,202,2},{141,189,308},{108,219,723},{118,191,215},{164,248,200},{164,218,1},{166,204,17},{163,199,35},{255,34,723},{137,218,200},{145,201,2},{105,192,200},{255,147,723}, +{105,192,200},{154,238,200},{154,238,200},{154,238,200},{154,195,200},{144,231,162},{144,200,1},{144,200,1},{143,179,19},{116,200,162},{126,182,0},{164,217,0},{164,217,0},{164,217,0},{164,190,0},{255,4,162},{146,199,0},{146,199,0},{126,182,0},{255,132,162},{126,182,0},{255,61,200},{163,220,0},{172,202,0},{139,202,0},{255,61,200},{254,161,200},{139,202,0},{0,192,200},{254,161,200},{0,192,200},{154,0,200}, +{154,0,200},{154,0,200},{154,0,200},{144,204,0},{144,204,0},{144,204,0},{144,173,0},{126,182,0},{126,182,0},{165,255,468},{163,234,212},{165,212,303},{162,207,213},{156,255,747},{151,222,207},{152,210,2},{149,197,308},{115,228,723},{126,199,215},{172,255,200},{172,226,1},{174,212,17},{171,207,35},{255,58,723},{145,226,200},{153,209,2},{113,200,200},{255,159,723},{113,200,200},{162,246,200},{162,246,200},{162,246,200}, +{162,203,200},{152,239,162},{152,208,1},{152,208,1},{151,187,19},{124,208,162},{134,190,0},{172,225,0},{172,225,0},{172,225,0},{172,198,0},{255,28,162},{155,206,0},{155,206,0},{134,190,0},{255,144,162},{134,190,0},{255,86,200},{171,228,0},{180,210,0},{147,210,0},{255,86,200},{255,172,200},{147,210,0},{0,200,200},{255,172,200},{0,200,200},{162,0,200},{162,0,200},{162,0,200},{162,0,200},{152,211,0}, +{152,211,0},{152,211,0},{152,181,0},{134,190,0},{134,190,0},{175,255,522},{171,242,212},{173,220,303},{170,216,213},{165,255,788},{158,232,208},{160,218,2},{157,205,308},{123,235,723},{134,207,215},{181,255,209},{180,234,1},{182,220,17},{179,215,35},{255,82,723},{153,234,200},{161,217,2},{121,208,200},{254,171,723},{121,208,200},{170,253,200},{170,253,200},{170,253,200},{170,211,200},{160,247,162},{160,216,1},{160,216,1}, +{159,195,19},{132,216,162},{141,198,1},{180,233,0},{180,233,0},{180,233,0},{180,206,0},{255,52,162},{163,214,0},{163,214,0},{142,198,0},{255,156,162},{142,198,0},{255,110,200},{179,236,0},{188,218,0},{155,218,0},{255,110,200},{255,184,200},{155,218,0},{0,208,200},{255,184,200},{0,208,200},{170,0,200},{170,0,200},{170,0,200},{170,0,200},{160,219,0},{160,219,0},{160,219,0},{160,189,0},{141,199,0}, +{141,199,0},{184,255,612},{180,251,212},{182,229,303},{179,225,213},{178,255,844},{167,239,210},{169,227,2},{165,214,315},{132,244,723},{143,216,215},{193,255,234},{189,243,1},{191,229,17},{187,224,38},{255,110,723},{162,243,200},{170,226,2},{130,217,200},{255,184,723},{130,217,200},{180,254,206},{180,254,206},{180,254,206},{179,220,200},{170,253,163},{169,225,1},{169,225,1},{168,204,19},{141,225,162},{150,207,0},{189,242,0}, +{189,242,0},{189,242,0},{189,215,0},{255,79,162},{172,223,0},{172,223,0},{150,207,0},{253,170,162},{150,207,0},{255,137,200},{188,245,0},{197,227,0},{164,227,0},{255,137,200},{254,198,200},{164,227,0},{0,217,200},{254,198,200},{0,217,200},{179,0,200},{179,0,200},{179,0,200},{179,0,200},{169,228,0},{169,228,0},{169,228,0},{169,198,0},{150,207,0},{150,207,0},{193,255,714},{189,255,225},{190,237,303}, +{187,233,213},{187,255,919},{175,247,210},{177,235,2},{173,222,315},{140,252,723},{151,224,215},{202,255,275},{197,251,1},{199,237,17},{195,232,38},{255,134,723},{170,251,200},{178,234,2},{138,225,200},{255,196,723},{138,225,200},{189,254,224},{189,254,224},{189,254,224},{187,228,200},{178,255,171},{177,233,1},{177,233,1},{176,212,19},{149,233,162},{158,215,0},{197,250,0},{197,250,0},{197,250,0},{197,223,0},{255,104,162}, +{180,231,0},{180,231,0},{158,215,0},{255,181,162},{158,215,0},{255,161,200},{196,253,0},{204,235,0},{172,235,0},{255,161,200},{254,210,200},{172,235,0},{0,225,200},{254,210,200},{0,225,200},{187,0,200},{187,0,200},{187,0,200},{187,0,200},{177,236,0},{177,236,0},{177,236,0},{177,206,0},{158,215,0},{158,215,0},{202,255,836},{198,255,290},{198,245,303},{195,241,213},{199,255,1015},{183,255,210},{185,243,2}, +{181,230,315},{152,255,732},{159,232,215},{214,254,331},{207,255,13},{207,245,17},{203,240,38},{255,158,723},{183,255,206},{186,242,2},{146,233,200},{255,208,723},{146,233,200},{196,255,251},{196,255,251},{196,255,251},{195,236,200},{190,255,195},{185,241,1},{185,241,1},{184,221,21},{157,241,162},{166,223,0},{205,255,1},{205,255,1},{205,255,1},{205,231,0},{255,128,162},{188,239,0},{188,239,0},{166,223,0},{255,193,162}, +{166,223,0},{255,186,200},{210,255,8},{212,243,0},{180,243,0},{255,186,200},{255,221,200},{180,243,0},{0,233,200},{255,221,200},{0,233,200},{195,0,200},{195,0,200},{195,0,200},{195,0,200},{185,244,0},{185,244,0},{185,244,0},{185,214,0},{166,223,0},{166,223,0},{215,255,976},{207,255,417},{206,253,303},{203,249,213},{208,255,1124},{195,255,258},{193,251,2},{189,238,315},{167,255,797},{166,240,215},{221,255,392}, +{216,255,77},{215,252,14},{211,248,38},{255,183,723},{198,255,248},{194,250,2},{154,241,200},{254,220,723},{154,241,200},{205,255,289},{205,255,289},{205,255,289},{203,244,200},{199,255,230},{193,249,1},{193,249,1},{192,229,21},{165,249,162},{174,231,0},{215,255,8},{215,255,8},{215,255,8},{213,239,0},{255,152,162},{196,247,0},{196,247,0},{174,231,0},{255,205,162},{174,231,0},{255,210,200},{222,255,40},{220,251,0}, +{188,251,0},{255,210,200},{255,233,200},{188,251,0},{0,241,200},{255,233,200},{0,241,200},{203,0,200},{203,0,200},{203,0,200},{203,0,200},{193,252,0},{193,252,0},{193,252,0},{193,222,0},{174,231,0},{174,231,0},{221,255,895},{217,255,494},{215,255,339},{212,255,201},{218,255,994},{207,255,251},{204,255,6},{199,245,198},{189,255,702},{176,247,121},{233,255,318},{228,255,109},{224,255,29},{222,253,13},{255,204,546}, +{213,255,198},{205,255,1},{169,247,113},{255,230,546},{169,247,113},{215,255,339},{215,255,339},{215,255,339},{212,253,200},{211,255,293},{204,255,6},{204,255,6},{201,238,21},{177,255,165},{183,240,0},{224,255,29},{224,255,29},{224,255,29},{222,248,0},{255,180,162},{206,254,1},{206,254,1},{183,240,0},{255,218,162},{183,240,0},{255,228,113},{237,255,34},{232,255,0},{207,255,0},{255,228,113},{255,242,113},{207,255,0}, +{0,247,113},{255,242,113},{0,247,113},{212,0,200},{212,0,200},{212,0,200},{212,0,200},{202,255,4},{202,255,4},{202,255,4},{202,231,0},{183,240,0},{183,240,0},{230,255,737},{226,255,497},{224,255,401},{220,255,216},{227,255,783},{216,255,206},{213,255,54},{209,249,74},{201,255,534},{189,251,26},{239,255,190},{235,255,97},{233,255,58},{230,255,1},{255,219,333},{225,255,110},{219,255,17},{185,251,25},{254,238,333}, +{185,251,25},{224,255,401},{224,255,401},{224,255,401},{220,255,216},{218,255,354},{213,255,54},{213,255,54},{209,246,21},{192,255,203},{191,248,0},{233,255,58},{233,255,58},{233,255,58},{230,254,1},{255,204,162},{219,255,17},{219,255,17},{191,248,0},{255,230,162},{191,248,0},{255,240,25},{246,255,5},{244,255,0},{231,255,0},{255,240,25},{255,248,25},{231,255,0},{0,251,25},{255,248,25},{0,251,25},{220,0,200}, +{220,0,200},{220,0,200},{220,0,200},{211,255,17},{211,255,17},{211,255,17},{210,239,0},{191,248,0},{191,248,0},{236,255,616},{233,255,495},{233,255,446},{228,255,264},{233,255,626},{225,255,220},{225,255,139},{217,254,19},{216,255,434},{199,255,1},{245,255,121},{244,255,94},{242,255,80},{240,255,20},{255,234,193},{237,255,75},{234,255,45},{201,255,0},{255,245,193},{201,255,0},{233,255,446},{233,255,446},{233,255,446}, +{228,255,264},{230,255,401},{225,255,139},{225,255,139},{216,253,17},{207,255,254},{199,255,1},{242,255,80},{242,255,80},{242,255,80},{240,255,20},{255,225,145},{234,255,45},{234,255,45},{201,255,0},{254,241,145},{201,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{228,0,200},{228,0,200},{228,0,200},{228,0,200},{221,255,34}, +{221,255,34},{221,255,34},{218,247,0},{200,254,1},{200,254,1},{242,255,400},{239,255,343},{239,255,318},{237,255,227},{239,255,370},{234,255,161},{232,255,121},{226,255,0},{225,255,243},{213,255,17},{251,255,33},{248,255,24},{248,255,20},{246,255,4},{255,243,54},{246,255,17},{243,255,10},{225,255,0},{254,250,54},{225,255,0},{239,255,318},{239,255,318},{239,255,318},{237,255,227},{236,255,253},{232,255,121},{232,255,121}, +{226,255,0},{219,255,150},{213,255,17},{248,255,20},{248,255,20},{248,255,20},{246,255,4},{255,237,41},{243,255,10},{243,255,10},{225,255,0},{254,247,41},{225,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{236,0,200},{236,0,200},{236,0,200},{236,0,200},{230,255,65},{230,255,65},{230,255,65},{226,255,0},{213,255,17}, +{213,255,17},{0,82,421},{0,60,40},{0,42,0},{0,34,145},{0,55,925},{0,36,566},{0,33,262},{0,22,677},{0,27,989},{0,22,726},{0,82,421},{0,60,40},{0,42,0},{0,34,145},{27,0,925},{0,36,566},{0,33,262},{0,22,677},{55,0,925},{0,22,677},{0,40,0},{0,40,0},{0,40,0},{0,20,0},{0,19,85},{0,15,25},{0,15,25},{0,10,45},{0,9,89},{0,8,54},{0,40,0}, +{0,40,0},{0,40,0},{0,20,0},{9,0,85},{0,15,25},{0,15,25},{0,10,45},{19,0,85},{0,10,45},{41,0,421},{0,60,40},{0,42,0},{0,34,145},{41,0,421},{82,0,421},{0,34,145},{0,27,421},{82,0,421},{0,27,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,107,421},{0,72,8},{1,50,18}, +{0,44,100},{0,73,1261},{0,48,670},{0,42,282},{0,28,857},{0,33,1369},{0,28,938},{0,107,421},{0,72,8},{2,51,14},{0,44,100},{36,0,1261},{0,48,670},{0,42,282},{0,28,857},{73,0,1261},{0,28,857},{0,64,0},{0,64,0},{0,64,0},{0,32,0},{0,31,221},{0,27,73},{0,27,73},{0,16,125},{0,15,237},{0,13,144},{0,64,0},{0,64,0},{0,64,0},{0,32,0},{15,0,221}, +{0,27,73},{0,27,73},{0,16,125},{31,0,221},{0,16,125},{52,0,421},{0,72,8},{7,50,0},{0,44,100},{52,0,421},{107,0,421},{0,44,100},{0,35,421},{107,0,421},{0,35,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,127,426},{1,86,5},{4,59,67},{0,53,70},{0,92,1514},{0,60,701},{0,51,243}, +{0,37,946},{0,42,1695},{0,34,1083},{3,125,421},{3,84,1},{7,59,42},{1,54,69},{45,0,1514},{0,60,701},{0,51,243},{0,37,946},{92,0,1514},{0,37,946},{2,84,5},{2,84,5},{2,84,5},{1,43,5},{0,49,338},{0,36,89},{0,36,89},{0,22,170},{0,21,382},{0,19,217},{3,82,0},{3,82,0},{3,82,0},{3,42,0},{24,0,338},{0,36,89},{0,36,89},{0,22,170},{49,0,338}, +{0,22,170},{64,0,421},{1,86,0},{15,58,0},{0,53,61},{64,0,421},{131,0,421},{0,53,61},{0,43,421},{131,0,421},{0,43,421},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,3,1},{0,3,1},{6,143,482},{6,97,63},{8,69,163},{4,63,110},{0,116,1514},{0,72,589},{0,60,109},{0,44,857},{0,54,1815},{0,44,1053},{11,133,421}, +{11,91,1},{15,67,42},{9,62,69},{57,0,1514},{0,72,589},{0,60,109},{0,44,857},{116,0,1514},{0,44,857},{6,101,61},{6,101,61},{6,101,61},{6,52,61},{0,73,338},{0,51,34},{0,51,34},{0,31,117},{0,33,446},{0,29,209},{11,90,0},{11,90,0},{11,90,0},{11,50,0},{36,0,338},{0,51,34},{0,51,34},{0,31,117},{73,0,338},{0,31,117},{76,0,421},{10,93,0},{23,66,0}, +{0,62,32},{76,0,421},{155,0,421},{0,62,32},{0,51,421},{155,0,421},{0,51,421},{5,0,61},{5,0,61},{5,0,61},{5,0,61},{0,34,0},{0,34,0},{0,34,0},{0,17,0},{0,15,17},{0,15,17},{10,162,621},{11,109,215},{14,78,362},{9,71,234},{0,143,1514},{0,88,489},{0,72,22},{0,56,750},{0,66,1982},{0,53,1047},{20,142,421},{20,100,1},{24,76,42},{18,71,69},{70,0,1514}, +{0,88,489},{0,72,22},{0,56,750},{143,0,1514},{0,56,750},{10,120,200},{10,120,200},{10,120,200},{10,64,200},{0,101,338},{0,69,4},{0,69,4},{0,40,72},{0,45,552},{0,39,229},{20,99,0},{20,99,0},{20,99,0},{20,59,0},{49,0,338},{0,69,4},{0,69,4},{0,40,72},{101,0,338},{0,40,72},{89,0,421},{19,102,0},{32,75,0},{0,74,10},{89,0,421},{183,0,421},{0,74,10}, +{0,60,421},{183,0,421},{0,60,421},{10,0,200},{10,0,200},{10,0,200},{10,0,200},{0,61,0},{0,61,0},{0,61,0},{0,30,0},{0,24,65},{0,24,65},{14,178,813},{15,119,423},{18,88,618},{13,81,414},{0,167,1514},{0,100,441},{0,83,2},{0,65,670},{0,75,2165},{0,60,1070},{28,150,421},{28,108,1},{32,84,42},{26,79,69},{82,0,1514},{0,100,441},{2,82,2},{0,65,670},{167,0,1514}, +{0,65,670},{14,136,392},{14,136,392},{14,136,392},{14,74,392},{0,125,338},{1,80,2},{1,80,2},{0,50,41},{0,54,677},{0,48,277},{28,107,0},{28,107,0},{28,107,0},{28,67,0},{61,0,338},{3,79,0},{3,79,0},{0,50,41},{125,0,338},{0,50,41},{101,0,421},{27,110,0},{40,83,0},{0,83,1},{101,0,421},{207,0,421},{0,83,1},{0,68,421},{207,0,421},{0,68,421},{14,0,392}, +{14,0,392},{14,0,392},{14,0,392},{0,85,0},{0,85,0},{0,85,0},{0,42,0},{0,33,136},{0,33,136},{22,186,842},{22,128,450},{26,96,655},{21,89,441},{7,177,1514},{5,111,434},{8,90,4},{4,72,639},{0,88,2003},{0,69,858},{36,157,421},{36,116,1},{40,92,42},{34,87,69},{94,0,1514},{0,113,422},{8,90,3},{0,71,602},{192,0,1514},{0,71,602},{22,144,421},{22,144,421},{22,144,421}, +{21,82,421},{7,135,338},{8,90,3},{8,90,3},{6,59,35},{0,69,581},{0,57,150},{36,115,0},{36,115,0},{36,115,0},{36,75,0},{73,0,338},{11,87,0},{11,87,0},{0,59,18},{149,0,338},{0,59,18},{113,0,421},{35,118,0},{48,91,0},{2,91,0},{113,0,421},{231,0,421},{2,91,0},{0,76,421},{231,0,421},{0,76,421},{21,0,421},{21,0,421},{21,0,421},{21,0,421},{7,95,0}, +{7,95,0},{7,95,0},{7,50,0},{0,48,80},{0,48,80},{30,194,842},{30,136,450},{34,104,655},{29,97,441},{15,185,1514},{13,119,434},{16,98,4},{12,80,639},{0,103,1850},{0,80,663},{44,165,421},{44,124,1},{48,100,42},{42,95,69},{106,0,1514},{6,122,421},{16,98,3},{0,80,542},{216,0,1514},{0,80,542},{30,152,421},{30,152,421},{30,152,421},{29,90,421},{15,143,338},{16,98,3},{16,98,3}, +{14,67,35},{0,81,477},{0,66,52},{44,123,0},{44,123,0},{44,123,0},{44,83,0},{85,0,338},{19,95,0},{19,95,0},{0,68,5},{174,0,338},{0,68,5},{125,0,421},{43,126,0},{56,99,0},{10,99,0},{125,0,421},{255,0,421},{10,99,0},{0,84,421},{255,0,421},{0,84,421},{29,0,421},{29,0,421},{29,0,421},{29,0,421},{15,103,0},{15,103,0},{15,103,0},{15,58,0},{0,63,29}, +{0,63,29},{39,203,842},{39,145,450},{43,113,655},{37,106,445},{24,194,1514},{22,126,438},{25,107,4},{21,89,639},{0,115,1710},{0,90,519},{53,174,421},{53,133,1},{56,110,38},{51,104,69},{119,0,1514},{15,131,421},{25,107,3},{0,90,494},{243,0,1514},{0,90,494},{39,160,421},{39,160,421},{39,160,421},{38,99,421},{24,152,338},{25,107,3},{25,107,3},{23,76,35},{0,97,389},{0,78,3},{53,132,0}, +{53,132,0},{53,132,0},{53,92,0},{98,0,338},{29,103,0},{29,103,0},{0,79,0},{201,0,338},{0,79,0},{138,0,421},{52,135,0},{65,108,0},{19,108,0},{138,0,421},{254,14,421},{19,108,0},{0,93,421},{254,14,421},{0,93,421},{38,0,421},{38,0,421},{38,0,421},{38,0,421},{24,112,0},{24,112,0},{24,112,0},{24,67,0},{0,78,2},{0,78,2},{47,211,842},{47,153,450},{51,121,655}, +{45,114,445},{32,202,1514},{30,134,438},{33,115,4},{29,97,639},{0,129,1617},{0,99,458},{61,182,421},{61,141,1},{64,118,38},{59,112,69},{131,0,1514},{23,139,421},{33,115,3},{0,99,458},{255,6,1514},{0,99,458},{47,168,421},{47,168,421},{47,168,421},{46,107,421},{32,160,338},{33,115,3},{33,115,3},{31,84,35},{0,109,349},{5,87,1},{61,140,0},{61,140,0},{61,140,0},{61,100,0},{110,0,338}, +{37,111,0},{37,111,0},{8,87,0},{225,0,338},{8,87,0},{150,0,421},{60,143,0},{73,116,0},{27,116,0},{150,0,421},{254,26,421},{27,116,0},{0,101,421},{254,26,421},{0,101,421},{46,0,421},{46,0,421},{46,0,421},{46,0,421},{32,120,0},{32,120,0},{32,120,0},{32,75,0},{5,88,0},{5,88,0},{55,219,842},{55,161,450},{59,129,655},{53,122,445},{40,210,1514},{38,142,438},{41,123,4}, +{36,105,646},{0,141,1553},{3,108,450},{69,190,421},{69,149,1},{72,126,38},{68,118,73},{143,0,1514},{32,146,421},{41,123,3},{0,108,434},{255,18,1514},{0,108,434},{55,176,421},{55,176,421},{55,176,421},{55,114,421},{40,168,338},{41,123,3},{41,123,3},{39,92,35},{0,122,338},{13,95,1},{69,148,0},{69,148,0},{69,148,0},{69,108,0},{122,0,338},{45,119,0},{45,119,0},{15,95,0},{249,0,338}, +{15,95,0},{162,0,421},{68,151,0},{81,124,0},{35,124,0},{162,0,421},{254,38,421},{35,124,0},{0,109,421},{254,38,421},{0,109,421},{54,0,421},{54,0,421},{54,0,421},{54,0,421},{40,128,0},{40,128,0},{40,128,0},{40,83,0},{13,96,0},{13,96,0},{63,227,842},{63,169,450},{68,134,654},{61,130,445},{48,218,1514},{46,151,434},{49,131,4},{44,113,646},{0,153,1521},{11,116,450},{77,198,421}, +{77,157,1},{80,134,38},{74,128,74},{155,0,1514},{40,154,421},{49,131,3},{0,117,422},{255,30,1514},{0,117,422},{63,184,421},{63,184,421},{63,184,421},{63,122,421},{48,175,338},{49,131,3},{49,131,3},{47,100,35},{8,130,338},{21,103,1},{77,156,0},{77,156,0},{77,156,0},{77,116,0},{134,0,338},{53,127,0},{53,127,0},{23,103,0},{255,9,338},{23,103,0},{174,0,421},{76,159,0},{89,132,0}, +{43,132,0},{174,0,421},{255,49,421},{43,132,0},{0,117,421},{255,49,421},{0,117,421},{62,0,421},{62,0,421},{62,0,421},{62,0,421},{48,136,0},{48,136,0},{48,136,0},{48,91,0},{21,104,0},{21,104,0},{72,236,842},{72,178,450},{76,145,646},{70,139,445},{57,227,1514},{55,160,434},{58,140,4},{53,122,646},{4,166,1514},{20,125,450},{86,207,421},{86,166,1},{89,143,38},{83,137,74},{168,0,1514}, +{49,163,421},{58,140,3},{4,126,421},{255,43,1514},{4,126,421},{72,193,421},{72,193,421},{72,193,421},{72,131,421},{57,184,338},{58,140,3},{58,140,3},{56,109,35},{18,138,338},{30,112,1},{86,164,0},{86,164,0},{86,164,0},{86,125,0},{147,0,338},{62,136,0},{62,136,0},{32,112,0},{254,23,338},{32,112,0},{187,0,421},{85,168,0},{98,141,0},{52,141,0},{187,0,421},{254,63,421},{52,141,0}, +{0,126,421},{254,63,421},{0,126,421},{71,0,421},{71,0,421},{71,0,421},{71,0,421},{57,145,0},{57,145,0},{57,145,0},{57,100,0},{30,113,0},{30,113,0},{80,243,842},{80,186,450},{84,153,646},{78,147,445},{65,235,1514},{63,168,434},{66,148,4},{61,130,646},{12,174,1514},{27,133,450},{94,215,421},{94,174,1},{97,151,38},{91,145,74},{180,0,1514},{57,171,421},{66,148,3},{11,134,421},{255,55,1514}, +{11,134,421},{80,201,421},{80,201,421},{80,201,421},{80,139,421},{65,192,338},{66,148,3},{66,148,3},{63,116,36},{26,146,338},{38,120,1},{94,172,0},{94,172,0},{94,172,0},{94,132,0},{159,0,338},{70,144,0},{70,144,0},{40,120,0},{254,35,338},{40,120,0},{199,0,421},{92,176,0},{106,149,0},{60,149,0},{199,0,421},{254,75,421},{60,149,0},{0,134,421},{254,75,421},{0,134,421},{79,0,421}, +{79,0,421},{79,0,421},{79,0,421},{65,153,0},{65,153,0},{65,153,0},{65,108,0},{38,121,0},{38,121,0},{88,251,842},{88,194,450},{92,161,646},{86,155,445},{73,243,1514},{71,176,434},{74,156,4},{69,138,646},{21,181,1514},{35,141,450},{102,223,421},{102,182,1},{105,159,38},{99,153,74},{192,0,1514},{65,179,421},{74,156,3},{19,142,421},{255,67,1514},{19,142,421},{88,209,421},{88,209,421},{88,209,421}, +{88,147,421},{73,200,338},{74,156,3},{74,156,3},{71,125,38},{34,154,338},{46,128,1},{102,180,0},{102,180,0},{102,180,0},{102,140,0},{171,0,338},{78,152,0},{78,152,0},{48,128,0},{255,46,338},{48,128,0},{211,0,421},{100,184,0},{114,157,0},{68,157,0},{211,0,421},{255,86,421},{68,157,0},{0,142,421},{255,86,421},{0,142,421},{87,0,421},{87,0,421},{87,0,421},{87,0,421},{73,161,0}, +{73,161,0},{73,161,0},{73,116,0},{46,129,0},{46,129,0},{97,254,850},{96,202,450},{100,169,646},{94,163,445},{81,251,1514},{79,184,434},{82,164,4},{77,146,646},{29,189,1514},{43,149,450},{110,231,421},{110,190,1},{113,167,38},{107,161,74},{204,0,1514},{73,187,421},{83,164,2},{27,150,421},{255,79,1514},{27,150,421},{96,217,421},{96,217,421},{96,217,421},{96,155,421},{81,208,338},{82,163,2},{82,163,2}, +{79,133,38},{42,162,338},{54,136,1},{110,188,0},{110,188,0},{110,188,0},{110,148,0},{183,0,338},{86,160,0},{86,160,0},{56,136,0},{255,58,338},{56,136,0},{223,0,421},{108,192,0},{122,165,0},{76,165,0},{223,0,421},{255,98,421},{76,165,0},{0,150,421},{255,98,421},{0,150,421},{95,0,421},{95,0,421},{95,0,421},{95,0,421},{81,169,0},{81,169,0},{81,169,0},{81,124,0},{54,137,0}, +{54,137,0},{107,255,878},{105,211,450},{109,178,646},{103,172,445},{91,254,1518},{88,193,434},{91,173,4},{86,155,646},{38,198,1514},{52,158,450},{119,240,421},{119,199,1},{122,176,38},{116,170,74},{217,0,1514},{82,196,421},{92,173,2},{36,159,421},{255,92,1514},{36,159,421},{105,226,421},{105,226,421},{105,226,421},{105,164,421},{90,217,338},{91,172,2},{91,172,2},{88,142,38},{51,171,338},{63,145,1},{119,197,0}, +{119,197,0},{119,197,0},{119,157,0},{196,0,338},{95,169,0},{95,169,0},{65,145,0},{254,72,338},{65,145,0},{236,0,421},{117,201,0},{130,174,0},{84,174,0},{236,0,421},{254,112,421},{84,174,0},{0,159,421},{254,112,421},{0,159,421},{104,0,421},{104,0,421},{104,0,421},{104,0,421},{90,177,0},{90,177,0},{90,177,0},{90,133,0},{63,146,0},{63,146,0},{116,255,926},{113,218,450},{117,186,646}, +{111,180,445},{101,255,1535},{96,201,434},{99,181,4},{94,163,646},{46,206,1514},{60,166,450},{127,247,421},{127,207,1},{130,184,38},{124,178,74},{229,0,1514},{90,204,421},{99,181,3},{44,167,421},{255,104,1514},{44,167,421},{113,234,421},{113,234,421},{113,234,421},{113,172,421},{98,225,338},{99,180,3},{99,180,3},{96,150,38},{59,179,338},{71,153,1},{127,205,0},{127,205,0},{127,205,0},{127,165,0},{208,0,338}, +{103,177,0},{103,177,0},{73,153,0},{254,84,338},{73,153,0},{248,0,421},{125,209,0},{138,182,0},{92,182,0},{248,0,421},{254,124,421},{92,182,0},{0,167,421},{254,124,421},{0,167,421},{112,0,421},{112,0,421},{112,0,421},{112,0,421},{98,185,0},{98,185,0},{98,185,0},{98,141,0},{71,154,0},{71,154,0},{125,255,994},{121,226,450},{125,194,646},{120,186,446},{113,255,1575},{104,209,434},{107,189,4}, +{102,171,646},{54,214,1514},{68,174,450},{135,255,421},{135,215,1},{139,192,36},{132,186,74},{241,0,1514},{98,212,421},{107,189,3},{52,175,421},{255,116,1514},{52,175,421},{121,241,421},{121,241,421},{121,241,421},{121,180,421},{106,233,338},{107,188,3},{107,188,3},{104,158,38},{67,187,338},{79,161,1},{135,213,0},{135,213,0},{135,213,0},{135,173,0},{220,0,338},{110,185,0},{110,185,0},{81,161,0},{255,95,338}, +{81,161,0},{255,10,421},{133,217,0},{146,190,0},{100,190,0},{255,10,421},{255,135,421},{100,190,0},{0,175,421},{255,135,421},{0,175,421},{120,0,421},{120,0,421},{120,0,421},{120,0,421},{106,193,0},{106,193,0},{106,193,0},{106,149,0},{79,162,0},{79,162,0},{135,255,1070},{129,234,450},{133,202,646},{128,195,446},{122,255,1626},{112,216,438},{115,197,4},{110,179,646},{62,222,1514},{76,182,450},{146,254,434}, +{143,223,1},{146,199,35},{140,194,74},{253,0,1514},{106,220,421},{115,197,3},{60,183,421},{254,128,1514},{60,183,421},{129,249,421},{129,249,421},{129,249,421},{129,188,421},{114,241,338},{115,196,3},{115,196,3},{112,166,38},{75,195,338},{87,169,1},{143,221,0},{143,221,0},{143,221,0},{143,181,0},{232,0,338},{118,193,0},{118,193,0},{89,169,0},{255,107,338},{89,169,0},{255,34,421},{141,225,0},{154,198,0}, +{108,198,0},{255,34,421},{255,147,421},{108,198,0},{0,183,421},{255,147,421},{0,183,421},{128,0,421},{128,0,421},{128,0,421},{128,0,421},{114,201,0},{114,201,0},{114,201,0},{114,157,0},{87,170,0},{87,170,0},{144,255,1190},{138,243,450},{142,211,646},{137,204,446},{132,255,1703},{121,225,438},{124,206,4},{121,187,654},{71,231,1514},{85,191,450},{156,255,461},{152,232,1},{155,208,35},{151,202,75},{255,22,1514}, +{114,229,421},{124,206,3},{69,192,421},{255,141,1514},{69,192,421},{138,255,422},{138,255,422},{138,255,422},{137,197,421},{123,250,338},{124,205,3},{124,205,3},{121,175,38},{84,204,338},{96,178,1},{152,230,0},{152,230,0},{152,230,0},{152,190,0},{245,0,338},{127,202,0},{127,202,0},{97,178,0},{254,121,338},{97,178,0},{255,61,421},{150,234,0},{163,207,0},{117,207,0},{255,61,421},{254,161,421},{117,207,0}, +{0,192,421},{254,161,421},{0,192,421},{137,0,421},{137,0,421},{137,0,421},{137,0,421},{123,210,0},{123,210,0},{123,210,0},{123,166,0},{95,179,0},{95,179,0},{153,255,1318},{146,251,450},{150,219,646},{145,212,446},{144,255,1791},{129,233,438},{132,214,4},{126,196,655},{78,240,1514},{93,199,450},{165,255,506},{160,240,1},{163,216,35},{158,210,78},{255,46,1514},{122,237,421},{132,214,3},{77,200,421},{255,153,1514}, +{77,200,421},{147,255,434},{147,255,434},{147,255,434},{145,205,421},{132,255,339},{132,213,3},{132,213,3},{129,183,38},{92,212,338},{104,186,1},{160,238,0},{160,238,0},{160,238,0},{160,198,0},{255,4,338},{135,210,0},{135,210,0},{105,186,0},{255,132,338},{105,186,0},{255,86,421},{158,242,0},{171,215,0},{125,215,0},{255,86,421},{255,172,421},{125,215,0},{0,200,421},{255,172,421},{0,200,421},{145,0,421}, +{145,0,421},{145,0,421},{145,0,421},{131,218,0},{131,218,0},{131,218,0},{131,174,0},{103,187,0},{103,187,0},{162,255,1466},{156,255,458},{158,226,639},{153,220,446},{153,255,1902},{137,240,438},{140,222,4},{134,204,655},{85,248,1514},{101,207,450},{175,255,554},{168,249,1},{171,224,35},{166,218,78},{255,70,1514},{130,245,421},{140,222,3},{85,208,421},{255,165,1514},{85,208,421},{156,255,458},{156,255,458},{156,255,458}, +{153,213,421},{141,255,350},{140,221,3},{140,221,3},{137,191,38},{99,220,338},{112,194,1},{168,245,0},{168,245,0},{168,245,0},{168,206,0},{255,28,338},{143,218,0},{143,218,0},{113,194,0},{255,144,338},{113,194,0},{255,110,421},{166,250,0},{179,223,0},{133,223,0},{255,110,421},{255,184,421},{133,223,0},{0,208,421},{255,184,421},{0,208,421},{153,0,421},{153,0,421},{153,0,421},{153,0,421},{139,226,0}, +{139,226,0},{139,226,0},{139,182,0},{111,195,0},{111,195,0},{172,255,1606},{165,255,519},{166,234,639},{161,228,446},{165,255,2030},{145,248,438},{148,230,4},{142,212,655},{95,255,1515},{109,215,450},{187,255,626},{177,255,3},{179,232,35},{174,226,78},{255,95,1514},{138,253,421},{148,230,3},{93,216,421},{254,177,1514},{93,216,421},{165,255,494},{165,255,494},{165,255,494},{161,221,421},{150,255,379},{148,229,3},{148,229,3}, +{145,199,38},{107,228,338},{120,202,1},{176,253,0},{176,253,0},{176,253,0},{176,214,0},{255,52,338},{151,226,0},{151,226,0},{121,202,0},{255,156,338},{121,202,0},{255,134,421},{177,255,2},{187,231,0},{141,231,0},{255,134,421},{255,196,421},{141,231,0},{0,216,421},{255,196,421},{0,216,421},{161,0,421},{161,0,421},{161,0,421},{161,0,421},{147,234,0},{147,234,0},{147,234,0},{147,190,0},{119,203,0}, +{119,203,0},{184,255,1818},{175,255,663},{175,243,639},{170,237,446},{175,255,2175},{155,255,443},{157,239,4},{151,221,655},{113,255,1557},{118,224,450},{196,255,722},{189,255,52},{188,241,35},{183,235,78},{255,122,1514},{155,255,442},{157,239,3},{101,225,421},{255,190,1514},{101,225,421},{175,255,542},{175,255,542},{175,255,542},{170,230,421},{162,255,424},{157,238,3},{157,238,3},{155,207,42},{116,237,338},{129,211,1},{186,254,5}, +{186,254,5},{186,254,5},{185,223,0},{255,79,338},{160,235,0},{160,235,0},{130,211,0},{253,170,338},{130,211,0},{255,161,421},{192,255,29},{196,240,0},{150,240,0},{255,161,421},{254,210,421},{150,240,0},{0,225,421},{254,210,421},{0,225,421},{170,0,421},{170,0,421},{170,0,421},{170,0,421},{156,243,0},{156,243,0},{156,243,0},{156,199,0},{128,212,0},{128,212,0},{193,255,2022},{184,255,858},{183,251,639}, +{178,245,446},{187,255,2343},{167,255,523},{165,247,4},{159,229,655},{131,255,1653},{126,232,450},{208,255,826},{198,255,150},{196,249,35},{191,243,78},{255,146,1514},{167,255,514},{165,247,3},{109,233,421},{255,202,1514},{109,233,421},{181,255,602},{181,255,602},{181,255,602},{178,238,421},{172,255,474},{165,246,3},{165,246,3},{163,215,42},{124,245,338},{137,219,1},{196,255,18},{196,255,18},{196,255,18},{193,231,0},{255,104,338}, +{168,243,0},{168,243,0},{138,219,0},{255,181,338},{138,219,0},{255,186,421},{207,255,80},{204,248,0},{158,248,0},{255,186,421},{255,221,421},{158,248,0},{0,233,421},{255,221,421},{0,233,421},{178,0,421},{178,0,421},{178,0,421},{178,0,421},{164,251,0},{164,251,0},{164,251,0},{164,207,0},{136,220,0},{136,220,0},{202,255,2175},{195,255,1070},{190,255,670},{186,253,441},{196,255,2443},{177,255,663},{172,255,2}, +{167,237,618},{146,255,1735},{135,240,423},{215,255,876},{207,255,277},{205,255,41},{199,251,69},{255,171,1459},{186,255,584},{174,254,2},{117,241,392},{254,214,1459},{117,241,392},{190,255,670},{190,255,670},{190,255,670},{186,246,421},{181,255,547},{173,253,2},{173,253,2},{171,223,42},{132,253,338},{145,227,1},{205,255,41},{205,255,41},{205,255,41},{201,239,0},{255,128,338},{176,251,0},{176,251,0},{146,227,0},{255,193,338}, +{146,227,0},{255,210,392},{222,255,136},{213,255,0},{167,255,0},{255,210,392},{255,233,392},{167,255,0},{0,241,392},{255,233,392},{0,241,392},{186,0,421},{186,0,421},{186,0,421},{186,0,421},{172,255,1},{172,255,1},{172,255,1},{172,214,0},{144,228,0},{144,228,0},{208,255,1867},{202,255,1047},{199,255,750},{194,255,421},{205,255,2052},{186,255,524},{183,255,22},{177,241,362},{161,255,1400},{145,244,215},{224,255,625}, +{216,255,229},{215,255,72},{207,253,17},{255,186,1064},{198,255,392},{186,255,4},{133,245,200},{255,221,1064},{133,245,200},{199,255,750},{199,255,750},{199,255,750},{194,254,421},{193,255,635},{183,255,22},{183,255,22},{179,231,42},{146,255,350},{153,235,1},{215,255,72},{215,255,72},{215,255,72},{209,247,0},{255,152,338},{186,255,4},{186,255,4},{154,235,0},{255,205,338},{154,235,0},{255,222,200},{231,255,65},{224,255,0}, +{192,255,0},{255,222,200},{255,239,200},{192,255,0},{0,245,200},{255,239,200},{0,245,200},{194,0,421},{194,0,421},{194,0,421},{194,0,421},{181,255,10},{181,255,10},{181,255,10},{180,222,0},{152,236,0},{152,236,0},{215,255,1586},{211,255,1053},{211,255,857},{204,255,446},{215,255,1698},{198,255,455},{195,255,109},{186,247,163},{177,255,1161},{158,249,63},{230,255,425},{226,255,209},{224,255,117},{218,255,1},{255,204,722}, +{210,255,254},{204,255,34},{152,249,61},{255,230,722},{152,249,61},{211,255,857},{211,255,857},{211,255,857},{204,255,446},{202,255,749},{195,255,109},{195,255,109},{188,240,42},{164,255,413},{162,244,1},{224,255,117},{224,255,117},{224,255,117},{218,254,1},{255,180,338},{204,255,34},{204,255,34},{163,244,0},{255,218,338},{163,244,0},{255,234,61},{240,255,17},{238,255,0},{219,255,0},{255,234,61},{255,245,61},{219,255,0}, +{0,249,61},{255,245,61},{0,249,61},{203,0,421},{203,0,421},{203,0,421},{203,0,421},{193,255,32},{193,255,32},{193,255,32},{189,231,0},{161,245,0},{161,245,0},{224,255,1422},{221,255,1083},{218,255,946},{213,255,525},{221,255,1470},{207,255,478},{204,255,243},{196,251,67},{189,255,1025},{169,253,5},{239,255,318},{235,255,217},{233,255,170},{228,255,29},{255,219,509},{222,255,198},{219,255,89},{169,253,5},{254,238,509}, +{169,253,5},{218,255,946},{218,255,946},{218,255,946},{213,255,525},{215,255,862},{204,255,243},{204,255,243},{196,248,42},{180,255,530},{169,252,1},{233,255,170},{233,255,170},{233,255,170},{228,255,29},{255,204,338},{219,255,89},{219,255,89},{171,252,0},{255,230,338},{171,252,0},{255,246,5},{251,254,1},{250,255,0},{243,255,0},{255,246,5},{255,251,5},{243,255,0},{0,253,5},{255,251,5},{0,253,5},{211,0,421}, +{211,0,421},{211,0,421},{211,0,421},{202,255,61},{202,255,61},{202,255,61},{197,239,0},{169,253,0},{169,253,0},{230,255,1153},{227,255,938},{227,255,857},{222,255,533},{227,255,1141},{216,255,434},{213,255,282},{204,253,18},{201,255,790},{183,255,8},{242,255,192},{242,255,144},{239,255,125},{237,255,34},{255,231,294},{234,255,121},{228,255,73},{189,255,0},{254,244,294},{189,255,0},{227,255,857},{227,255,857},{227,255,857}, +{222,255,533},{221,255,741},{213,255,282},{213,255,282},{204,253,14},{192,255,465},{183,255,8},{239,255,125},{239,255,125},{239,255,125},{237,255,34},{255,219,221},{228,255,73},{228,255,73},{189,255,0},{254,238,221},{189,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{219,0,421},{219,0,421},{219,0,421},{219,0,421},{211,255,100}, +{211,255,100},{211,255,100},{205,247,0},{183,255,8},{183,255,8},{236,255,853},{233,255,726},{233,255,677},{228,255,485},{233,255,793},{225,255,355},{222,255,262},{213,255,0},{213,255,534},{195,255,40},{248,255,68},{245,255,54},{245,255,45},{243,255,10},{255,240,113},{240,255,41},{240,255,25},{213,255,0},{255,248,113},{213,255,0},{233,255,677},{233,255,677},{233,255,677},{228,255,485},{227,255,545},{222,255,262},{222,255,262}, +{213,255,0},{204,255,329},{195,255,40},{245,255,45},{245,255,45},{245,255,45},{243,255,10},{255,231,85},{240,255,25},{240,255,25},{213,255,0},{254,244,85},{213,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{227,0,421},{227,0,421},{227,0,421},{227,0,421},{221,255,145},{221,255,145},{221,255,145},{213,255,0},{195,255,40}, +{195,255,40},{0,119,882},{0,84,97},{0,60,1},{0,50,325},{0,79,1896},{0,51,1188},{0,47,563},{0,31,1410},{0,36,2029},{0,31,1510},{0,119,882},{0,84,97},{0,60,1},{0,50,325},{39,0,1896},{0,51,1188},{0,47,563},{0,31,1410},{79,0,1896},{0,31,1410},{0,55,0},{0,55,0},{0,55,0},{0,27,0},{0,28,162},{0,21,52},{0,21,52},{0,13,89},{0,12,173},{0,13,105},{0,55,0}, +{0,55,0},{0,55,0},{0,27,0},{14,0,162},{0,21,52},{0,21,52},{0,13,89},{28,0,162},{0,13,89},{58,0,882},{0,84,97},{0,60,1},{0,50,325},{58,0,882},{119,0,882},{0,50,325},{0,39,882},{119,0,882},{0,39,882},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,143,882},{0,97,34},{1,68,11}, +{0,59,250},{0,95,2355},{0,63,1332},{0,54,585},{0,40,1656},{0,45,2556},{0,37,1802},{0,143,882},{0,97,34},{2,69,9},{0,59,250},{46,0,2355},{0,63,1332},{0,54,585},{0,40,1656},{95,0,2355},{0,40,1656},{0,79,0},{0,79,0},{0,79,0},{0,39,0},{0,40,338},{0,33,116},{0,33,116},{0,19,193},{0,18,365},{0,16,225},{0,79,0},{0,79,0},{0,79,0},{0,39,0},{20,0,338}, +{0,33,116},{0,33,116},{0,19,193},{40,0,338},{0,19,193},{70,0,882},{0,97,34},{6,68,0},{0,59,250},{70,0,882},{143,0,882},{0,59,250},{0,47,882},{143,0,882},{0,47,882},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,167,882},{0,112,5},{2,78,61},{0,68,185},{0,113,2899},{0,75,1508},{0,63,633}, +{0,44,1965},{0,51,3176},{0,44,2161},{0,167,882},{0,112,5},{4,77,53},{0,68,185},{55,0,2899},{0,75,1508},{0,63,633},{0,44,1965},{113,0,2899},{0,44,1965},{0,104,0},{0,104,0},{0,104,0},{0,51,0},{0,52,578},{0,42,205},{0,42,205},{0,25,337},{0,24,629},{0,22,389},{0,104,0},{0,104,0},{0,104,0},{0,51,0},{26,0,578},{0,42,205},{0,42,205},{0,25,337},{52,0,578}, +{0,25,337},{82,0,882},{0,112,5},{14,76,0},{0,68,185},{82,0,882},{167,0,882},{0,68,185},{0,55,882},{167,0,882},{0,55,882},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,186,900},{3,124,18},{6,88,133},{1,78,162},{0,134,3048},{0,88,1398},{0,72,469},{0,53,1923},{0,60,3457},{0,50,2205},{6,179,882}, +{6,121,2},{10,86,69},{3,77,158},{66,0,3048},{0,88,1398},{0,72,469},{0,53,1923},{134,0,3048},{0,53,1923},{3,122,18},{3,122,18},{3,122,18},{3,61,18},{0,73,648},{0,54,157},{0,54,157},{0,31,317},{0,33,756},{0,31,417},{6,116,0},{6,116,0},{6,116,0},{6,60,0},{36,0,648},{0,54,157},{0,54,157},{0,31,317},{73,0,648},{0,31,317},{94,0,882},{2,124,0},{22,84,0}, +{0,77,130},{94,0,882},{192,0,882},{0,77,130},{0,63,882},{192,0,882},{0,63,882},{3,0,18},{3,0,18},{3,0,18},{3,0,18},{0,19,0},{0,19,0},{0,19,0},{0,9,0},{0,9,4},{0,9,4},{8,203,995},{8,136,115},{11,96,290},{6,86,230},{0,161,3048},{0,100,1221},{0,84,250},{0,62,1758},{0,75,3651},{0,60,2156},{15,188,882},{15,130,2},{19,95,69},{12,86,158},{79,0,3048}, +{0,100,1221},{0,84,250},{0,62,1758},{161,0,3048},{0,62,1758},{8,139,113},{8,139,113},{8,139,113},{8,72,113},{0,101,648},{0,72,73},{0,72,73},{0,40,242},{0,45,862},{0,39,409},{15,125,0},{15,125,0},{15,125,0},{15,69,0},{49,0,648},{0,72,73},{0,72,73},{0,40,242},{101,0,648},{0,40,242},{107,0,882},{11,133,0},{31,93,0},{0,87,85},{107,0,882},{219,0,882},{0,87,85}, +{0,72,882},{219,0,882},{0,72,882},{7,0,113},{7,0,113},{7,0,113},{7,0,113},{0,46,0},{0,46,0},{0,46,0},{0,23,0},{0,18,34},{0,18,34},{12,219,1147},{12,146,275},{16,104,510},{11,95,365},{0,186,3048},{0,115,1096},{0,94,114},{0,71,1620},{0,88,3844},{0,69,2137},{23,196,882},{23,138,2},{27,103,69},{20,94,158},{91,0,3048},{0,115,1096},{0,94,114},{0,71,1620},{186,0,3048}, +{0,71,1620},{12,155,265},{12,155,265},{12,155,265},{12,82,265},{0,125,648},{0,84,25},{0,84,25},{0,53,180},{0,54,987},{0,48,427},{23,133,0},{23,133,0},{23,133,0},{23,77,0},{61,0,648},{0,84,25},{0,84,25},{0,53,180},{125,0,648},{0,53,180},{119,0,882},{20,140,0},{39,101,0},{0,96,50},{119,0,882},{243,0,882},{0,96,50},{0,80,882},{243,0,882},{0,80,882},{11,0,265}, +{11,0,265},{11,0,265},{11,0,265},{0,70,0},{0,70,0},{0,70,0},{0,35,0},{0,27,89},{0,27,89},{16,235,1363},{17,157,505},{20,114,802},{14,104,559},{0,210,3048},{0,127,1000},{0,105,34},{0,80,1494},{0,94,4056},{0,78,2148},{31,204,882},{31,145,2},{35,111,69},{27,102,165},{103,0,3048},{0,127,1000},{0,105,34},{0,80,1494},{210,0,3048},{0,80,1494},{16,171,481},{16,171,481},{16,171,481}, +{16,92,481},{0,149,648},{0,100,1},{0,100,1},{0,62,125},{0,66,1139},{0,57,473},{31,140,0},{31,140,0},{31,140,0},{31,85,0},{73,0,648},{0,100,1},{0,100,1},{0,62,125},{149,0,648},{0,62,125},{131,0,882},{28,148,0},{47,109,0},{0,105,25},{131,0,882},{255,6,882},{0,105,25},{0,88,882},{255,6,882},{0,88,882},{15,0,481},{15,0,481},{15,0,481},{15,0,481},{0,95,0}, +{0,95,0},{0,95,0},{0,46,0},{0,39,169},{0,39,169},{20,251,1643},{21,167,805},{25,122,1170},{19,112,822},{0,234,3048},{0,141,933},{1,115,10},{0,90,1395},{0,106,4312},{0,84,2188},{39,212,882},{39,153,2},{43,119,69},{35,110,165},{115,0,3048},{0,141,933},{1,115,9},{0,90,1395},{234,0,3048},{0,90,1395},{20,187,761},{20,187,761},{20,187,761},{19,102,761},{0,174,648},{1,111,5},{1,111,5}, +{0,71,80},{0,75,1322},{0,66,547},{39,148,0},{39,148,0},{39,148,0},{39,93,0},{85,0,648},{5,109,0},{5,109,0},{0,71,80},{174,0,648},{0,71,80},{143,0,882},{36,156,0},{55,117,0},{0,115,8},{143,0,882},{255,18,882},{0,115,8},{0,96,882},{255,18,882},{0,96,882},{19,0,761},{19,0,761},{19,0,761},{19,0,761},{0,119,0},{0,119,0},{0,119,0},{0,58,0},{0,48,274}, +{0,48,274},{29,254,1780},{29,178,935},{33,133,1327},{26,122,936},{6,249,3048},{3,153,909},{8,125,13},{0,99,1314},{0,121,4212},{0,97,1924},{48,221,882},{48,162,2},{52,128,69},{44,119,165},{128,0,3048},{0,156,891},{10,124,9},{0,99,1278},{255,3,3048},{0,99,1278},{27,200,882},{27,200,882},{27,200,882},{27,112,882},{6,189,648},{7,123,11},{7,123,11},{3,80,61},{0,91,1227},{0,75,409},{48,157,0}, +{48,157,0},{48,157,0},{48,102,0},{98,0,648},{14,118,0},{14,118,0},{0,80,41},{201,0,648},{0,80,41},{156,0,882},{45,165,0},{63,126,0},{0,126,0},{156,0,882},{254,32,882},{0,126,0},{0,105,882},{254,32,882},{0,105,882},{27,0,882},{27,0,882},{27,0,882},{27,0,882},{6,134,0},{6,134,0},{6,134,0},{6,69,0},{0,63,232},{0,63,232},{38,254,1814},{37,186,935},{41,141,1327}, +{34,130,936},{15,255,3049},{11,161,909},{16,133,13},{8,107,1314},{0,132,3964},{0,106,1605},{56,229,882},{56,170,2},{60,136,69},{52,127,165},{140,0,3048},{2,167,882},{18,132,9},{0,108,1188},{255,15,3048},{0,108,1188},{35,208,882},{35,208,882},{35,208,882},{35,120,882},{14,196,648},{15,131,11},{15,131,11},{11,88,61},{0,103,1059},{0,88,221},{56,165,0},{56,165,0},{56,165,0},{56,110,0},{110,0,648}, +{22,126,0},{22,126,0},{0,90,20},{225,0,648},{0,90,20},{168,0,882},{53,173,0},{71,134,0},{5,134,0},{168,0,882},{255,43,882},{5,134,0},{0,113,882},{255,43,882},{0,113,882},{35,0,882},{35,0,882},{35,0,882},{35,0,882},{14,142,0},{14,142,0},{14,142,0},{14,77,0},{0,75,136},{0,75,136},{46,255,1854},{45,194,935},{49,149,1327},{42,138,936},{24,255,3064},{19,169,909},{22,141,14}, +{16,115,1314},{0,144,3748},{0,115,1348},{64,237,882},{64,178,2},{68,144,69},{60,135,165},{152,0,3048},{10,175,882},{26,140,9},{0,117,1110},{255,27,3048},{0,117,1110},{43,216,882},{43,216,882},{43,216,882},{43,128,882},{22,204,648},{23,139,11},{23,139,11},{21,95,62},{0,118,922},{0,97,91},{64,173,0},{64,173,0},{64,173,0},{64,117,0},{122,0,648},{30,134,0},{30,134,0},{0,99,5},{249,0,648}, +{0,99,5},{180,0,882},{61,181,0},{79,142,0},{13,142,0},{180,0,882},{255,55,882},{13,142,0},{0,121,882},{255,55,882},{0,121,882},{43,0,882},{43,0,882},{43,0,882},{43,0,882},{22,150,0},{22,150,0},{22,150,0},{22,85,0},{0,91,58},{0,91,58},{55,255,1924},{53,202,935},{57,157,1327},{50,146,936},{36,255,3096},{27,177,909},{30,149,14},{24,123,1314},{0,159,3559},{0,124,1153},{72,245,882}, +{72,186,2},{77,152,65},{68,143,165},{164,0,3048},{19,182,882},{33,148,9},{0,126,1044},{255,39,3048},{0,126,1044},{51,224,882},{51,224,882},{51,224,882},{51,136,882},{30,212,648},{32,147,9},{32,147,9},{28,103,65},{0,129,810},{0,106,21},{72,181,0},{72,181,0},{72,181,0},{72,125,0},{134,0,648},{38,142,0},{38,142,0},{0,108,0},{255,9,648},{0,108,0},{192,0,882},{69,189,0},{87,150,0}, +{21,150,0},{192,0,882},{255,67,882},{21,150,0},{0,129,882},{255,67,882},{0,129,882},{51,0,882},{51,0,882},{51,0,882},{51,0,882},{30,158,0},{30,158,0},{30,158,0},{30,93,0},{0,106,17},{0,106,17},{67,255,2024},{62,211,935},{66,166,1327},{59,155,936},{46,255,3145},{36,186,909},{40,158,10},{33,132,1314},{0,172,3364},{0,133,1012},{81,254,882},{81,195,2},{86,161,65},{77,152,165},{177,0,3048}, +{28,191,882},{42,157,9},{0,136,990},{255,52,3048},{0,136,990},{60,233,882},{60,233,882},{60,233,882},{60,145,882},{39,221,648},{41,156,9},{41,156,9},{37,112,65},{0,144,720},{2,118,3},{81,190,0},{81,190,0},{81,190,0},{81,134,0},{147,0,648},{47,151,0},{47,151,0},{7,117,0},{254,23,648},{7,117,0},{205,0,882},{78,198,0},{96,159,0},{30,159,0},{205,0,882},{254,81,882},{30,159,0}, +{0,138,882},{254,81,882},{0,138,882},{60,0,882},{60,0,882},{60,0,882},{60,0,882},{39,167,0},{39,167,0},{39,167,0},{39,102,0},{0,121,0},{0,121,0},{76,255,2134},{70,218,935},{74,174,1327},{66,163,942},{58,255,3217},{45,193,904},{48,166,10},{41,140,1314},{0,184,3244},{0,145,948},{91,254,888},{89,203,2},{94,169,65},{85,160,165},{189,0,3048},{36,199,882},{50,165,9},{0,145,948},{255,64,3048}, +{0,145,948},{68,241,882},{68,241,882},{68,241,882},{68,153,882},{47,229,648},{49,164,9},{49,164,9},{45,120,65},{0,156,672},{10,126,3},{89,198,0},{89,198,0},{89,198,0},{89,142,0},{159,0,648},{56,158,0},{56,158,0},{15,125,0},{254,35,648},{15,125,0},{217,0,882},{86,206,0},{104,167,0},{38,167,0},{217,0,882},{255,92,882},{38,167,0},{0,146,882},{255,92,882},{0,146,882},{68,0,882}, +{68,0,882},{68,0,882},{68,0,882},{47,174,0},{47,174,0},{47,174,0},{47,109,0},{7,129,0},{7,129,0},{86,255,2252},{78,226,935},{82,182,1327},{74,171,942},{67,255,3300},{53,201,904},{56,174,10},{49,148,1314},{0,199,3151},{3,152,935},{101,255,906},{97,211,2},{102,177,65},{93,168,165},{201,0,3048},{44,207,882},{58,173,9},{0,152,915},{255,76,3048},{0,152,915},{76,249,882},{76,249,882},{76,249,882}, +{76,161,882},{55,237,648},{57,172,9},{57,172,9},{53,128,65},{0,171,649},{18,134,3},{97,206,0},{97,206,0},{97,206,0},{97,150,0},{171,0,648},{64,166,0},{64,166,0},{23,133,0},{255,46,648},{23,133,0},{229,0,882},{94,214,0},{112,175,0},{46,175,0},{229,0,882},{255,104,882},{46,175,0},{0,154,882},{255,104,882},{0,154,882},{76,0,882},{76,0,882},{76,0,882},{76,0,882},{55,182,0}, +{55,182,0},{55,182,0},{55,117,0},{16,136,0},{16,136,0},{95,255,2398},{86,234,935},{90,190,1327},{82,179,942},{76,255,3409},{61,209,904},{64,182,10},{56,155,1318},{0,211,3087},{11,160,935},{110,255,939},{105,219,2},{110,185,65},{101,176,165},{213,0,3048},{52,215,882},{66,181,9},{0,161,893},{254,88,3048},{0,161,893},{84,254,883},{84,254,883},{84,254,883},{84,169,882},{63,245,648},{65,180,9},{65,180,9}, +{61,136,65},{7,179,648},{27,141,2},{105,214,0},{105,214,0},{105,214,0},{105,158,0},{183,0,648},{72,174,0},{72,174,0},{31,141,0},{255,58,648},{31,141,0},{241,0,882},{101,222,0},{120,183,0},{54,183,0},{241,0,882},{255,116,882},{54,183,0},{0,162,882},{255,116,882},{0,162,882},{84,0,882},{84,0,882},{84,0,882},{84,0,882},{63,190,0},{63,190,0},{63,190,0},{63,125,0},{24,144,0}, +{24,144,0},{104,255,2584},{95,243,935},{100,199,1318},{91,188,942},{89,255,3529},{69,219,909},{73,191,10},{65,165,1327},{0,224,3052},{20,169,935},{122,255,996},{114,228,2},{119,194,65},{111,183,171},{226,0,3048},{61,224,882},{75,190,9},{0,171,883},{255,101,3048},{0,171,883},{94,254,893},{94,254,893},{94,254,893},{93,177,882},{72,254,648},{74,189,9},{74,189,9},{70,145,65},{16,188,648},{36,150,2},{114,222,0}, +{114,222,0},{114,222,0},{114,167,0},{196,0,648},{81,183,0},{81,183,0},{39,150,0},{254,72,648},{39,150,0},{254,0,882},{110,231,0},{129,192,0},{63,192,0},{254,0,882},{255,129,882},{63,192,0},{0,171,882},{255,129,882},{0,171,882},{93,0,882},{93,0,882},{93,0,882},{93,0,882},{72,199,0},{72,199,0},{72,199,0},{72,134,0},{33,153,0},{33,153,0},{113,255,2774},{103,251,935},{107,206,1314}, +{99,196,942},{98,255,3672},{77,227,909},{81,199,10},{73,173,1327},{5,235,3048},{28,177,935},{132,255,1054},{121,236,3},{127,202,65},{119,192,173},{238,0,3048},{69,232,882},{83,198,9},{4,179,882},{255,113,3048},{4,179,882},{103,254,915},{103,254,915},{103,254,915},{101,185,882},{82,255,654},{82,197,9},{82,197,9},{78,153,65},{24,196,648},{44,158,2},{122,230,0},{122,230,0},{122,230,0},{122,175,0},{208,0,648}, +{89,191,0},{89,191,0},{47,158,0},{254,84,648},{47,158,0},{255,22,882},{118,239,0},{137,200,0},{71,200,0},{255,22,882},{255,141,882},{71,200,0},{0,179,882},{255,141,882},{0,179,882},{101,0,882},{101,0,882},{101,0,882},{101,0,882},{80,207,0},{80,207,0},{80,207,0},{80,142,0},{41,161,0},{41,161,0},{122,255,2984},{110,255,948},{115,214,1314},{107,204,942},{110,255,3832},{85,235,909},{89,207,10}, +{81,181,1327},{13,243,3048},{36,185,935},{141,255,1131},{129,244,3},{135,210,65},{127,200,173},{250,0,3048},{77,240,882},{91,206,9},{12,187,882},{255,125,3048},{12,187,882},{110,255,948},{110,255,948},{110,255,948},{109,193,882},{92,255,672},{90,205,9},{90,205,9},{86,161,65},{32,204,648},{52,166,2},{130,238,0},{130,238,0},{130,238,0},{130,183,0},{220,0,648},{97,199,0},{97,199,0},{55,166,0},{255,95,648}, +{55,166,0},{255,46,882},{126,247,0},{145,208,0},{79,208,0},{255,46,882},{255,153,882},{79,208,0},{0,187,882},{255,153,882},{0,187,882},{109,0,882},{109,0,882},{109,0,882},{109,0,882},{88,215,0},{88,215,0},{88,215,0},{88,150,0},{49,169,0},{49,169,0},{132,255,3182},{122,255,1012},{123,222,1314},{115,212,942},{119,255,4009},{93,243,909},{97,215,10},{89,189,1327},{21,251,3048},{44,193,935},{150,255,1226}, +{137,252,3},{143,218,65},{135,208,173},{255,13,3048},{83,249,882},{99,214,9},{20,195,882},{254,137,3048},{20,195,882},{119,255,990},{119,255,990},{119,255,990},{117,201,882},{101,255,705},{98,213,9},{98,213,9},{94,169,65},{40,212,648},{60,174,2},{138,246,0},{138,246,0},{138,246,0},{138,191,0},{232,0,648},{104,208,0},{104,208,0},{63,174,0},{255,107,648},{63,174,0},{255,70,882},{134,255,0},{153,216,0}, +{86,216,0},{255,70,882},{255,165,882},{86,216,0},{0,195,882},{255,165,882},{0,195,882},{117,0,882},{117,0,882},{117,0,882},{117,0,882},{96,223,0},{96,223,0},{96,223,0},{96,158,0},{57,177,0},{57,177,0},{141,255,3464},{131,255,1153},{132,231,1314},{124,221,942},{132,255,4209},{102,252,909},{105,224,14},{98,198,1327},{37,255,3060},{53,202,935},{162,255,1349},{149,255,21},{152,227,65},{144,217,173},{255,40,3048}, +{95,255,885},{108,223,9},{29,204,882},{255,150,3048},{29,204,882},{129,255,1044},{129,255,1044},{129,255,1044},{126,210,882},{113,255,762},{107,222,9},{107,222,9},{103,178,65},{49,221,648},{69,183,2},{147,255,0},{147,255,0},{147,255,0},{147,200,0},{245,0,648},{112,217,0},{112,217,0},{72,183,0},{254,121,648},{72,183,0},{255,98,882},{149,255,17},{162,225,0},{95,225,0},{255,98,882},{255,178,882},{95,225,0}, +{0,204,882},{255,178,882},{0,204,882},{126,0,882},{126,0,882},{126,0,882},{126,0,882},{105,232,0},{105,232,0},{105,232,0},{105,167,0},{66,186,0},{66,186,0},{150,255,3734},{140,255,1348},{140,239,1314},{132,229,942},{141,255,4420},{113,255,925},{113,232,14},{106,206,1327},{52,255,3132},{61,210,935},{172,255,1459},{158,255,91},{160,234,62},{152,225,173},{255,64,3048},{110,255,923},{116,232,11},{37,212,882},{255,162,3048}, +{37,212,882},{138,255,1110},{138,255,1110},{138,255,1110},{134,218,882},{122,255,827},{115,229,9},{115,229,9},{111,187,69},{57,229,648},{77,191,2},{156,255,5},{156,255,5},{156,255,5},{155,208,0},{255,4,648},{120,225,0},{120,225,0},{80,191,0},{255,132,648},{80,191,0},{255,122,882},{164,255,58},{170,233,0},{103,233,0},{255,122,882},{255,190,882},{103,233,0},{0,212,882},{255,190,882},{0,212,882},{134,0,882}, +{134,0,882},{134,0,882},{134,0,882},{113,240,0},{113,240,0},{113,240,0},{113,175,0},{74,194,0},{74,194,0},{162,255,4022},{149,255,1605},{148,247,1314},{140,237,942},{150,255,4657},{122,255,1020},{122,239,13},{114,214,1327},{70,255,3256},{69,218,935},{181,255,1598},{167,255,221},{167,244,61},{160,233,173},{255,89,3048},{128,255,1003},{123,240,11},{45,220,882},{254,174,3048},{45,220,882},{147,255,1188},{147,255,1188},{147,255,1188}, +{142,226,882},{132,255,897},{123,237,9},{123,237,9},{119,195,69},{65,237,648},{85,199,2},{165,255,20},{165,255,20},{165,255,20},{163,216,0},{255,28,648},{128,233,0},{128,233,0},{88,199,0},{255,144,648},{88,199,0},{255,146,882},{180,255,136},{178,241,0},{111,241,0},{255,146,882},{255,202,882},{111,241,0},{0,220,882},{255,202,882},{0,220,882},{142,0,882},{142,0,882},{142,0,882},{142,0,882},{121,248,0}, +{121,248,0},{121,248,0},{121,183,0},{82,202,0},{82,202,0},{172,255,4300},{158,255,1924},{156,255,1314},{150,244,943},{162,255,4905},{134,255,1204},{130,247,13},{122,222,1327},{82,255,3448},{77,226,935},{190,255,1755},{180,255,409},{175,252,61},{168,241,173},{255,113,3048},{143,255,1125},{131,248,11},{53,228,882},{254,186,3048},{53,228,882},{156,255,1278},{156,255,1278},{156,255,1278},{150,234,882},{141,255,992},{131,245,9},{131,245,9}, +{127,203,69},{73,245,648},{93,207,2},{175,255,41},{175,255,41},{175,255,41},{171,224,0},{255,52,648},{137,240,0},{137,240,0},{96,207,0},{255,156,648},{96,207,0},{255,171,882},{192,255,232},{186,249,0},{119,249,0},{255,171,882},{254,214,882},{119,249,0},{0,228,882},{254,214,882},{0,228,882},{150,0,882},{150,0,882},{150,0,882},{150,0,882},{129,255,0},{129,255,0},{129,255,0},{129,191,0},{90,210,0}, +{90,210,0},{178,255,4349},{171,255,2188},{165,255,1395},{159,251,923},{172,255,4837},{146,255,1309},{140,254,10},{132,229,1170},{104,255,3433},{88,234,805},{202,255,1725},{189,255,547},{184,255,80},{176,249,133},{255,137,2814},{158,255,1125},{143,254,5},{66,235,761},{254,198,2814},{66,235,761},{165,255,1395},{165,255,1395},{165,255,1395},{159,243,882},{153,255,1115},{140,254,9},{140,254,9},{136,212,69},{81,254,648},{102,216,2},{184,255,80}, +{184,255,80},{184,255,80},{180,233,0},{255,79,648},{146,249,0},{146,249,0},{105,216,0},{253,170,648},{105,216,0},{255,192,761},{207,255,274},{196,255,0},{134,255,0},{255,192,761},{255,224,761},{134,255,0},{0,235,761},{255,224,761},{0,235,761},{159,0,882},{159,0,882},{159,0,882},{159,0,882},{140,254,8},{140,254,8},{140,254,8},{138,200,0},{99,219,0},{99,219,0},{187,255,3903},{177,255,2148},{175,255,1494}, +{167,253,887},{181,255,4274},{155,255,1106},{149,255,34},{140,234,802},{119,255,2958},{98,238,505},{208,255,1361},{198,255,473},{193,255,125},{187,251,53},{255,152,2249},{167,255,857},{155,255,1},{82,239,481},{255,205,2249},{82,239,481},{175,255,1494},{175,255,1494},{175,255,1494},{167,251,882},{162,255,1242},{149,255,34},{149,255,34},{144,220,69},{95,255,670},{110,224,2},{193,255,125},{193,255,125},{193,255,125},{188,241,0},{255,104,648}, +{155,255,1},{155,255,1},{113,224,0},{255,181,648},{113,224,0},{255,204,481},{216,255,169},{208,255,0},{158,255,0},{255,204,481},{255,230,481},{158,255,0},{0,239,481},{255,230,481},{0,239,481},{167,0,882},{167,0,882},{167,0,882},{167,0,882},{149,254,25},{149,254,25},{149,254,25},{146,208,0},{106,227,0},{106,227,0},{193,255,3535},{186,255,2137},{184,255,1620},{175,255,891},{187,255,3794},{167,255,978},{159,255,114}, +{150,238,510},{131,255,2574},{109,243,275},{215,255,1046},{207,255,427},{202,255,180},{195,253,9},{255,171,1769},{183,255,650},{167,255,25},{98,243,265},{254,214,1769},{98,243,265},{184,255,1620},{184,255,1620},{184,255,1620},{175,255,891},{172,255,1364},{159,255,114},{159,255,114},{152,228,69},{113,255,734},{117,232,2},{202,255,180},{202,255,180},{202,255,180},{196,249,0},{255,128,648},{167,255,25},{167,255,25},{120,232,0},{255,193,648}, +{120,232,0},{255,216,265},{228,255,89},{220,255,0},{183,255,0},{255,216,265},{255,236,265},{183,255,0},{0,243,265},{255,236,265},{0,243,265},{175,0,882},{175,0,882},{175,0,882},{175,0,882},{159,255,50},{159,255,50},{159,255,50},{154,216,0},{114,235,0},{114,235,0},{202,255,3229},{195,255,2156},{193,255,1758},{183,255,946},{196,255,3397},{174,255,950},{171,255,250},{158,243,290},{146,255,2281},{119,247,115},{221,255,822}, +{216,255,409},{215,255,242},{204,255,1},{255,186,1374},{195,255,498},{183,255,73},{114,247,113},{255,221,1374},{114,247,113},{193,255,1758},{193,255,1758},{193,255,1758},{183,255,946},{181,255,1521},{171,255,250},{171,255,250},{160,236,69},{128,255,840},{125,240,2},{215,255,242},{215,255,242},{215,255,242},{204,255,1},{255,152,648},{183,255,73},{183,255,73},{128,240,0},{255,205,648},{128,240,0},{255,228,113},{237,255,34},{232,255,0}, +{207,255,0},{255,228,113},{255,242,113},{207,255,0},{0,247,113},{255,242,113},{0,247,113},{183,0,882},{183,0,882},{183,0,882},{183,0,882},{168,255,85},{168,255,85},{168,255,85},{162,224,0},{122,243,0},{122,243,0},{211,255,2974},{205,255,2205},{202,255,1923},{195,255,1069},{205,255,3055},{186,255,981},{180,255,469},{167,249,133},{161,255,2061},{131,252,18},{230,255,645},{224,255,417},{224,255,317},{216,255,45},{255,204,1032}, +{210,255,404},{201,255,157},{131,252,18},{255,230,1032},{131,252,18},{202,255,1923},{202,255,1923},{202,255,1923},{195,255,1069},{193,255,1710},{180,255,469},{180,255,469},{169,245,69},{146,255,1011},{134,249,2},{224,255,317},{224,255,317},{224,255,317},{216,255,45},{255,180,648},{201,255,157},{201,255,157},{137,249,0},{255,218,648},{137,249,0},{255,243,18},{246,255,4},{245,255,0},{234,255,0},{255,243,18},{254,250,18},{234,255,0}, +{0,252,18},{254,250,18},{0,252,18},{192,0,882},{192,0,882},{192,0,882},{192,0,882},{178,255,130},{178,255,130},{178,255,130},{171,233,0},{131,252,0},{131,252,0},{218,255,2682},{211,255,2161},{211,255,1965},{204,255,1170},{215,255,2712},{195,255,1014},{192,255,633},{177,253,61},{167,255,1893},{143,255,5},{236,255,513},{233,255,389},{230,255,337},{225,255,97},{255,219,771},{219,255,342},{213,255,205},{149,255,0},{254,238,771}, +{149,255,0},{211,255,1965},{211,255,1965},{211,255,1965},{204,255,1170},{202,255,1755},{192,255,633},{192,255,633},{178,251,53},{161,255,1085},{143,255,5},{230,255,337},{230,255,337},{230,255,337},{225,255,97},{255,201,578},{213,255,205},{213,255,205},{149,255,0},{254,229,578},{149,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{200,0,882}, +{200,0,882},{200,0,882},{200,0,882},{187,255,185},{187,255,185},{187,255,185},{179,241,0},{143,255,5},{143,255,5},{221,255,2188},{218,255,1802},{215,255,1656},{210,255,1086},{218,255,2117},{204,255,865},{201,255,585},{187,254,11},{183,255,1467},{158,255,34},{242,255,297},{239,255,225},{236,255,193},{231,255,53},{255,225,451},{228,255,192},{222,255,116},{174,255,0},{254,241,451},{174,255,0},{215,255,1656},{215,255,1656},{215,255,1656}, +{210,255,1086},{211,255,1426},{201,255,585},{201,255,585},{186,253,9},{167,255,869},{158,255,34},{236,255,193},{236,255,193},{236,255,193},{231,255,53},{255,213,338},{222,255,116},{222,255,116},{174,255,0},{254,235,338},{174,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{208,0,882},{208,0,882},{208,0,882},{208,0,882},{196,255,250}, +{196,255,250},{196,255,250},{187,249,0},{158,255,34},{158,255,34},{227,255,1772},{224,255,1510},{224,255,1410},{219,255,1021},{224,255,1645},{210,255,761},{208,255,563},{195,255,1},{195,255,1123},{171,255,97},{245,255,136},{242,255,105},{242,255,89},{237,255,25},{255,234,216},{237,255,86},{234,255,52},{198,255,0},{255,245,216},{198,255,0},{224,255,1410},{224,255,1410},{224,255,1410},{219,255,1021},{215,255,1140},{208,255,563},{208,255,563}, +{195,255,1},{186,255,696},{171,255,97},{242,255,89},{242,255,89},{242,255,89},{237,255,25},{255,225,162},{234,255,52},{234,255,52},{198,255,0},{254,241,162},{198,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{216,0,882},{216,0,882},{216,0,882},{216,0,882},{205,255,325},{205,255,325},{205,255,325},{195,255,1},{171,255,97}, +{171,255,97},{0,158,1568},{0,112,169},{0,80,4},{0,68,585},{0,107,3371},{0,69,2124},{0,62,1013},{0,40,2532},{0,48,3617},{0,40,2701},{0,158,1568},{0,112,169},{0,80,4},{0,68,585},{52,0,3371},{0,69,2124},{0,62,1013},{0,40,2532},{107,0,3371},{0,40,2532},{0,73,0},{0,73,0},{0,73,0},{0,36,0},{0,37,288},{0,30,97},{0,30,97},{0,16,164},{0,15,312},{0,16,189},{0,73,0}, +{0,73,0},{0,73,0},{0,36,0},{18,0,288},{0,30,97},{0,30,97},{0,16,164},{37,0,288},{0,16,164},{78,0,1568},{0,112,169},{0,80,4},{0,68,585},{78,0,1568},{158,0,1568},{0,68,585},{0,52,1568},{158,0,1568},{0,52,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,183,1568},{0,124,89},{0,89,10}, +{0,77,482},{0,122,3968},{0,81,2316},{0,69,1041},{0,50,2857},{0,57,4304},{0,47,3092},{0,183,1568},{0,124,89},{2,88,8},{0,77,482},{60,0,3968},{0,81,2316},{0,69,1041},{0,50,2857},{122,0,3968},{0,50,2857},{0,98,0},{0,98,0},{0,98,0},{0,48,0},{0,49,512},{0,39,180},{0,39,180},{0,22,296},{0,21,556},{0,22,345},{0,98,0},{0,98,0},{0,98,0},{0,48,0},{24,0,512}, +{0,39,180},{0,39,180},{0,22,296},{49,0,512},{0,22,296},{89,0,1568},{0,124,89},{5,88,0},{0,77,482},{89,0,1568},{183,0,1568},{0,77,482},{0,60,1568},{183,0,1568},{0,60,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,207,1568},{0,138,34},{2,97,58},{0,83,394},{0,137,4651},{0,91,2507},{0,78,1093}, +{0,56,3225},{0,63,5084},{0,53,3532},{0,207,1568},{0,138,34},{3,98,49},{0,83,394},{67,0,4651},{0,91,2507},{0,78,1093},{0,56,3225},{137,0,4651},{0,56,3225},{0,122,0},{0,122,0},{0,122,0},{0,60,0},{0,61,800},{0,48,289},{0,48,289},{0,28,468},{0,27,872},{0,25,545},{0,122,0},{0,122,0},{0,122,0},{0,60,0},{30,0,800},{0,48,289},{0,48,289},{0,28,468},{61,0,800}, +{0,28,468},{101,0,1568},{0,138,34},{13,96,0},{0,83,394},{101,0,1568},{207,0,1568},{0,83,394},{0,68,1568},{207,0,1568},{0,68,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,231,1568},{0,153,5},{3,107,148},{0,93,317},{0,155,5419},{0,100,2754},{0,88,1161},{0,62,3641},{0,69,5968},{0,59,4028},{0,231,1568}, +{0,153,5},{6,107,126},{0,93,317},{76,0,5419},{0,100,2754},{0,88,1161},{0,62,3641},{155,0,5419},{0,62,3641},{0,146,0},{0,146,0},{0,146,0},{0,72,0},{0,73,1152},{0,57,424},{0,57,424},{0,34,680},{0,33,1260},{0,31,789},{0,146,0},{0,146,0},{0,146,0},{0,72,0},{36,0,1152},{0,57,424},{0,57,424},{0,34,680},{73,0,1152},{0,34,680},{113,0,1568},{0,153,5},{21,104,0}, +{0,93,317},{113,0,1568},{231,0,1568},{0,93,317},{0,76,1568},{231,0,1568},{0,76,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,248,1609},{4,166,41},{9,116,259},{2,104,303},{0,183,5419},{0,115,2480},{0,100,798},{0,71,3404},{0,84,6188},{0,68,3926},{9,240,1568},{9,162,5},{15,115,121},{5,104,293},{89,0,5419}, +{0,115,2480},{0,100,798},{0,71,3404},{183,0,5419},{0,71,3404},{5,163,41},{5,163,41},{5,163,41},{4,83,41},{0,101,1152},{0,75,274},{0,75,274},{0,44,569},{0,45,1366},{0,40,747},{9,155,0},{9,155,0},{9,155,0},{9,81,0},{49,0,1152},{0,75,274},{0,75,274},{0,44,569},{101,0,1152},{0,44,569},{127,0,1568},{4,166,0},{30,113,0},{0,105,233},{127,0,1568},{254,2,1568},{0,105,233}, +{0,85,1568},{254,2,1568},{0,85,1568},{4,0,41},{4,0,41},{4,0,41},{4,0,41},{0,28,0},{0,28,0},{0,28,0},{0,14,0},{0,12,10},{0,12,10},{9,255,1731},{9,176,146},{13,126,435},{7,112,374},{0,207,5419},{0,129,2265},{0,109,532},{0,80,3202},{0,94,6384},{0,77,3861},{17,248,1568},{17,170,5},{23,123,121},{13,112,293},{101,0,5419},{0,129,2265},{0,109,532},{0,80,3202},{207,0,5419}, +{0,80,3202},{9,179,145},{9,179,145},{9,179,145},{9,92,145},{0,125,1152},{0,88,157},{0,88,157},{0,53,468},{0,54,1491},{0,50,737},{17,163,0},{17,163,0},{17,163,0},{17,89,0},{61,0,1152},{0,88,157},{0,88,157},{0,53,468},{125,0,1152},{0,53,468},{138,0,1568},{12,174,0},{38,121,0},{0,114,170},{138,0,1568},{254,14,1568},{0,114,170},{0,93,1568},{254,14,1568},{0,93,1568},{8,0,145}, +{8,0,145},{8,0,145},{8,0,145},{0,52,0},{0,52,0},{0,52,0},{0,26,0},{0,21,45},{0,21,45},{15,255,1991},{13,189,321},{18,134,687},{10,121,510},{0,231,5419},{0,141,2081},{0,121,324},{0,90,3035},{0,106,6640},{0,87,3833},{26,254,1569},{25,178,5},{31,131,121},{21,120,293},{113,0,5419},{0,141,2081},{0,121,324},{0,90,3035},{231,0,5419},{0,90,3035},{13,195,313},{13,195,313},{13,195,313}, +{13,102,313},{0,149,1152},{0,103,80},{0,103,80},{0,62,377},{0,66,1643},{0,57,749},{25,171,0},{25,171,0},{25,171,0},{25,97,0},{73,0,1152},{0,103,80},{0,103,80},{0,62,377},{149,0,1152},{0,62,377},{150,0,1568},{21,181,0},{46,129,0},{0,123,117},{150,0,1568},{254,26,1568},{0,123,117},{0,101,1568},{254,26,1568},{0,101,1568},{12,0,313},{12,0,313},{12,0,313},{12,0,313},{0,76,0}, +{0,76,0},{0,76,0},{0,38,0},{0,30,106},{0,30,106},{24,255,2387},{17,199,565},{23,142,1015},{15,129,713},{0,255,5419},{0,156,1924},{0,130,166},{0,99,2857},{0,115,6921},{0,94,3818},{36,255,1579},{33,187,4},{39,139,121},{29,128,293},{125,0,5419},{0,156,1924},{0,130,166},{0,99,2857},{255,0,5419},{0,99,2857},{17,212,545},{17,212,545},{17,212,545},{17,112,545},{0,174,1152},{0,118,29},{0,118,29}, +{0,71,296},{0,75,1826},{0,66,787},{33,179,0},{33,179,0},{33,179,0},{33,104,0},{85,0,1152},{0,118,29},{0,118,29},{0,71,296},{174,0,1152},{0,71,296},{162,0,1568},{29,189,0},{54,137,0},{0,133,80},{162,0,1568},{254,38,1568},{0,133,80},{0,109,1568},{254,38,1568},{0,109,1568},{16,0,545},{16,0,545},{16,0,545},{16,0,545},{0,101,0},{0,101,0},{0,101,0},{0,49,0},{0,39,193}, +{0,39,193},{30,255,3004},{22,210,924},{28,153,1470},{19,140,1026},{6,255,5520},{0,172,1772},{0,142,57},{0,108,2668},{0,127,7276},{0,103,3836},{46,255,1602},{41,195,3},{48,148,121},{38,137,293},{138,0,5419},{0,172,1772},{0,142,57},{0,108,2668},{254,14,5419},{0,108,2668},{21,231,882},{21,231,882},{21,231,882},{21,124,882},{0,201,1152},{0,132,2},{0,132,2},{0,83,218},{0,88,2034},{0,75,865},{42,188,0}, +{42,188,0},{42,188,0},{42,113,0},{98,0,1152},{0,132,2},{0,132,2},{0,83,218},{201,0,1152},{0,83,218},{175,0,1568},{38,198,0},{63,146,0},{0,142,41},{175,0,1568},{254,51,1568},{0,142,41},{0,118,1568},{254,51,1568},{0,118,1568},{21,0,882},{21,0,882},{21,0,882},{21,0,882},{0,128,0},{0,128,0},{0,128,0},{0,63,0},{0,51,320},{0,51,320},{36,255,3708},{27,221,1316},{33,161,1956}, +{24,148,1369},{15,255,5777},{0,184,1676},{0,151,19},{0,117,2514},{0,138,7620},{0,112,3881},{55,255,1643},{49,203,3},{56,156,121},{46,145,293},{150,0,5419},{0,184,1676},{0,151,19},{0,117,2514},{254,26,5419},{0,117,2514},{25,247,1250},{25,247,1250},{25,247,1250},{25,134,1250},{0,225,1152},{1,147,3},{1,147,3},{0,90,164},{0,100,2274},{0,84,961},{50,196,0},{50,196,0},{50,196,0},{50,121,0},{110,0,1152}, +{5,143,0},{5,143,0},{0,90,164},{225,0,1152},{0,90,164},{187,0,1568},{46,206,0},{71,154,0},{0,151,18},{187,0,1568},{254,63,1568},{0,151,18},{0,126,1568},{254,63,1568},{0,126,1568},{25,0,1250},{25,0,1250},{25,0,1250},{25,0,1250},{0,152,0},{0,152,0},{0,152,0},{0,75,0},{0,60,461},{0,60,461},{43,255,4356},{32,232,1665},{38,169,2370},{29,156,1670},{21,255,6121},{0,196,1616},{3,161,20}, +{0,126,2376},{0,150,7804},{0,121,3804},{67,255,1699},{57,211,3},{64,164,121},{54,153,293},{162,0,5419},{0,196,1612},{5,160,17},{0,126,2372},{254,38,5419},{0,126,2372},{30,255,1572},{30,255,1572},{30,255,1572},{30,143,1568},{2,245,1152},{4,159,17},{4,159,17},{0,99,117},{0,109,2403},{0,94,953},{58,204,0},{58,204,0},{58,204,0},{58,129,0},{122,0,1152},{13,151,0},{13,151,0},{0,99,113},{249,0,1152}, +{0,99,113},{199,0,1568},{54,214,0},{79,162,0},{0,160,5},{199,0,1568},{254,75,1568},{0,160,5},{0,134,1568},{254,75,1568},{0,134,1568},{30,0,1568},{30,0,1568},{30,0,1568},{30,0,1568},{2,172,0},{2,172,0},{2,172,0},{2,86,0},{0,72,541},{0,72,541},{52,255,4586},{40,240,1665},{47,177,2355},{37,164,1670},{33,255,6289},{7,206,1615},{11,169,20},{1,134,2353},{0,162,7444},{0,130,3321},{76,255,1766}, +{65,219,3},{72,172,121},{61,161,302},{174,0,5419},{0,211,1577},{13,168,17},{0,133,2259},{255,49,5419},{0,133,2259},{39,255,1586},{39,255,1586},{39,255,1586},{38,151,1568},{10,253,1152},{12,167,17},{12,167,17},{7,109,115},{0,124,2150},{0,103,659},{66,211,0},{66,211,0},{66,211,0},{66,137,0},{134,0,1152},{21,159,0},{21,159,0},{0,108,72},{255,9,1152},{0,108,72},{211,0,1568},{62,222,0},{86,170,0}, +{0,170,0},{211,0,1568},{255,86,1568},{0,170,0},{0,142,1568},{255,86,1568},{0,142,1568},{38,0,1568},{38,0,1568},{38,0,1568},{38,0,1568},{10,180,0},{10,180,0},{10,180,0},{10,93,0},{0,88,373},{0,88,373},{64,255,4866},{49,249,1665},{55,188,2353},{46,173,1670},{43,255,6476},{16,215,1615},{20,178,20},{10,143,2353},{0,178,7036},{0,139,2856},{86,255,1851},{75,228,5},{81,181,121},{70,170,302},{187,0,5419}, +{4,222,1568},{22,177,17},{0,145,2124},{254,63,5419},{0,145,2124},{49,255,1612},{49,255,1612},{49,255,1612},{47,160,1568},{21,255,1158},{21,176,17},{21,176,17},{16,118,115},{0,138,1900},{0,115,392},{75,220,0},{75,220,0},{75,220,0},{75,146,0},{147,0,1152},{30,168,0},{30,168,0},{0,120,34},{254,23,1152},{0,120,34},{224,0,1568},{71,231,0},{95,179,0},{7,179,0},{224,0,1568},{254,100,1568},{7,179,0}, +{0,151,1568},{254,100,1568},{0,151,1568},{47,0,1568},{47,0,1568},{47,0,1568},{47,0,1568},{19,189,0},{19,189,0},{19,189,0},{19,102,0},{0,103,232},{0,103,232},{73,255,5136},{57,254,1666},{63,196,2353},{54,181,1670},{55,255,6684},{24,223,1615},{28,186,20},{18,151,2353},{0,190,6740},{0,151,2504},{95,255,1954},{83,236,5},{89,189,121},{78,178,302},{199,0,5419},{12,230,1568},{30,185,17},{0,154,2018},{254,75,5419}, +{0,154,2018},{58,255,1650},{58,255,1650},{58,255,1650},{55,168,1568},{30,255,1179},{29,184,17},{29,184,17},{24,126,115},{0,150,1708},{0,127,216},{83,228,0},{83,228,0},{83,228,0},{83,154,0},{159,0,1152},{38,176,0},{38,176,0},{0,130,17},{254,35,1152},{0,130,17},{236,0,1568},{78,240,0},{103,187,0},{15,187,0},{236,0,1568},{254,112,1568},{15,187,0},{0,159,1568},{254,112,1568},{0,159,1568},{55,0,1568}, +{55,0,1568},{55,0,1568},{55,0,1568},{27,197,0},{27,197,0},{27,197,0},{27,110,0},{0,115,136},{0,115,136},{82,255,5426},{67,255,1701},{71,204,2353},{62,189,1670},{64,255,6905},{32,231,1615},{36,194,20},{26,159,2353},{0,202,6476},{0,160,2211},{107,255,2066},{91,244,5},{97,197,121},{86,186,302},{211,0,5419},{20,238,1568},{38,193,17},{0,160,1922},{255,86,5419},{0,160,1922},{67,255,1700},{67,255,1700},{67,255,1700}, +{63,176,1568},{39,255,1218},{37,192,17},{37,192,17},{32,134,115},{0,165,1545},{0,136,90},{91,236,0},{91,236,0},{91,236,0},{91,162,0},{171,0,1152},{46,184,0},{46,184,0},{0,139,4},{255,46,1152},{0,139,4},{248,0,1568},{85,248,0},{111,195,0},{23,195,0},{248,0,1568},{254,124,1568},{23,195,0},{0,167,1568},{254,124,1568},{0,167,1568},{63,0,1568},{63,0,1568},{63,0,1568},{63,0,1568},{35,205,0}, +{35,205,0},{35,205,0},{35,118,0},{0,129,65},{0,129,65},{92,255,5700},{76,255,1798},{79,212,2353},{70,197,1670},{73,255,7152},{40,239,1615},{44,202,20},{34,167,2353},{0,215,6213},{0,169,1980},{116,255,2195},{99,252,5},{104,206,115},{94,194,302},{223,0,5419},{28,246,1568},{46,201,17},{0,169,1836},{255,98,5419},{0,169,1836},{76,255,1762},{76,255,1762},{76,255,1762},{71,184,1568},{49,255,1260},{45,200,17},{45,200,17}, +{40,142,115},{0,178,1395},{0,145,24},{99,244,0},{99,244,0},{99,244,0},{99,170,0},{183,0,1152},{54,192,0},{54,192,0},{0,147,0},{255,58,1152},{0,147,0},{255,10,1568},{94,254,1},{119,203,0},{31,203,0},{255,10,1568},{255,135,1568},{31,203,0},{0,175,1568},{255,135,1568},{0,175,1568},{71,0,1568},{71,0,1568},{71,0,1568},{71,0,1568},{43,213,0},{43,213,0},{43,213,0},{43,126,0},{0,144,20}, +{0,144,20},{101,255,6066},{86,255,1980},{88,221,2353},{79,206,1670},{86,255,7408},{49,248,1615},{53,211,20},{43,176,2353},{0,230,5988},{0,179,1798},{129,255,2347},{110,255,24},{113,215,115},{103,203,302},{236,0,5419},{37,255,1568},{55,210,17},{0,179,1762},{254,112,5419},{0,179,1762},{86,255,1836},{86,255,1836},{86,255,1836},{80,193,1568},{61,255,1331},{54,209,17},{54,209,17},{49,151,115},{0,193,1281},{3,156,5},{108,253,0}, +{108,253,0},{108,253,0},{108,179,0},{196,0,1152},{63,201,0},{63,201,0},{9,156,0},{254,72,1152},{9,156,0},{255,37,1568},{110,255,20},{128,212,0},{40,212,0},{255,37,1568},{254,149,1568},{40,212,0},{0,184,1568},{254,149,1568},{0,184,1568},{80,0,1568},{80,0,1568},{80,0,1568},{80,0,1568},{52,222,0},{52,222,0},{52,222,0},{52,135,0},{0,159,1},{0,159,1},{110,255,6416},{95,255,2211},{96,229,2353}, +{86,213,1674},{95,255,7689},{58,254,1616},{61,219,20},{51,184,2353},{0,242,5820},{0,188,1701},{138,255,2502},{119,255,90},{121,223,115},{111,211,302},{248,0,5419},{52,255,1595},{63,218,17},{0,188,1700},{254,124,5419},{0,188,1700},{95,255,1922},{95,255,1922},{95,255,1922},{88,201,1568},{70,255,1414},{62,217,17},{62,217,17},{58,158,121},{0,205,1209},{11,164,5},{116,255,4},{116,255,4},{116,255,4},{116,187,0},{208,0,1152}, +{70,209,0},{70,209,0},{17,164,0},{254,84,1152},{17,164,0},{255,61,1568},{125,255,65},{136,220,0},{48,220,0},{255,61,1568},{254,161,1568},{48,220,0},{0,192,1568},{254,161,1568},{0,192,1568},{88,0,1568},{88,0,1568},{88,0,1568},{88,0,1568},{60,230,0},{60,230,0},{60,230,0},{60,143,0},{7,169,0},{7,169,0},{119,255,6786},{104,255,2504},{104,237,2353},{94,222,1676},{107,255,7985},{68,255,1665},{69,227,20}, +{59,192,2353},{0,254,5684},{0,197,1666},{147,255,2675},{128,255,216},{129,231,115},{119,219,302},{255,10,5419},{67,255,1665},{71,226,17},{0,197,1650},{255,135,5419},{0,197,1650},{101,255,2018},{101,255,2018},{101,255,2018},{96,209,1568},{82,255,1510},{70,224,17},{70,224,17},{66,166,121},{0,218,1163},{19,172,5},{125,255,17},{125,255,17},{125,255,17},{124,195,0},{220,0,1152},{78,217,0},{78,217,0},{25,172,0},{255,95,1152}, +{25,172,0},{255,86,1568},{140,255,136},{144,228,0},{56,228,0},{255,86,1568},{255,172,1568},{56,228,0},{0,200,1568},{255,172,1568},{0,200,1568},{96,0,1568},{96,0,1568},{96,0,1568},{96,0,1568},{68,238,0},{68,238,0},{68,238,0},{68,151,0},{15,177,0},{15,177,0},{129,255,7124},{116,255,2856},{112,245,2353},{102,230,1676},{116,255,8300},{79,255,1802},{77,235,20},{67,200,2353},{7,255,5788},{5,206,1665},{156,255,2866}, +{140,255,392},{137,239,115},{127,227,302},{255,34,5419},{82,255,1779},{79,234,17},{0,206,1612},{255,147,5419},{0,206,1612},{110,255,2124},{110,255,2124},{110,255,2124},{104,217,1568},{92,255,1608},{78,232,17},{78,232,17},{74,174,121},{1,231,1152},{27,180,5},{135,255,34},{135,255,34},{135,255,34},{132,203,0},{232,0,1152},{86,225,0},{86,225,0},{33,180,0},{255,107,1152},{33,180,0},{255,110,1568},{152,255,232},{152,236,0}, +{64,236,0},{255,110,1568},{255,184,1568},{64,236,0},{0,208,1568},{255,184,1568},{0,208,1568},{104,0,1568},{104,0,1568},{104,0,1568},{104,0,1568},{76,246,0},{76,246,0},{76,246,0},{76,159,0},{24,184,0},{24,184,0},{138,255,7586},{125,255,3321},{121,254,2353},{111,239,1676},{129,255,8636},{92,255,2092},{86,244,20},{78,208,2355},{28,255,6049},{14,215,1665},{168,255,3097},{152,255,659},{146,248,115},{136,236,302},{255,61,5419}, +{101,255,1977},{88,243,17},{0,216,1586},{254,161,5419},{0,216,1586},{122,255,2259},{122,255,2259},{122,255,2259},{113,226,1568},{101,255,1746},{87,241,17},{87,241,17},{83,183,121},{10,240,1152},{36,190,3},{147,255,72},{147,255,72},{147,255,72},{141,212,0},{245,0,1152},{95,234,0},{95,234,0},{42,189,0},{254,121,1152},{42,189,0},{255,137,1568},{167,255,373},{161,245,0},{73,245,0},{255,137,1568},{254,198,1568},{73,245,0}, +{0,217,1568},{254,198,1568},{0,217,1568},{113,0,1568},{113,0,1568},{113,0,1568},{113,0,1568},{85,254,0},{85,254,0},{85,254,0},{85,168,0},{33,193,0},{33,193,0},{147,255,8016},{134,255,3804},{129,255,2376},{119,247,1676},{138,255,8985},{104,255,2436},{94,252,20},{85,216,2370},{40,255,6353},{22,223,1665},{178,255,3291},{161,255,953},{156,255,117},{146,243,305},{255,86,5419},{119,255,2185},{96,251,17},{0,225,1572},{255,172,5419}, +{0,225,1572},{129,255,2372},{129,255,2372},{129,255,2372},{121,233,1568},{113,255,1890},{95,249,17},{95,249,17},{91,191,121},{18,248,1152},{44,198,3},{156,255,113},{156,255,113},{156,255,113},{149,220,0},{255,4,1152},{103,242,0},{103,242,0},{49,197,0},{255,132,1152},{49,197,0},{255,161,1568},{183,255,541},{169,253,0},{80,253,0},{255,161,1568},{254,210,1568},{80,253,0},{0,225,1568},{254,210,1568},{0,225,1568},{121,0,1568}, +{121,0,1568},{121,0,1568},{121,0,1568},{94,254,5},{94,254,5},{94,254,5},{93,176,0},{41,201,0},{41,201,0},{156,255,7638},{143,255,3881},{138,255,2514},{128,250,1620},{147,255,8460},{113,255,2285},{104,255,19},{94,222,1956},{58,255,5932},{34,228,1316},{184,255,2947},{171,255,961},{165,255,164},{152,246,206},{255,104,4803},{131,255,1925},{108,254,3},{6,230,1250},{255,181,4803},{6,230,1250},{138,255,2514},{138,255,2514},{138,255,2514}, +{129,241,1568},{122,255,2043},{104,255,19},{104,255,19},{99,199,121},{28,255,1153},{52,206,3},{165,255,164},{165,255,164},{165,255,164},{157,228,0},{255,28,1152},{111,250,0},{111,250,0},{57,205,0},{255,144,1152},{57,205,0},{255,177,1250},{195,255,461},{180,255,0},{101,255,0},{255,177,1250},{254,217,1250},{101,255,0},{0,230,1250},{254,217,1250},{0,230,1250},{129,0,1568},{129,0,1568},{129,0,1568},{129,0,1568},{104,255,18}, +{104,255,18},{104,255,18},{101,184,0},{49,209,0},{49,209,0},{165,255,7060},{152,255,3836},{147,255,2668},{137,253,1576},{156,255,7717},{122,255,2020},{113,255,57},{102,227,1470},{73,255,5307},{44,232,924},{193,255,2466},{180,255,865},{172,255,218},{162,250,98},{255,119,4056},{143,255,1557},{122,255,2},{22,234,882},{254,189,4056},{22,234,882},{147,255,2668},{147,255,2668},{147,255,2668},{137,249,1568},{132,255,2193},{113,255,57},{113,255,57}, +{107,207,121},{40,255,1185},{60,214,3},{172,255,218},{172,255,218},{172,255,218},{165,236,0},{255,52,1152},{122,255,2},{122,255,2},{65,213,0},{255,156,1152},{65,213,0},{255,189,882},{204,255,320},{192,255,0},{125,255,0},{255,189,882},{254,223,882},{125,255,0},{0,234,882},{254,223,882},{0,234,882},{137,0,1568},{137,0,1568},{137,0,1568},{137,0,1568},{113,255,41},{113,255,41},{113,255,41},{109,192,0},{57,217,0}, +{57,217,0},{172,255,6429},{161,255,3818},{156,255,2857},{146,255,1572},{165,255,6979},{134,255,1813},{125,255,166},{113,232,1015},{82,255,4731},{56,238,565},{199,255,2010},{189,255,787},{184,255,296},{173,252,26},{255,137,3318},{155,255,1221},{137,255,29},{41,238,545},{254,198,3318},{41,238,545},{156,255,2857},{156,255,2857},{156,255,2857},{146,255,1572},{141,255,2403},{125,255,166},{125,255,166},{116,216,121},{61,255,1273},{68,222,4},{184,255,296}, +{184,255,296},{184,255,296},{174,245,0},{255,79,1152},{137,255,29},{137,255,29},{74,222,0},{253,170,1152},{74,222,0},{255,201,545},{216,255,193},{205,255,0},{152,255,0},{255,201,545},{254,229,545},{152,255,0},{0,238,545},{254,229,545},{0,238,545},{146,0,1568},{146,0,1568},{146,0,1568},{146,0,1568},{122,255,80},{122,255,80},{122,255,80},{118,201,0},{66,226,0},{66,226,0},{178,255,5997},{168,255,3833},{165,255,3035}, +{155,255,1619},{172,255,6365},{143,255,1710},{134,255,324},{121,237,687},{101,255,4330},{66,242,321},{208,255,1673},{198,255,749},{193,255,377},{182,255,1},{255,152,2753},{167,255,989},{152,255,80},{57,242,313},{255,205,2753},{57,242,313},{165,255,3035},{165,255,3035},{165,255,3035},{155,255,1619},{153,255,2603},{134,255,324},{134,255,324},{124,224,121},{76,255,1395},{76,230,5},{193,255,377},{193,255,377},{193,255,377},{182,253,0},{255,104,1152}, +{152,255,80},{152,255,80},{82,230,0},{255,181,1152},{82,230,0},{255,213,313},{225,255,106},{217,255,0},{177,255,0},{255,213,313},{254,235,313},{177,255,0},{0,242,313},{254,235,313},{0,242,313},{154,0,1568},{154,0,1568},{154,0,1568},{154,0,1568},{132,255,117},{132,255,117},{132,255,117},{126,209,0},{74,234,0},{74,234,0},{187,255,5627},{178,255,3861},{175,255,3202},{164,255,1720},{178,255,5889},{152,255,1685},{146,255,532}, +{129,242,435},{116,255,3993},{79,246,146},{215,255,1382},{205,255,737},{202,255,468},{192,255,13},{255,171,2273},{180,255,850},{167,255,157},{74,246,145},{254,214,2273},{74,246,145},{175,255,3202},{175,255,3202},{175,255,3202},{164,255,1720},{162,255,2818},{146,255,532},{146,255,532},{132,232,121},{92,255,1584},{84,238,5},{202,255,468},{202,255,468},{202,255,468},{192,255,13},{255,128,1152},{167,255,157},{167,255,157},{90,238,0},{255,193,1152}, +{90,238,0},{255,225,145},{234,255,45},{229,255,0},{201,255,0},{255,225,145},{254,241,145},{201,255,0},{0,246,145},{254,241,145},{0,246,145},{162,0,1568},{162,0,1568},{162,0,1568},{162,0,1568},{141,255,170},{141,255,170},{141,255,170},{134,217,0},{80,243,0},{80,243,0},{193,255,5331},{187,255,3926},{184,255,3404},{174,255,1889},{187,255,5490},{161,255,1738},{155,255,798},{139,246,259},{128,255,3745},{88,251,41},{221,255,1182}, +{215,255,747},{211,255,569},{201,255,73},{255,186,1878},{192,255,746},{180,255,274},{90,250,41},{255,221,1878},{90,250,41},{184,255,3404},{184,255,3404},{184,255,3404},{174,255,1889},{172,255,3020},{155,255,798},{155,255,798},{140,240,121},{107,255,1798},{92,246,5},{211,255,569},{211,255,569},{211,255,569},{201,255,73},{255,152,1152},{180,255,274},{180,255,274},{98,246,0},{255,205,1152},{98,246,0},{255,237,41},{243,255,10},{241,255,0}, +{225,255,0},{255,237,41},{254,247,41},{225,255,0},{0,250,41},{254,247,41},{0,250,41},{170,0,1568},{170,0,1568},{170,0,1568},{170,0,1568},{150,255,233},{150,255,233},{150,255,233},{142,225,0},{88,251,0},{88,251,0},{202,255,5076},{196,255,4028},{193,255,3641},{183,255,2129},{196,255,5148},{174,255,1917},{167,255,1161},{147,251,148},{143,255,3577},{101,255,5},{230,255,1041},{224,255,789},{221,255,680},{210,255,205},{255,204,1536}, +{207,255,706},{198,255,424},{107,255,0},{255,230,1536},{107,255,0},{193,255,3641},{193,255,3641},{193,255,3641},{183,255,2129},{184,255,3299},{167,255,1161},{167,255,1161},{148,249,126},{125,255,2089},{101,255,5},{221,255,680},{221,255,680},{221,255,680},{210,255,205},{255,180,1152},{198,255,424},{198,255,424},{107,255,0},{255,218,1152},{107,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0}, +{0,255,0},{255,254,0},{0,255,0},{179,0,1568},{179,0,1568},{179,0,1568},{179,0,1568},{162,255,317},{162,255,317},{162,255,317},{151,234,0},{101,255,5},{101,255,5},{208,255,4372},{202,255,3532},{199,255,3225},{189,255,2017},{202,255,4324},{180,255,1693},{177,255,1093},{157,252,58},{155,255,2953},{116,255,34},{233,255,716},{230,255,545},{227,255,468},{219,255,137},{255,213,1067},{213,255,482},{207,255,289},{131,255,0},{254,235,1067}, +{131,255,0},{199,255,3225},{199,255,3225},{199,255,3225},{189,255,2017},{190,255,2819},{177,255,1093},{177,255,1093},{157,252,49},{137,255,1737},{116,255,34},{227,255,468},{227,255,468},{227,255,468},{219,255,137},{255,192,800},{207,255,289},{207,255,289},{131,255,0},{255,224,800},{131,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{187,0,1568}, +{187,0,1568},{187,0,1568},{187,0,1568},{172,255,394},{172,255,394},{172,255,394},{159,242,0},{116,255,34},{116,255,34},{215,255,3720},{208,255,3092},{205,255,2857},{198,255,1910},{208,255,3604},{189,255,1510},{183,255,1041},{165,254,10},{164,255,2420},{131,255,89},{239,255,456},{233,255,345},{233,255,296},{225,255,85},{255,219,683},{222,255,300},{216,255,180},{155,255,0},{254,238,683},{155,255,0},{205,255,2857},{205,255,2857},{205,255,2857}, +{198,255,1910},{196,255,2411},{183,255,1041},{183,255,1041},{167,253,8},{149,255,1449},{131,255,89},{233,255,296},{233,255,296},{233,255,296},{225,255,85},{255,204,512},{216,255,180},{216,255,180},{155,255,0},{255,230,512},{155,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{195,0,1568},{195,0,1568},{195,0,1568},{195,0,1568},{178,255,482}, +{178,255,482},{178,255,482},{167,250,0},{131,255,89},{131,255,89},{218,255,3170},{215,255,2701},{215,255,2532},{207,255,1825},{215,255,2956},{198,255,1373},{192,255,1013},{175,255,4},{167,255,2025},{143,255,169},{242,255,249},{239,255,189},{239,255,164},{234,255,45},{255,228,384},{231,255,162},{225,255,97},{180,255,0},{255,242,384},{180,255,0},{215,255,2532},{215,255,2532},{215,255,2532},{207,255,1825},{205,255,2070},{192,255,1013},{192,255,1013}, +{175,255,4},{161,255,1225},{143,255,169},{239,255,164},{239,255,164},{239,255,164},{234,255,45},{255,216,288},{225,255,97},{225,255,97},{180,255,0},{255,236,288},{180,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{203,0,1568},{203,0,1568},{203,0,1568},{203,0,1568},{187,255,585},{187,255,585},{187,255,585},{175,255,4},{143,255,169}, +{143,255,169},{0,210,2665},{0,147,274},{0,106,1},{0,90,985},{0,140,5885},{0,94,3649},{0,81,1742},{0,56,4398},{0,63,6341},{0,56,4722},{0,210,2665},{0,147,274},{0,106,1},{0,90,985},{69,0,5885},{0,94,3649},{0,81,1742},{0,56,4398},{140,0,5885},{0,56,4398},{0,101,0},{0,101,0},{0,101,0},{0,49,0},{0,49,545},{0,39,193},{0,39,193},{0,22,317},{0,21,593},{0,22,366},{0,101,0}, +{0,101,0},{0,101,0},{0,49,0},{24,0,545},{0,39,193},{0,39,193},{0,22,317},{49,0,545},{0,22,317},{103,0,2665},{0,147,274},{0,106,1},{0,90,985},{103,0,2665},{210,0,2665},{0,90,985},{0,69,2665},{210,0,2665},{0,69,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,234,2665},{0,162,169},{1,114,11}, +{0,99,850},{0,158,6669},{0,103,3898},{0,91,1770},{0,62,4826},{0,72,7238},{0,62,5226},{0,234,2665},{0,162,169},{2,115,9},{0,99,850},{78,0,6669},{0,103,3898},{0,91,1770},{0,62,4826},{158,0,6669},{0,62,4826},{0,125,0},{0,125,0},{0,125,0},{0,61,0},{0,61,841},{0,51,305},{0,51,305},{0,28,493},{0,27,917},{0,28,574},{0,125,0},{0,125,0},{0,125,0},{0,61,0},{30,0,841}, +{0,51,305},{0,51,305},{0,28,493},{61,0,841},{0,28,493},{115,0,2665},{0,162,169},{6,114,0},{0,99,850},{115,0,2665},{234,0,2665},{0,99,850},{0,77,2665},{234,0,2665},{0,77,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,255,2669},{0,175,80},{2,124,61},{0,108,725},{0,174,7538},{0,115,4178},{0,100,1832}, +{0,71,5294},{0,78,8238},{0,68,5786},{2,254,2669},{0,175,80},{4,123,53},{0,108,725},{85,0,7538},{0,115,4178},{0,100,1832},{0,71,5294},{174,0,7538},{0,71,5294},{0,149,0},{0,149,0},{0,149,0},{0,73,0},{0,73,1201},{0,60,442},{0,60,442},{0,34,709},{0,33,1313},{0,31,824},{0,149,0},{0,149,0},{0,149,0},{0,73,0},{36,0,1201},{0,60,442},{0,60,442},{0,34,709},{73,0,1201}, +{0,34,709},{127,0,2665},{0,175,80},{14,122,0},{0,108,725},{127,0,2665},{254,2,2665},{0,108,725},{0,85,2665},{254,2,2665},{0,85,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,255,2795},{0,190,29},{3,134,155},{0,117,610},{0,189,8493},{0,124,4485},{0,109,1922},{0,77,5810},{0,88,9310},{0,74,6402},{6,255,2761}, +{0,190,29},{6,134,133},{0,117,610},{92,0,8493},{0,124,4485},{0,109,1922},{0,77,5810},{189,0,8493},{0,77,5810},{0,174,0},{0,174,0},{0,174,0},{0,85,0},{0,85,1625},{0,69,605},{0,69,605},{0,40,965},{0,39,1781},{0,37,1120},{0,174,0},{0,174,0},{0,174,0},{0,85,0},{42,0,1625},{0,69,605},{0,69,605},{0,40,965},{85,0,1625},{0,40,965},{138,0,2665},{0,190,29},{22,130,0}, +{0,117,610},{138,0,2665},{254,14,2665},{0,117,610},{0,93,2665},{254,14,2665},{0,93,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{9,255,3139},{0,205,2},{5,145,311},{0,126,493},{0,207,9669},{0,135,4865},{0,118,2054},{0,83,6450},{0,94,10654},{0,80,7162},{12,255,3029},{0,205,2},{9,143,266},{0,126,493},{101,0,9669}, +{0,135,4865},{0,118,2054},{0,83,6450},{207,0,9669},{0,83,6450},{0,201,0},{0,201,0},{0,201,0},{0,98,0},{0,101,2178},{0,81,820},{0,81,820},{0,47,1322},{0,45,2392},{0,40,1521},{0,201,0},{0,201,0},{0,201,0},{0,98,0},{49,0,2178},{0,81,820},{0,81,820},{0,47,1322},{101,0,2178},{0,47,1322},{152,0,2665},{0,205,2},{30,139,0},{0,126,493},{152,0,2665},{255,27,2665},{0,126,493}, +{0,102,2665},{255,27,2665},{0,102,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{15,255,3483},{4,217,32},{10,153,429},{2,135,473},{0,231,9669},{0,150,4526},{0,127,1610},{0,93,6193},{0,106,10910},{0,90,7050},{24,255,3141},{8,213,2},{17,151,266},{2,135,469},{113,0,9669},{0,150,4526},{0,127,1610},{0,93,6193},{231,0,9669}, +{0,93,6193},{4,217,32},{4,217,32},{4,217,32},{4,108,32},{0,125,2178},{0,94,605},{0,94,605},{0,56,1165},{0,54,2517},{0,50,1457},{8,209,0},{8,209,0},{8,209,0},{8,106,0},{61,0,2178},{0,94,605},{0,94,605},{0,56,1165},{125,0,2178},{0,56,1165},{164,0,2665},{5,216,0},{38,147,0},{0,136,410},{164,0,2665},{255,39,2665},{0,136,410},{0,110,2665},{255,39,2665},{0,110,2665},{4,0,32}, +{4,0,32},{4,0,32},{4,0,32},{0,25,0},{0,25,0},{0,25,0},{0,12,0},{0,9,8},{0,9,8},{21,255,3971},{8,227,132},{15,161,623},{5,144,523},{0,255,9669},{0,162,4214},{0,139,1218},{0,102,5913},{0,118,11198},{0,96,6942},{33,255,3266},{16,222,1},{25,159,266},{10,143,469},{125,0,9669},{0,162,4214},{0,139,1218},{0,102,5913},{255,0,9669},{0,102,5913},{8,233,128},{8,233,128},{8,233,128}, +{8,118,128},{0,149,2178},{0,109,442},{0,109,442},{0,65,1018},{0,66,2669},{0,59,1419},{16,217,0},{16,217,0},{16,217,0},{16,114,0},{73,0,2178},{0,109,442},{0,109,442},{0,65,1018},{149,0,2178},{0,65,1018},{175,0,2665},{14,223,0},{46,155,0},{0,145,325},{175,0,2665},{254,51,2665},{0,145,325},{0,118,2665},{254,51,2665},{0,118,2665},{8,0,128},{8,0,128},{8,0,128},{8,0,128},{0,49,0}, +{0,49,0},{0,49,0},{0,24,0},{0,21,40},{0,21,40},{27,255,4603},{13,238,300},{19,171,891},{10,152,642},{6,255,9761},{0,175,3898},{0,148,882},{0,111,5645},{0,127,11511},{0,105,6861},{43,255,3390},{24,230,1},{33,167,266},{18,151,469},{137,0,9669},{0,175,3898},{0,148,882},{0,111,5645},{255,12,9669},{0,111,5645},{12,249,288},{12,249,288},{12,249,288},{12,128,288},{0,174,2178},{0,124,305},{0,124,305}, +{0,74,881},{0,75,2852},{0,68,1409},{24,225,0},{24,225,0},{24,225,0},{24,122,0},{85,0,2178},{0,124,305},{0,124,305},{0,74,881},{174,0,2178},{0,74,881},{187,0,2665},{22,231,0},{54,163,0},{0,154,250},{187,0,2665},{254,63,2665},{0,154,250},{0,126,2665},{254,63,2665},{0,126,2665},{12,0,288},{12,0,288},{12,0,288},{12,0,288},{0,73,0},{0,73,0},{0,73,0},{0,36,0},{0,30,97}, +{0,30,97},{36,255,5482},{17,251,574},{24,179,1282},{14,162,853},{15,255,10055},{0,190,3618},{0,160,569},{0,120,5354},{0,138,11902},{0,114,6807},{55,255,3569},{33,239,1},{42,176,266},{27,160,469},{150,0,9669},{0,190,3618},{0,160,569},{0,120,5354},{254,26,9669},{0,120,5354},{18,255,558},{18,255,558},{18,255,558},{16,139,545},{0,201,2178},{0,138,180},{0,138,180},{0,83,740},{0,88,3060},{0,78,1427},{33,233,0}, +{33,233,0},{33,233,0},{33,131,0},{98,0,2178},{0,138,180},{0,138,180},{0,83,740},{201,0,2178},{0,83,740},{201,0,2665},{31,240,0},{63,172,0},{0,166,180},{201,0,2665},{255,76,2665},{0,166,180},{0,135,2665},{255,76,2665},{0,135,2665},{16,0,545},{16,0,545},{16,0,545},{16,0,545},{0,101,0},{0,101,0},{0,101,0},{0,49,0},{0,39,193},{0,39,193},{43,255,6378},{24,255,915},{29,187,1710}, +{18,172,1113},{21,255,10495},{0,205,3401},{0,169,353},{0,126,5126},{0,150,12278},{0,123,6786},{64,255,3738},{41,246,2},{50,183,259},{35,168,469},{162,0,9669},{0,205,3401},{0,169,353},{0,126,5126},{254,38,9669},{0,126,5126},{24,255,914},{24,255,914},{24,255,914},{20,149,841},{0,225,2178},{0,153,97},{0,153,97},{0,93,637},{0,100,3300},{0,88,1469},{41,241,0},{41,241,0},{41,241,0},{41,139,0},{110,0,2178}, +{0,153,97},{0,153,97},{0,93,637},{225,0,2178},{0,93,637},{213,0,2665},{38,249,0},{71,180,0},{0,173,130},{213,0,2665},{254,88,2665},{0,173,130},{0,143,2665},{254,88,2665},{0,143,2665},{20,0,841},{20,0,841},{20,0,841},{20,0,841},{0,125,0},{0,125,0},{0,125,0},{0,61,0},{0,51,305},{0,51,305},{49,255,7446},{30,255,1431},{33,197,2210},{22,179,1438},{30,255,11102},{0,218,3189},{0,182,185}, +{0,136,4909},{0,162,12686},{0,130,6797},{73,255,3925},{49,254,2},{57,193,258},{43,176,469},{174,0,9669},{0,218,3189},{0,182,185},{0,136,4909},{255,49,9669},{0,136,4909},{27,255,1382},{27,255,1382},{27,255,1382},{24,159,1201},{0,249,2178},{0,168,40},{0,168,40},{0,102,530},{0,109,3565},{0,94,1537},{49,249,0},{49,249,0},{49,249,0},{49,147,0},{122,0,2178},{0,168,40},{0,168,40},{0,102,530},{249,0,2178}, +{0,102,530},{224,0,2665},{46,255,1},{79,188,0},{0,182,85},{224,0,2665},{254,100,2665},{0,182,85},{0,151,2665},{254,100,2665},{0,151,2665},{24,0,1201},{24,0,1201},{24,0,1201},{24,0,1201},{0,149,0},{0,149,0},{0,149,0},{0,73,0},{0,60,442},{0,60,442},{55,255,8658},{36,255,2131},{38,205,2786},{27,188,1837},{36,255,11866},{0,230,3029},{0,191,75},{0,145,4685},{0,172,13066},{0,139,6826},{86,255,4118}, +{58,255,26},{65,201,258},{51,184,469},{186,0,9669},{0,230,3029},{0,191,75},{0,145,4685},{255,61,9669},{0,145,4685},{33,255,1954},{33,255,1954},{33,255,1954},{28,169,1625},{3,255,2219},{0,181,5},{0,181,5},{0,111,433},{0,121,3861},{0,103,1633},{57,254,1},{57,254,1},{57,254,1},{57,155,0},{134,0,2178},{0,181,5},{0,181,5},{0,111,433},{255,9,2178},{0,111,433},{236,0,2665},{61,255,20},{87,196,0}, +{0,191,50},{236,0,2665},{254,112,2665},{0,191,50},{0,159,2665},{254,112,2665},{0,159,2665},{28,0,1625},{28,0,1625},{28,0,1625},{28,0,1625},{0,174,0},{0,174,0},{0,174,0},{0,85,0},{0,69,605},{0,69,605},{61,255,10195},{43,255,3100},{43,216,3523},{31,198,2356},{43,255,12883},{0,245,2885},{0,203,20},{0,157,4450},{0,184,13589},{0,148,6898},{95,255,4346},{70,255,117},{74,210,258},{60,193,469},{199,0,9669}, +{0,245,2885},{0,203,20},{0,157,4450},{254,75,9669},{0,157,4450},{39,255,2734},{39,255,2734},{39,255,2734},{33,180,2178},{12,255,2420},{1,196,2},{1,196,2},{0,123,337},{0,132,4227},{0,112,1777},{67,255,10},{67,255,10},{67,255,10},{66,164,0},{147,0,2178},{4,194,0},{4,194,0},{0,123,337},{254,23,2178},{0,123,337},{250,0,2665},{76,255,73},{96,205,0},{0,203,20},{250,0,2665},{255,125,2665},{0,203,20}, +{0,168,2665},{255,125,2665},{0,168,2665},{33,0,2178},{33,0,2178},{33,0,2178},{33,0,2178},{0,201,0},{0,201,0},{0,201,0},{0,98,0},{0,81,820},{0,81,820},{67,255,11582},{49,255,4083},{48,224,4162},{36,206,2818},{49,255,13898},{1,255,2805},{2,212,20},{0,163,4255},{0,196,13958},{0,157,6886},{104,255,4577},{79,255,259},{82,218,258},{68,201,469},{211,0,9669},{1,255,2805},{4,211,17},{0,163,4254},{255,86,9669}, +{0,163,4254},{46,255,3434},{46,255,3434},{46,255,3434},{37,190,2665},{18,255,2709},{3,210,17},{3,210,17},{0,130,270},{0,141,4491},{0,121,1854},{76,255,29},{76,255,29},{76,255,29},{74,172,0},{159,0,2178},{12,202,0},{12,202,0},{0,130,269},{254,35,2178},{0,130,269},{255,13,2665},{92,255,157},{104,213,0},{0,212,5},{255,13,2665},{254,137,2665},{0,212,5},{0,176,2665},{254,137,2665},{0,176,2665},{37,0,2665}, +{37,0,2665},{37,0,2665},{37,0,2665},{1,223,0},{1,223,0},{1,223,0},{1,110,0},{0,91,953},{0,91,953},{79,255,12086},{58,255,4502},{56,232,4162},{44,214,2818},{61,255,14298},{10,255,2910},{10,220,20},{0,173,4166},{0,208,13470},{0,166,6215},{113,255,4826},{89,255,465},{90,226,258},{78,208,474},{223,0,9669},{10,255,2909},{12,219,17},{0,173,4085},{255,98,9669},{0,173,4085},{55,255,3574},{55,255,3574},{55,255,3574}, +{46,197,2665},{27,255,2840},{11,218,17},{11,218,17},{4,140,258},{0,156,4142},{0,133,1430},{86,255,52},{86,255,52},{86,255,52},{82,180,0},{171,0,2178},{20,210,0},{20,210,0},{0,139,202},{255,46,2178},{0,139,202},{255,37,2665},{107,255,260},{112,221,0},{0,220,1},{255,37,2665},{254,149,2665},{0,220,1},{0,184,2665},{254,149,2665},{0,184,2665},{45,0,2665},{45,0,2665},{45,0,2665},{45,0,2665},{9,231,0}, +{9,231,0},{9,231,0},{9,118,0},{0,103,745},{0,103,745},{86,255,12542},{67,255,4983},{64,240,4162},{52,222,2818},{70,255,14719},{22,255,3118},{18,228,20},{5,181,4162},{0,221,12955},{0,176,5593},{125,255,5090},{101,255,713},{98,234,258},{84,218,481},{235,0,9669},{28,255,3073},{20,227,17},{0,182,3909},{255,110,9669},{0,182,3909},{64,255,3726},{64,255,3726},{64,255,3726},{54,205,2665},{36,255,2989},{19,226,17},{19,226,17}, +{12,148,258},{0,172,3797},{0,142,1062},{95,255,89},{95,255,89},{95,255,89},{90,188,0},{183,0,2178},{28,218,0},{28,218,0},{0,148,145},{255,58,2178},{0,148,145},{255,61,2665},{119,255,388},{120,229,0},{5,229,0},{255,61,2665},{254,161,2665},{5,229,0},{0,192,2665},{254,161,2665},{0,192,2665},{53,0,2665},{53,0,2665},{53,0,2665},{53,0,2665},{17,239,0},{17,239,0},{17,239,0},{17,126,0},{0,118,562}, +{0,118,562},{98,255,13154},{79,255,5593},{73,249,4162},{61,231,2818},{86,255,15194},{34,255,3462},{27,237,20},{14,190,4162},{0,236,12478},{0,188,4983},{135,255,5365},{113,255,1062},{107,243,258},{93,227,481},{248,0,9669},{40,255,3330},{29,236,17},{0,191,3726},{254,124,9669},{0,191,3726},{73,255,3909},{73,255,3909},{73,255,3909},{63,214,2665},{46,255,3156},{28,235,17},{28,235,17},{21,157,258},{0,184,3462},{0,154,713},{107,255,145}, +{107,255,145},{107,255,145},{99,197,0},{196,0,2178},{37,227,0},{37,227,0},{0,160,89},{254,72,2178},{0,160,89},{255,89,2665},{137,255,562},{129,238,0},{14,238,0},{255,89,2665},{254,174,2665},{14,238,0},{0,201,2665},{254,174,2665},{0,201,2665},{62,0,2665},{62,0,2665},{62,0,2665},{62,0,2665},{26,248,0},{26,248,0},{26,248,0},{26,135,0},{0,135,388},{0,135,388},{107,255,13718},{89,255,6215},{82,255,4166}, +{69,239,2818},{92,255,15614},{46,255,3885},{35,245,20},{22,198,4162},{0,248,12086},{0,197,4502},{144,255,5658},{122,255,1430},{115,251,258},{101,235,481},{255,10,9669},{61,255,3601},{37,244,17},{0,200,3574},{255,135,9669},{0,200,3574},{82,255,4085},{82,255,4085},{82,255,4085},{71,222,2665},{58,255,3332},{36,242,17},{36,242,17},{29,165,258},{0,196,3206},{0,163,465},{116,255,202},{116,255,202},{116,255,202},{107,205,0},{208,0,2178}, +{44,235,0},{44,235,0},{0,169,52},{254,84,2178},{0,169,52},{255,113,2665},{152,255,745},{137,246,0},{22,246,0},{255,113,2665},{254,186,2665},{22,246,0},{0,209,2665},{254,186,2665},{0,209,2665},{70,0,2665},{70,0,2665},{70,0,2665},{70,0,2665},{34,253,1},{34,253,1},{34,253,1},{34,143,0},{0,147,260},{0,147,260},{116,255,14302},{98,255,6886},{89,255,4255},{77,247,2818},{104,255,16094},{55,255,4382},{43,253,20}, +{30,206,4162},{0,254,11806},{0,206,4083},{153,255,5969},{134,255,1854},{125,255,270},{109,243,481},{255,34,9669},{76,255,3905},{45,252,17},{0,209,3434},{255,147,9669},{0,209,3434},{89,255,4254},{89,255,4254},{89,255,4254},{79,230,2665},{67,255,3525},{44,250,17},{44,250,17},{37,173,258},{0,211,2979},{0,176,259},{125,255,269},{125,255,269},{125,255,269},{115,213,0},{220,0,2178},{52,243,0},{52,243,0},{0,179,29},{255,95,2178}, +{0,179,29},{255,137,2665},{164,255,953},{145,254,0},{30,254,0},{255,137,2665},{254,198,2665},{30,254,0},{0,217,2665},{254,198,2665},{0,217,2665},{78,0,2665},{78,0,2665},{78,0,2665},{78,0,2665},{43,255,5},{43,255,5},{43,255,5},{42,150,0},{0,162,157},{0,162,157},{122,255,13635},{107,255,6898},{98,255,4450},{86,250,2739},{110,255,15195},{67,255,4071},{52,255,20},{39,212,3523},{1,255,10735},{0,212,3100},{162,255,5381}, +{143,255,1777},{132,255,337},{118,246,331},{255,52,8712},{82,255,3492},{59,254,2},{0,216,2734},{255,156,8712},{0,216,2734},{98,255,4450},{98,255,4450},{98,255,4450},{87,238,2665},{76,255,3736},{52,255,20},{52,255,20},{45,181,258},{0,224,2757},{0,185,117},{132,255,337},{132,255,337},{132,255,337},{123,221,0},{232,0,2178},{60,251,0},{60,251,0},{0,188,10},{255,107,2178},{0,188,10},{255,152,2178},{174,255,820},{156,255,0}, +{52,255,0},{255,152,2178},{255,205,2178},{52,255,0},{0,222,2178},{255,205,2178},{0,222,2178},{86,0,2665},{86,0,2665},{86,0,2665},{86,0,2665},{52,255,20},{52,255,20},{52,255,20},{50,158,0},{0,178,73},{0,178,73},{132,255,12678},{116,255,6826},{110,255,4685},{95,253,2678},{119,255,14061},{76,255,3663},{64,255,75},{49,216,2786},{10,255,9739},{0,219,2131},{172,255,4629},{152,255,1633},{144,255,433},{129,248,179},{255,70,7578}, +{101,255,2949},{73,255,5},{0,222,1954},{255,165,7578},{0,222,1954},{110,255,4685},{110,255,4685},{110,255,4685},{96,247,2665},{89,255,3960},{64,255,75},{64,255,75},{54,190,258},{0,239,2571},{0,197,26},{144,255,433},{144,255,433},{144,255,433},{132,230,0},{245,0,2178},{73,255,5},{73,255,5},{0,197,1},{254,121,2178},{0,197,1},{255,164,1625},{186,255,605},{170,255,0},{79,255,0},{255,164,1625},{255,211,1625},{79,255,0}, +{0,226,1625},{255,211,1625},{0,226,1625},{95,0,2665},{95,0,2665},{95,0,2665},{95,0,2665},{64,255,50},{64,255,50},{64,255,50},{59,167,0},{0,193,20},{0,193,20},{138,255,11970},{125,255,6797},{119,255,4909},{104,255,2665},{129,255,13086},{82,255,3411},{73,255,185},{57,221,2210},{22,255,8987},{0,225,1431},{178,255,4049},{161,255,1537},{153,255,530},{137,250,83},{255,86,6661},{113,255,2525},{86,255,40},{0,225,1382},{255,172,6661}, +{0,225,1382},{119,255,4909},{119,255,4909},{119,255,4909},{104,255,2665},{98,255,4197},{73,255,185},{73,255,185},{62,198,258},{0,251,2435},{1,206,2},{153,255,530},{153,255,530},{153,255,530},{140,238,0},{255,4,2178},{86,255,40},{86,255,40},{4,206,0},{255,132,2178},{4,206,0},{255,177,1201},{195,255,442},{181,255,0},{104,255,0},{255,177,1201},{254,217,1201},{104,255,0},{0,230,1201},{254,217,1201},{0,230,1201},{103,0,2665}, +{103,0,2665},{103,0,2665},{103,0,2665},{73,255,85},{73,255,85},{73,255,85},{67,175,0},{0,208,1},{0,208,1},{147,255,11330},{132,255,6786},{129,255,5126},{113,255,2694},{135,255,12250},{95,255,3225},{86,255,353},{67,225,1710},{37,255,8326},{0,231,915},{184,255,3541},{167,255,1469},{162,255,637},{146,253,24},{255,104,5829},{125,255,2165},{101,255,97},{0,231,914},{255,181,5829},{0,231,914},{129,255,5126},{129,255,5126},{129,255,5126}, +{113,255,2694},{107,255,4452},{86,255,353},{86,255,353},{72,205,259},{1,255,2421},{9,214,2},{162,255,637},{162,255,637},{162,255,637},{148,245,0},{255,28,2178},{101,255,97},{101,255,97},{12,214,0},{255,144,2178},{12,214,0},{255,189,841},{204,255,305},{193,255,0},{128,255,0},{255,189,841},{254,223,841},{128,255,0},{0,234,841},{254,223,841},{0,234,841},{111,0,2665},{111,0,2665},{111,0,2665},{111,0,2665},{82,255,130}, +{82,255,130},{82,255,130},{75,183,0},{6,217,0},{6,217,0},{153,255,10758},{141,255,6807},{135,255,5354},{122,255,2777},{144,255,11503},{104,255,3102},{95,255,569},{75,230,1282},{49,255,7825},{3,237,574},{190,255,3105},{177,255,1427},{172,255,740},{156,254,1},{255,119,5082},{137,255,1869},{116,255,180},{0,237,558},{254,189,5082},{0,237,558},{135,255,5354},{135,255,5354},{135,255,5354},{122,255,2777},{119,255,4724},{95,255,569},{95,255,569}, +{79,213,266},{16,255,2587},{16,222,1},{172,255,740},{172,255,740},{172,255,740},{156,253,0},{255,52,2178},{116,255,180},{116,255,180},{20,222,0},{255,156,2178},{20,222,0},{255,201,545},{216,255,193},{205,255,0},{152,255,0},{255,201,545},{254,229,545},{152,255,0},{0,238,545},{254,229,545},{0,238,545},{119,0,2665},{119,0,2665},{119,0,2665},{119,0,2665},{89,255,180},{89,255,180},{89,255,180},{83,191,0},{15,224,0}, +{15,224,0},{162,255,10197},{150,255,6861},{144,255,5645},{131,255,2933},{153,255,10765},{116,255,3051},{107,255,882},{84,236,891},{64,255,7297},{17,242,300},{199,255,2694},{186,255,1409},{181,255,881},{167,255,20},{255,137,4344},{152,255,1611},{131,255,305},{4,243,288},{254,198,4344},{4,243,288},{144,255,5645},{144,255,5645},{144,255,5645},{131,255,2933},{129,255,5005},{107,255,882},{107,255,882},{88,222,266},{34,255,2824},{25,231,1},{181,255,881}, +{181,255,881},{181,255,881},{167,255,20},{255,79,2178},{131,255,305},{131,255,305},{28,231,0},{253,170,2178},{28,231,0},{255,216,288},{225,255,97},{218,255,0},{180,255,0},{255,216,288},{255,236,288},{180,255,0},{0,243,288},{255,236,288},{0,243,288},{128,0,2665},{128,0,2665},{128,0,2665},{128,0,2665},{101,255,250},{101,255,250},{101,255,250},{92,200,0},{24,233,0},{24,233,0},{172,255,9731},{159,255,6942},{153,255,5913}, +{140,255,3130},{162,255,10204},{125,255,3090},{116,255,1218},{94,240,623},{79,255,6924},{27,246,132},{205,255,2402},{196,255,1419},{190,255,1018},{177,255,97},{255,152,3779},{164,255,1451},{146,255,442},{20,247,128},{255,205,3779},{20,247,128},{153,255,5913},{153,255,5913},{153,255,5913},{140,255,3130},{138,255,5304},{116,255,1218},{116,255,1218},{96,230,266},{49,255,3115},{33,239,1},{190,255,1018},{190,255,1018},{190,255,1018},{177,255,97},{255,104,2178}, +{146,255,442},{146,255,442},{36,239,0},{255,181,2178},{36,239,0},{255,228,128},{234,255,40},{230,255,0},{204,255,0},{255,228,128},{255,242,128},{204,255,0},{0,247,128},{255,242,128},{0,247,128},{136,0,2665},{136,0,2665},{136,0,2665},{136,0,2665},{110,255,325},{110,255,325},{110,255,325},{100,208,0},{32,241,0},{32,241,0},{175,255,9359},{165,255,7050},{162,255,6193},{149,255,3381},{172,255,9691},{134,255,3207},{128,255,1610}, +{102,245,429},{92,255,6719},{38,251,32},{215,255,2156},{205,255,1457},{199,255,1165},{186,255,221},{255,171,3299},{177,255,1398},{161,255,605},{36,251,32},{254,214,3299},{36,251,32},{162,255,6193},{162,255,6193},{162,255,6193},{149,255,3381},{147,255,5621},{128,255,1610},{128,255,1610},{104,238,266},{67,255,3419},{41,247,2},{199,255,1165},{199,255,1165},{199,255,1165},{186,255,221},{255,128,2178},{161,255,605},{161,255,605},{44,247,0},{255,193,2178}, +{44,247,0},{255,240,32},{246,255,8},{242,255,0},{228,255,0},{255,240,32},{255,248,32},{228,255,0},{0,251,32},{255,248,32},{0,251,32},{144,0,2665},{144,0,2665},{144,0,2665},{144,0,2665},{119,255,410},{119,255,410},{119,255,410},{108,216,0},{39,250,0},{39,250,0},{184,255,9067},{175,255,7162},{172,255,6450},{158,255,3686},{175,255,9268},{146,255,3399},{137,255,2054},{110,250,311},{107,255,6532},{49,255,2},{221,255,1992}, +{211,255,1521},{208,255,1322},{195,255,397},{255,186,2904},{189,255,1366},{174,255,820},{52,255,0},{255,221,2904},{52,255,0},{172,255,6450},{172,255,6450},{172,255,6450},{158,255,3686},{159,255,5949},{137,255,2054},{137,255,2054},{112,246,266},{82,255,3765},{49,255,2},{208,255,1322},{208,255,1322},{208,255,1322},{195,255,397},{255,152,2178},{174,255,820},{174,255,820},{52,255,0},{255,205,2178},{52,255,0},{255,252,0},{255,254,0},{254,255,0}, +{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{152,0,2665},{152,0,2665},{152,0,2665},{152,0,2665},{129,255,493},{129,255,493},{129,255,493},{116,224,0},{49,255,2},{49,255,2},{190,255,7987},{181,255,6402},{178,255,5810},{167,255,3509},{184,255,7999},{155,255,3048},{146,255,1922},{121,252,155},{119,255,5562},{64,255,29},{224,255,1476},{218,255,1120},{215,255,965},{204,255,292},{255,195,2166}, +{198,255,1009},{186,255,605},{79,255,0},{254,226,2166},{79,255,0},{178,255,5810},{178,255,5810},{178,255,5810},{167,255,3509},{165,255,5209},{146,255,1922},{146,255,1922},{121,249,133},{95,255,3258},{64,255,29},{215,255,965},{215,255,965},{215,255,965},{204,255,292},{255,164,1625},{186,255,605},{186,255,605},{79,255,0},{255,211,1625},{79,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0}, +{0,255,0},{255,254,0},{0,255,0},{161,0,2665},{161,0,2665},{161,0,2665},{161,0,2665},{138,255,610},{138,255,610},{138,255,610},{125,233,0},{64,255,29},{64,255,29},{196,255,7111},{187,255,5786},{184,255,5294},{174,255,3381},{187,255,6982},{161,255,2780},{155,255,1832},{131,253,61},{128,255,4795},{79,255,80},{230,255,1088},{224,255,824},{221,255,709},{210,255,212},{255,204,1601},{204,255,737},{195,255,442},{104,255,0},{255,230,1601}, +{104,255,0},{184,255,5294},{184,255,5294},{184,255,5294},{174,255,3381},{172,255,4582},{155,255,1832},{155,255,1832},{132,251,53},{107,255,2834},{79,255,80},{221,255,709},{221,255,709},{221,255,709},{210,255,212},{255,177,1201},{195,255,442},{195,255,442},{104,255,0},{254,217,1201},{104,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{169,0,2665}, +{169,0,2665},{169,0,2665},{169,0,2665},{147,255,725},{147,255,725},{147,255,725},{133,241,0},{79,255,80},{79,255,80},{202,255,6315},{193,255,5226},{190,255,4826},{180,255,3253},{193,255,6066},{167,255,2568},{164,255,1770},{141,254,11},{137,255,4122},{92,255,169},{233,255,753},{227,255,574},{227,255,493},{219,255,146},{255,210,1121},{213,255,507},{204,255,305},{128,255,0},{255,233,1121},{128,255,0},{190,255,4826},{190,255,4826},{190,255,4826}, +{180,255,3253},{181,255,4065},{164,255,1770},{164,255,1770},{140,253,9},{119,255,2474},{92,255,169},{227,255,493},{227,255,493},{227,255,493},{219,255,146},{255,189,841},{204,255,305},{204,255,305},{128,255,0},{254,223,841},{128,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{177,0,2665},{177,0,2665},{177,0,2665},{177,0,2665},{156,255,850}, +{156,255,850},{156,255,850},{141,249,0},{92,255,169},{92,255,169},{208,255,5599},{199,255,4722},{199,255,4398},{189,255,3130},{199,255,5254},{177,255,2395},{171,255,1742},{149,255,1},{149,255,3538},{107,255,274},{236,255,484},{233,255,366},{233,255,317},{225,255,90},{255,219,726},{222,255,321},{216,255,193},{152,255,0},{254,238,726},{152,255,0},{199,255,4398},{199,255,4398},{199,255,4398},{189,255,3130},{187,255,3613},{171,255,1742},{171,255,1742}, +{149,255,1},{131,255,2178},{107,255,274},{233,255,317},{233,255,317},{233,255,317},{225,255,90},{255,201,545},{216,255,193},{216,255,193},{152,255,0},{254,229,545},{152,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{185,0,2665},{185,0,2665},{185,0,2665},{185,0,2665},{165,255,985},{165,255,985},{165,255,985},{149,255,1},{107,255,274}, +{107,255,274},{43,255,50657},{1,255,1974},{0,182,128},{0,176,4572},{36,255,59540},{0,242,19268},{0,176,7306},{0,160,23941},{0,187,65535},{0,148,40590},{21,255,10267},{0,248,1412},{0,179,137},{0,148,3929},{115,0,18065},{0,153,12036},{0,139,6077},{0,93,14060},{234,0,18065},{0,93,14060},{0,143,0},{0,143,0},{0,143,0},{0,70,0},{0,70,1105},{0,57,405},{0,57,405},{0,34,653},{0,33,1209},{0,31,756},{0,143,0}, +{0,143,0},{0,143,0},{0,70,0},{35,0,1105},{0,57,405},{0,57,405},{0,34,653},{70,0,1105},{0,34,653},{171,0,9248},{0,248,1412},{0,179,137},{0,148,3929},{171,0,9248},{255,46,9248},{0,148,3929},{0,115,9248},{255,46,9248},{0,115,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{43,255,53600},{4,255,2885},{0,191,38}, +{0,185,3941},{43,255,62123},{0,254,18376},{0,182,6726},{0,169,23131},{0,196,65535},{0,154,40086},{27,255,10859},{0,254,1184},{0,188,45},{0,157,3656},{122,0,19334},{0,162,12449},{0,145,6089},{0,102,14754},{249,0,19334},{0,102,14754},{0,167,0},{0,167,0},{0,167,0},{0,82,0},{0,82,1513},{0,66,562},{0,66,562},{0,37,900},{0,36,1658},{0,37,1044},{0,167,0},{0,167,0},{0,167,0},{0,82,0},{41,0,1513}, +{0,66,562},{0,66,562},{0,37,900},{82,0,1513},{0,37,900},{183,0,9248},{0,254,1184},{0,188,45},{0,157,3656},{183,0,9248},{255,58,9248},{0,157,3656},{0,123,9248},{255,58,9248},{0,123,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{46,255,56765},{7,255,4404},{0,199,3},{0,194,3404},{43,255,64774},{1,255,17986},{0,191,6229}, +{0,176,22449},{0,215,65535},{0,160,39678},{33,255,11587},{1,255,1171},{0,199,4},{0,166,3393},{129,0,20689},{0,172,12834},{0,154,6125},{0,108,15490},{254,5,20689},{0,108,15490},{0,192,0},{0,192,0},{0,192,0},{0,94,0},{0,95,1985},{0,75,745},{0,75,745},{0,44,1202},{0,42,2178},{0,40,1374},{0,192,0},{0,192,0},{0,192,0},{0,94,0},{46,0,1985},{0,75,745},{0,75,745},{0,44,1202},{95,0,1985}, +{0,44,1202},{195,0,9248},{1,255,1170},{0,199,4},{0,166,3393},{195,0,9248},{255,70,9248},{0,166,3393},{0,131,9248},{255,70,9248},{0,131,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{49,255,58131},{7,255,6200},{0,207,6},{0,203,2858},{46,255,65535},{1,255,17772},{0,200,5638},{0,182,21148},{0,215,63337},{0,166,38166},{43,255,12449}, +{1,255,1395},{1,208,6},{0,176,3170},{138,0,22129},{0,184,13298},{0,163,6189},{0,114,16274},{254,14,22129},{0,114,16274},{0,216,0},{0,216,0},{0,216,0},{0,106,0},{0,107,2521},{0,88,928},{0,88,928},{0,50,1530},{0,48,2770},{0,47,1762},{0,216,0},{0,216,0},{0,216,0},{0,106,0},{52,0,2521},{0,88,928},{0,88,928},{0,50,1530},{107,0,2521},{0,50,1530},{207,0,9248},{7,255,1378},{5,207,0}, +{0,176,3170},{207,0,9248},{255,82,9248},{0,176,3170},{0,139,9248},{255,82,9248},{0,139,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{55,255,58853},{10,255,8410},{0,216,47},{0,212,2312},{52,255,65535},{4,255,18024},{0,209,5015},{0,191,19619},{0,224,60697},{0,176,36050},{46,255,13542},{7,255,1877},{4,217,53},{0,185,2897},{147,0,23851}, +{0,196,13856},{0,173,6281},{0,120,17216},{254,23,23851},{0,120,17216},{0,243,0},{0,243,0},{0,243,0},{0,119,0},{0,122,3200},{0,97,1186},{0,97,1186},{0,56,1945},{0,54,3521},{0,53,2243},{0,243,0},{0,243,0},{0,243,0},{0,119,0},{60,0,3200},{0,97,1186},{0,97,1186},{0,56,1945},{122,0,3200},{0,56,1945},{220,0,9248},{22,255,1693},{14,216,0},{0,185,2897},{220,0,9248},{255,95,9248},{0,185,2897}, +{0,148,9248},{255,95,9248},{0,148,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{58,255,59395},{13,255,10486},{0,225,107},{0,219,1933},{55,255,65535},{7,255,18658},{0,215,4619},{0,200,18436},{0,233,58566},{0,182,34489},{52,255,14690},{13,255,2489},{6,228,133},{0,194,2664},{155,0,25472},{0,208,14384},{0,182,6401},{0,126,18104},{255,30,25472}, +{0,126,18104},{0,255,16},{0,255,16},{0,255,16},{0,131,0},{0,134,3872},{0,106,1445},{0,106,1445},{0,62,2357},{0,60,4265},{0,56,2717},{2,254,13},{2,254,13},{2,254,13},{0,131,0},{66,0,3872},{0,106,1445},{0,106,1445},{0,62,2357},{134,0,3872},{0,62,2357},{232,0,9248},{37,255,2000},{22,224,0},{0,194,2664},{232,0,9248},{255,107,9248},{0,194,2664},{0,156,9248},{255,107,9248},{0,156,9248},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{61,255,59976},{16,255,12621},{2,233,174},{0,228,1613},{58,255,65535},{10,255,19459},{0,224,4093},{0,206,17181},{0,242,56514},{0,188,32973},{58,255,15746},{19,255,3205},{10,235,217},{0,206,2444},{164,0,26744},{0,218,14587},{0,191,6305},{0,136,18737},{255,39,26744},{0,136,18737},{3,255,110},{3,255,110},{3,255,110}, +{1,142,2},{0,149,4418},{0,118,1585},{0,118,1585},{0,68,2633},{0,66,4909},{0,62,3077},{6,255,80},{6,255,80},{6,255,80},{2,142,0},{73,0,4418},{0,118,1585},{0,118,1585},{0,68,2633},{149,0,4418},{0,68,2633},{244,0,9248},{49,255,2377},{30,232,0},{0,206,2440},{244,0,9248},{255,119,9248},{0,206,2440},{0,164,9248},{255,119,9248},{0,164,9248},{1,0,2},{1,0,2},{1,0,2},{1,0,2},{0,7,0}, +{0,7,0},{0,7,0},{0,3,0},{0,3,0},{0,3,0},{67,255,60796},{19,255,14846},{3,240,286},{0,234,1405},{64,255,65535},{13,255,20226},{0,233,3321},{0,212,15538},{0,254,54317},{0,197,31240},{67,255,16195},{31,255,3805},{18,243,217},{0,212,2328},{175,0,26744},{0,230,14051},{0,200,5525},{0,142,18273},{254,51,26744},{0,142,18273},{9,255,278},{9,255,278},{9,255,278},{5,152,50},{0,174,4418},{0,129,1313},{0,129,1313}, +{0,77,2410},{0,75,5092},{0,71,2987},{15,255,125},{15,255,125},{15,255,125},{10,150,0},{85,0,4418},{0,129,1313},{0,129,1313},{0,77,2410},{174,0,4418},{0,77,2410},{255,1,9248},{64,255,2738},{37,240,0},{0,212,2228},{255,1,9248},{254,131,9248},{0,212,2228},{0,172,9248},{254,131,9248},{0,172,9248},{5,0,50},{5,0,50},{5,0,50},{5,0,50},{0,31,0},{0,31,0},{0,31,0},{0,15,0},{0,12,13}, +{0,12,13},{70,255,61549},{25,255,17357},{4,250,459},{1,244,1256},{70,255,65535},{16,255,21346},{0,242,2603},{0,225,13862},{0,254,52221},{0,206,29474},{79,255,16720},{43,255,4545},{27,252,217},{7,223,2341},{189,0,26744},{0,245,13481},{0,212,4710},{0,154,17762},{255,64,26744},{0,154,17762},{15,255,602},{15,255,602},{15,255,602},{10,163,181},{0,201,4418},{0,147,1037},{0,147,1037},{0,83,2196},{0,88,5300},{0,80,2921},{27,255,185}, +{27,255,185},{27,255,185},{19,159,0},{98,0,4418},{0,147,1037},{0,147,1037},{0,83,2196},{201,0,4418},{0,83,2196},{255,28,9248},{82,255,3176},{46,249,0},{0,225,2020},{255,28,9248},{255,144,9248},{0,225,2020},{0,181,9248},{255,144,9248},{0,181,9248},{9,0,181},{9,0,181},{9,0,181},{9,0,181},{0,58,0},{0,58,0},{0,58,0},{0,29,0},{0,24,58},{0,24,58},{73,255,62082},{28,255,19099},{6,255,688}, +{2,251,1170},{73,255,65535},{19,255,22086},{0,248,2054},{0,231,12530},{0,254,51038},{0,212,28165},{86,255,16691},{52,255,4985},{36,255,250},{14,230,2238},{199,0,26259},{0,254,12692},{0,221,3965},{0,160,16946},{254,75,26259},{0,160,16946},{21,255,1006},{21,255,1006},{21,255,1006},{14,173,365},{0,225,4418},{0,162,820},{0,162,820},{0,96,1994},{0,100,5540},{0,90,2891},{36,255,250},{36,255,250},{36,255,250},{27,167,0},{110,0,4418}, +{0,162,820},{0,162,820},{0,96,1994},{225,0,4418},{0,96,1994},{255,49,8978},{95,255,3433},{55,255,0},{0,231,1732},{255,49,8978},{254,155,8978},{0,231,1732},{0,188,8978},{254,155,8978},{0,188,8978},{13,0,365},{13,0,365},{13,0,365},{13,0,365},{0,82,0},{0,82,0},{0,82,0},{0,41,0},{0,33,125},{0,33,125},{76,255,62399},{28,255,19454},{6,255,1075},{2,251,1090},{73,255,65535},{19,255,21590},{0,250,1503}, +{0,231,11251},{0,254,50424},{0,212,27242},{95,255,15410},{58,255,4661},{46,255,317},{24,231,1853},{208,0,24371},{0,254,11124},{0,227,2881},{0,166,15066},{254,84,24371},{0,166,15066},{27,255,1522},{27,255,1522},{27,255,1522},{17,183,613},{0,249,4418},{0,175,605},{0,175,605},{0,105,1801},{0,109,5805},{0,97,2885},{46,255,317},{46,255,317},{46,255,317},{35,175,0},{122,0,4418},{0,175,605},{0,175,605},{0,105,1801},{249,0,4418}, +{0,105,1801},{255,61,7938},{104,255,3026},{67,255,0},{0,237,1224},{255,61,7938},{254,161,7938},{0,237,1224},{0,192,7938},{254,161,7938},{0,192,7938},{17,0,613},{17,0,613},{17,0,613},{17,0,613},{0,107,0},{0,107,0},{0,107,0},{0,52,0},{0,42,218},{0,42,218},{76,255,62711},{28,255,19886},{9,255,1549},{3,252,1093},{73,255,65535},{19,255,21152},{0,251,1032},{0,234,10008},{0,254,49821},{0,212,26360},{101,255,14198}, +{67,255,4361},{55,255,400},{33,234,1502},{215,0,22568},{1,255,9795},{0,230,1973},{0,169,13320},{254,91,22568},{0,169,13320},{33,255,2150},{33,255,2150},{33,255,2150},{21,193,925},{3,255,4459},{0,190,442},{0,190,442},{0,114,1618},{0,121,6101},{0,106,2901},{55,255,400},{55,255,400},{55,255,400},{43,183,0},{134,0,4418},{0,190,442},{0,190,442},{0,114,1618},{255,9,4418},{0,114,1618},{255,73,6962},{113,255,2645},{79,255,0}, +{0,240,801},{255,73,6962},{254,167,6962},{0,240,801},{0,196,6962},{254,167,6962},{0,196,6962},{21,0,925},{21,0,925},{21,0,925},{21,0,925},{0,131,0},{0,131,0},{0,131,0},{0,64,0},{0,51,337},{0,51,337},{76,255,63078},{31,255,20439},{9,255,2192},{4,253,1202},{76,255,65535},{19,255,20732},{0,251,606},{0,234,8676},{0,254,49164},{0,212,25424},{110,255,12917},{79,255,4059},{64,255,505},{43,234,1147},{224,0,20642}, +{1,255,8589},{0,236,1155},{0,179,11489},{254,100,20642},{0,179,11489},{39,255,2986},{39,255,2986},{39,255,2986},{26,204,1352},{12,255,4660},{0,205,289},{0,205,289},{0,126,1424},{0,132,6467},{0,115,2955},{64,255,505},{64,255,505},{64,255,505},{52,192,0},{147,0,4418},{0,205,289},{0,205,289},{0,126,1424},{254,23,4418},{0,126,1424},{255,86,5941},{125,255,2248},{92,255,0},{0,243,433},{255,86,5941},{255,172,5941},{0,243,433}, +{0,200,5941},{255,172,5941},{0,200,5941},{26,0,1352},{26,0,1352},{26,0,1352},{26,0,1352},{0,158,0},{0,158,0},{0,158,0},{0,78,0},{0,63,500},{0,63,500},{79,255,63411},{31,255,21008},{12,255,2858},{7,253,1393},{76,255,65535},{22,255,20416},{0,253,320},{0,237,7549},{0,254,48613},{0,218,24643},{116,255,11849},{82,255,3845},{73,255,610},{53,238,867},{232,0,19021},{10,255,7741},{0,242,611},{0,182,9957},{255,107,19021}, +{0,182,9957},{43,255,3819},{43,255,3819},{43,255,3819},{30,214,1800},{15,255,4981},{0,221,169},{0,221,169},{0,133,1282},{0,141,6822},{0,124,3029},{73,255,610},{73,255,610},{73,255,610},{60,200,0},{159,0,4418},{0,221,169},{0,221,169},{0,133,1282},{254,35,4418},{0,133,1282},{255,98,5101},{134,255,1921},{104,255,0},{0,246,202},{255,98,5101},{255,178,5101},{0,246,202},{0,204,5101},{255,178,5101},{0,204,5101},{30,0,1800}, +{30,0,1800},{30,0,1800},{30,0,1800},{0,183,0},{0,183,0},{0,183,0},{0,89,0},{0,72,673},{0,72,673},{86,255,63733},{34,255,21637},{12,255,3614},{8,254,1668},{76,255,65535},{22,255,20164},{0,254,123},{0,237,6489},{0,254,48082},{0,218,23857},{122,255,10853},{95,255,3629},{86,255,724},{62,241,632},{241,0,17485},{22,255,6965},{0,248,243},{0,188,8529},{255,116,17485},{0,188,8529},{49,255,4787},{49,255,4787},{49,255,4787}, +{34,224,2312},{21,255,5437},{0,233,89},{0,233,89},{0,142,1129},{0,153,7206},{0,133,3131},{86,255,724},{86,255,724},{86,255,724},{68,207,0},{171,0,4418},{0,233,89},{0,233,89},{0,142,1129},{255,46,4418},{0,142,1129},{255,110,4325},{143,255,1620},{116,255,0},{0,252,58},{255,110,4325},{255,184,4325},{0,252,58},{0,208,4325},{255,184,4325},{0,208,4325},{34,0,2312},{34,0,2312},{34,0,2312},{34,0,2312},{0,207,0}, +{0,207,0},{0,207,0},{0,101,0},{0,88,865},{0,88,865},{86,255,63992},{34,255,22322},{15,255,4457},{8,255,2033},{76,255,65535},{22,255,19980},{0,254,23},{0,240,5494},{0,254,47573},{0,218,23129},{129,255,9866},{104,255,3441},{92,255,832},{71,244,435},{248,0,16034},{34,255,6253},{0,254,51},{0,194,7213},{254,124,16034},{0,194,7213},{55,255,5867},{55,255,5867},{55,255,5867},{38,234,2888},{27,255,6029},{0,248,34},{0,248,34}, +{0,154,985},{0,162,7619},{0,142,3261},{92,255,832},{92,255,832},{92,255,832},{76,215,0},{183,0,4418},{0,248,34},{0,248,34},{0,154,985},{255,58,4418},{0,154,985},{255,122,3613},{152,255,1345},{128,255,0},{0,255,1},{255,122,3613},{255,190,3613},{0,255,1},{0,212,3613},{255,190,3613},{0,212,3613},{38,0,2888},{38,0,2888},{38,0,2888},{38,0,2888},{0,231,0},{0,231,0},{0,231,0},{0,113,0},{0,91,1066}, +{0,91,1066},{86,255,64310},{37,255,23174},{15,255,5504},{10,255,2546},{79,255,65535},{25,255,19854},{1,255,23},{0,240,4466},{0,254,47048},{0,221,22366},{138,255,8897},{113,255,3261},{101,255,985},{80,247,258},{255,4,14504},{40,255,5561},{7,255,34},{0,200,5867},{255,132,14504},{0,200,5867},{61,255,7213},{61,255,7213},{61,255,7213},{42,245,3613},{33,255,6859},{1,255,51},{1,255,51},{0,163,832},{0,175,8059},{0,151,3441},{101,255,985}, +{101,255,985},{101,255,985},{85,224,0},{196,0,4418},{7,255,34},{7,255,34},{0,163,832},{254,72,4418},{0,163,832},{255,137,2888},{164,255,1066},{141,255,0},{22,255,0},{255,137,2888},{254,198,2888},{22,255,0},{0,217,2888},{254,198,2888},{0,217,2888},{42,0,3613},{42,0,3613},{42,0,3613},{42,0,3613},{0,255,1},{0,255,1},{0,255,1},{0,127,0},{0,103,1345},{0,103,1345},{86,255,64605},{37,255,23983},{18,255,6523}, +{10,255,3097},{86,255,65535},{25,255,19808},{1,255,124},{0,243,3633},{0,254,46617},{0,221,21751},{144,255,8113},{122,255,3131},{113,255,1129},{90,248,139},{255,19,13235},{58,255,5012},{22,255,89},{0,206,4787},{254,140,13235},{0,206,4787},{67,255,8529},{67,255,8529},{67,255,8529},{46,255,4325},{43,255,7725},{7,255,243},{7,255,243},{0,169,724},{0,184,8530},{0,160,3629},{113,255,1129},{113,255,1129},{113,255,1129},{93,232,0},{208,0,4418}, +{22,255,89},{22,255,89},{0,169,724},{254,84,4418},{0,169,724},{255,149,2312},{167,255,865},{153,255,0},{46,255,0},{255,149,2312},{254,204,2312},{46,255,0},{0,221,2312},{254,204,2312},{0,221,2312},{46,0,4325},{46,0,4325},{46,0,4325},{46,0,4325},{3,255,58},{3,255,58},{3,255,58},{0,138,0},{0,112,1620},{0,112,1620},{86,255,64960},{37,255,24878},{18,255,7621},{13,255,3738},{86,255,65535},{25,255,19851},{2,255,323}, +{0,243,2885},{0,254,46257},{0,224,21209},{153,255,7392},{131,255,3029},{122,255,1282},{99,251,56},{255,37,12051},{70,255,4500},{34,255,169},{0,212,3819},{254,149,12051},{0,212,3819},{70,255,9957},{70,255,9957},{70,255,9957},{52,255,5141},{46,255,8712},{13,255,611},{13,255,611},{0,182,610},{0,196,9026},{0,169,3845},{122,255,1282},{122,255,1282},{122,255,1282},{101,240,0},{220,0,4418},{34,255,169},{34,255,169},{0,182,610},{255,95,4418}, +{0,182,610},{255,161,1800},{183,255,673},{165,255,0},{70,255,0},{255,161,1800},{254,210,1800},{70,255,0},{0,225,1800},{254,210,1800},{0,225,1800},{50,0,5101},{50,0,5101},{50,0,5101},{50,0,5101},{9,255,202},{9,255,202},{9,255,202},{0,150,0},{0,121,1921},{0,121,1921},{86,255,65314},{43,255,25774},{21,255,8796},{13,255,4456},{86,255,65535},{25,255,19965},{4,255,614},{0,246,2222},{0,254,45929},{0,224,20720},{159,255,6740}, +{140,255,2955},{129,255,1424},{108,254,11},{255,52,10952},{82,255,4052},{49,255,289},{0,216,2986},{255,156,10952},{0,216,2986},{76,255,11489},{76,255,11489},{76,255,11489},{58,255,6109},{52,255,9860},{19,255,1155},{19,255,1155},{0,191,505},{0,208,9554},{0,176,4059},{129,255,1424},{129,255,1424},{129,255,1424},{109,248,0},{232,0,4418},{49,255,289},{49,255,289},{0,191,505},{255,107,4418},{0,191,505},{255,174,1352},{192,255,500},{177,255,0}, +{95,255,0},{255,174,1352},{255,215,1352},{95,255,0},{0,229,1352},{255,215,1352},{0,229,1352},{54,0,5941},{54,0,5941},{54,0,5941},{54,0,5941},{12,255,433},{12,255,433},{12,255,433},{0,162,0},{0,129,2248},{0,129,2248},{86,255,65535},{43,255,26766},{21,255,10162},{13,255,5358},{86,255,65359},{28,255,20101},{4,255,1047},{0,246,1573},{0,254,45474},{0,227,20192},{172,255,6085},{149,255,2901},{141,255,1618},{119,255,2},{255,70,9818}, +{95,255,3685},{64,255,442},{0,222,2150},{255,165,9818},{0,222,2150},{86,255,13320},{86,255,13320},{86,255,13320},{61,255,7370},{58,255,11310},{22,255,1973},{22,255,1973},{0,200,400},{0,218,10107},{0,188,4361},{141,255,1618},{141,255,1618},{141,255,1618},{119,255,2},{245,0,4418},{64,255,442},{64,255,442},{0,200,400},{254,121,4418},{0,200,400},{255,186,925},{204,255,337},{190,255,0},{122,255,0},{255,186,925},{255,221,925},{122,255,0}, +{0,233,925},{255,221,925},{0,233,925},{59,0,6962},{59,0,6962},{59,0,6962},{59,0,6962},{15,255,801},{15,255,801},{15,255,801},{0,175,0},{0,141,2645},{0,141,2645},{86,255,65535},{43,255,27616},{24,255,11405},{16,255,6203},{86,255,65014},{28,255,20233},{5,255,1524},{0,249,1090},{1,255,44974},{0,227,19721},{175,255,5534},{156,255,2885},{150,255,1801},{128,255,40},{255,86,8901},{107,255,3373},{79,255,605},{0,228,1522},{255,172,8901}, +{0,228,1522},{89,255,15066},{89,255,15066},{89,255,15066},{67,255,8646},{64,255,12746},{28,255,2881},{28,255,2881},{0,209,317},{0,230,10691},{0,194,4661},{150,255,1801},{150,255,1801},{150,255,1801},{128,255,40},{255,4,4418},{79,255,605},{79,255,605},{0,209,317},{255,132,4418},{0,209,317},{255,198,613},{213,255,218},{202,255,0},{146,255,0},{255,198,613},{255,227,613},{146,255,0},{0,237,613},{255,227,613},{0,237,613},{63,0,7938}, +{63,0,7938},{63,0,7938},{63,0,7938},{18,255,1224},{18,255,1224},{18,255,1224},{0,187,0},{0,150,3026},{0,150,3026},{89,255,65535},{43,255,28505},{24,255,12681},{16,255,7117},{86,255,64678},{28,255,20430},{7,255,2079},{0,249,697},{1,255,44506},{0,227,19330},{181,255,5094},{165,255,2891},{159,255,1994},{137,255,130},{255,104,8069},{119,255,3125},{92,255,820},{0,234,1006},{255,181,8069},{0,234,1006},{95,255,16946},{95,255,16946},{95,255,16946}, +{73,255,10074},{67,255,14315},{34,255,3965},{34,255,3965},{0,219,250},{0,239,11302},{0,203,4985},{159,255,1994},{159,255,1994},{159,255,1994},{137,255,130},{255,28,4418},{92,255,820},{92,255,820},{0,219,250},{255,144,4418},{0,219,250},{255,210,365},{222,255,125},{214,255,0},{171,255,0},{255,210,365},{255,233,365},{171,255,0},{0,241,365},{255,233,365},{0,241,365},{67,0,8978},{67,0,8978},{67,0,8978},{67,0,8978},{24,255,1732}, +{24,255,1732},{24,255,1732},{0,199,0},{0,159,3433},{0,159,3433},{92,255,65535},{49,255,29231},{30,255,13748},{22,255,7832},{89,255,64474},{34,255,20616},{13,255,2581},{5,251,455},{1,255,43254},{0,230,17214},{187,255,4726},{175,255,2921},{172,255,2196},{146,255,272},{255,119,7322},{131,255,2941},{107,255,1037},{0,240,602},{254,189,7322},{0,240,602},{101,255,17762},{101,255,17762},{101,255,17762},{79,255,10742},{76,255,15150},{43,255,4710},{43,255,4710}, +{3,228,217},{0,251,10994},{0,212,4545},{172,255,2196},{172,255,2196},{172,255,2196},{146,255,272},{255,52,4418},{107,255,1037},{107,255,1037},{0,228,185},{255,156,4418},{0,228,185},{255,222,181},{231,255,58},{226,255,0},{195,255,0},{255,222,181},{255,239,181},{195,255,0},{0,245,181},{255,239,181},{0,245,181},{74,0,9248},{74,0,9248},{74,0,9248},{74,0,9248},{30,255,2020},{30,255,2020},{30,255,2020},{6,208,0},{0,172,3176}, +{0,172,3176},{98,255,65535},{58,255,30030},{43,255,14936},{31,255,8624},{95,255,64295},{43,255,20818},{22,255,3192},{15,252,275},{1,255,41806},{0,236,14271},{196,255,4387},{184,255,2987},{178,255,2410},{158,255,490},{255,137,6584},{146,255,2811},{125,255,1313},{0,246,278},{254,198,6584},{0,246,278},{113,255,18273},{113,255,18273},{113,255,18273},{89,255,11256},{89,255,15726},{55,255,5525},{55,255,5525},{12,237,217},{0,254,10500},{0,224,3805},{178,255,2410}, +{178,255,2410},{178,255,2410},{158,255,490},{255,79,4418},{125,255,1313},{125,255,1313},{0,240,125},{253,170,4418},{0,240,125},{255,237,50},{243,255,13},{239,255,0},{222,255,0},{255,237,50},{254,247,50},{222,255,0},{0,250,50},{254,247,50},{0,250,50},{83,0,9248},{83,0,9248},{83,0,9248},{83,0,9248},{43,255,2228},{43,255,2228},{43,255,2228},{15,217,0},{0,190,2738},{0,190,2738},{104,255,65535},{67,255,30820},{49,255,16060}, +{40,255,9410},{101,255,64140},{52,255,21086},{31,255,3826},{22,253,162},{1,255,40863},{0,239,11797},{202,255,4163},{193,255,3077},{187,255,2633},{167,255,740},{255,152,6019},{158,255,2763},{137,255,1585},{0,252,110},{255,205,6019},{0,252,110},{119,255,18737},{119,255,18737},{119,255,18737},{98,255,11747},{98,255,16315},{64,255,6305},{64,255,6305},{20,245,217},{1,255,10451},{0,236,3205},{187,255,2633},{187,255,2633},{187,255,2633},{167,255,740},{255,104,4418}, +{137,255,1585},{137,255,1585},{0,249,80},{255,181,4418},{0,249,80},{255,249,2},{252,255,0},{251,255,0},{246,255,0},{255,249,2},{254,253,2},{246,255,0},{0,254,2},{254,253,2},{0,254,2},{91,0,9248},{91,0,9248},{91,0,9248},{91,0,9248},{49,255,2440},{49,255,2440},{49,255,2440},{23,225,0},{0,205,2377},{0,205,2377},{110,255,65535},{73,255,31223},{55,255,16690},{49,255,9985},{107,255,63957},{58,255,21217},{38,255,4182}, +{30,255,97},{1,255,40169},{0,242,9493},{208,255,3603},{199,255,2717},{193,255,2357},{174,255,725},{255,164,5163},{167,255,2409},{149,255,1445},{0,255,16},{255,211,5163},{0,255,16},{129,255,18104},{129,255,18104},{129,255,18104},{107,255,11680},{107,255,15698},{73,255,6401},{73,255,6401},{27,249,133},{1,255,9723},{0,242,2489},{193,255,2357},{193,255,2357},{193,255,2357},{174,255,725},{255,119,3872},{149,255,1445},{149,255,1445},{0,252,13},{254,189,3872}, +{0,252,13},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{99,0,9248},{99,0,9248},{99,0,9248},{99,0,9248},{61,255,2664},{61,255,2664},{61,255,2664},{31,233,0},{0,218,2000},{0,218,2000},{116,255,65535},{79,255,31523},{64,255,17156},{55,255,10522},{113,255,63756},{67,255,21315},{46,255,4385},{38,254,41},{4,255,39799},{0,245,7354},{215,255,2952}, +{202,255,2243},{199,255,1945},{183,255,593},{255,171,4267},{167,255,2009},{158,255,1186},{10,255,0},{254,214,4267},{10,255,0},{135,255,17216},{135,255,17216},{135,255,17216},{116,255,11435},{113,255,14726},{82,255,6281},{82,255,6281},{38,251,53},{1,255,8923},{0,248,1877},{199,255,1945},{199,255,1945},{199,255,1945},{183,255,593},{255,131,3200},{158,255,1186},{158,255,1186},{10,255,0},{254,195,3200},{10,255,0},{255,252,0},{255,254,0},{254,255,0}, +{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{107,0,9248},{107,0,9248},{107,0,9248},{107,0,9248},{70,255,2897},{70,255,2897},{70,255,2897},{39,241,0},{0,233,1693},{0,233,1693},{122,255,65535},{89,255,32024},{73,255,17745},{64,255,11181},{119,255,63505},{73,255,21450},{55,255,4731},{48,255,5},{13,255,39517},{0,248,5202},{218,255,2308},{208,255,1762},{205,255,1530},{192,255,464},{255,180,3361}, +{183,255,1587},{167,255,928},{37,255,0},{255,218,3361},{37,255,0},{141,255,16274},{141,255,16274},{141,255,16274},{122,255,11169},{122,255,13721},{92,255,6189},{92,255,6189},{47,254,6},{13,255,8241},{0,254,1395},{205,255,1530},{205,255,1530},{205,255,1530},{192,255,464},{255,143,2521},{167,255,928},{167,255,928},{37,255,0},{254,201,2521},{37,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0}, +{0,255,0},{255,254,0},{0,255,0},{116,0,9248},{116,0,9248},{116,0,9248},{116,0,9248},{79,255,3170},{79,255,3170},{79,255,3170},{48,250,0},{0,248,1378},{0,248,1378},{129,255,65535},{95,255,32533},{79,255,18407},{73,255,11877},{129,255,63435},{82,255,21690},{64,255,5107},{56,255,2},{25,255,39436},{0,248,3611},{221,255,1809},{215,255,1374},{211,255,1202},{198,255,360},{255,189,2646},{192,255,1241},{180,255,745},{61,255,0},{254,223,2646}, +{61,255,0},{147,255,15490},{147,255,15490},{147,255,15490},{131,255,10946},{129,255,12826},{101,255,6125},{101,255,6125},{56,255,4},{25,255,7705},{0,254,1171},{211,255,1202},{211,255,1202},{211,255,1202},{198,255,360},{255,155,1985},{180,255,745},{180,255,745},{61,255,0},{254,207,1985},{61,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{124,0,9248}, +{124,0,9248},{124,0,9248},{124,0,9248},{89,255,3393},{89,255,3393},{89,255,3393},{56,255,4},{0,254,1170},{0,254,1170},{132,255,65535},{101,255,32957},{86,255,19017},{82,255,12610},{129,255,62977},{89,255,22061},{73,255,5530},{64,255,31},{34,255,39178},{0,251,2372},{224,255,1376},{218,255,1044},{218,255,900},{204,255,272},{255,198,2017},{198,255,937},{189,255,562},{86,255,0},{255,227,2017},{86,255,0},{153,255,14754},{153,255,14754},{153,255,14754}, +{137,255,10742},{135,255,12066},{107,255,6089},{107,255,6089},{67,255,45},{37,255,7233},{1,255,1184},{218,255,900},{218,255,900},{218,255,900},{204,255,272},{255,167,1513},{189,255,562},{189,255,562},{86,255,0},{253,213,1513},{86,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{132,0,9248},{132,0,9248},{132,0,9248},{132,0,9248},{98,255,3656}, +{98,255,3656},{98,255,3656},{67,255,45},{1,255,1184},{1,255,1184},{138,255,65535},{107,255,33448},{95,255,19729},{89,255,13446},{135,255,62717},{95,255,22307},{79,255,6021},{73,255,105},{40,255,38959},{0,254,1627},{230,255,996},{224,255,756},{221,255,653},{213,255,194},{255,204,1473},{207,255,675},{198,255,405},{110,255,0},{255,230,1473},{110,255,0},{162,255,14060},{162,255,14060},{162,255,14060},{146,255,10545},{141,255,11378},{116,255,6077},{116,255,6077}, +{76,255,137},{40,255,6873},{7,255,1412},{221,255,653},{221,255,653},{221,255,653},{213,255,194},{255,180,1105},{198,255,405},{198,255,405},{110,255,0},{255,218,1105},{110,255,0},{255,252,0},{255,254,0},{254,255,0},{252,255,0},{255,252,0},{255,254,0},{252,255,0},{0,255,0},{255,254,0},{0,255,0},{140,0,9248},{140,0,9248},{140,0,9248},{140,0,9248},{107,255,3929},{107,255,3929},{107,255,3929},{76,255,137},{7,255,1412}, +{7,255,1412}, diff --git a/ext/basis_universal/basisu_transcoder_tables_atc_55.inc b/ext/basis_universal/basisu_transcoder_tables_atc_55.inc new file mode 100644 index 0000000000..7acedd6a6f --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_atc_55.inc @@ -0,0 +1,481 @@ +{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{0,1,52},{0,0,68},{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{1,0,35},{0,1,61},{0,1,1},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1}, +{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{1,0,18},{0,1,10},{0,1,1},{0,1,9},{1,0,18},{0,1,18},{0,1,9},{0,1,36},{0,1,18},{0,1,36},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,4,56},{0,3,38},{0,2,52}, +{0,2,36},{0,4,56},{0,3,35},{0,2,0},{0,2,52},{0,2,88},{0,1,78},{1,3,24},{1,2,14},{1,2,5},{1,2,13},{1,2,51},{0,3,35},{0,2,0},{0,2,52},{2,1,51},{0,2,52},{0,3,37},{0,3,37},{0,3,37},{0,2,36},{0,3,10},{0,2,0},{0,2,0},{0,1,5},{0,1,35},{0,1,14},{1,2,5},{1,2,5},{1,2,5},{1,1,8},{1,1,8}, +{0,2,0},{0,2,0},{0,1,5},{1,1,8},{0,1,5},{2,1,18},{0,3,2},{1,2,1},{0,2,0},{2,1,18},{1,2,18},{0,2,0},{0,2,36},{1,2,18},{0,2,36},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{1,5,56},{1,4,38},{1,3,52},{1,3,36},{1,5,56},{1,4,35},{1,3,0}, +{1,3,52},{0,4,72},{0,3,38},{2,4,24},{2,3,14},{2,3,5},{2,3,13},{2,3,51},{0,4,24},{1,3,0},{0,3,37},{3,2,51},{0,3,37},{1,4,37},{1,4,37},{1,4,37},{1,3,36},{1,4,10},{1,3,0},{1,3,0},{1,2,5},{0,3,11},{1,2,14},{2,3,5},{2,3,5},{2,3,5},{2,2,8},{2,2,8},{1,3,0},{1,3,0},{1,2,5},{2,2,8}, +{1,2,5},{3,2,18},{1,4,2},{2,3,1},{1,3,0},{3,2,18},{7,0,18},{1,3,0},{0,3,36},{7,0,18},{0,3,36},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,3,0},{1,3,0},{1,3,0},{1,2,1},{0,3,2},{0,3,2},{2,6,56},{2,5,38},{2,4,53},{2,4,37},{2,6,56},{2,5,35},{2,4,1},{2,4,66},{0,5,60},{1,4,52},{3,5,24}, +{3,4,14},{3,4,6},{3,4,14},{3,4,51},{1,5,24},{2,4,1},{1,4,51},{9,0,51},{1,4,51},{2,5,37},{2,5,37},{2,5,37},{2,4,36},{2,5,10},{2,4,0},{2,4,0},{2,3,5},{1,4,11},{2,3,14},{3,4,5},{3,4,5},{3,4,5},{3,3,8},{3,3,8},{2,4,0},{2,4,0},{2,3,5},{8,0,8},{2,3,5},{4,3,18},{2,5,2},{3,4,2}, +{2,4,1},{4,3,18},{8,1,18},{2,4,1},{0,4,50},{8,1,18},{0,4,50},{2,0,36},{2,0,36},{2,0,36},{2,0,36},{2,4,0},{2,4,0},{2,4,0},{2,3,1},{1,4,2},{1,4,2},{3,8,70},{3,6,58},{4,5,69},{3,5,51},{3,7,52},{3,6,25},{3,5,3},{3,5,46},{2,6,60},{2,5,36},{4,6,24},{4,5,14},{4,5,5},{4,5,13},{6,2,51}, +{3,6,24},{3,5,2},{2,5,36},{7,3,51},{2,5,36},{3,7,51},{3,7,51},{3,7,51},{3,5,51},{3,6,9},{3,5,3},{3,5,3},{3,4,9},{1,6,12},{3,4,12},{4,5,5},{4,5,5},{4,5,5},{4,4,8},{6,1,8},{3,5,2},{3,5,2},{3,4,8},{11,0,8},{3,4,8},{7,1,18},{3,6,8},{4,5,1},{3,5,1},{7,1,18},{11,1,18},{3,5,1}, +{0,5,36},{11,1,18},{0,5,36},{3,0,50},{3,0,50},{3,0,50},{3,0,50},{3,5,2},{3,5,2},{3,5,2},{3,4,5},{2,5,0},{2,5,0},{4,8,56},{4,7,38},{4,6,52},{4,6,36},{4,8,56},{4,7,35},{4,6,0},{4,6,52},{3,7,60},{3,6,36},{5,7,24},{5,6,14},{5,6,5},{5,6,13},{8,1,51},{3,7,35},{4,6,0},{3,6,36},{6,5,51}, +{3,6,36},{4,7,37},{4,7,37},{4,7,37},{4,6,36},{4,7,10},{4,6,0},{4,6,0},{4,5,5},{2,7,12},{4,5,14},{5,6,5},{5,6,5},{5,6,5},{5,5,8},{8,0,8},{4,6,0},{4,6,0},{4,5,5},{5,5,8},{4,5,5},{9,0,18},{4,7,2},{5,6,1},{4,6,0},{9,0,18},{15,0,18},{4,6,0},{0,6,36},{15,0,18},{0,6,36},{4,0,36}, +{4,0,36},{4,0,36},{4,0,36},{4,6,0},{4,6,0},{4,6,0},{4,5,1},{3,6,0},{3,6,0},{5,9,56},{5,8,38},{5,7,52},{5,7,36},{5,9,56},{5,8,35},{5,7,0},{5,7,52},{3,8,63},{4,7,38},{6,8,24},{6,7,14},{6,7,5},{6,7,13},{9,2,51},{4,8,24},{5,7,0},{4,7,37},{17,0,51},{4,7,37},{5,8,37},{5,8,37},{5,8,37}, +{5,7,36},{5,8,10},{5,7,0},{5,7,0},{5,6,5},{4,7,11},{5,6,14},{6,7,5},{6,7,5},{6,7,5},{6,6,8},{9,1,8},{5,7,0},{5,7,0},{5,6,5},{16,0,8},{5,6,5},{10,1,18},{5,8,2},{6,7,1},{5,7,0},{10,1,18},{16,1,18},{5,7,0},{0,7,36},{16,1,18},{0,7,36},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,7,0}, +{5,7,0},{5,7,0},{5,6,1},{4,7,2},{4,7,2},{6,10,56},{6,9,38},{6,8,53},{6,8,37},{6,10,56},{6,9,35},{6,8,1},{6,8,66},{4,9,60},{5,8,52},{7,9,24},{7,8,14},{7,8,6},{7,8,14},{10,3,51},{5,9,24},{6,8,1},{5,8,51},{18,1,51},{5,8,51},{6,9,37},{6,9,37},{6,9,37},{6,8,36},{6,9,10},{6,8,0},{6,8,0}, +{6,7,5},{5,8,11},{6,7,14},{7,8,5},{7,8,5},{7,8,5},{7,7,8},{10,2,8},{6,8,0},{6,8,0},{6,7,5},{17,1,8},{6,7,5},{11,2,18},{6,9,2},{7,8,2},{6,8,1},{11,2,18},{17,2,18},{6,8,1},{0,8,50},{17,2,18},{0,8,50},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,8,0},{6,8,0},{6,8,0},{6,7,1},{5,8,2}, +{5,8,2},{7,12,70},{7,10,58},{8,9,69},{7,9,51},{7,11,52},{7,10,25},{7,9,3},{7,9,46},{6,10,60},{6,9,36},{8,10,24},{8,9,14},{8,9,5},{8,9,13},{13,1,51},{7,10,24},{7,9,2},{6,9,36},{21,1,51},{6,9,36},{7,11,51},{7,11,51},{7,11,51},{7,9,51},{7,10,9},{7,9,3},{7,9,3},{7,8,9},{5,10,12},{7,8,12},{8,9,5}, +{8,9,5},{8,9,5},{8,8,8},{13,0,8},{7,9,2},{7,9,2},{7,8,8},{20,1,8},{7,8,8},{14,0,18},{7,10,8},{8,9,1},{7,9,1},{14,0,18},{20,2,18},{7,9,1},{0,9,36},{20,2,18},{0,9,36},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,9,2},{7,9,2},{7,9,2},{7,8,5},{6,9,0},{6,9,0},{8,12,56},{8,11,38},{8,10,52}, +{8,10,36},{8,12,56},{8,11,35},{8,10,0},{8,10,52},{7,11,60},{7,10,36},{9,11,24},{9,10,14},{9,10,5},{9,10,13},{14,2,51},{7,11,35},{8,10,0},{7,10,36},{25,0,51},{7,10,36},{8,11,37},{8,11,37},{8,11,37},{8,10,36},{8,11,10},{8,10,0},{8,10,0},{8,9,5},{6,11,12},{8,9,14},{9,10,5},{9,10,5},{9,10,5},{9,9,8},{14,1,8}, +{8,10,0},{8,10,0},{8,9,5},{24,0,8},{8,9,5},{15,1,18},{8,11,2},{9,10,1},{8,10,0},{15,1,18},{24,1,18},{8,10,0},{0,10,36},{24,1,18},{0,10,36},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,10,0},{8,10,0},{8,10,0},{8,9,1},{7,10,0},{7,10,0},{9,13,56},{9,12,38},{9,11,52},{9,11,36},{9,13,56},{9,12,35},{9,11,0}, +{9,11,52},{7,12,63},{8,11,38},{10,12,24},{10,11,14},{10,11,5},{10,11,13},{16,1,51},{8,12,24},{9,11,0},{8,11,37},{26,1,51},{8,11,37},{9,12,37},{9,12,37},{9,12,37},{9,11,36},{9,12,10},{9,11,0},{9,11,0},{9,10,5},{8,11,11},{9,10,14},{10,11,5},{10,11,5},{10,11,5},{10,10,8},{16,0,8},{9,11,0},{9,11,0},{9,10,5},{25,1,8}, +{9,10,5},{17,0,18},{9,12,2},{10,11,1},{9,11,0},{17,0,18},{25,2,18},{9,11,0},{0,11,36},{25,2,18},{0,11,36},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,11,0},{9,11,0},{9,11,0},{9,10,1},{8,11,2},{8,11,2},{10,14,56},{10,13,38},{10,12,53},{10,12,37},{10,14,56},{10,13,35},{10,12,1},{10,12,66},{8,13,60},{9,12,52},{11,13,24}, +{11,12,14},{11,12,6},{11,12,14},{17,2,51},{9,13,24},{10,12,1},{9,12,51},{27,2,51},{9,12,51},{10,13,37},{10,13,37},{10,13,37},{10,12,36},{10,13,10},{10,12,0},{10,12,0},{10,11,5},{9,12,11},{10,11,14},{11,12,5},{11,12,5},{11,12,5},{11,11,8},{17,1,8},{10,12,0},{10,12,0},{10,11,5},{26,2,8},{10,11,5},{18,1,18},{10,13,2},{11,12,2}, +{10,12,1},{18,1,18},{31,0,18},{10,12,1},{0,12,50},{31,0,18},{0,12,50},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,12,0},{10,12,0},{10,12,0},{10,11,1},{9,12,2},{9,12,2},{11,16,70},{11,14,58},{12,13,69},{11,13,51},{11,15,52},{11,14,25},{11,13,3},{11,13,46},{10,14,60},{10,13,36},{12,14,24},{12,13,14},{12,13,5},{12,13,13},{17,5,51}, +{11,14,24},{11,13,2},{10,13,36},{30,2,51},{10,13,36},{11,15,51},{11,15,51},{11,15,51},{11,13,51},{11,14,9},{11,13,3},{11,13,3},{11,12,9},{9,14,12},{11,12,12},{12,13,5},{12,13,5},{12,13,5},{12,12,8},{17,4,8},{11,13,2},{11,13,2},{11,12,8},{29,2,8},{11,12,8},{18,4,18},{11,14,8},{12,13,1},{11,13,1},{18,4,18},{29,3,18},{11,13,1}, +{0,13,36},{29,3,18},{0,13,36},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,13,2},{11,13,2},{11,13,2},{11,12,5},{10,13,0},{10,13,0},{12,16,56},{12,15,38},{12,14,52},{12,14,36},{12,16,56},{12,15,35},{12,14,0},{12,14,52},{11,15,60},{11,14,36},{13,15,24},{13,14,14},{13,14,5},{13,14,13},{18,6,51},{11,15,35},{12,14,0},{11,14,36},{31,3,51}, +{11,14,36},{12,15,37},{12,15,37},{12,15,37},{12,14,36},{12,15,10},{12,14,0},{12,14,0},{12,13,5},{10,15,12},{12,13,14},{13,14,5},{13,14,5},{13,14,5},{13,13,8},{18,5,8},{12,14,0},{12,14,0},{12,13,5},{30,3,8},{12,13,5},{20,3,18},{12,15,2},{13,14,1},{12,14,0},{20,3,18},{28,5,18},{12,14,0},{0,14,36},{28,5,18},{0,14,36},{12,0,36}, +{12,0,36},{12,0,36},{12,0,36},{12,14,0},{12,14,0},{12,14,0},{12,13,1},{11,14,0},{11,14,0},{13,17,56},{13,16,38},{13,15,52},{13,15,36},{13,17,56},{13,16,35},{13,15,0},{13,15,52},{11,16,63},{12,15,38},{14,16,24},{14,15,14},{14,15,5},{14,15,13},{23,0,51},{12,16,24},{13,15,0},{12,15,37},{30,5,51},{12,15,37},{13,16,37},{13,16,37},{13,16,37}, +{13,15,36},{13,16,10},{13,15,0},{13,15,0},{13,14,5},{12,15,11},{13,14,14},{14,15,5},{14,15,5},{14,15,5},{14,14,8},{20,4,8},{13,15,0},{13,15,0},{13,14,5},{29,5,8},{13,14,5},{21,4,18},{13,16,2},{14,15,1},{13,15,0},{21,4,18},{29,6,18},{13,15,0},{0,15,36},{29,6,18},{0,15,36},{13,0,36},{13,0,36},{13,0,36},{13,0,36},{13,15,0}, +{13,15,0},{13,15,0},{13,14,1},{12,15,2},{12,15,2},{14,18,56},{14,17,38},{14,16,53},{14,16,37},{14,18,56},{14,17,35},{14,16,1},{14,16,66},{12,17,60},{13,16,52},{15,17,24},{15,16,14},{15,16,6},{15,16,14},{24,1,51},{13,17,24},{14,16,1},{13,16,51},{31,6,51},{13,16,51},{14,17,37},{14,17,37},{14,17,37},{14,16,36},{14,17,10},{14,16,0},{14,16,0}, +{14,15,5},{13,16,11},{14,15,14},{15,16,5},{15,16,5},{15,16,5},{15,15,8},{24,0,8},{14,16,0},{14,16,0},{14,15,5},{30,6,8},{14,15,5},{25,0,18},{14,17,2},{15,16,2},{14,16,1},{25,0,18},{30,7,18},{14,16,1},{0,16,50},{30,7,18},{0,16,50},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,16,0},{14,16,0},{14,16,0},{14,15,1},{13,16,2}, +{13,16,2},{15,20,70},{15,18,58},{16,17,69},{15,17,51},{15,19,52},{15,18,25},{15,17,3},{15,17,46},{14,18,60},{14,17,36},{16,18,24},{16,17,14},{16,17,5},{16,17,13},{21,9,51},{15,18,24},{15,17,2},{14,17,36},{29,9,51},{14,17,36},{15,19,51},{15,19,51},{15,19,51},{15,17,51},{15,18,9},{15,17,3},{15,17,3},{15,16,9},{13,18,12},{15,16,12},{16,17,5}, +{16,17,5},{16,17,5},{16,16,8},{24,3,8},{15,17,2},{15,17,2},{15,16,8},{28,9,8},{15,16,8},{25,3,18},{15,18,8},{16,17,1},{15,17,1},{25,3,18},{28,10,18},{15,17,1},{0,17,36},{28,10,18},{0,17,36},{15,0,50},{15,0,50},{15,0,50},{15,0,50},{15,17,2},{15,17,2},{15,17,2},{15,16,5},{14,17,0},{14,17,0},{16,20,56},{16,19,38},{16,18,52}, +{16,18,36},{16,20,56},{16,19,35},{16,18,0},{16,18,52},{15,19,60},{15,18,36},{17,19,24},{17,18,14},{17,18,5},{17,18,13},{22,10,51},{15,19,35},{16,18,0},{15,18,36},{30,10,51},{15,18,36},{16,19,37},{16,19,37},{16,19,37},{16,18,36},{16,19,10},{16,18,0},{16,18,0},{16,17,5},{14,19,12},{16,17,14},{17,18,5},{17,18,5},{17,18,5},{17,17,8},{22,9,8}, +{16,18,0},{16,18,0},{16,17,5},{29,10,8},{16,17,5},{24,7,18},{16,19,2},{17,18,1},{16,18,0},{24,7,18},{29,11,18},{16,18,0},{0,18,36},{29,11,18},{0,18,36},{16,0,36},{16,0,36},{16,0,36},{16,0,36},{16,18,0},{16,18,0},{16,18,0},{16,17,1},{15,18,0},{15,18,0},{17,21,56},{17,20,38},{17,19,52},{17,19,36},{17,21,56},{17,20,35},{17,19,0}, +{17,19,52},{15,20,63},{16,19,38},{18,20,24},{18,19,14},{18,19,5},{18,19,13},{27,4,51},{16,20,24},{17,19,0},{16,19,37},{31,11,51},{16,19,37},{17,20,37},{17,20,37},{17,20,37},{17,19,36},{17,20,10},{17,19,0},{17,19,0},{17,18,5},{16,19,11},{17,18,14},{18,19,5},{18,19,5},{18,19,5},{18,18,8},{24,8,8},{17,19,0},{17,19,0},{17,18,5},{30,11,8}, +{17,18,5},{28,3,18},{17,20,2},{18,19,1},{17,19,0},{28,3,18},{28,13,18},{17,19,0},{0,19,36},{28,13,18},{0,19,36},{17,0,36},{17,0,36},{17,0,36},{17,0,36},{17,19,0},{17,19,0},{17,19,0},{17,18,1},{16,19,2},{16,19,2},{18,22,56},{18,21,38},{18,20,53},{18,20,37},{18,22,56},{18,21,35},{18,20,1},{18,20,66},{16,21,60},{17,20,52},{19,21,24}, +{19,20,14},{19,20,6},{19,20,14},{31,0,51},{17,21,24},{18,20,1},{17,20,51},{30,13,51},{17,20,51},{18,21,37},{18,21,37},{18,21,37},{18,20,36},{18,21,10},{18,20,0},{18,20,0},{18,19,5},{17,20,11},{18,19,14},{19,20,5},{19,20,5},{19,20,5},{19,19,8},{28,4,8},{18,20,0},{18,20,0},{18,19,5},{29,13,8},{18,19,5},{29,4,18},{18,21,2},{19,20,2}, +{18,20,1},{29,4,18},{29,14,18},{18,20,1},{0,20,50},{29,14,18},{0,20,50},{18,0,36},{18,0,36},{18,0,36},{18,0,36},{18,20,0},{18,20,0},{18,20,0},{18,19,1},{17,20,2},{17,20,2},{19,24,70},{19,22,58},{20,21,69},{19,21,51},{19,23,52},{19,22,25},{19,21,3},{19,21,46},{18,22,60},{18,21,36},{20,22,24},{20,21,14},{20,21,5},{20,21,13},{31,3,51}, +{19,22,24},{19,21,2},{18,21,36},{23,19,51},{18,21,36},{19,23,51},{19,23,51},{19,23,51},{19,21,51},{19,22,9},{19,21,3},{19,21,3},{19,20,9},{17,22,12},{19,20,12},{20,21,5},{20,21,5},{20,21,5},{20,20,8},{31,2,8},{19,21,2},{19,21,2},{19,20,8},{27,16,8},{19,20,8},{29,7,18},{19,22,8},{20,21,1},{19,21,1},{29,7,18},{27,17,18},{19,21,1}, +{0,21,36},{27,17,18},{0,21,36},{19,0,50},{19,0,50},{19,0,50},{19,0,50},{19,21,2},{19,21,2},{19,21,2},{19,20,5},{18,21,0},{18,21,0},{20,24,56},{20,23,38},{20,22,52},{20,22,36},{20,24,56},{20,23,35},{20,22,0},{20,22,52},{19,23,60},{19,22,36},{21,23,24},{21,22,14},{21,22,5},{21,22,13},{26,14,51},{19,23,35},{20,22,0},{19,22,36},{22,21,51}, +{19,22,36},{20,23,37},{20,23,37},{20,23,37},{20,22,36},{20,23,10},{20,22,0},{20,22,0},{20,21,5},{18,23,12},{20,21,14},{21,22,5},{21,22,5},{21,22,5},{21,21,8},{26,13,8},{20,22,0},{20,22,0},{20,21,5},{21,21,8},{20,21,5},{28,11,18},{20,23,2},{21,22,1},{20,22,0},{28,11,18},{31,16,18},{20,22,0},{0,22,36},{31,16,18},{0,22,36},{20,0,36}, +{20,0,36},{20,0,36},{20,0,36},{20,22,0},{20,22,0},{20,22,0},{20,21,1},{19,22,0},{19,22,0},{21,25,56},{21,24,38},{21,23,52},{21,23,36},{21,25,56},{21,24,35},{21,23,0},{21,23,52},{19,24,63},{20,23,38},{22,24,24},{22,23,14},{22,23,5},{22,23,13},{31,8,51},{20,24,24},{21,23,0},{20,23,37},{28,19,51},{20,23,37},{21,24,37},{21,24,37},{21,24,37}, +{21,23,36},{21,24,10},{21,23,0},{21,23,0},{21,22,5},{20,23,11},{21,22,14},{22,23,5},{22,23,5},{22,23,5},{22,22,8},{28,12,8},{21,23,0},{21,23,0},{21,22,5},{22,22,8},{21,22,5},{29,12,18},{21,24,2},{22,23,1},{21,23,0},{29,12,18},{27,20,18},{21,23,0},{0,23,36},{27,20,18},{0,23,36},{21,0,36},{21,0,36},{21,0,36},{21,0,36},{21,23,0}, +{21,23,0},{21,23,0},{21,22,1},{20,23,2},{20,23,2},{22,26,56},{22,25,38},{22,24,53},{22,24,37},{22,26,56},{22,25,35},{22,24,1},{22,24,66},{20,25,60},{21,24,52},{23,25,24},{23,24,14},{23,24,6},{23,24,14},{29,14,51},{21,25,24},{22,24,1},{21,24,51},{29,20,51},{21,24,51},{22,25,37},{22,25,37},{22,25,37},{22,24,36},{22,25,10},{22,24,0},{22,24,0}, +{22,23,5},{21,24,11},{22,23,14},{23,24,5},{23,24,5},{23,24,5},{23,23,8},{29,13,8},{22,24,0},{22,24,0},{22,23,5},{28,20,8},{22,23,5},{30,13,18},{22,25,2},{23,24,2},{22,24,1},{30,13,18},{28,21,18},{22,24,1},{0,24,50},{28,21,18},{0,24,50},{22,0,36},{22,0,36},{22,0,36},{22,0,36},{22,24,0},{22,24,0},{22,24,0},{22,23,1},{21,24,2}, +{21,24,2},{23,28,70},{23,26,58},{24,25,69},{23,25,51},{23,27,52},{23,26,25},{23,25,3},{23,25,46},{22,26,60},{22,25,36},{24,26,24},{24,25,14},{24,25,5},{24,25,13},{29,17,51},{23,26,24},{23,25,2},{22,25,36},{27,23,51},{22,25,36},{23,27,51},{23,27,51},{23,27,51},{23,25,51},{23,26,9},{23,25,3},{23,25,3},{23,24,9},{21,26,12},{23,24,12},{24,25,5}, +{24,25,5},{24,25,5},{24,24,8},{29,16,8},{23,25,2},{23,25,2},{23,24,8},{31,20,8},{23,24,8},{30,16,18},{23,26,8},{24,25,1},{23,25,1},{30,16,18},{31,21,18},{23,25,1},{0,25,36},{31,21,18},{0,25,36},{23,0,50},{23,0,50},{23,0,50},{23,0,50},{23,25,2},{23,25,2},{23,25,2},{23,24,5},{22,25,0},{22,25,0},{24,28,56},{24,27,38},{24,26,52}, +{24,26,36},{24,28,56},{24,27,35},{24,26,0},{24,26,52},{23,27,60},{23,26,36},{25,27,24},{25,26,14},{25,26,5},{25,26,13},{30,18,51},{23,27,35},{24,26,0},{23,26,36},{26,25,51},{23,26,36},{24,27,37},{24,27,37},{24,27,37},{24,26,36},{24,27,10},{24,26,0},{24,26,0},{24,25,5},{22,27,12},{24,25,14},{25,26,5},{25,26,5},{25,26,5},{25,25,8},{30,17,8}, +{24,26,0},{24,26,0},{24,25,5},{25,25,8},{24,25,5},{31,17,18},{24,27,2},{25,26,1},{24,26,0},{31,17,18},{25,26,18},{24,26,0},{0,26,36},{25,26,18},{0,26,36},{24,0,36},{24,0,36},{24,0,36},{24,0,36},{24,26,0},{24,26,0},{24,26,0},{24,25,1},{23,26,0},{23,26,0},{25,29,56},{25,28,38},{25,27,52},{25,27,36},{25,29,56},{25,28,35},{25,27,0}, +{25,27,52},{23,28,63},{24,27,38},{26,28,24},{26,27,14},{26,27,5},{26,27,13},{31,19,51},{24,28,24},{25,27,0},{24,27,37},{27,26,51},{24,27,37},{25,28,37},{25,28,37},{25,28,37},{25,27,36},{25,28,10},{25,27,0},{25,27,0},{25,26,5},{24,27,11},{25,26,14},{26,27,5},{26,27,5},{26,27,5},{26,26,8},{31,18,8},{25,27,0},{25,27,0},{25,26,5},{26,26,8}, +{25,26,5},{30,21,18},{25,28,2},{26,27,1},{25,27,0},{30,21,18},{31,24,18},{25,27,0},{0,27,36},{31,24,18},{0,27,36},{25,0,36},{25,0,36},{25,0,36},{25,0,36},{25,27,0},{25,27,0},{25,27,0},{25,26,1},{24,27,2},{24,27,2},{26,30,56},{26,29,38},{26,28,53},{26,28,37},{26,30,56},{26,29,35},{26,28,1},{26,28,66},{24,29,60},{25,28,52},{27,29,24}, +{27,28,14},{27,28,6},{27,28,14},{30,23,51},{25,29,24},{26,28,1},{25,28,51},{28,27,51},{25,28,51},{26,29,37},{26,29,37},{26,29,37},{26,28,36},{26,29,10},{26,28,0},{26,28,0},{26,27,5},{25,28,11},{26,27,14},{27,28,5},{27,28,5},{27,28,5},{27,27,8},{30,22,8},{26,28,0},{26,28,0},{26,27,5},{27,27,8},{26,27,5},{31,22,18},{26,29,2},{27,28,2}, +{26,28,1},{31,22,18},{27,28,18},{26,28,1},{0,28,50},{27,28,18},{0,28,50},{26,0,36},{26,0,36},{26,0,36},{26,0,36},{26,28,0},{26,28,0},{26,28,0},{26,27,1},{25,28,2},{25,28,2},{27,31,76},{27,30,58},{28,29,69},{27,29,51},{27,31,52},{27,30,25},{27,29,3},{27,29,46},{26,30,60},{26,29,36},{28,30,24},{28,29,14},{28,29,5},{28,29,13},{30,26,51}, +{27,30,24},{27,29,2},{26,29,36},{31,27,51},{26,29,36},{27,31,51},{27,31,51},{27,31,51},{27,29,51},{27,30,9},{27,29,3},{27,29,3},{27,28,9},{25,30,12},{27,28,12},{28,29,5},{28,29,5},{28,29,5},{28,28,8},{30,25,8},{27,29,2},{27,29,2},{27,28,8},{30,27,8},{27,28,8},{31,25,18},{27,30,8},{28,29,1},{27,29,1},{31,25,18},{28,29,18},{27,29,1}, +{0,29,36},{28,29,18},{0,29,36},{27,0,50},{27,0,50},{27,0,50},{27,0,50},{27,29,2},{27,29,2},{27,29,2},{27,28,5},{26,29,0},{26,29,0},{28,31,86},{28,31,38},{28,30,52},{28,30,36},{28,31,59},{28,31,35},{28,30,0},{28,30,52},{27,31,60},{27,30,36},{29,31,24},{29,30,14},{29,30,5},{29,30,13},{31,27,51},{27,31,35},{28,30,0},{27,30,36},{30,29,51}, +{27,30,36},{28,31,37},{28,31,37},{28,31,37},{28,30,36},{28,31,10},{28,30,0},{28,30,0},{28,29,5},{26,31,12},{28,29,14},{29,30,5},{29,30,5},{29,30,5},{29,29,8},{31,26,8},{28,30,0},{28,30,0},{28,29,5},{29,29,8},{28,29,5},{30,29,18},{28,31,2},{29,30,1},{28,30,0},{30,29,18},{29,30,18},{28,30,0},{0,30,36},{29,30,18},{0,30,36},{28,0,36}, +{28,0,36},{28,0,36},{28,0,36},{28,30,0},{28,30,0},{28,30,0},{28,29,1},{27,30,0},{27,30,0},{30,31,94},{30,31,78},{29,31,52},{29,31,36},{30,31,115},{29,31,36},{29,31,0},{29,31,52},{29,31,88},{28,31,38},{30,31,30},{30,31,14},{30,31,5},{30,31,13},{30,31,51},{29,31,36},{29,31,0},{28,31,37},{31,30,51},{28,31,37},{29,31,52},{29,31,52},{29,31,52}, +{29,31,36},{29,31,16},{29,31,0},{29,31,0},{29,30,5},{28,31,11},{29,30,14},{30,31,5},{30,31,5},{30,31,5},{30,30,8},{30,30,8},{29,31,0},{29,31,0},{29,30,5},{30,30,8},{29,30,5},{31,30,18},{30,31,10},{30,31,1},{29,31,0},{31,30,18},{30,31,18},{29,31,0},{0,31,36},{30,31,18},{0,31,36},{29,0,36},{29,0,36},{29,0,36},{29,0,36},{29,31,0}, +{29,31,0},{29,31,0},{29,30,1},{28,31,2},{28,31,2},{31,31,68},{31,31,68},{30,31,61},{30,31,45},{30,31,59},{30,31,27},{30,31,18},{30,31,1},{30,31,28},{30,31,10},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{30,31,61},{30,31,61},{30,31,61},{30,31,45},{30,31,34},{30,31,18},{30,31,18}, +{30,31,1},{30,31,19},{30,31,10},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,36},{30,0,36},{30,0,36},{30,0,36},{30,31,9},{30,31,9},{30,31,9},{30,31,1},{30,31,10}, +{30,31,10},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{0,2,158},{0,2,110},{0,2,62},{0,1,115},{0,1,178},{0,1,124},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{1,1,154},{0,2,110},{0,2,62},{0,1,115},{1,1,154},{0,1,115},{0,2,1},{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{0,0,25},{0,0,25},{0,2,1}, +{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{1,0,13},{0,0,25},{1,2,72},{0,3,20},{0,2,2},{0,2,26},{1,2,72},{2,1,72},{0,2,26},{0,1,90},{2,1,72},{0,1,90},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,6,83},{0,5,13},{0,3,26}, +{0,3,14},{0,5,248},{0,3,140},{0,3,41},{0,2,139},{0,2,319},{0,2,175},{0,6,83},{0,5,13},{0,3,26},{0,3,14},{1,3,243},{0,3,140},{0,3,41},{0,2,139},{3,1,243},{0,2,139},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{0,3,52},{0,2,18},{0,2,18},{0,1,29},{0,1,77},{0,1,38},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{1,1,50}, +{0,2,18},{0,2,18},{0,1,29},{1,1,50},{0,1,29},{2,3,72},{0,5,4},{1,3,2},{0,3,5},{2,3,72},{3,2,72},{0,3,5},{0,2,90},{3,2,72},{0,2,90},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{1,7,147},{1,6,77},{1,4,89},{1,4,77},{0,7,244},{0,5,96},{0,4,2}, +{0,3,106},{0,4,395},{0,3,187},{1,7,83},{1,6,13},{1,4,25},{1,4,13},{2,4,243},{0,5,96},{0,4,2},{0,3,106},{4,2,243},{0,3,106},{1,5,74},{1,5,74},{1,5,74},{1,4,77},{0,5,52},{0,4,2},{0,4,2},{0,3,25},{0,3,133},{0,2,62},{1,5,10},{1,5,10},{1,5,10},{1,4,13},{2,2,50},{0,4,2},{0,4,2},{0,3,25},{2,2,50}, +{0,3,25},{3,4,72},{1,6,4},{2,4,1},{0,4,1},{3,4,72},{9,0,72},{0,4,1},{0,3,90},{9,0,72},{0,3,90},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{2,8,164},{2,7,94},{2,5,106},{2,5,94},{1,8,245},{1,6,97},{1,5,3},{1,4,97},{0,6,364},{0,4,106},{2,8,83}, +{2,7,13},{2,5,25},{2,5,13},{6,0,243},{0,7,76},{1,5,2},{0,4,81},{10,0,243},{0,4,81},{2,6,91},{2,6,91},{2,6,91},{2,5,94},{1,6,53},{1,5,3},{1,5,3},{1,3,27},{0,4,107},{0,4,42},{2,6,10},{2,6,10},{2,6,10},{2,5,13},{3,3,50},{1,5,2},{1,5,2},{0,4,17},{8,0,50},{0,4,17},{7,0,72},{2,7,4},{3,5,1}, +{1,5,1},{7,0,72},{10,1,72},{1,5,1},{0,4,80},{10,1,72},{0,4,80},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{1,5,2},{1,5,2},{1,5,2},{1,3,2},{0,3,20},{0,3,20},{3,10,154},{3,8,81},{3,6,106},{3,6,82},{2,10,248},{2,7,99},{2,6,5},{2,5,99},{0,7,308},{0,5,100},{3,10,90},{3,8,17},{4,6,27},{3,6,18},{6,3,243}, +{1,8,73},{2,6,5},{1,5,90},{8,3,243},{1,5,90},{3,8,81},{3,8,81},{3,8,81},{3,6,81},{2,8,52},{2,6,4},{2,6,4},{2,5,18},{0,6,72},{0,5,19},{3,8,17},{3,8,17},{3,8,17},{3,6,17},{6,1,50},{2,6,4},{2,6,4},{1,5,9},{11,0,50},{1,5,9},{8,1,72},{3,8,1},{4,6,2},{3,6,2},{8,1,72},{6,5,72},{3,6,2}, +{0,5,90},{6,5,72},{0,5,90},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{2,6,0},{2,6,0},{2,6,0},{2,4,4},{0,6,8},{0,6,8},{4,10,164},{4,9,94},{4,7,107},{4,7,95},{3,11,248},{3,8,89},{3,7,5},{3,6,99},{0,9,253},{1,6,100},{4,10,83},{4,9,13},{4,7,26},{4,7,14},{8,2,243},{2,9,73},{3,7,5},{2,6,90},{12,2,243}, +{2,6,90},{4,8,91},{4,8,91},{4,8,91},{4,7,94},{3,9,52},{3,7,4},{3,7,4},{3,6,18},{0,8,50},{1,6,19},{4,8,10},{4,8,10},{4,8,10},{4,7,13},{8,0,50},{3,7,4},{3,7,4},{2,6,9},{5,5,50},{2,6,9},{9,2,72},{4,9,4},{5,7,2},{3,7,5},{9,2,72},{17,0,72},{3,7,5},{0,6,90},{17,0,72},{0,6,90},{4,0,90}, +{4,0,90},{4,0,90},{4,0,90},{3,7,0},{3,7,0},{3,7,0},{3,5,4},{1,7,8},{1,7,8},{5,11,164},{5,10,94},{5,8,106},{5,8,94},{4,11,245},{4,9,97},{4,8,3},{4,7,107},{0,11,249},{2,7,100},{5,11,83},{5,10,13},{5,8,25},{5,8,13},{9,3,243},{3,10,73},{4,8,2},{3,7,90},{18,0,243},{3,7,90},{5,9,91},{5,9,91},{5,9,91}, +{5,8,94},{4,9,53},{4,8,3},{4,8,3},{4,7,26},{1,9,50},{2,7,19},{5,9,10},{5,9,10},{5,9,10},{5,8,13},{9,1,50},{4,8,2},{4,8,2},{3,7,9},{16,0,50},{3,7,9},{10,3,72},{5,10,4},{6,8,1},{4,8,1},{10,3,72},{18,1,72},{4,8,1},{0,7,90},{18,1,72},{0,7,90},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,8,2}, +{4,8,2},{4,8,2},{4,6,2},{1,8,9},{1,8,9},{6,12,164},{6,11,94},{6,9,106},{6,9,94},{5,12,245},{5,10,97},{5,9,3},{5,8,97},{1,12,252},{3,8,85},{6,12,83},{6,11,13},{6,9,25},{6,9,13},{10,4,243},{4,11,76},{5,9,2},{4,8,81},{19,1,243},{4,8,81},{6,10,91},{6,10,91},{6,10,91},{6,9,94},{5,10,53},{5,9,3},{5,9,3}, +{5,7,27},{2,10,50},{3,8,21},{6,10,10},{6,10,10},{6,10,10},{6,9,13},{10,2,50},{5,9,2},{5,9,2},{4,8,17},{17,1,50},{4,8,17},{11,4,72},{6,11,4},{7,9,1},{5,9,1},{11,4,72},{19,2,72},{5,9,1},{0,8,80},{19,2,72},{0,8,80},{6,0,90},{6,0,90},{6,0,90},{6,0,90},{5,9,2},{5,9,2},{5,9,2},{5,7,2},{3,8,5}, +{3,8,5},{7,14,154},{7,12,81},{7,10,106},{7,10,82},{6,14,248},{6,11,99},{6,10,5},{6,9,99},{2,13,244},{4,9,100},{7,14,90},{7,12,17},{8,10,27},{7,10,18},{13,2,243},{5,12,73},{6,10,5},{5,9,90},{22,1,243},{5,9,90},{7,12,81},{7,12,81},{7,12,81},{7,10,81},{6,12,52},{6,10,4},{6,10,4},{6,9,18},{3,11,53},{4,9,19},{7,12,17}, +{7,12,17},{7,12,17},{7,10,17},{13,0,50},{6,10,4},{6,10,4},{5,9,9},{20,1,50},{5,9,9},{14,2,72},{7,12,1},{8,10,2},{7,10,2},{14,2,72},{25,0,72},{7,10,2},{0,9,90},{25,0,72},{0,9,90},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{6,10,0},{6,10,0},{6,10,0},{6,8,4},{4,10,8},{4,10,8},{8,14,164},{8,13,94},{8,11,107}, +{8,11,95},{7,15,248},{7,12,89},{7,11,5},{7,10,99},{3,14,244},{5,10,100},{8,14,83},{8,13,13},{8,11,26},{8,11,14},{14,3,243},{6,13,73},{7,11,5},{6,10,90},{26,0,243},{6,10,90},{8,12,91},{8,12,91},{8,12,91},{8,11,94},{7,13,52},{7,11,4},{7,11,4},{7,10,18},{4,12,50},{5,10,19},{8,12,10},{8,12,10},{8,12,10},{8,11,13},{14,1,50}, +{7,11,4},{7,11,4},{6,10,9},{24,0,50},{6,10,9},{16,1,72},{8,13,4},{9,11,2},{7,11,5},{16,1,72},{26,1,72},{7,11,5},{0,10,90},{26,1,72},{0,10,90},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{7,11,0},{7,11,0},{7,11,0},{7,9,4},{5,11,8},{5,11,8},{9,15,164},{9,14,94},{9,12,106},{9,12,94},{8,15,245},{8,13,97},{8,12,3}, +{8,11,107},{4,15,249},{6,11,100},{9,15,83},{9,14,13},{9,12,25},{9,12,13},{16,2,243},{7,14,73},{8,12,2},{7,11,90},{27,1,243},{7,11,90},{9,13,91},{9,13,91},{9,13,91},{9,12,94},{8,13,53},{8,12,3},{8,12,3},{8,11,26},{5,13,50},{6,11,19},{9,13,10},{9,13,10},{9,13,10},{9,12,13},{16,0,50},{8,12,2},{8,12,2},{7,11,9},{25,1,50}, +{7,11,9},{17,2,72},{9,14,4},{10,12,1},{8,12,1},{17,2,72},{27,2,72},{8,12,1},{0,11,90},{27,2,72},{0,11,90},{9,0,90},{9,0,90},{9,0,90},{9,0,90},{8,12,2},{8,12,2},{8,12,2},{8,10,2},{5,12,9},{5,12,9},{10,16,164},{10,15,94},{10,13,106},{10,13,94},{9,16,245},{9,14,97},{9,13,3},{9,12,97},{5,16,252},{7,12,85},{10,16,83}, +{10,15,13},{10,13,25},{10,13,13},{17,3,243},{8,15,76},{9,13,2},{8,12,81},{28,2,243},{8,12,81},{10,14,91},{10,14,91},{10,14,91},{10,13,94},{9,14,53},{9,13,3},{9,13,3},{9,11,27},{6,14,50},{7,12,21},{10,14,10},{10,14,10},{10,14,10},{10,13,13},{17,1,50},{9,13,2},{9,13,2},{8,12,17},{26,2,50},{8,12,17},{18,3,72},{10,15,4},{11,13,1}, +{9,13,1},{18,3,72},{28,3,72},{9,13,1},{0,12,80},{28,3,72},{0,12,80},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,13,2},{9,13,2},{9,13,2},{9,11,2},{7,12,5},{7,12,5},{11,18,154},{11,16,81},{11,14,106},{11,14,82},{10,18,248},{10,15,99},{10,14,5},{10,13,99},{6,17,244},{8,13,100},{11,18,90},{11,16,17},{12,14,27},{11,14,18},{17,6,243}, +{9,16,73},{10,14,5},{9,13,90},{31,2,243},{9,13,90},{11,16,81},{11,16,81},{11,16,81},{11,14,81},{10,16,52},{10,14,4},{10,14,4},{10,13,18},{7,15,53},{8,13,19},{11,16,17},{11,16,17},{11,16,17},{11,14,17},{17,4,50},{10,14,4},{10,14,4},{9,13,9},{29,2,50},{9,13,9},{18,6,72},{11,16,1},{12,14,2},{11,14,2},{18,6,72},{31,3,72},{11,14,2}, +{0,13,90},{31,3,72},{0,13,90},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,14,0},{10,14,0},{10,14,0},{10,12,4},{8,14,8},{8,14,8},{12,18,164},{12,17,94},{12,15,107},{12,15,95},{11,19,248},{11,16,89},{11,15,5},{11,14,99},{7,18,244},{9,14,100},{12,18,83},{12,17,13},{12,15,26},{12,15,14},{22,0,243},{10,17,73},{11,15,5},{10,14,90},{30,4,243}, +{10,14,90},{12,16,91},{12,16,91},{12,16,91},{12,15,94},{11,17,52},{11,15,4},{11,15,4},{11,14,18},{8,16,50},{9,14,19},{12,16,10},{12,16,10},{12,16,10},{12,15,13},{18,5,50},{11,15,4},{11,15,4},{10,14,9},{30,3,50},{10,14,9},{23,0,72},{12,17,4},{13,15,2},{11,15,5},{23,0,72},{30,5,72},{11,15,5},{0,14,90},{30,5,72},{0,14,90},{12,0,90}, +{12,0,90},{12,0,90},{12,0,90},{11,15,0},{11,15,0},{11,15,0},{11,13,4},{9,15,8},{9,15,8},{13,19,164},{13,18,94},{13,16,106},{13,16,94},{12,19,245},{12,17,97},{12,16,3},{12,15,107},{8,19,249},{10,15,100},{13,19,83},{13,18,13},{13,16,25},{13,16,13},{23,1,243},{11,18,73},{12,16,2},{11,15,90},{31,5,243},{11,15,90},{13,17,91},{13,17,91},{13,17,91}, +{13,16,94},{12,17,53},{12,16,3},{12,16,3},{12,15,26},{9,17,50},{10,15,19},{13,17,10},{13,17,10},{13,17,10},{13,16,13},{20,4,50},{12,16,2},{12,16,2},{11,15,9},{29,5,50},{11,15,9},{24,1,72},{13,18,4},{14,16,1},{12,16,1},{24,1,72},{31,6,72},{12,16,1},{0,15,90},{31,6,72},{0,15,90},{13,0,90},{13,0,90},{13,0,90},{13,0,90},{12,16,2}, +{12,16,2},{12,16,2},{12,14,2},{9,16,9},{9,16,9},{14,20,164},{14,19,94},{14,17,106},{14,17,94},{13,20,245},{13,18,97},{13,17,3},{13,16,97},{9,20,252},{11,16,85},{14,20,83},{14,19,13},{14,17,25},{14,17,13},{24,2,243},{12,19,76},{13,17,2},{12,16,81},{27,9,243},{12,16,81},{14,18,91},{14,18,91},{14,18,91},{14,17,94},{13,18,53},{13,17,3},{13,17,3}, +{13,15,27},{10,18,50},{11,16,21},{14,18,10},{14,18,10},{14,18,10},{14,17,13},{24,0,50},{13,17,2},{13,17,2},{12,16,17},{30,6,50},{12,16,17},{25,2,72},{14,19,4},{15,17,1},{13,17,1},{25,2,72},{27,10,72},{13,17,1},{0,16,80},{27,10,72},{0,16,80},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{13,17,2},{13,17,2},{13,17,2},{13,15,2},{11,16,5}, +{11,16,5},{15,22,154},{15,20,81},{15,18,106},{15,18,82},{14,22,248},{14,19,99},{14,18,5},{14,17,99},{10,21,244},{12,17,100},{15,22,90},{15,20,17},{16,18,27},{15,18,18},{27,0,243},{13,20,73},{14,18,5},{13,17,90},{30,9,243},{13,17,90},{15,20,81},{15,20,81},{15,20,81},{15,18,81},{14,20,52},{14,18,4},{14,18,4},{14,17,18},{11,19,53},{12,17,19},{15,20,17}, +{15,20,17},{15,20,17},{15,18,17},{24,3,50},{14,18,4},{14,18,4},{13,17,9},{28,9,50},{13,17,9},{22,10,72},{15,20,1},{16,18,2},{15,18,2},{22,10,72},{30,10,72},{15,18,2},{0,17,90},{30,10,72},{0,17,90},{15,0,80},{15,0,80},{15,0,80},{15,0,80},{14,18,0},{14,18,0},{14,18,0},{14,16,4},{12,18,8},{12,18,8},{16,22,164},{16,21,94},{16,19,107}, +{16,19,95},{15,23,248},{15,20,89},{15,19,5},{15,18,99},{11,22,244},{13,18,100},{16,22,83},{16,21,13},{16,19,26},{16,19,14},{26,4,243},{14,21,73},{15,19,5},{14,18,90},{31,10,243},{14,18,90},{16,20,91},{16,20,91},{16,20,91},{16,19,94},{15,21,52},{15,19,4},{15,19,4},{15,18,18},{12,20,50},{13,18,19},{16,20,10},{16,20,10},{16,20,10},{16,19,13},{22,9,50}, +{15,19,4},{15,19,4},{14,18,9},{29,10,50},{14,18,9},{27,4,72},{16,21,4},{17,19,2},{15,19,5},{27,4,72},{31,11,72},{15,19,5},{0,18,90},{31,11,72},{0,18,90},{16,0,90},{16,0,90},{16,0,90},{16,0,90},{15,19,0},{15,19,0},{15,19,0},{15,17,4},{13,19,8},{13,19,8},{17,23,164},{17,22,94},{17,20,106},{17,20,94},{16,23,245},{16,21,97},{16,20,3}, +{16,19,107},{12,23,249},{14,19,100},{17,23,83},{17,22,13},{17,20,25},{17,20,13},{30,0,243},{15,22,73},{16,20,2},{15,19,90},{30,12,243},{15,19,90},{17,21,91},{17,21,91},{17,21,91},{17,20,94},{16,21,53},{16,20,3},{16,20,3},{16,19,26},{13,21,50},{14,19,19},{17,21,10},{17,21,10},{17,21,10},{17,20,13},{24,8,50},{16,20,2},{16,20,2},{15,19,9},{30,11,50}, +{15,19,9},{31,0,72},{17,22,4},{18,20,1},{16,20,1},{31,0,72},{30,13,72},{16,20,1},{0,19,90},{30,13,72},{0,19,90},{17,0,90},{17,0,90},{17,0,90},{17,0,90},{16,20,2},{16,20,2},{16,20,2},{16,18,2},{13,20,9},{13,20,9},{18,24,164},{18,23,94},{18,21,106},{18,21,94},{17,24,245},{17,22,97},{17,21,3},{17,20,97},{13,24,252},{15,20,85},{18,24,83}, +{18,23,13},{18,21,25},{18,21,13},{31,1,243},{16,23,76},{17,21,2},{16,20,81},{31,13,243},{16,20,81},{18,22,91},{18,22,91},{18,22,91},{18,21,94},{17,22,53},{17,21,3},{17,21,3},{17,19,27},{14,22,50},{15,20,21},{18,22,10},{18,22,10},{18,22,10},{18,21,13},{28,4,50},{17,21,2},{17,21,2},{16,20,17},{29,13,50},{16,20,17},{29,6,72},{18,23,4},{19,21,1}, +{17,21,1},{29,6,72},{31,14,72},{17,21,1},{0,20,80},{31,14,72},{0,20,80},{18,0,90},{18,0,90},{18,0,90},{18,0,90},{17,21,2},{17,21,2},{17,21,2},{17,19,2},{15,20,5},{15,20,5},{19,26,154},{19,24,81},{19,22,106},{19,22,82},{18,26,248},{18,23,99},{18,22,5},{18,21,99},{14,25,244},{16,21,100},{19,26,90},{19,24,17},{20,22,27},{19,22,18},{31,4,243}, +{17,24,73},{18,22,5},{17,21,90},{24,19,243},{17,21,90},{19,24,81},{19,24,81},{19,24,81},{19,22,81},{18,24,52},{18,22,4},{18,22,4},{18,21,18},{15,23,53},{16,21,19},{19,24,17},{19,24,17},{19,24,17},{19,22,17},{31,2,50},{18,22,4},{18,22,4},{17,21,9},{27,16,50},{17,21,9},{26,14,72},{19,24,1},{20,22,2},{19,22,2},{26,14,72},{22,21,72},{19,22,2}, +{0,21,90},{22,21,72},{0,21,90},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,22,0},{18,22,0},{18,22,0},{18,20,4},{16,22,8},{16,22,8},{20,26,164},{20,25,94},{20,23,107},{20,23,95},{19,27,248},{19,24,89},{19,23,5},{19,22,99},{15,26,244},{17,22,100},{20,26,83},{20,25,13},{20,23,26},{20,23,14},{30,8,243},{18,25,73},{19,23,5},{18,22,90},{28,18,243}, +{18,22,90},{20,24,91},{20,24,91},{20,24,91},{20,23,94},{19,25,52},{19,23,4},{19,23,4},{19,22,18},{16,24,50},{17,22,19},{20,24,10},{20,24,10},{20,24,10},{20,23,13},{26,13,50},{19,23,4},{19,23,4},{18,22,9},{21,21,50},{18,22,9},{31,8,72},{20,25,4},{21,23,2},{19,23,5},{31,8,72},{28,19,72},{19,23,5},{0,22,90},{28,19,72},{0,22,90},{20,0,90}, +{20,0,90},{20,0,90},{20,0,90},{19,23,0},{19,23,0},{19,23,0},{19,21,4},{17,23,8},{17,23,8},{21,27,164},{21,26,94},{21,24,106},{21,24,94},{20,27,245},{20,25,97},{20,24,3},{20,23,107},{16,27,249},{18,23,100},{21,27,83},{21,26,13},{21,24,25},{21,24,13},{31,9,243},{19,26,73},{20,24,2},{19,23,90},{29,19,243},{19,23,90},{21,25,91},{21,25,91},{21,25,91}, +{21,24,94},{20,25,53},{20,24,3},{20,24,3},{20,23,26},{17,25,50},{18,23,19},{21,25,10},{21,25,10},{21,25,10},{21,24,13},{28,12,50},{20,24,2},{20,24,2},{19,23,9},{22,22,50},{19,23,9},{29,14,72},{21,26,4},{22,24,1},{20,24,1},{29,14,72},{29,20,72},{20,24,1},{0,23,90},{29,20,72},{0,23,90},{21,0,90},{21,0,90},{21,0,90},{21,0,90},{20,24,2}, +{20,24,2},{20,24,2},{20,22,2},{17,24,9},{17,24,9},{22,28,164},{22,27,94},{22,25,106},{22,25,94},{21,28,245},{21,26,97},{21,25,3},{21,24,97},{17,28,252},{19,24,85},{22,28,83},{22,27,13},{22,25,25},{22,25,13},{29,15,243},{20,27,76},{21,25,2},{20,24,81},{30,20,243},{20,24,81},{22,26,91},{22,26,91},{22,26,91},{22,25,94},{21,26,53},{21,25,3},{21,25,3}, +{21,23,27},{18,26,50},{19,24,21},{22,26,10},{22,26,10},{22,26,10},{22,25,13},{29,13,50},{21,25,2},{21,25,2},{20,24,17},{28,20,50},{20,24,17},{30,15,72},{22,27,4},{23,25,1},{21,25,1},{30,15,72},{30,21,72},{21,25,1},{0,24,80},{30,21,72},{0,24,80},{22,0,90},{22,0,90},{22,0,90},{22,0,90},{21,25,2},{21,25,2},{21,25,2},{21,23,2},{19,24,5}, +{19,24,5},{23,30,154},{23,28,81},{23,26,106},{23,26,82},{22,30,248},{22,27,99},{22,26,5},{22,25,99},{18,29,244},{20,25,100},{23,30,90},{23,28,17},{24,26,27},{23,26,18},{29,18,243},{21,28,73},{22,26,5},{21,25,90},{28,23,243},{21,25,90},{23,28,81},{23,28,81},{23,28,81},{23,26,81},{22,28,52},{22,26,4},{22,26,4},{22,25,18},{19,27,53},{20,25,19},{23,28,17}, +{23,28,17},{23,28,17},{23,26,17},{29,16,50},{22,26,4},{22,26,4},{21,25,9},{31,20,50},{21,25,9},{30,18,72},{23,28,1},{24,26,2},{23,26,2},{30,18,72},{26,25,72},{23,26,2},{0,25,90},{26,25,72},{0,25,90},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{22,26,0},{22,26,0},{22,26,0},{22,24,4},{20,26,8},{20,26,8},{24,30,164},{24,29,94},{24,27,107}, +{24,27,95},{23,31,248},{23,28,89},{23,27,5},{23,26,99},{19,30,244},{21,26,100},{24,30,83},{24,29,13},{24,27,26},{24,27,14},{30,19,243},{22,29,73},{23,27,5},{22,26,90},{27,25,243},{22,26,90},{24,28,91},{24,28,91},{24,28,91},{24,27,94},{23,29,52},{23,27,4},{23,27,4},{23,26,18},{20,28,50},{21,26,19},{24,28,10},{24,28,10},{24,28,10},{24,27,13},{30,17,50}, +{23,27,4},{23,27,4},{22,26,9},{25,25,50},{22,26,9},{31,19,72},{24,29,4},{25,27,2},{23,27,5},{31,19,72},{27,26,72},{23,27,5},{0,26,90},{27,26,72},{0,26,90},{24,0,90},{24,0,90},{24,0,90},{24,0,90},{23,27,0},{23,27,0},{23,27,0},{23,25,4},{21,27,8},{21,27,8},{25,31,164},{25,30,94},{25,28,106},{25,28,94},{24,31,245},{24,29,97},{24,28,3}, +{24,27,107},{20,31,249},{22,27,100},{25,31,83},{25,30,13},{25,28,25},{25,28,13},{29,23,243},{23,30,73},{24,28,2},{23,27,90},{28,26,243},{23,27,90},{25,29,91},{25,29,91},{25,29,91},{25,28,94},{24,29,53},{24,28,3},{24,28,3},{24,27,26},{21,29,50},{22,27,19},{25,29,10},{25,29,10},{25,29,10},{25,28,13},{31,18,50},{24,28,2},{24,28,2},{23,27,9},{26,26,50}, +{23,27,9},{30,23,72},{25,30,4},{26,28,1},{24,28,1},{30,23,72},{28,27,72},{24,28,1},{0,27,90},{28,27,72},{0,27,90},{25,0,90},{25,0,90},{25,0,90},{25,0,90},{24,28,2},{24,28,2},{24,28,2},{24,26,2},{21,28,9},{21,28,9},{26,31,194},{26,31,94},{26,29,106},{26,29,94},{25,31,284},{25,30,97},{25,29,3},{25,28,97},{22,31,253},{23,28,85},{27,31,99}, +{26,31,13},{26,29,25},{26,29,13},{30,24,243},{24,31,76},{25,29,2},{24,28,81},{29,27,243},{24,28,81},{26,30,91},{26,30,91},{26,30,91},{26,29,94},{25,30,53},{25,29,3},{25,29,3},{25,27,27},{22,30,50},{23,28,21},{26,30,10},{26,30,10},{26,30,10},{26,29,13},{30,22,50},{25,29,2},{25,29,2},{24,28,17},{27,27,50},{24,28,17},{31,24,72},{26,31,4},{27,29,1}, +{25,29,1},{31,24,72},{24,31,72},{25,29,1},{0,28,80},{24,31,72},{0,28,80},{26,0,90},{26,0,90},{26,0,90},{26,0,90},{25,29,2},{25,29,2},{25,29,2},{25,27,2},{23,28,5},{23,28,5},{27,31,280},{27,31,120},{27,30,106},{27,30,82},{27,31,328},{26,31,99},{26,30,5},{26,29,99},{24,31,308},{24,29,100},{28,31,105},{28,31,45},{28,30,27},{27,30,18},{30,27,243}, +{26,31,99},{26,30,5},{25,29,90},{30,28,243},{25,29,90},{27,31,84},{27,31,84},{27,31,84},{27,30,81},{26,31,58},{26,30,4},{26,30,4},{26,29,18},{23,31,53},{24,29,19},{27,31,20},{27,31,20},{27,31,20},{27,30,17},{30,25,50},{26,30,4},{26,30,4},{25,29,9},{30,27,50},{25,29,9},{31,27,72},{28,31,20},{28,30,2},{27,30,2},{31,27,72},{30,29,72},{27,30,2}, +{0,29,90},{30,29,72},{0,29,90},{27,0,80},{27,0,80},{27,0,80},{27,0,80},{26,30,0},{26,30,0},{26,30,0},{26,28,4},{24,30,8},{24,30,8},{28,31,331},{28,31,187},{28,31,106},{28,31,94},{28,31,358},{27,31,173},{27,31,4},{27,30,82},{26,31,355},{25,30,83},{29,31,126},{29,31,62},{28,31,25},{28,31,13},{30,29,221},{28,31,121},{27,31,4},{26,30,73},{29,30,221}, +{26,30,73},{28,31,106},{28,31,106},{28,31,106},{28,31,94},{27,31,100},{27,31,4},{27,31,4},{27,30,18},{25,31,72},{25,30,19},{28,31,25},{28,31,25},{28,31,25},{28,31,13},{31,26,50},{27,31,4},{27,31,4},{26,30,9},{29,29,50},{26,30,9},{31,29,61},{29,31,37},{29,31,1},{27,31,4},{31,29,61},{31,30,61},{27,31,4},{0,30,73},{31,30,61},{0,30,73},{28,0,90}, +{28,0,90},{28,0,90},{28,0,90},{27,31,0},{27,31,0},{27,31,0},{27,29,4},{25,31,8},{25,31,8},{29,31,239},{29,31,175},{29,31,139},{29,31,99},{29,31,239},{28,31,122},{28,31,41},{28,31,26},{28,31,233},{26,31,19},{30,31,54},{30,31,38},{30,31,29},{29,31,18},{30,31,93},{29,31,54},{29,31,18},{27,31,9},{31,30,93},{27,31,9},{29,31,139},{29,31,139},{29,31,139}, +{29,31,99},{29,31,139},{28,31,41},{28,31,41},{28,31,26},{27,31,116},{26,31,19},{30,31,29},{30,31,29},{30,31,29},{29,31,18},{30,30,50},{29,31,18},{29,31,18},{27,31,9},{30,30,50},{27,31,9},{31,30,9},{31,31,9},{30,31,4},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{29,0,90},{29,0,90},{29,0,90},{29,0,90},{28,31,5}, +{28,31,5},{28,31,5},{28,30,2},{26,31,10},{26,31,10},{30,31,140},{30,31,124},{30,31,115},{30,31,99},{30,31,131},{29,31,98},{29,31,62},{29,31,2},{29,31,122},{28,31,20},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,22},{30,31,18},{30,31,9},{29,31,1},{30,31,22},{29,31,1},{30,31,115},{30,31,115},{30,31,115},{30,31,99},{30,31,106},{29,31,62},{29,31,62}, +{29,31,2},{29,31,86},{28,31,20},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,13},{30,31,9},{30,31,9},{29,31,1},{30,31,13},{29,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,90},{30,0,90},{30,0,90},{30,0,90},{29,31,26},{29,31,26},{29,31,26},{29,31,2},{28,31,20}, +{28,31,20},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{0,4,442},{0,3,313},{0,3,142},{0,2,318},{0,2,498},{0,2,354},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{2,1,441},{0,3,313},{0,3,142},{0,2,318},{1,2,441},{0,2,318},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,45},{0,1,25},{0,1,25},{0,1,26},{0,1,50},{0,1,35},{0,3,0}, +{0,3,0},{0,3,0},{0,2,1},{1,0,41},{0,1,25},{0,1,25},{0,1,26},{0,1,41},{0,1,26},{2,3,200},{0,5,52},{0,3,25},{0,3,61},{2,3,200},{3,2,200},{0,3,61},{0,2,218},{3,2,200},{0,2,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,9,200},{0,7,20},{0,5,20}, +{0,4,25},{0,6,686},{0,5,433},{0,4,169},{0,3,443},{0,3,794},{0,3,524},{0,9,200},{0,7,20},{0,5,20},{0,4,25},{3,1,686},{0,5,433},{0,4,169},{0,3,443},{6,0,686},{0,3,443},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,3,145},{0,2,85},{0,2,85},{0,2,101},{0,1,178},{0,1,115},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{1,1,145}, +{0,2,85},{0,2,85},{0,2,101},{3,0,145},{0,2,101},{3,4,200},{0,7,20},{1,4,16},{0,4,25},{3,4,200},{9,0,200},{0,4,25},{0,3,218},{9,0,200},{0,3,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,11,257},{0,9,54},{1,6,85},{0,5,65},{0,9,728},{0,6,371},{0,5,80}, +{0,4,377},{0,5,949},{0,4,521},{1,10,201},{1,8,18},{1,6,21},{1,5,26},{4,2,723},{0,6,371},{0,5,80},{0,4,377},{7,1,723},{0,4,377},{0,8,50},{0,8,50},{0,8,50},{0,5,49},{0,5,164},{0,4,50},{0,4,50},{0,3,65},{0,3,245},{0,2,126},{1,7,2},{1,7,2},{1,7,2},{1,4,5},{2,2,162},{0,4,50},{0,4,50},{0,3,65},{2,2,162}, +{0,3,65},{7,0,200},{0,9,5},{2,5,16},{0,5,16},{7,0,200},{10,1,200},{0,5,16},{0,4,208},{10,1,200},{0,4,208},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,2,1},{0,2,1},{0,2,1},{0,1,4},{0,1,13},{0,1,13},{1,12,315},{1,10,118},{1,7,178},{1,6,129},{0,11,724},{0,8,289},{0,6,34},{0,5,308},{0,6,1087},{0,5,533},{2,11,201}, +{2,9,18},{2,7,21},{2,6,26},{5,3,723},{0,8,289},{0,6,34},{0,5,308},{8,2,723},{0,5,308},{1,9,114},{1,9,114},{1,9,114},{1,6,113},{0,8,162},{0,6,18},{0,6,18},{0,4,25},{0,4,338},{0,3,162},{2,8,2},{2,8,2},{2,8,2},{2,5,5},{3,3,162},{0,6,18},{0,6,18},{0,4,25},{8,0,162},{0,4,25},{6,4,200},{1,10,5},{3,6,16}, +{1,6,16},{6,4,200},{14,0,200},{1,6,16},{0,5,208},{14,0,200},{0,5,208},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{2,14,410},{2,11,209},{2,8,288},{2,7,234},{0,14,739},{0,10,254},{0,8,33},{0,6,270},{0,8,1131},{0,6,450},{3,12,200},{3,10,13},{3,8,25},{3,7,29},{6,4,723}, +{0,10,238},{0,8,17},{0,6,254},{14,0,723},{0,6,254},{2,11,209},{2,11,209},{2,11,209},{2,7,209},{0,11,178},{0,8,17},{0,8,17},{0,5,18},{0,6,376},{0,5,123},{3,9,0},{3,9,0},{3,9,0},{3,7,4},{6,1,162},{0,8,1},{0,8,1},{0,5,2},{11,0,162},{0,5,2},{9,2,200},{2,11,1},{4,7,25},{0,8,17},{9,2,200},{17,0,200},{0,8,17}, +{0,6,218},{17,0,200},{0,6,218},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{0,8,16},{0,8,16},{0,8,16},{1,4,17},{0,4,80},{0,4,80},{3,15,410},{3,12,212},{3,9,288},{3,8,224},{1,15,739},{1,11,254},{1,9,33},{1,7,270},{0,9,1013},{0,7,308},{4,13,201},{4,11,21},{4,9,21},{4,8,26},{10,0,723},{0,12,227},{1,9,17},{0,7,227},{15,1,723}, +{0,7,227},{3,11,212},{3,11,212},{3,11,212},{3,8,208},{2,10,180},{1,9,17},{1,9,17},{1,6,18},{0,8,306},{0,6,41},{4,10,2},{4,10,2},{4,10,2},{4,7,5},{8,0,162},{1,9,1},{1,9,1},{1,6,2},{5,5,162},{1,6,2},{10,3,200},{3,12,4},{5,8,16},{3,8,16},{10,3,200},{18,1,200},{3,8,16},{0,7,218},{18,1,200},{0,7,218},{3,0,208}, +{3,0,208},{3,0,208},{3,0,208},{1,9,16},{1,9,16},{1,9,16},{2,5,17},{0,6,40},{0,6,40},{4,15,426},{4,13,223},{4,10,283},{4,9,234},{2,16,739},{2,12,267},{2,10,33},{2,8,273},{0,11,913},{0,8,225},{5,14,201},{5,12,18},{5,10,21},{5,9,26},{11,1,723},{0,13,208},{2,10,17},{0,8,209},{16,2,723},{0,8,209},{4,12,219},{4,12,219},{4,12,219}, +{4,9,218},{3,11,180},{2,10,17},{2,10,17},{2,7,18},{0,9,229},{0,7,27},{5,11,2},{5,11,2},{5,11,2},{5,8,5},{9,1,162},{2,10,1},{2,10,1},{2,7,2},{16,0,162},{2,7,2},{11,4,200},{3,14,4},{6,9,16},{4,9,16},{11,4,200},{19,2,200},{4,9,16},{0,8,208},{19,2,200},{0,8,208},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{2,10,16}, +{2,10,16},{2,10,16},{3,6,17},{0,8,17},{0,8,17},{5,16,420},{5,14,223},{5,11,283},{5,10,234},{3,17,739},{3,13,267},{3,11,33},{3,9,273},{0,13,868},{0,9,213},{6,15,201},{6,13,18},{6,11,21},{6,10,26},{12,2,723},{0,15,204},{3,11,17},{1,9,209},{22,0,723},{1,9,209},{5,13,219},{5,13,219},{5,13,219},{5,10,218},{3,14,180},{3,11,17},{3,11,17}, +{3,8,20},{0,11,189},{1,8,17},{6,12,2},{6,12,2},{6,12,2},{6,9,5},{10,2,162},{3,11,1},{3,11,1},{2,8,1},{17,1,162},{2,8,1},{15,0,200},{5,14,5},{7,10,16},{5,10,16},{15,0,200},{20,3,200},{5,10,16},{0,9,208},{20,3,200},{0,9,208},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{3,11,16},{3,11,16},{3,11,16},{3,8,20},{0,9,5}, +{0,9,5},{6,18,410},{6,15,209},{6,12,288},{6,11,234},{4,18,739},{4,14,254},{4,12,33},{4,10,270},{0,15,804},{2,10,227},{7,16,200},{7,14,13},{7,12,25},{7,11,29},{15,0,723},{1,16,209},{4,12,17},{2,10,218},{20,3,723},{2,10,218},{6,15,209},{6,15,209},{6,15,209},{6,11,209},{4,15,178},{4,12,17},{4,12,17},{4,9,18},{0,13,171},{2,9,26},{7,13,0}, +{7,13,0},{7,13,0},{7,11,4},{13,0,162},{4,12,1},{4,12,1},{4,9,2},{20,1,162},{4,9,2},{16,1,200},{6,15,1},{8,11,25},{4,12,17},{16,1,200},{26,1,200},{4,12,17},{0,10,218},{26,1,200},{0,10,218},{6,0,208},{6,0,208},{6,0,208},{6,0,208},{4,12,16},{4,12,16},{4,12,16},{5,8,17},{1,11,5},{1,11,5},{7,19,410},{7,16,212},{7,13,288}, +{7,12,224},{5,19,739},{5,15,254},{5,13,33},{5,11,270},{0,16,747},{3,11,227},{8,17,201},{8,15,21},{8,13,21},{8,12,26},{14,4,723},{3,16,209},{5,13,17},{3,11,218},{24,2,723},{3,11,218},{7,15,212},{7,15,212},{7,15,212},{7,12,208},{6,14,180},{5,13,17},{5,13,17},{5,10,18},{1,14,171},{3,10,26},{8,14,2},{8,14,2},{8,14,2},{8,11,5},{14,1,162}, +{5,13,1},{5,13,1},{5,10,2},{24,0,162},{5,10,2},{17,2,200},{7,16,4},{9,12,16},{7,12,16},{17,2,200},{27,2,200},{7,12,16},{0,11,218},{27,2,200},{0,11,218},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{5,13,16},{5,13,16},{5,13,16},{6,9,17},{2,12,8},{2,12,8},{8,19,426},{8,17,223},{8,14,283},{8,13,234},{6,20,739},{6,16,267},{6,14,33}, +{6,12,273},{0,18,727},{3,12,218},{9,18,201},{9,16,18},{9,14,21},{9,13,26},{18,0,723},{4,17,208},{6,14,17},{4,12,209},{30,0,723},{4,12,209},{8,16,219},{8,16,219},{8,16,219},{8,13,218},{7,15,180},{6,14,17},{6,14,17},{6,11,18},{2,15,171},{4,11,27},{9,15,2},{9,15,2},{9,15,2},{9,12,5},{16,0,162},{6,14,1},{6,14,1},{6,11,2},{25,1,162}, +{6,11,2},{18,3,200},{7,18,4},{10,13,16},{8,13,16},{18,3,200},{28,3,200},{8,13,16},{0,12,208},{28,3,200},{0,12,208},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{6,14,16},{6,14,16},{6,14,16},{7,10,17},{3,13,8},{3,13,8},{9,20,420},{9,18,223},{9,15,283},{9,14,234},{7,21,739},{7,17,267},{7,15,33},{7,13,273},{1,19,727},{4,13,213},{10,19,201}, +{10,17,18},{10,15,21},{10,14,26},{19,1,723},{4,19,204},{7,15,17},{5,13,209},{31,1,723},{5,13,209},{9,17,219},{9,17,219},{9,17,219},{9,14,218},{7,18,180},{7,15,17},{7,15,17},{7,12,20},{3,16,173},{5,12,17},{10,16,2},{10,16,2},{10,16,2},{10,13,5},{17,1,162},{7,15,1},{7,15,1},{6,12,1},{26,2,162},{6,12,1},{20,2,200},{9,18,5},{11,14,16}, +{9,14,16},{20,2,200},{24,7,200},{9,14,16},{0,13,208},{24,7,200},{0,13,208},{9,0,218},{9,0,218},{9,0,218},{9,0,218},{7,15,16},{7,15,16},{7,15,16},{7,12,20},{4,13,5},{4,13,5},{10,22,410},{10,19,209},{10,16,288},{10,15,234},{8,22,739},{8,18,254},{8,16,33},{8,14,270},{2,20,724},{6,14,227},{11,20,200},{11,18,13},{11,16,25},{11,15,29},{20,2,723}, +{5,20,209},{8,16,17},{6,14,218},{24,7,723},{6,14,218},{10,19,209},{10,19,209},{10,19,209},{10,15,209},{8,19,178},{8,16,17},{8,16,17},{8,13,18},{3,18,170},{6,13,26},{11,17,0},{11,17,0},{11,17,0},{11,15,4},{17,4,162},{8,16,1},{8,16,1},{8,13,2},{29,2,162},{8,13,2},{23,0,200},{10,19,1},{12,15,25},{8,16,17},{23,0,200},{30,5,200},{8,16,17}, +{0,14,218},{30,5,200},{0,14,218},{10,0,208},{10,0,208},{10,0,208},{10,0,208},{8,16,16},{8,16,16},{8,16,16},{9,12,17},{5,15,5},{5,15,5},{11,23,410},{11,20,212},{11,17,288},{11,16,224},{9,23,739},{9,19,254},{9,17,33},{9,15,270},{3,21,724},{7,15,227},{12,21,201},{12,19,21},{12,17,21},{12,16,26},{21,3,723},{7,20,209},{9,17,17},{7,15,218},{28,6,723}, +{7,15,218},{11,19,212},{11,19,212},{11,19,212},{11,16,208},{10,18,180},{9,17,17},{9,17,17},{9,14,18},{5,18,171},{7,14,26},{12,18,2},{12,18,2},{12,18,2},{12,15,5},{18,5,162},{9,17,1},{9,17,1},{9,14,2},{30,3,162},{9,14,2},{24,1,200},{11,20,4},{13,16,16},{11,16,16},{24,1,200},{31,6,200},{11,16,16},{0,15,218},{31,6,200},{0,15,218},{11,0,208}, +{11,0,208},{11,0,208},{11,0,208},{9,17,16},{9,17,16},{9,17,16},{10,13,17},{6,16,8},{6,16,8},{12,23,426},{12,21,223},{12,18,283},{12,17,234},{10,24,739},{10,20,267},{10,18,33},{10,16,273},{4,22,727},{7,16,218},{13,22,201},{13,20,18},{13,18,21},{13,17,26},{22,4,723},{8,21,208},{10,18,17},{8,16,209},{29,7,723},{8,16,209},{12,20,219},{12,20,219},{12,20,219}, +{12,17,218},{11,19,180},{10,18,17},{10,18,17},{10,15,18},{6,19,171},{8,15,27},{13,19,2},{13,19,2},{13,19,2},{13,16,5},{20,4,162},{10,18,1},{10,18,1},{10,15,2},{29,5,162},{10,15,2},{25,2,200},{11,22,4},{14,17,16},{12,17,16},{25,2,200},{27,10,200},{12,17,16},{0,16,208},{27,10,200},{0,16,208},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{10,18,16}, +{10,18,16},{10,18,16},{11,14,17},{7,17,8},{7,17,8},{13,24,420},{13,22,223},{13,19,283},{13,18,234},{11,25,739},{11,21,267},{11,19,33},{11,17,273},{5,23,727},{8,17,213},{14,23,201},{14,21,18},{14,19,21},{14,18,26},{26,0,723},{8,23,204},{11,19,17},{9,17,209},{30,8,723},{9,17,209},{13,21,219},{13,21,219},{13,21,219},{13,18,218},{11,22,180},{11,19,17},{11,19,17}, +{11,16,20},{7,20,173},{9,16,17},{14,20,2},{14,20,2},{14,20,2},{14,17,5},{24,0,162},{11,19,1},{11,19,1},{10,16,1},{30,6,162},{10,16,1},{26,3,200},{13,22,5},{15,18,16},{13,18,16},{26,3,200},{28,11,200},{13,18,16},{0,17,208},{28,11,200},{0,17,208},{13,0,218},{13,0,218},{13,0,218},{13,0,218},{11,19,16},{11,19,16},{11,19,16},{11,16,20},{8,17,5}, +{8,17,5},{14,26,410},{14,23,209},{14,20,288},{14,19,234},{12,26,739},{12,22,254},{12,20,33},{12,18,270},{6,24,724},{10,18,227},{15,24,200},{15,22,13},{15,20,25},{15,19,29},{26,3,723},{9,24,209},{12,20,17},{10,18,218},{28,11,723},{10,18,218},{14,23,209},{14,23,209},{14,23,209},{14,19,209},{12,23,178},{12,20,17},{12,20,17},{12,17,18},{7,22,170},{10,17,26},{15,21,0}, +{15,21,0},{15,21,0},{15,19,4},{24,3,162},{12,20,1},{12,20,1},{12,17,2},{28,9,162},{12,17,2},{27,4,200},{14,23,1},{16,19,25},{12,20,17},{27,4,200},{31,11,200},{12,20,17},{0,18,218},{31,11,200},{0,18,218},{14,0,208},{14,0,208},{14,0,208},{14,0,208},{12,20,16},{12,20,16},{12,20,16},{13,16,17},{9,19,5},{9,19,5},{15,27,410},{15,24,212},{15,21,288}, +{15,20,224},{13,27,739},{13,23,254},{13,21,33},{13,19,270},{7,25,724},{11,19,227},{16,25,201},{16,23,21},{16,21,21},{16,20,26},{28,2,723},{11,24,209},{13,21,17},{11,19,218},{27,13,723},{11,19,218},{15,23,212},{15,23,212},{15,23,212},{15,20,208},{14,22,180},{13,21,17},{13,21,17},{13,18,18},{9,22,171},{11,18,26},{16,22,2},{16,22,2},{16,22,2},{16,19,5},{22,9,162}, +{13,21,1},{13,21,1},{13,18,2},{29,10,162},{13,18,2},{31,0,200},{15,24,4},{17,20,16},{15,20,16},{31,0,200},{30,13,200},{15,20,16},{0,19,218},{30,13,200},{0,19,218},{15,0,208},{15,0,208},{15,0,208},{15,0,208},{13,21,16},{13,21,16},{13,21,16},{14,17,17},{10,20,8},{10,20,8},{16,27,426},{16,25,223},{16,22,283},{16,21,234},{14,28,739},{14,24,267},{14,22,33}, +{14,20,273},{8,26,727},{11,20,218},{17,26,201},{17,24,18},{17,22,21},{17,21,26},{29,3,723},{12,25,208},{14,22,17},{12,20,209},{28,14,723},{12,20,209},{16,24,219},{16,24,219},{16,24,219},{16,21,218},{15,23,180},{14,22,17},{14,22,17},{14,19,18},{10,23,171},{12,19,27},{17,23,2},{17,23,2},{17,23,2},{17,20,5},{24,8,162},{14,22,1},{14,22,1},{14,19,2},{30,11,162}, +{14,19,2},{29,6,200},{15,26,4},{18,21,16},{16,21,16},{29,6,200},{31,14,200},{16,21,16},{0,20,208},{31,14,200},{0,20,208},{16,0,218},{16,0,218},{16,0,218},{16,0,218},{14,22,16},{14,22,16},{14,22,16},{15,18,17},{11,21,8},{11,21,8},{17,28,420},{17,26,223},{17,23,283},{17,22,234},{15,29,739},{15,25,267},{15,23,33},{15,21,273},{9,27,727},{12,21,213},{18,27,201}, +{18,25,18},{18,23,21},{18,22,26},{30,4,723},{12,27,204},{15,23,17},{13,21,209},{29,15,723},{13,21,209},{17,25,219},{17,25,219},{17,25,219},{17,22,218},{15,26,180},{15,23,17},{15,23,17},{15,20,20},{11,24,173},{13,20,17},{18,24,2},{18,24,2},{18,24,2},{18,21,5},{28,4,162},{15,23,1},{15,23,1},{14,20,1},{29,13,162},{14,20,1},{30,7,200},{17,26,5},{19,22,16}, +{17,22,16},{30,7,200},{30,16,200},{17,22,16},{0,21,208},{30,16,200},{0,21,208},{17,0,218},{17,0,218},{17,0,218},{17,0,218},{15,23,16},{15,23,16},{15,23,16},{15,20,20},{12,21,5},{12,21,5},{18,30,410},{18,27,209},{18,24,288},{18,23,234},{16,30,739},{16,26,254},{16,24,33},{16,22,270},{10,28,724},{14,22,227},{19,28,200},{19,26,13},{19,24,25},{19,23,29},{30,7,723}, +{13,28,209},{16,24,17},{14,22,218},{30,16,723},{14,22,218},{18,27,209},{18,27,209},{18,27,209},{18,23,209},{16,27,178},{16,24,17},{16,24,17},{16,21,18},{11,26,170},{14,21,26},{19,25,0},{19,25,0},{19,25,0},{19,23,4},{31,2,162},{16,24,1},{16,24,1},{16,21,2},{27,16,162},{16,21,2},{31,8,200},{18,27,1},{20,23,25},{16,24,17},{31,8,200},{28,19,200},{16,24,17}, +{0,22,218},{28,19,200},{0,22,218},{18,0,208},{18,0,208},{18,0,208},{18,0,208},{16,24,16},{16,24,16},{16,24,16},{17,20,17},{13,23,5},{13,23,5},{19,31,410},{19,28,212},{19,25,288},{19,24,224},{17,31,739},{17,27,254},{17,25,33},{17,23,270},{11,29,724},{15,23,227},{20,29,201},{20,27,21},{20,25,21},{20,24,26},{29,11,723},{15,28,209},{17,25,17},{15,23,218},{31,17,723}, +{15,23,218},{19,27,212},{19,27,212},{19,27,212},{19,24,208},{18,26,180},{17,25,17},{17,25,17},{17,22,18},{13,26,171},{15,22,26},{20,26,2},{20,26,2},{20,26,2},{20,23,5},{26,13,162},{17,25,1},{17,25,1},{17,22,2},{21,21,162},{17,22,2},{29,14,200},{19,28,4},{21,24,16},{19,24,16},{29,14,200},{29,20,200},{19,24,16},{0,23,218},{29,20,200},{0,23,218},{19,0,208}, +{19,0,208},{19,0,208},{19,0,208},{17,25,16},{17,25,16},{17,25,16},{18,21,17},{14,24,8},{14,24,8},{20,31,426},{20,29,223},{20,26,283},{20,25,234},{19,30,740},{18,28,267},{18,26,33},{18,24,273},{12,30,727},{15,24,218},{21,30,201},{21,28,18},{21,26,21},{21,25,26},{30,12,723},{16,29,208},{18,26,17},{16,24,209},{27,21,723},{16,24,209},{20,28,219},{20,28,219},{20,28,219}, +{20,25,218},{19,27,180},{18,26,17},{18,26,17},{18,23,18},{14,27,171},{16,23,27},{21,27,2},{21,27,2},{21,27,2},{21,24,5},{28,12,162},{18,26,1},{18,26,1},{18,23,2},{22,22,162},{18,23,2},{30,15,200},{19,30,4},{22,25,16},{20,25,16},{30,15,200},{30,21,200},{20,25,16},{0,24,208},{30,21,200},{0,24,208},{20,0,218},{20,0,218},{20,0,218},{20,0,218},{18,26,16}, +{18,26,16},{18,26,16},{19,22,17},{15,25,8},{15,25,8},{21,31,468},{21,30,223},{21,27,283},{21,26,234},{20,31,749},{19,29,267},{19,27,33},{19,25,273},{13,31,727},{16,25,213},{22,31,201},{22,29,18},{22,27,21},{22,26,26},{31,13,723},{16,31,204},{19,27,17},{17,25,209},{28,22,723},{17,25,209},{21,29,219},{21,29,219},{21,29,219},{21,26,218},{19,30,180},{19,27,17},{19,27,17}, +{19,24,20},{15,28,173},{17,24,17},{22,28,2},{22,28,2},{22,28,2},{22,25,5},{29,13,162},{19,27,1},{19,27,1},{18,24,1},{28,20,162},{18,24,1},{31,16,200},{21,30,5},{23,26,16},{21,26,16},{31,16,200},{31,22,200},{21,26,16},{0,25,208},{31,22,200},{0,25,208},{21,0,218},{21,0,218},{21,0,218},{21,0,218},{19,27,16},{19,27,16},{19,27,16},{19,24,20},{16,25,5}, +{16,25,5},{22,31,570},{22,31,209},{22,28,288},{22,27,234},{21,31,804},{20,30,254},{20,28,33},{20,26,270},{15,31,753},{18,26,227},{23,31,232},{23,30,13},{23,28,25},{23,27,29},{31,16,723},{19,31,216},{20,28,17},{18,26,218},{31,22,723},{18,26,218},{22,31,209},{22,31,209},{22,31,209},{22,27,209},{20,31,178},{20,28,17},{20,28,17},{20,25,18},{15,30,170},{18,25,26},{23,29,0}, +{23,29,0},{23,29,0},{23,27,4},{29,16,162},{20,28,1},{20,28,1},{20,25,2},{31,20,162},{20,25,2},{31,19,200},{22,31,1},{24,27,25},{20,28,17},{31,19,200},{27,26,200},{20,28,17},{0,26,218},{27,26,200},{0,26,218},{22,0,208},{22,0,208},{22,0,208},{22,0,208},{20,28,16},{20,28,16},{20,28,16},{21,24,17},{17,27,5},{17,27,5},{23,31,696},{23,31,237},{23,29,288}, +{23,28,224},{23,31,888},{21,31,254},{21,29,33},{21,27,270},{17,31,824},{19,27,227},{24,31,273},{24,31,21},{24,29,21},{24,28,26},{30,20,723},{20,31,233},{21,29,17},{19,27,218},{30,24,723},{19,27,218},{23,31,212},{23,31,212},{23,31,212},{23,28,208},{22,30,180},{21,29,17},{21,29,17},{21,26,18},{17,30,171},{19,26,26},{24,30,2},{24,30,2},{24,30,2},{24,27,5},{30,17,162}, +{21,29,1},{21,29,1},{21,26,2},{25,25,162},{21,26,2},{30,23,200},{24,31,20},{25,28,16},{23,28,16},{30,23,200},{28,27,200},{23,28,16},{0,27,218},{28,27,200},{0,27,218},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{21,29,16},{21,29,16},{21,29,16},{22,25,17},{18,28,8},{18,28,8},{25,31,804},{24,31,334},{24,30,283},{24,29,234},{24,31,957},{22,31,297},{22,30,33}, +{22,28,273},{20,31,913},{19,28,218},{26,31,313},{25,31,51},{25,30,21},{25,29,26},{31,21,723},{22,31,281},{22,30,17},{20,28,209},{31,25,723},{20,28,209},{24,31,234},{24,31,234},{24,31,234},{24,29,218},{23,31,180},{22,30,17},{22,30,17},{22,27,18},{18,31,171},{20,27,27},{25,31,2},{25,31,2},{25,31,2},{25,28,5},{31,18,162},{22,30,1},{22,30,1},{22,27,2},{26,26,162}, +{22,27,2},{31,24,200},{25,31,50},{26,29,16},{24,29,16},{31,24,200},{24,31,200},{24,29,16},{0,28,208},{24,31,200},{0,28,208},{24,0,218},{24,0,218},{24,0,218},{24,0,218},{22,30,16},{22,30,16},{22,30,16},{23,26,17},{19,29,8},{19,29,8},{26,31,930},{25,31,492},{25,31,283},{25,30,234},{25,31,1068},{24,31,389},{23,31,33},{23,29,273},{21,31,999},{20,29,213},{27,31,379}, +{26,31,149},{26,31,21},{26,30,26},{29,27,723},{24,31,364},{23,31,17},{21,29,209},{27,29,723},{21,29,209},{25,31,267},{25,31,267},{25,31,267},{25,30,218},{24,31,205},{23,31,17},{23,31,17},{23,28,20},{20,31,189},{21,28,17},{26,31,5},{26,31,5},{26,31,5},{26,29,5},{30,22,162},{23,31,1},{23,31,1},{22,28,1},{27,27,162},{22,28,1},{30,28,200},{27,31,90},{27,30,16}, +{25,30,16},{30,28,200},{28,30,200},{25,30,16},{0,29,208},{28,30,200},{0,29,208},{25,0,218},{25,0,218},{25,0,218},{25,0,218},{23,31,16},{23,31,16},{23,31,16},{23,28,20},{20,29,5},{20,29,5},{27,31,877},{26,31,585},{26,31,329},{26,31,209},{26,31,990},{25,31,397},{25,31,36},{24,30,165},{23,31,910},{22,30,122},{28,31,306},{28,31,162},{27,31,36},{27,31,4},{31,26,546}, +{26,31,306},{25,31,20},{22,30,113},{29,29,546},{22,30,113},{26,31,329},{26,31,329},{26,31,329},{26,31,209},{25,31,276},{25,31,36},{25,31,36},{24,29,18},{22,31,230},{22,29,26},{27,31,36},{27,31,36},{27,31,36},{27,31,4},{30,25,162},{25,31,20},{25,31,20},{24,29,2},{30,27,162},{24,29,2},{30,30,113},{29,31,61},{28,31,0},{26,31,1},{30,30,113},{30,30,113},{26,31,1}, +{0,30,113},{30,30,113},{0,30,113},{26,0,208},{26,0,208},{26,0,208},{26,0,208},{25,30,17},{25,30,17},{25,30,17},{25,28,17},{21,31,5},{21,31,5},{28,31,731},{27,31,573},{27,31,404},{27,31,244},{27,31,797},{26,31,354},{26,31,98},{25,30,82},{25,31,737},{23,31,58},{29,31,190},{29,31,126},{28,31,65},{28,31,5},{30,29,333},{28,31,185},{27,31,52},{23,31,49},{29,30,333}, +{23,31,49},{27,31,404},{27,31,404},{27,31,404},{27,31,244},{27,31,356},{26,31,98},{26,31,98},{25,30,18},{24,31,315},{23,30,26},{28,31,65},{28,31,65},{28,31,65},{28,31,5},{31,26,162},{27,31,52},{27,31,52},{25,30,2},{29,29,162},{25,30,2},{31,30,25},{30,31,13},{30,31,4},{29,31,1},{31,30,25},{30,31,25},{29,31,1},{0,31,49},{30,31,25},{0,31,49},{27,0,208}, +{27,0,208},{27,0,208},{27,0,208},{26,31,17},{26,31,17},{26,31,17},{26,29,17},{23,31,9},{23,31,9},{29,31,642},{28,31,524},{28,31,443},{28,31,299},{28,31,623},{28,31,335},{27,31,201},{26,31,17},{27,31,610},{24,31,26},{30,31,131},{30,31,115},{29,31,101},{29,31,37},{31,29,193},{29,31,121},{28,31,85},{26,31,1},{29,31,193},{26,31,1},{28,31,443},{28,31,443},{28,31,443}, +{28,31,299},{28,31,398},{27,31,201},{27,31,201},{26,31,17},{26,31,378},{24,31,26},{29,31,101},{29,31,101},{29,31,101},{29,31,37},{31,28,145},{28,31,85},{28,31,85},{26,31,1},{30,30,145},{26,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,218},{28,0,218},{28,0,218},{28,0,218},{27,31,32}, +{27,31,32},{27,31,32},{27,30,17},{24,31,26},{24,31,26},{29,31,418},{29,31,354},{29,31,318},{29,31,254},{29,31,370},{28,31,223},{28,31,142},{28,31,25},{28,31,358},{26,31,58},{30,31,51},{30,31,35},{30,31,26},{30,31,10},{31,30,54},{30,31,34},{30,31,25},{28,31,0},{30,31,54},{28,31,0},{29,31,318},{29,31,318},{29,31,318},{29,31,254},{29,31,270},{28,31,142},{28,31,142}, +{28,31,25},{27,31,249},{26,31,58},{30,31,26},{30,31,26},{30,31,26},{30,31,10},{30,31,41},{30,31,25},{30,31,25},{28,31,0},{31,30,41},{28,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{29,0,218},{29,0,218},{29,0,218},{29,0,218},{28,31,61},{28,31,61},{28,31,61},{28,31,25},{26,31,58}, +{26,31,58},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{0,6,925},{0,5,658},{0,4,274},{0,3,670},{0,3,1039},{0,3,751},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{3,1,925},{0,5,658},{0,4,274},{0,3,670},{6,0,925},{0,3,670},{0,4,1},{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{0,1,98},{0,1,59},{0,4,1}, +{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{2,0,85},{0,1,50},{5,1,421},{0,7,113},{0,5,5},{0,4,130},{5,1,421},{9,0,421},{0,4,130},{0,3,445},{9,0,421},{0,3,445},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,12,425},{0,9,52},{0,6,10}, +{0,6,82},{0,8,1261},{0,6,805},{0,5,322},{0,4,833},{0,4,1445},{0,4,977},{0,12,425},{0,9,52},{0,6,10},{0,6,82},{3,3,1261},{0,6,805},{0,5,322},{0,4,833},{8,0,1261},{0,4,833},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{0,3,225},{0,3,117},{0,3,117},{0,2,125},{0,2,257},{0,2,161},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{2,0,221}, +{0,3,117},{0,3,117},{0,2,125},{2,1,221},{0,2,125},{7,0,421},{0,9,52},{1,6,5},{0,6,82},{7,0,421},{10,1,421},{0,6,82},{0,4,433},{10,1,421},{0,4,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,14,430},{0,11,29},{0,7,74},{0,7,46},{0,10,1514},{0,8,874},{0,6,307}, +{0,5,917},{0,5,1814},{0,4,1074},{0,14,430},{0,11,29},{1,7,35},{0,7,46},{6,0,1514},{0,8,874},{0,6,307},{0,5,917},{10,0,1514},{0,5,917},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{0,5,340},{0,5,160},{0,5,160},{0,3,169},{0,3,421},{0,3,250},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{2,2,338},{0,5,160},{0,5,160},{0,3,169},{2,2,338}, +{0,3,169},{8,1,421},{0,11,20},{2,7,5},{0,7,37},{8,1,421},{14,0,421},{0,7,37},{0,5,433},{14,0,421},{0,5,433},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{1,15,494},{1,12,102},{1,8,137},{1,8,122},{0,12,1517},{0,9,737},{0,7,185},{0,6,794},{0,7,1982},{0,5,1062},{1,15,430}, +{1,12,38},{2,8,34},{1,8,58},{7,1,1514},{0,9,737},{0,7,185},{0,6,794},{11,1,1514},{0,6,794},{1,11,74},{1,11,74},{1,11,74},{1,7,74},{0,8,338},{0,6,98},{0,6,98},{0,4,97},{0,4,514},{0,4,241},{1,11,10},{1,11,10},{1,11,10},{1,7,10},{3,3,338},{0,6,98},{0,6,98},{0,4,97},{8,0,338},{0,4,97},{10,0,421},{0,13,9},{3,8,4}, +{0,8,16},{10,0,421},{17,0,421},{0,8,16},{0,6,433},{17,0,421},{0,6,433},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{1,18,629},{1,14,213},{2,9,354},{1,9,218},{0,15,1517},{0,11,630},{0,9,50},{0,7,670},{0,8,2198},{0,6,1109},{3,15,437},{2,13,41},{3,9,33},{2,9,53},{8,2,1514}, +{0,11,630},{0,9,50},{0,7,670},{12,2,1514},{0,7,670},{1,13,209},{1,13,209},{1,13,209},{1,8,212},{0,11,338},{0,8,41},{0,8,41},{0,5,50},{0,6,680},{0,5,275},{3,10,17},{3,10,17},{3,10,17},{2,8,17},{6,1,338},{0,8,41},{0,8,41},{0,5,50},{11,0,338},{0,5,50},{12,0,421},{0,15,1},{4,9,5},{0,9,1},{12,0,421},{20,0,421},{0,9,1}, +{0,7,445},{20,0,421},{0,7,445},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,7,1},{0,7,1},{0,7,1},{0,4,0},{0,3,106},{0,3,106},{2,19,821},{2,15,405},{2,11,570},{2,10,410},{0,18,1514},{0,13,577},{0,10,14},{0,8,602},{0,10,2462},{0,7,1175},{3,17,441},{3,14,41},{4,10,35},{3,10,53},{9,3,1514},{0,13,577},{0,10,14},{0,8,602},{18,0,1514}, +{0,8,602},{2,14,401},{2,14,401},{2,14,401},{2,9,404},{0,13,340},{0,10,13},{0,10,13},{0,6,29},{0,7,851},{0,6,353},{3,13,17},{3,13,17},{3,13,17},{3,9,17},{8,0,338},{0,10,13},{0,10,13},{0,6,29},{5,5,338},{0,6,29},{13,1,421},{1,16,4},{5,10,5},{1,10,1},{13,1,421},{21,1,421},{1,10,1},{0,8,433},{21,1,421},{0,8,433},{2,0,400}, +{2,0,400},{2,0,400},{2,0,400},{0,9,1},{0,9,1},{0,9,1},{0,6,4},{0,4,208},{0,4,208},{3,20,854},{3,16,437},{3,12,597},{3,11,443},{1,19,1515},{0,15,570},{1,11,15},{0,9,582},{0,11,2337},{0,9,933},{4,18,430},{4,15,29},{5,11,35},{4,11,46},{10,4,1514},{0,15,521},{1,11,14},{0,9,533},{19,1,1514},{0,9,533},{3,15,434},{3,15,434},{3,15,434}, +{3,10,437},{1,14,341},{1,11,14},{1,11,14},{1,7,30},{0,8,755},{0,7,222},{4,14,10},{4,14,10},{4,14,10},{4,10,10},{9,1,338},{0,12,2},{0,12,2},{0,7,26},{16,0,338},{0,7,26},{15,0,421},{3,16,4},{6,11,5},{2,11,1},{15,0,421},{25,0,421},{2,11,1},{0,9,433},{25,0,421},{0,9,433},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{1,10,2}, +{1,10,2},{1,10,2},{1,7,5},{0,6,157},{0,6,157},{4,21,866},{4,17,454},{4,13,609},{4,12,461},{2,20,1515},{1,16,570},{2,12,19},{1,10,582},{0,13,2214},{0,10,707},{5,19,430},{5,16,38},{6,12,34},{5,12,58},{14,0,1514},{0,16,458},{2,12,18},{0,10,482},{20,2,1514},{0,10,482},{4,16,445},{4,16,445},{4,16,445},{4,11,449},{2,15,341},{2,12,19},{2,12,19}, +{2,8,26},{0,10,635},{0,8,106},{5,15,10},{5,15,10},{5,15,10},{5,11,10},{10,2,338},{1,13,2},{1,13,2},{1,8,16},{17,1,338},{1,8,16},{16,1,421},{3,18,4},{7,12,4},{3,12,0},{16,1,421},{26,1,421},{3,12,0},{0,10,433},{26,1,421},{0,10,433},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{2,11,2},{2,11,2},{2,11,2},{2,7,10},{0,8,90}, +{0,8,90},{5,22,854},{5,18,438},{5,14,603},{5,13,443},{3,21,1517},{3,16,554},{3,13,21},{3,11,589},{0,15,2046},{0,11,535},{7,19,437},{6,17,41},{7,13,33},{6,13,53},{14,3,1514},{0,18,429},{3,13,21},{0,11,454},{26,0,1514},{0,11,454},{5,17,434},{5,17,434},{5,17,434},{5,12,437},{3,17,340},{3,13,20},{3,13,20},{3,9,29},{0,12,557},{0,10,49},{7,14,17}, +{7,14,17},{7,14,17},{6,12,17},{13,0,338},{2,14,4},{2,14,4},{1,10,10},{20,1,338},{1,10,10},{17,2,421},{4,19,1},{8,13,5},{4,13,1},{17,2,421},{29,1,421},{4,13,1},{0,11,445},{29,1,421},{0,11,445},{5,0,433},{5,0,433},{5,0,433},{5,0,433},{3,12,1},{3,12,1},{3,12,1},{3,9,4},{0,10,40},{0,10,40},{6,23,854},{6,19,438},{6,15,603}, +{6,14,443},{4,22,1515},{3,18,566},{4,14,15},{3,12,578},{0,16,1911},{0,12,458},{7,21,441},{7,18,41},{8,14,35},{7,14,53},{16,2,1514},{0,20,425},{4,14,14},{0,12,433},{27,1,1514},{0,12,433},{6,18,434},{6,18,434},{6,18,434},{6,13,437},{4,17,341},{4,14,14},{4,14,14},{4,10,30},{0,14,477},{0,11,35},{7,17,17},{7,17,17},{7,17,17},{7,13,17},{14,1,338}, +{3,15,4},{3,15,4},{2,11,10},{24,0,338},{2,11,10},{18,3,421},{5,20,4},{9,14,5},{5,14,1},{18,3,421},{30,2,421},{5,14,1},{0,12,433},{30,2,421},{0,12,433},{6,0,433},{6,0,433},{6,0,433},{6,0,433},{4,13,2},{4,13,2},{4,13,2},{4,10,5},{0,12,25},{0,12,25},{7,24,854},{7,20,437},{7,16,597},{7,15,443},{5,23,1515},{4,19,570},{5,15,15}, +{4,13,582},{0,18,1787},{0,13,442},{8,22,430},{8,19,29},{9,15,35},{8,15,46},{17,3,1514},{2,20,425},{5,15,14},{1,13,433},{28,2,1514},{1,13,433},{7,19,434},{7,19,434},{7,19,434},{7,14,437},{5,18,341},{5,15,14},{5,15,14},{5,11,30},{0,16,419},{1,12,45},{8,18,10},{8,18,10},{8,18,10},{8,14,10},{16,0,338},{4,16,2},{4,16,2},{3,12,17},{25,1,338}, +{3,12,17},{20,2,421},{7,20,4},{10,15,5},{6,15,1},{20,2,421},{31,3,421},{6,15,1},{0,13,433},{31,3,421},{0,13,433},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{5,14,2},{5,14,2},{5,14,2},{5,11,5},{0,13,9},{0,13,9},{8,25,866},{8,21,454},{8,17,609},{8,16,461},{6,24,1515},{5,20,570},{6,16,19},{5,14,582},{0,20,1686},{1,14,442},{9,23,430}, +{9,20,38},{10,16,34},{9,16,58},{18,4,1514},{3,21,425},{6,16,18},{2,14,433},{29,3,1514},{2,14,433},{8,20,445},{8,20,445},{8,20,445},{8,15,449},{6,19,341},{6,16,19},{6,16,19},{6,12,26},{0,17,372},{2,13,45},{9,19,10},{9,19,10},{9,19,10},{9,15,10},{17,1,338},{5,17,2},{5,17,2},{5,12,16},{26,2,338},{5,12,16},{23,0,421},{7,22,4},{11,16,4}, +{7,16,0},{23,0,421},{30,5,421},{7,16,0},{0,14,433},{30,5,421},{0,14,433},{8,0,445},{8,0,445},{8,0,445},{8,0,445},{6,15,2},{6,15,2},{6,15,2},{6,11,10},{0,15,5},{0,15,5},{9,26,854},{9,22,438},{9,18,603},{9,17,443},{7,25,1517},{7,20,554},{7,17,21},{7,15,589},{0,22,1614},{2,15,462},{11,23,437},{10,21,41},{11,17,33},{10,17,53},{22,0,1514}, +{3,23,422},{7,17,21},{3,15,446},{30,4,1514},{3,15,446},{9,21,434},{9,21,434},{9,21,434},{9,16,437},{7,21,340},{7,17,20},{7,17,20},{7,13,29},{0,19,347},{3,14,46},{11,18,17},{11,18,17},{11,18,17},{10,16,17},{17,4,338},{6,18,4},{6,18,4},{5,14,10},{29,2,338},{5,14,10},{24,1,421},{8,23,1},{12,17,5},{8,17,1},{24,1,421},{31,6,421},{8,17,1}, +{0,15,445},{31,6,421},{0,15,445},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{7,16,1},{7,16,1},{7,16,1},{7,13,4},{2,16,8},{2,16,8},{10,27,854},{10,23,438},{10,19,603},{10,18,443},{8,26,1515},{7,22,566},{8,18,15},{7,16,578},{0,23,1566},{3,16,443},{11,25,441},{11,22,41},{12,18,35},{11,18,53},{23,1,1514},{4,24,425},{8,18,14},{4,16,433},{31,5,1514}, +{4,16,433},{10,22,434},{10,22,434},{10,22,434},{10,17,437},{8,21,341},{8,18,14},{8,18,14},{8,14,30},{1,20,341},{4,15,35},{11,21,17},{11,21,17},{11,21,17},{11,17,17},{18,5,338},{7,19,4},{7,19,4},{6,15,10},{30,3,338},{6,15,10},{25,2,421},{9,24,4},{13,18,5},{9,18,1},{25,2,421},{29,9,421},{9,18,1},{0,16,433},{29,9,421},{0,16,433},{10,0,433}, +{10,0,433},{10,0,433},{10,0,433},{8,17,2},{8,17,2},{8,17,2},{8,14,5},{3,17,8},{3,17,8},{11,28,854},{11,24,437},{11,20,597},{11,19,443},{9,27,1515},{8,23,570},{9,19,15},{8,17,582},{0,25,1533},{4,17,442},{12,26,430},{12,23,29},{13,19,35},{12,19,46},{24,2,1514},{6,24,425},{9,19,14},{5,17,433},{27,9,1514},{5,17,433},{11,23,434},{11,23,434},{11,23,434}, +{11,18,437},{9,22,341},{9,19,14},{9,19,14},{9,15,30},{2,21,341},{5,16,45},{12,22,10},{12,22,10},{12,22,10},{12,18,10},{20,4,338},{8,20,2},{8,20,2},{7,16,17},{29,5,338},{7,16,17},{26,3,421},{11,24,4},{14,19,5},{10,19,1},{26,3,421},{30,10,421},{10,19,1},{0,17,433},{30,10,421},{0,17,433},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{9,18,2}, +{9,18,2},{9,18,2},{9,15,5},{4,17,9},{4,17,9},{12,29,866},{12,25,454},{12,21,609},{12,20,461},{10,28,1515},{9,24,570},{10,20,19},{9,18,582},{0,27,1521},{5,18,442},{13,27,430},{13,24,38},{14,20,34},{13,20,58},{25,3,1514},{7,25,425},{10,20,18},{6,18,433},{28,10,1514},{6,18,433},{12,24,445},{12,24,445},{12,24,445},{12,19,449},{10,23,341},{10,20,19},{10,20,19}, +{10,16,26},{3,22,341},{6,17,45},{13,23,10},{13,23,10},{13,23,10},{13,19,10},{24,0,338},{9,21,2},{9,21,2},{9,16,16},{30,6,338},{9,16,16},{28,2,421},{11,26,4},{15,20,4},{11,20,0},{28,2,421},{31,11,421},{11,20,0},{0,18,433},{31,11,421},{0,18,433},{12,0,445},{12,0,445},{12,0,445},{12,0,445},{10,19,2},{10,19,2},{10,19,2},{10,15,10},{4,19,5}, +{4,19,5},{13,30,854},{13,26,438},{13,22,603},{13,21,443},{11,29,1517},{11,24,554},{11,21,21},{11,19,589},{1,28,1518},{6,19,462},{15,27,437},{14,25,41},{15,21,33},{14,21,53},{26,4,1514},{7,27,422},{11,21,21},{7,19,446},{31,10,1514},{7,19,446},{13,25,434},{13,25,434},{13,25,434},{13,20,437},{11,25,340},{11,21,20},{11,21,20},{11,17,29},{3,24,339},{7,18,46},{15,22,17}, +{15,22,17},{15,22,17},{14,20,17},{24,3,338},{10,22,4},{10,22,4},{9,18,10},{28,9,338},{9,18,10},{31,0,421},{12,27,1},{16,21,5},{12,21,1},{31,0,421},{30,13,421},{12,21,1},{0,19,445},{30,13,421},{0,19,445},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{11,20,1},{11,20,1},{11,20,1},{11,17,4},{6,20,8},{6,20,8},{14,31,854},{14,27,438},{14,23,603}, +{14,22,443},{12,30,1515},{11,26,566},{12,22,15},{11,20,578},{2,29,1518},{7,20,443},{15,29,441},{15,26,41},{16,22,35},{15,22,53},{30,0,1514},{8,28,425},{12,22,14},{8,20,433},{30,12,1514},{8,20,433},{14,26,434},{14,26,434},{14,26,434},{14,21,437},{12,25,341},{12,22,14},{12,22,14},{12,18,30},{5,24,341},{8,19,35},{15,25,17},{15,25,17},{15,25,17},{15,21,17},{22,9,338}, +{11,23,4},{11,23,4},{10,19,10},{29,10,338},{10,19,10},{31,3,421},{13,28,4},{17,22,5},{13,22,1},{31,3,421},{31,14,421},{13,22,1},{0,20,433},{31,14,421},{0,20,433},{14,0,433},{14,0,433},{14,0,433},{14,0,433},{12,21,2},{12,21,2},{12,21,2},{12,18,5},{7,21,8},{7,21,8},{15,31,878},{15,28,437},{15,24,597},{15,23,443},{13,31,1515},{12,27,570},{13,23,15}, +{12,21,582},{3,30,1518},{8,21,442},{16,30,430},{16,27,29},{17,23,35},{16,23,46},{31,1,1514},{10,28,425},{13,23,14},{9,21,433},{31,13,1514},{9,21,433},{15,27,434},{15,27,434},{15,27,434},{15,22,437},{13,26,341},{13,23,14},{13,23,14},{13,19,30},{6,25,341},{9,20,45},{16,26,10},{16,26,10},{16,26,10},{16,22,10},{24,8,338},{12,24,2},{12,24,2},{11,20,17},{30,11,338}, +{11,20,17},{30,7,421},{15,28,4},{18,23,5},{14,23,1},{30,7,421},{30,16,421},{14,23,1},{0,21,433},{30,16,421},{0,21,433},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{13,22,2},{13,22,2},{13,22,2},{13,19,5},{8,21,9},{8,21,9},{16,31,926},{16,29,454},{16,25,609},{16,24,461},{14,31,1542},{13,28,570},{14,24,19},{13,22,582},{4,31,1521},{9,22,442},{17,31,430}, +{17,28,38},{18,24,34},{17,24,58},{29,7,1514},{11,29,425},{14,24,18},{10,22,433},{27,17,1514},{10,22,433},{16,28,445},{16,28,445},{16,28,445},{16,23,449},{14,27,341},{14,24,19},{14,24,19},{14,20,26},{7,26,341},{10,21,45},{17,27,10},{17,27,10},{17,27,10},{17,23,10},{28,4,338},{13,25,2},{13,25,2},{13,20,16},{29,13,338},{13,20,16},{31,8,421},{15,30,4},{19,24,4}, +{15,24,0},{31,8,421},{31,17,421},{15,24,0},{0,22,433},{31,17,421},{0,22,433},{16,0,445},{16,0,445},{16,0,445},{16,0,445},{14,23,2},{14,23,2},{14,23,2},{14,19,10},{8,23,5},{8,23,5},{17,31,1034},{17,30,438},{17,26,603},{17,25,443},{16,31,1598},{15,28,554},{15,25,21},{15,23,589},{6,31,1535},{10,23,462},{19,31,437},{18,29,41},{19,25,33},{18,25,53},{30,8,1514}, +{11,31,422},{15,25,21},{11,23,446},{28,18,1514},{11,23,446},{17,29,434},{17,29,434},{17,29,434},{17,24,437},{15,29,340},{15,25,20},{15,25,20},{15,21,29},{7,28,339},{11,22,46},{19,26,17},{19,26,17},{19,26,17},{18,24,17},{31,2,338},{14,26,4},{14,26,4},{13,22,10},{27,16,338},{13,22,10},{31,11,421},{16,31,1},{20,25,5},{16,25,1},{31,11,421},{31,19,421},{16,25,1}, +{0,23,445},{31,19,421},{0,23,445},{17,0,433},{17,0,433},{17,0,433},{17,0,433},{15,24,1},{15,24,1},{15,24,1},{15,21,4},{10,24,8},{10,24,8},{18,31,1166},{18,31,438},{18,27,603},{18,26,443},{17,31,1643},{15,30,566},{16,26,15},{15,24,578},{8,31,1566},{11,24,443},{20,31,458},{19,30,41},{20,26,35},{19,26,53},{31,9,1514},{13,31,429},{16,26,14},{12,24,433},{29,19,1514}, +{12,24,433},{18,30,434},{18,30,434},{18,30,434},{18,25,437},{16,29,341},{16,26,14},{16,26,14},{16,22,30},{9,28,341},{12,23,35},{19,29,17},{19,29,17},{19,29,17},{19,25,17},{26,13,338},{15,27,4},{15,27,4},{14,23,10},{21,21,338},{14,23,10},{30,15,421},{18,31,5},{21,26,5},{17,26,1},{30,15,421},{30,21,421},{17,26,1},{0,24,433},{30,21,421},{0,24,433},{18,0,433}, +{18,0,433},{18,0,433},{18,0,433},{16,25,2},{16,25,2},{16,25,2},{16,22,5},{11,25,8},{11,25,8},{20,31,1326},{19,31,470},{19,28,597},{19,27,443},{18,31,1742},{16,31,570},{17,27,15},{16,25,582},{10,31,1638},{12,25,442},{21,31,506},{20,31,29},{21,27,35},{20,27,46},{29,15,1514},{15,31,461},{17,27,14},{13,25,433},{30,20,1514},{13,25,433},{19,31,434},{19,31,434},{19,31,434}, +{19,26,437},{17,30,341},{17,27,14},{17,27,14},{17,23,30},{10,29,341},{13,24,45},{20,30,10},{20,30,10},{20,30,10},{20,26,10},{28,12,338},{16,28,2},{16,28,2},{15,24,17},{22,22,338},{15,24,17},{31,16,421},{20,31,20},{22,27,5},{18,27,1},{31,16,421},{31,22,421},{18,27,1},{0,25,433},{31,22,421},{0,25,433},{19,0,433},{19,0,433},{19,0,433},{19,0,433},{17,26,2}, +{17,26,2},{17,26,2},{17,23,5},{12,25,9},{12,25,9},{21,31,1470},{20,31,561},{20,29,609},{20,28,461},{19,31,1895},{18,31,578},{18,28,19},{17,26,582},{12,31,1761},{13,26,442},{22,31,590},{21,31,59},{22,28,34},{21,28,58},{30,16,1514},{17,31,530},{18,28,18},{14,26,433},{31,21,1514},{14,26,433},{20,31,461},{20,31,461},{20,31,461},{20,27,449},{18,31,341},{18,28,19},{18,28,19}, +{18,24,26},{11,30,341},{14,25,45},{21,31,10},{21,31,10},{21,31,10},{21,27,10},{29,13,338},{17,29,2},{17,29,2},{17,24,16},{28,20,338},{17,24,16},{31,19,421},{21,31,50},{23,28,4},{19,28,0},{31,19,421},{30,24,421},{19,28,0},{0,26,433},{30,24,421},{0,26,433},{20,0,445},{20,0,445},{20,0,445},{20,0,445},{18,27,2},{18,27,2},{18,27,2},{18,23,10},{12,27,5}, +{12,27,5},{22,31,1674},{21,31,753},{21,30,603},{21,29,443},{21,31,2046},{19,31,629},{19,29,21},{19,27,589},{15,31,1917},{14,27,462},{24,31,674},{23,31,120},{23,29,33},{22,29,53},{30,19,1514},{19,31,629},{19,29,21},{15,27,446},{27,25,1514},{15,27,446},{21,31,497},{21,31,497},{21,31,497},{21,28,437},{19,31,388},{19,29,20},{19,29,20},{19,25,29},{12,31,347},{15,26,46},{23,30,17}, +{23,30,17},{23,30,17},{22,28,17},{29,16,338},{18,30,4},{18,30,4},{17,26,10},{31,20,338},{17,26,10},{30,23,421},{23,31,104},{24,29,5},{20,29,1},{30,23,421},{30,26,421},{20,29,1},{0,27,445},{30,26,421},{0,27,445},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{19,28,1},{19,28,1},{19,28,1},{19,25,4},{14,28,8},{14,28,8},{23,31,1902},{22,31,995},{22,31,603}, +{22,30,443},{22,31,2235},{20,31,759},{20,30,15},{19,28,578},{17,31,2118},{15,28,443},{25,31,770},{24,31,250},{24,30,35},{23,30,53},{29,23,1514},{21,31,701},{20,30,14},{16,28,433},{28,26,1514},{16,28,433},{22,31,554},{22,31,554},{22,31,554},{22,29,437},{21,31,437},{20,30,14},{20,30,14},{20,26,30},{14,31,379},{16,27,35},{24,31,25},{24,31,25},{24,31,25},{23,29,17},{30,17,338}, +{19,31,4},{19,31,4},{18,27,10},{25,25,338},{18,27,10},{31,24,421},{25,31,169},{25,30,5},{21,30,1},{31,24,421},{31,27,421},{21,30,1},{0,28,433},{31,27,421},{0,28,433},{22,0,433},{22,0,433},{22,0,433},{22,0,433},{20,29,2},{20,29,2},{20,29,2},{20,26,5},{15,29,8},{15,29,8},{24,31,2045},{24,31,1233},{23,31,629},{23,31,442},{24,31,2360},{22,31,914},{21,31,14}, +{20,29,549},{19,31,2241},{16,29,409},{26,31,849},{25,31,395},{25,31,34},{24,31,45},{30,24,1459},{23,31,778},{21,31,13},{17,29,400},{29,27,1459},{17,29,400},{23,31,629},{23,31,629},{23,31,629},{23,30,437},{22,31,491},{21,31,14},{21,31,14},{21,27,30},{16,31,446},{17,28,45},{25,31,34},{25,31,34},{25,31,34},{24,30,10},{31,18,338},{21,31,13},{21,31,13},{19,28,17},{26,26,338}, +{19,28,17},{30,28,392},{27,31,218},{26,31,4},{22,31,0},{30,28,392},{28,30,392},{22,31,0},{0,29,400},{28,30,392},{0,29,400},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{21,30,2},{21,30,2},{21,30,2},{21,27,5},{16,29,9},{16,29,9},{25,31,1767},{25,31,1167},{24,31,701},{24,31,449},{24,31,1976},{23,31,747},{22,31,66},{22,29,337},{20,31,1820},{17,30,217},{27,31,611}, +{26,31,317},{26,31,61},{25,31,10},{31,24,1064},{25,31,587},{23,31,41},{18,30,208},{24,31,1064},{18,30,208},{24,31,701},{24,31,701},{24,31,701},{24,31,449},{23,31,581},{22,31,66},{22,31,66},{22,28,26},{18,31,530},{18,29,45},{26,31,61},{26,31,61},{26,31,61},{25,31,10},{30,22,338},{23,31,41},{23,31,41},{21,28,16},{27,27,338},{21,28,16},{29,31,200},{28,31,106},{27,31,1}, +{25,31,1},{29,31,200},{31,29,200},{25,31,1},{0,30,208},{31,29,200},{0,30,208},{24,0,445},{24,0,445},{24,0,445},{24,0,445},{22,31,2},{22,31,2},{22,31,2},{22,27,10},{16,31,5},{16,31,5},{26,31,1542},{26,31,1122},{25,31,833},{25,31,497},{26,31,1647},{24,31,687},{24,31,203},{23,30,122},{22,31,1515},{19,30,110},{28,31,410},{28,31,266},{27,31,116},{27,31,20},{31,26,722}, +{26,31,402},{25,31,100},{21,30,74},{29,29,722},{21,30,74},{25,31,833},{25,31,833},{25,31,833},{25,31,497},{24,31,707},{24,31,203},{24,31,203},{23,29,29},{20,31,619},{19,30,46},{27,31,116},{27,31,116},{27,31,116},{27,31,20},{30,25,338},{25,31,100},{25,31,100},{21,30,10},{30,27,338},{21,30,10},{31,29,61},{29,31,37},{29,31,1},{27,31,4},{31,29,61},{31,30,61},{27,31,4}, +{0,30,73},{31,30,61},{0,30,73},{25,0,433},{25,0,433},{25,0,433},{25,0,433},{23,31,25},{23,31,25},{23,31,25},{23,29,4},{18,31,17},{18,31,17},{27,31,1406},{27,31,1134},{26,31,962},{26,31,602},{27,31,1454},{25,31,702},{25,31,341},{24,31,59},{24,31,1378},{20,31,35},{29,31,318},{28,31,250},{28,31,169},{28,31,61},{30,29,509},{28,31,313},{27,31,164},{22,31,10},{29,30,509}, +{22,31,10},{26,31,962},{26,31,962},{26,31,962},{26,31,602},{26,31,827},{25,31,341},{25,31,341},{24,30,30},{22,31,747},{20,31,35},{28,31,169},{28,31,169},{28,31,169},{28,31,61},{31,26,338},{27,31,164},{27,31,164},{22,31,10},{29,29,338},{22,31,10},{31,30,9},{31,31,9},{30,31,4},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{26,0,433}, +{26,0,433},{26,0,433},{26,0,433},{24,31,50},{24,31,50},{24,31,50},{24,30,5},{20,31,26},{20,31,26},{28,31,1135},{28,31,991},{27,31,874},{27,31,602},{28,31,1162},{26,31,618},{26,31,362},{25,31,5},{25,31,1087},{22,31,58},{30,31,219},{29,31,161},{29,31,125},{29,31,61},{31,29,297},{29,31,193},{28,31,117},{24,31,1},{30,30,297},{24,31,1},{27,31,874},{27,31,874},{27,31,874}, +{27,31,602},{27,31,730},{26,31,362},{26,31,362},{25,31,5},{24,31,681},{22,31,58},{29,31,125},{29,31,125},{29,31,125},{29,31,61},{30,29,221},{28,31,117},{28,31,117},{24,31,1},{31,29,221},{24,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{27,0,433},{27,0,433},{27,0,433},{27,0,433},{25,31,101}, +{25,31,101},{25,31,101},{25,31,5},{22,31,58},{22,31,58},{29,31,885},{28,31,751},{28,31,670},{28,31,526},{28,31,778},{27,31,483},{27,31,314},{26,31,10},{26,31,777},{24,31,117},{30,31,75},{30,31,59},{30,31,50},{30,31,34},{30,31,114},{29,31,81},{29,31,45},{27,31,0},{31,30,114},{27,31,0},{28,31,670},{28,31,670},{28,31,670},{28,31,526},{28,31,553},{27,31,314},{27,31,314}, +{26,31,10},{25,31,518},{24,31,117},{30,31,50},{30,31,50},{30,31,50},{30,31,34},{31,29,85},{29,31,45},{29,31,45},{27,31,0},{29,31,85},{27,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,445},{28,0,445},{28,0,445},{28,0,445},{27,31,145},{27,31,145},{27,31,145},{26,31,10},{24,31,117}, +{24,31,117},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{0,9,1899},{0,7,1355},{0,6,589},{0,4,1354},{0,5,2124},{0,4,1498},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{4,2,1896},{0,7,1355},{0,6,589},{0,4,1354},{7,1,1896},{0,4,1354},{0,6,0},{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{0,2,200},{0,1,134},{0,6,0}, +{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{3,0,162},{0,2,104},{6,3,882},{0,10,225},{0,7,18},{0,6,265},{6,3,882},{8,3,882},{0,6,265},{0,5,890},{8,3,882},{0,5,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,15,884},{0,12,170},{0,8,8}, +{0,7,202},{0,10,2360},{0,8,1530},{0,7,643},{0,5,1579},{0,6,2684},{0,5,1804},{0,15,884},{0,12,170},{0,8,8},{0,7,202},{5,2,2355},{0,8,1530},{0,7,643},{0,5,1579},{7,2,2355},{0,5,1579},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{0,4,340},{0,4,180},{0,4,180},{0,2,200},{0,2,392},{0,2,236},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{2,1,338}, +{0,4,180},{0,4,180},{0,2,200},{1,2,338},{0,2,200},{8,2,882},{0,12,170},{0,8,8},{0,7,202},{8,2,882},{12,2,882},{0,7,202},{0,6,890},{12,2,882},{0,6,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{0,12,2899},{0,9,1773},{0,8,725}, +{0,6,1854},{0,7,3348},{0,5,2124},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{2,9,2899},{0,9,1773},{0,8,725},{0,6,1854},{12,0,2899},{0,6,1854},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{0,6,580},{0,5,306},{0,5,306},{0,3,325},{0,3,667},{0,3,406},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{1,4,578},{0,5,306},{0,5,306},{0,3,325},{4,1,578}, +{0,3,325},{9,3,882},{0,14,106},{1,9,8},{0,9,148},{9,3,882},{18,0,882},{0,9,148},{0,7,890},{18,0,882},{0,7,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,21,920},{0,16,89},{1,11,120},{0,10,121},{0,14,3051},{0,11,1709},{0,9,557},{0,7,1795},{0,8,3651},{0,6,2174},{1,19,886}, +{0,16,89},{1,11,56},{0,10,121},{8,1,3048},{0,11,1709},{0,9,557},{0,7,1795},{6,5,3048},{0,7,1795},{0,14,37},{0,14,37},{0,14,37},{0,8,37},{0,8,648},{0,7,274},{0,7,274},{0,4,277},{0,4,824},{0,4,421},{1,12,4},{1,12,4},{1,12,4},{1,8,8},{3,3,648},{0,7,274},{0,7,274},{0,4,277},{8,0,648},{0,4,277},{10,4,882},{0,16,53},{2,10,8}, +{0,10,85},{10,4,882},{19,1,882},{0,10,85},{0,8,900},{19,1,882},{0,8,900},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{1,22,995},{1,17,158},{1,12,230},{1,11,186},{0,17,3051},{0,13,1579},{0,10,346},{0,8,1630},{0,9,3924},{0,7,2173},{2,20,885},{2,16,90},{2,12,53},{1,11,122},{8,4,3048}, +{0,13,1579},{0,10,346},{0,8,1630},{14,2,3048},{0,8,1630},{1,15,113},{1,15,113},{1,15,113},{1,9,117},{0,11,648},{0,9,169},{0,9,169},{0,5,200},{0,6,990},{0,5,425},{2,13,2},{2,13,2},{2,13,2},{2,9,2},{6,1,648},{0,9,169},{0,9,169},{0,5,200},{11,0,648},{0,5,200},{13,2,882},{0,18,17},{3,11,18},{0,11,34},{13,2,882},{22,1,882},{0,11,34}, +{0,9,890},{22,1,882},{0,9,890},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{1,24,1173},{1,19,306},{2,13,422},{1,12,318},{0,20,3048},{0,15,1443},{0,12,204},{0,9,1483},{0,11,4212},{0,8,2174},{3,21,885},{3,17,90},{3,13,53},{2,12,117},{12,0,3048},{0,15,1443},{0,12,204},{0,9,1483},{20,0,3048}, +{0,9,1483},{1,18,290},{1,18,290},{1,18,290},{1,11,289},{0,13,650},{0,11,109},{0,11,109},{0,7,148},{0,7,1161},{0,6,473},{3,14,2},{3,14,2},{3,14,2},{3,10,2},{8,0,648},{0,11,109},{0,11,109},{0,7,148},{5,5,648},{0,7,148},{14,3,882},{0,20,8},{4,12,8},{0,12,8},{14,3,882},{26,0,882},{0,12,8},{0,10,890},{26,0,882},{0,10,890},{1,0,289}, +{1,0,289},{1,0,289},{1,0,289},{0,8,1},{0,8,1},{0,8,1},{0,5,4},{0,3,145},{0,3,145},{2,25,1365},{2,20,497},{2,14,713},{2,13,510},{0,23,3051},{0,16,1278},{0,13,86},{0,10,1354},{0,12,4609},{0,9,2228},{4,22,886},{3,19,94},{4,14,56},{3,13,117},{13,1,3048},{0,16,1278},{0,13,86},{0,10,1354},{21,1,3048},{0,10,1354},{2,19,482},{2,19,482},{2,19,482}, +{2,12,481},{0,16,648},{0,12,72},{0,12,72},{0,8,101},{0,8,1352},{0,7,557},{4,15,5},{4,15,5},{4,15,5},{4,11,5},{9,1,648},{0,12,72},{0,12,72},{0,8,101},{16,0,648},{0,8,101},{16,2,882},{1,21,8},{5,13,8},{0,13,5},{16,2,882},{27,1,882},{0,13,5},{0,11,890},{27,1,882},{0,11,890},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,10,1}, +{0,10,1},{0,10,1},{0,6,1},{0,5,261},{0,5,261},{2,28,1667},{2,22,793},{3,15,1033},{2,14,793},{0,25,3048},{0,18,1170},{0,14,36},{0,11,1243},{0,14,5005},{0,10,2318},{5,23,886},{4,20,89},{5,15,56},{4,14,121},{14,2,3048},{0,18,1170},{0,14,36},{0,11,1243},{25,0,3048},{0,11,1243},{2,21,786},{2,21,786},{2,21,786},{2,14,789},{0,19,650},{0,14,32},{0,14,32}, +{0,9,50},{0,9,1619},{0,8,661},{5,16,4},{5,16,4},{5,16,4},{5,12,8},{10,2,648},{0,14,32},{0,14,32},{0,9,50},{17,1,648},{0,9,50},{17,3,882},{2,22,8},{6,14,8},{1,14,5},{17,3,882},{28,2,882},{1,14,5},{0,12,900},{28,2,882},{0,12,900},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{0,13,1},{0,13,1},{0,13,1},{0,8,4},{0,6,405}, +{0,6,405},{3,29,1784},{3,23,902},{4,16,1186},{3,15,910},{1,26,3055},{0,20,1095},{1,15,47},{0,12,1159},{0,16,4945},{0,12,2084},{6,24,885},{6,20,90},{6,16,53},{5,15,122},{12,8,3048},{0,20,1059},{0,16,41},{0,12,1123},{28,0,3048},{0,12,1123},{3,23,901},{3,23,901},{3,23,901},{3,15,901},{1,20,652},{1,15,38},{1,15,38},{1,10,44},{0,11,1577},{0,9,545},{6,17,2}, +{6,17,2},{6,17,2},{6,13,2},{13,0,648},{0,16,5},{0,16,5},{0,10,13},{20,1,648},{0,10,13},{17,6,882},{3,23,2},{7,15,18},{3,15,10},{17,6,882},{31,2,882},{3,15,10},{0,13,890},{31,2,882},{0,13,890},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{1,14,4},{1,14,4},{1,14,4},{1,9,5},{0,8,373},{0,8,373},{4,30,1772},{4,24,898},{5,17,1186}, +{4,16,898},{2,27,3055},{1,21,1095},{2,16,33},{1,13,1159},{0,17,4639},{0,13,1730},{7,25,885},{7,21,90},{7,17,53},{6,16,117},{16,4,3048},{0,21,996},{2,16,29},{0,13,1054},{29,1,3048},{0,13,1054},{4,23,891},{4,23,891},{4,23,891},{4,16,894},{2,21,652},{2,16,29},{2,16,29},{2,11,44},{0,13,1452},{0,11,365},{7,18,2},{7,18,2},{7,18,2},{7,14,2},{14,1,648}, +{0,18,1},{0,18,1},{0,11,4},{24,0,648},{0,11,4},{22,0,882},{4,24,8},{8,16,8},{3,16,5},{22,0,882},{30,4,882},{3,16,5},{0,14,890},{30,4,882},{0,14,890},{4,0,890},{4,0,890},{4,0,890},{4,0,890},{2,15,4},{2,15,4},{2,15,4},{2,10,5},{0,9,269},{0,9,269},{5,31,1772},{5,25,898},{6,18,1186},{5,17,898},{3,28,3055},{2,22,1095},{3,17,33}, +{2,14,1159},{0,19,4419},{0,14,1444},{8,26,886},{7,23,94},{8,18,56},{7,17,117},{17,5,3048},{0,23,936},{3,17,29},{0,14,1003},{30,2,3048},{0,14,1003},{5,24,891},{5,24,891},{5,24,891},{5,17,894},{3,22,652},{3,17,29},{3,17,29},{3,12,41},{0,15,1296},{0,12,235},{8,19,5},{8,19,5},{8,19,5},{8,15,5},{16,0,648},{1,19,1},{1,19,1},{1,12,1},{25,1,648}, +{1,12,1},{23,1,882},{5,25,8},{9,17,8},{4,17,5},{23,1,882},{31,5,882},{4,17,5},{0,15,890},{31,5,882},{0,15,890},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{3,16,4},{3,16,4},{3,16,4},{3,11,5},{0,11,185},{0,11,185},{6,31,1790},{6,26,898},{7,19,1186},{6,18,898},{4,29,3057},{3,23,1095},{4,18,45},{3,15,1159},{0,20,4156},{0,15,1226},{9,27,886}, +{8,24,89},{9,19,56},{8,18,121},{18,6,3048},{0,25,909},{4,18,36},{0,15,970},{31,3,3048},{0,15,970},{6,25,891},{6,25,891},{6,25,891},{6,18,894},{4,23,659},{4,18,41},{4,18,41},{3,13,46},{0,16,1137},{0,13,137},{9,20,4},{9,20,4},{9,20,4},{9,16,8},{17,1,648},{2,20,2},{2,20,2},{2,13,1},{26,2,648},{2,13,1},{24,2,882},{6,26,8},{10,18,8}, +{5,18,5},{24,2,882},{27,9,882},{5,18,5},{0,16,900},{27,9,882},{0,16,900},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{4,17,10},{4,17,10},{4,17,10},{4,12,13},{0,13,136},{0,13,136},{8,31,1844},{7,27,902},{8,20,1186},{7,19,910},{5,30,3055},{4,24,1095},{5,19,47},{4,16,1159},{0,22,3940},{0,16,1055},{10,28,885},{10,24,90},{10,20,53},{9,19,122},{22,2,3048}, +{0,27,886},{4,20,41},{0,17,926},{22,10,3048},{0,17,926},{7,27,901},{7,27,901},{7,27,901},{7,19,901},{5,24,652},{5,19,38},{5,19,38},{5,14,44},{0,18,1002},{0,15,110},{10,21,2},{10,21,2},{10,21,2},{10,17,2},{17,4,648},{3,21,4},{3,21,4},{3,14,5},{29,2,648},{3,14,5},{27,0,882},{7,27,2},{11,19,18},{7,19,10},{27,0,882},{30,9,882},{7,19,10}, +{0,17,890},{30,9,882},{0,17,890},{7,0,900},{7,0,900},{7,0,900},{7,0,900},{5,18,4},{5,18,4},{5,18,4},{5,13,5},{0,15,74},{0,15,74},{9,31,1886},{8,28,898},{9,21,1186},{8,20,898},{6,31,3055},{5,25,1095},{6,20,33},{5,17,1159},{0,23,3820},{0,18,963},{11,29,885},{11,25,90},{11,21,53},{10,20,117},{23,3,3048},{1,28,888},{6,20,29},{0,18,899},{28,8,3048}, +{0,18,899},{8,27,891},{8,27,891},{8,27,891},{8,20,894},{6,25,652},{6,20,29},{6,20,29},{6,15,44},{0,20,876},{0,16,102},{11,22,2},{11,22,2},{11,22,2},{11,18,2},{18,5,648},{4,22,1},{4,22,1},{4,15,4},{30,3,648},{4,15,4},{26,4,882},{8,28,8},{12,20,8},{7,20,5},{26,4,882},{31,10,882},{7,20,5},{0,18,890},{31,10,882},{0,18,890},{8,0,890}, +{8,0,890},{8,0,890},{8,0,890},{6,19,4},{6,19,4},{6,19,4},{6,14,5},{0,17,29},{0,17,29},{10,31,1964},{9,29,898},{10,22,1186},{9,21,898},{7,31,3100},{6,26,1095},{7,21,33},{6,18,1159},{0,25,3679},{0,19,899},{12,30,886},{11,27,94},{12,22,56},{11,21,117},{21,9,3048},{2,29,888},{7,21,29},{0,19,890},{29,9,3048},{0,19,890},{9,28,891},{9,28,891},{9,28,891}, +{9,21,894},{7,26,652},{7,21,29},{7,21,29},{7,16,41},{0,22,800},{2,16,98},{12,23,5},{12,23,5},{12,23,5},{12,19,5},{20,4,648},{5,23,1},{5,23,1},{5,16,1},{29,5,648},{5,16,1},{30,0,882},{9,29,8},{13,21,8},{8,21,5},{30,0,882},{30,12,882},{8,21,5},{0,19,890},{30,12,882},{0,19,890},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{7,20,4}, +{7,20,4},{7,20,4},{7,15,5},{0,19,9},{0,19,9},{11,31,2078},{10,30,898},{11,23,1186},{10,22,898},{9,31,3181},{7,27,1095},{8,22,45},{7,19,1159},{0,27,3523},{0,20,908},{13,31,886},{12,28,89},{13,23,56},{12,22,121},{22,10,3048},{3,30,888},{8,22,36},{1,20,901},{30,10,3048},{1,20,901},{10,29,891},{10,29,891},{10,29,891},{10,22,894},{8,27,659},{8,22,41},{8,22,41}, +{7,17,46},{0,23,747},{3,17,98},{13,24,4},{13,24,4},{13,24,4},{13,20,8},{24,0,648},{6,24,2},{6,24,2},{6,17,1},{30,6,648},{6,17,1},{31,1,882},{10,30,8},{14,22,8},{9,22,5},{31,1,882},{31,13,882},{9,22,5},{0,20,900},{31,13,882},{0,20,900},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{8,21,10},{8,21,10},{8,21,10},{8,16,13},{0,20,8}, +{0,20,8},{12,31,2228},{11,31,902},{12,24,1186},{11,23,910},{10,31,3256},{8,28,1095},{9,23,47},{8,20,1159},{0,29,3364},{2,21,894},{14,31,915},{14,28,90},{14,24,53},{13,23,122},{29,1,3048},{4,31,886},{8,24,41},{2,21,890},{26,14,3048},{2,21,890},{11,31,901},{11,31,901},{11,31,901},{11,23,901},{9,28,652},{9,23,38},{9,23,38},{9,18,44},{0,25,705},{3,19,101},{14,25,2}, +{14,25,2},{14,25,2},{14,21,2},{24,3,648},{7,25,4},{7,25,4},{7,18,5},{28,9,648},{7,18,5},{31,4,882},{11,31,2},{15,23,18},{11,23,10},{31,4,882},{24,19,882},{11,23,10},{0,21,890},{24,19,882},{0,21,890},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{9,22,4},{9,22,4},{9,22,4},{9,17,5},{2,21,4},{2,21,4},{13,31,2414},{12,31,907},{13,25,1186}, +{12,24,898},{11,31,3391},{9,29,1095},{10,24,33},{9,21,1159},{0,31,3276},{3,22,894},{15,31,981},{15,29,90},{15,25,53},{14,24,117},{30,2,3048},{6,31,906},{10,24,29},{3,22,890},{27,15,3048},{3,22,890},{12,31,891},{12,31,891},{12,31,891},{12,24,894},{10,29,652},{10,24,29},{10,24,29},{10,19,44},{0,27,665},{4,20,102},{15,26,2},{15,26,2},{15,26,2},{15,22,2},{22,9,648}, +{8,26,1},{8,26,1},{8,19,4},{29,10,648},{8,19,4},{30,8,882},{12,31,17},{16,24,8},{11,24,5},{30,8,882},{28,18,882},{11,24,5},{0,22,890},{28,18,882},{0,22,890},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{10,23,4},{10,23,4},{10,23,4},{10,18,5},{3,22,4},{3,22,4},{15,31,2606},{13,31,987},{14,26,1186},{13,25,898},{13,31,3517},{10,30,1095},{11,25,33}, +{10,22,1159},{1,31,3300},{4,23,899},{17,31,1014},{15,31,94},{16,26,56},{15,25,117},{31,3,3048},{8,31,936},{11,25,29},{4,23,890},{23,19,3048},{4,23,890},{13,31,906},{13,31,906},{13,31,906},{13,25,894},{11,30,652},{11,25,29},{11,25,29},{11,20,41},{0,29,651},{6,20,98},{16,27,5},{16,27,5},{16,27,5},{16,23,5},{24,8,648},{9,27,1},{9,27,1},{9,20,1},{30,11,648}, +{9,20,1},{31,9,882},{14,31,37},{17,25,8},{12,25,5},{31,9,882},{29,19,882},{12,25,5},{0,23,890},{29,19,882},{0,23,890},{13,0,890},{13,0,890},{13,0,890},{13,0,890},{11,24,4},{11,24,4},{11,24,4},{11,19,5},{3,24,5},{3,24,5},{16,31,2792},{15,31,1079},{15,27,1186},{14,26,898},{14,31,3652},{11,31,1095},{12,26,45},{11,23,1159},{3,31,3436},{4,24,908},{18,31,1080}, +{17,31,110},{17,27,56},{16,26,121},{26,14,3048},{10,31,996},{12,26,36},{5,24,901},{22,21,3048},{5,24,901},{14,31,939},{14,31,939},{14,31,939},{14,26,894},{12,31,659},{12,26,41},{12,26,41},{11,21,46},{1,30,651},{7,21,98},{17,28,4},{17,28,4},{17,28,4},{17,24,8},{28,4,648},{10,28,2},{10,28,2},{10,21,1},{29,13,648},{10,21,1},{29,15,882},{16,31,80},{18,26,8}, +{13,26,5},{29,15,882},{30,20,882},{13,26,5},{0,24,900},{30,20,882},{0,24,900},{14,0,890},{14,0,890},{14,0,890},{14,0,890},{12,25,10},{12,25,10},{12,25,10},{12,20,13},{4,24,8},{4,24,8},{17,31,3038},{16,31,1268},{16,28,1186},{15,27,910},{15,31,3879},{12,31,1146},{13,27,47},{12,24,1159},{5,31,3667},{6,25,894},{19,31,1205},{18,31,147},{18,28,53},{17,27,122},{30,10,3048}, +{12,31,1110},{12,28,41},{6,25,890},{30,18,3048},{6,25,890},{16,31,979},{16,31,979},{16,31,979},{15,27,901},{13,31,670},{13,27,38},{13,27,38},{13,22,44},{2,31,648},{7,23,101},{18,29,2},{18,29,2},{18,29,2},{18,25,2},{31,2,648},{11,29,4},{11,29,4},{11,22,5},{27,16,648},{11,22,5},{29,18,882},{18,31,146},{19,27,18},{15,27,10},{29,18,882},{28,23,882},{15,27,10}, +{0,25,890},{28,23,882},{0,25,890},{15,0,900},{15,0,900},{15,0,900},{15,0,900},{13,26,4},{13,26,4},{13,26,4},{13,21,5},{6,25,4},{6,25,4},{18,31,3308},{17,31,1502},{17,29,1186},{16,28,898},{17,31,4077},{14,31,1230},{14,28,33},{13,25,1159},{8,31,3820},{7,26,894},{21,31,1368},{19,31,261},{19,29,53},{18,28,117},{31,11,3048},{14,31,1226},{14,28,29},{7,26,890},{31,19,3048}, +{7,26,890},{17,31,1018},{17,31,1018},{17,31,1018},{16,28,894},{14,31,724},{14,28,29},{14,28,29},{14,23,44},{4,31,665},{8,24,102},{19,30,2},{19,30,2},{19,30,2},{19,26,2},{26,13,648},{12,30,1},{12,30,1},{12,23,4},{21,21,648},{12,23,4},{30,19,882},{20,31,193},{20,28,8},{15,28,5},{30,19,882},{27,25,882},{15,28,5},{0,26,890},{27,25,882},{0,26,890},{16,0,890}, +{16,0,890},{16,0,890},{16,0,890},{14,27,4},{14,27,4},{14,27,4},{14,22,5},{7,26,4},{7,26,4},{19,31,3614},{18,31,1804},{18,30,1186},{17,29,898},{18,31,4284},{15,31,1417},{15,29,33},{14,26,1159},{9,31,4036},{8,27,899},{22,31,1494},{20,31,405},{20,30,56},{19,29,117},{29,17,3048},{16,31,1395},{15,29,29},{8,27,890},{27,23,3048},{8,27,890},{18,31,1075},{18,31,1075},{18,31,1075}, +{17,29,894},{16,31,787},{15,29,29},{15,29,29},{15,24,41},{6,31,705},{10,24,98},{20,31,5},{20,31,5},{20,31,5},{20,27,5},{28,12,648},{13,31,1},{13,31,1},{13,24,1},{22,22,648},{13,24,1},{29,23,882},{22,31,277},{21,29,8},{16,29,5},{29,23,882},{28,26,882},{16,29,5},{0,27,890},{28,26,882},{0,27,890},{17,0,890},{17,0,890},{17,0,890},{17,0,890},{15,28,4}, +{15,28,4},{15,28,4},{15,23,5},{7,28,5},{7,28,5},{20,31,4014},{19,31,2174},{19,31,1186},{18,30,898},{19,31,4545},{17,31,1725},{16,30,45},{15,27,1159},{11,31,4300},{8,28,908},{23,31,1656},{22,31,585},{21,31,56},{20,30,121},{30,18,3048},{18,31,1563},{16,30,36},{9,28,901},{26,25,3048},{9,28,901},{19,31,1150},{19,31,1150},{19,31,1150},{18,30,894},{17,31,841},{16,30,41},{16,30,41}, +{15,25,46},{8,31,747},{11,25,98},{21,31,20},{21,31,20},{21,31,20},{21,28,8},{29,13,648},{15,31,5},{15,31,5},{14,25,1},{28,20,648},{14,25,1},{30,24,882},{23,31,397},{22,30,8},{17,30,5},{30,24,882},{29,27,882},{17,30,5},{0,28,900},{29,27,882},{0,28,900},{18,0,890},{18,0,890},{18,0,890},{18,0,890},{16,29,10},{16,29,10},{16,29,10},{16,24,13},{8,28,8}, +{8,28,8},{22,31,4123},{21,31,2404},{20,31,1278},{19,31,901},{20,31,4626},{18,31,1849},{17,31,38},{16,28,1006},{14,31,4330},{10,29,789},{24,31,1629},{23,31,715},{22,31,65},{22,30,101},{31,19,2814},{20,31,1505},{17,31,34},{10,29,785},{27,26,2814},{10,29,785},{20,31,1278},{20,31,1278},{20,31,1278},{19,31,901},{18,31,948},{17,31,38},{17,31,38},{17,26,44},{10,31,840},{11,27,101},{22,31,65}, +{22,31,65},{22,31,65},{22,29,2},{29,16,648},{17,31,34},{17,31,34},{15,26,5},{31,20,648},{15,26,5},{31,25,761},{25,31,425},{23,31,9},{19,31,1},{31,25,761},{28,29,761},{19,31,1},{0,29,785},{28,29,761},{0,29,785},{19,0,900},{19,0,900},{19,0,900},{19,0,900},{17,30,4},{17,30,4},{17,30,4},{17,25,5},{10,29,4},{10,29,4},{23,31,3735},{22,31,2314},{21,31,1395}, +{20,31,899},{22,31,4090},{19,31,1618},{18,31,104},{17,29,686},{15,31,3826},{11,29,507},{25,31,1285},{24,31,609},{23,31,122},{23,31,37},{30,22,2249},{21,31,1186},{19,31,74},{13,29,482},{27,27,2249},{13,29,482},{21,31,1395},{21,31,1395},{21,31,1395},{20,31,899},{19,31,1086},{18,31,104},{18,31,104},{18,27,44},{12,31,969},{12,28,102},{23,31,122},{23,31,122},{23,31,122},{23,30,2},{30,17,648}, +{19,31,74},{19,31,74},{16,27,4},{25,25,648},{16,27,4},{31,26,481},{27,31,269},{25,31,0},{21,31,0},{31,26,481},{31,28,481},{21,31,0},{0,29,481},{31,28,481},{0,29,481},{20,0,890},{20,0,890},{20,0,890},{20,0,890},{18,31,4},{18,31,4},{18,31,4},{18,26,5},{11,30,4},{11,30,4},{23,31,3399},{23,31,2260},{22,31,1530},{21,31,954},{23,31,3639},{20,31,1402},{19,31,238}, +{18,29,405},{17,31,3443},{12,30,314},{26,31,1009},{25,31,525},{25,31,164},{24,31,5},{30,24,1769},{23,31,918},{21,31,113},{14,30,290},{29,27,1769},{14,30,290},{22,31,1530},{22,31,1530},{22,31,1530},{21,31,954},{21,31,1251},{19,31,238},{19,31,238},{19,28,41},{14,31,1105},{14,28,98},{25,31,164},{25,31,164},{25,31,164},{24,31,5},{31,18,648},{21,31,113},{21,31,113},{17,28,1},{26,26,648}, +{17,28,1},{30,29,265},{28,31,145},{27,31,4},{24,31,1},{30,29,265},{29,30,265},{24,31,1},{0,30,289},{29,30,265},{0,30,289},{21,0,890},{21,0,890},{21,0,890},{21,0,890},{19,31,13},{19,31,13},{19,31,13},{19,27,5},{12,31,9},{12,31,9},{24,31,3069},{24,31,2257},{23,31,1683},{23,31,1054},{24,31,3258},{22,31,1330},{21,31,378},{19,30,213},{20,31,3102},{14,30,166},{27,31,801}, +{26,31,477},{26,31,221},{25,31,20},{31,24,1374},{24,31,758},{23,31,181},{16,30,114},{24,31,1374},{16,30,114},{23,31,1683},{23,31,1683},{23,31,1683},{23,31,1054},{22,31,1401},{21,31,378},{21,31,378},{19,29,46},{16,31,1296},{15,29,98},{26,31,221},{26,31,221},{26,31,221},{25,31,20},{30,22,648},{23,31,181},{23,31,181},{18,29,1},{27,27,648},{18,29,1},{30,30,113},{29,31,61},{28,31,0}, +{26,31,1},{30,30,113},{30,30,113},{26,31,1},{0,30,113},{30,30,113},{0,30,113},{22,0,890},{22,0,890},{22,0,890},{22,0,890},{20,31,45},{20,31,45},{20,31,45},{20,28,13},{13,31,25},{13,31,25},{25,31,2860},{25,31,2260},{24,31,1854},{24,31,1210},{25,31,2932},{23,31,1310},{22,31,609},{21,30,108},{21,31,2731},{15,31,101},{28,31,630},{27,31,475},{27,31,306},{26,31,101},{31,26,1032}, +{26,31,612},{25,31,290},{18,31,37},{29,29,1032},{18,31,37},{24,31,1854},{24,31,1854},{24,31,1854},{24,31,1210},{23,31,1620},{22,31,609},{22,31,609},{21,30,44},{18,31,1515},{15,31,101},{27,31,306},{27,31,306},{27,31,306},{26,31,101},{30,25,648},{25,31,290},{25,31,290},{19,30,5},{30,27,648},{19,30,5},{31,30,18},{30,31,10},{30,31,1},{29,31,0},{31,30,18},{30,31,18},{29,31,0}, +{0,31,36},{30,31,18},{0,31,36},{23,0,900},{23,0,900},{23,0,900},{23,0,900},{21,31,104},{21,31,104},{21,31,104},{21,29,5},{15,31,65},{15,31,65},{26,31,2626},{26,31,2206},{25,31,1915},{25,31,1315},{26,31,2641},{24,31,1333},{23,31,789},{22,31,40},{22,31,2445},{17,31,116},{29,31,524},{28,31,406},{28,31,325},{27,31,170},{30,29,771},{27,31,507},{26,31,320},{20,31,0},{29,30,771}, +{20,31,0},{25,31,1915},{25,31,1915},{25,31,1915},{25,31,1315},{24,31,1661},{23,31,789},{23,31,789},{22,31,40},{20,31,1517},{17,31,116},{28,31,325},{28,31,325},{28,31,325},{27,31,170},{31,26,580},{26,31,320},{26,31,320},{20,31,0},{30,28,580},{20,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,890}, +{24,0,890},{24,0,890},{24,0,890},{23,31,164},{23,31,164},{23,31,164},{22,30,5},{17,31,116},{17,31,116},{27,31,2156},{27,31,1884},{26,31,1630},{26,31,1210},{26,31,2081},{25,31,1108},{24,31,705},{23,31,5},{23,31,1927},{19,31,180},{29,31,300},{29,31,236},{29,31,200},{28,31,85},{31,28,451},{28,31,283},{27,31,194},{23,31,1},{28,31,451},{23,31,1},{26,31,1630},{26,31,1630},{26,31,1630}, +{26,31,1210},{25,31,1347},{24,31,705},{24,31,705},{23,31,5},{22,31,1229},{19,31,180},{29,31,200},{29,31,200},{29,31,200},{28,31,85},{31,27,338},{27,31,194},{27,31,194},{23,31,1},{30,29,338},{23,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{24,31,221}, +{24,31,221},{24,31,221},{23,31,5},{19,31,180},{19,31,180},{28,31,1782},{27,31,1564},{27,31,1395},{27,31,1123},{27,31,1620},{26,31,937},{25,31,651},{24,31,25},{24,31,1560},{21,31,233},{30,31,150},{30,31,134},{29,31,104},{29,31,40},{31,29,216},{29,31,136},{28,31,90},{25,31,1},{29,31,216},{25,31,1},{27,31,1395},{27,31,1395},{27,31,1395},{27,31,1123},{26,31,1101},{25,31,651},{25,31,651}, +{24,31,25},{23,31,998},{21,31,233},{29,31,104},{29,31,104},{29,31,104},{29,31,40},{31,28,162},{28,31,90},{28,31,90},{25,31,1},{28,31,162},{25,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{25,31,290},{25,31,290},{25,31,290},{24,31,25},{21,31,233}, +{21,31,233},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{0,11,3379},{0,9,2369},{0,8,1061},{0,5,2435},{0,6,3760},{0,5,2660},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{7,0,3371},{0,9,2369},{0,8,1061},{0,5,2435},{10,1,3371},{0,5,2435},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{0,2,332},{0,2,200},{0,8,0}, +{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{4,0,288},{0,2,164},{9,2,1568},{0,14,442},{0,10,40},{0,8,485},{9,2,1568},{17,0,1568},{0,8,485},{0,6,1586},{17,0,1568},{0,6,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,1570},{0,16,325},{0,11,5}, +{0,9,392},{0,13,3968},{0,10,2630},{0,9,1121},{0,6,2710},{0,7,4484},{0,6,3034},{0,20,1570},{0,16,325},{0,11,5},{0,9,392},{2,10,3968},{0,10,2630},{0,9,1121},{0,6,2710},{13,0,3968},{0,6,2710},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{0,5,514},{0,5,274},{0,5,274},{0,3,289},{0,3,595},{0,3,370},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{2,2,512}, +{0,5,274},{0,5,274},{0,3,289},{2,2,512},{0,3,289},{10,3,1568},{0,16,325},{0,11,5},{0,9,392},{10,3,1568},{18,1,1568},{0,9,392},{0,7,1586},{18,1,1568},{0,7,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{0,15,4652},{0,11,2945},{0,10,1217}, +{0,7,3035},{0,8,5283},{0,7,3476},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{4,8,4651},{0,11,2945},{0,10,1217},{0,7,3035},{13,1,4651},{0,7,3035},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{0,7,802},{0,6,424},{0,6,424},{0,4,449},{0,3,931},{0,3,562},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{4,0,800},{0,6,424},{0,6,424},{0,4,449},{5,1,800}, +{0,4,449},{11,4,1568},{0,17,225},{1,12,13},{0,11,292},{11,4,1568},{19,2,1568},{0,11,292},{0,8,1576},{19,2,1568},{0,8,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1570},{0,19,149},{0,13,73},{0,12,194},{0,17,5424},{0,13,3368},{0,11,1349},{0,8,3449},{0,9,6213},{0,7,3956},{0,25,1570}, +{0,19,149},{0,13,73},{0,12,194},{10,0,5419},{0,13,3368},{0,11,1349},{0,8,3449},{15,1,5419},{0,8,3449},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{0,8,1152},{0,7,610},{0,7,610},{0,4,625},{0,4,1328},{0,4,769},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{3,3,1152},{0,7,610},{0,7,610},{0,4,625},{8,0,1152},{0,4,625},{15,0,1568},{0,19,149},{2,13,13}, +{0,12,194},{15,0,1568},{20,3,1568},{0,12,194},{0,9,1576},{20,3,1568},{0,9,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,26,1633},{0,21,155},{1,14,150},{0,13,198},{0,20,5424},{0,15,3099},{0,12,996},{0,9,3179},{0,10,6544},{0,8,3890},{1,26,1569},{1,20,131},{2,14,69},{1,13,181},{10,3,5419}, +{0,15,3099},{0,12,996},{0,9,3179},{18,1,5419},{0,9,3179},{1,17,65},{1,17,65},{1,17,65},{1,11,69},{0,11,1152},{0,9,445},{0,9,445},{0,6,505},{0,6,1494},{0,5,737},{1,17,1},{1,17,1},{1,17,1},{1,11,5},{6,1,1152},{0,9,445},{0,9,445},{0,6,505},{11,0,1152},{0,6,505},{16,1,1568},{0,21,74},{3,14,5},{0,13,117},{16,1,1568},{26,1,1568},{0,13,117}, +{0,10,1586},{26,1,1568},{0,10,1586},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,25},{0,1,25},{1,29,1715},{1,22,219},{2,15,342},{1,14,262},{0,22,5420},{0,16,2834},{0,13,726},{0,10,2966},{0,11,6916},{0,9,3860},{2,27,1569},{2,21,131},{3,15,69},{2,14,181},{11,4,5419},{0,16,2834},{0,13,726},{0,10,2966},{19,2,5419}, +{0,10,2966},{1,20,146},{1,20,146},{1,20,146},{1,12,146},{0,13,1154},{0,11,337},{0,11,337},{0,7,388},{0,7,1665},{0,6,749},{2,18,1},{2,18,1},{2,18,1},{2,12,5},{8,0,1152},{0,11,337},{0,11,337},{0,7,388},{5,5,1152},{0,7,388},{17,2,1568},{0,23,34},{4,15,5},{0,14,72},{17,2,1568},{27,2,1568},{0,14,72},{0,11,1586},{27,2,1568},{0,11,1586},{1,0,145}, +{1,0,145},{1,0,145},{1,0,145},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,2,85},{0,2,85},{2,30,1907},{1,24,398},{2,16,542},{1,15,425},{0,25,5424},{0,18,2630},{0,15,486},{0,11,2771},{0,13,7299},{0,11,3860},{3,28,1569},{3,22,131},{4,16,82},{3,15,181},{15,0,5419},{0,18,2630},{0,15,486},{0,11,2771},{20,3,5419},{0,11,2771},{2,21,338},{2,21,338},{2,21,338}, +{2,13,338},{0,16,1152},{0,13,274},{0,13,274},{0,8,305},{0,8,1856},{0,7,797},{3,19,1},{3,19,1},{3,19,1},{3,13,5},{9,1,1152},{0,13,274},{0,13,274},{0,8,305},{16,0,1152},{0,8,305},{18,3,1568},{0,25,17},{5,16,13},{0,15,45},{18,3,1568},{28,3,1568},{0,15,45},{0,12,1576},{28,3,1568},{0,12,1576},{2,0,337},{2,0,337},{2,0,337},{2,0,337},{0,8,1}, +{0,8,1},{0,8,1},{0,5,0},{0,4,169},{0,4,169},{2,31,2145},{2,25,590},{3,17,862},{2,16,619},{0,27,5420},{0,20,2424},{0,16,282},{0,12,2552},{0,15,7711},{0,11,3908},{4,29,1570},{4,23,149},{4,17,73},{4,16,194},{14,4,5419},{0,20,2424},{0,16,282},{0,12,2552},{24,2,5419},{0,12,2552},{2,23,546},{2,23,546},{2,23,546},{2,15,546},{0,19,1154},{0,15,194},{0,15,194}, +{0,9,218},{0,9,2123},{0,8,865},{4,20,1},{4,20,1},{4,20,1},{4,13,4},{10,2,1152},{0,15,194},{0,15,194},{0,9,218},{17,1,1152},{0,9,218},{20,2,1568},{0,27,5},{6,17,13},{0,16,26},{20,2,1568},{24,7,1568},{0,16,26},{0,13,1576},{24,7,1568},{0,13,1576},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289}, +{0,5,289},{3,31,2596},{3,26,941},{3,19,1289},{3,17,972},{0,30,5420},{0,22,2243},{0,17,145},{0,13,2386},{0,16,8161},{0,13,3986},{5,30,1569},{5,24,131},{6,18,69},{5,17,181},{17,2,5419},{0,22,2243},{0,17,145},{0,13,2386},{27,2,5419},{0,13,2386},{3,24,901},{3,24,901},{3,24,901},{3,16,901},{0,22,1154},{0,17,109},{0,17,109},{0,10,145},{0,11,2441},{0,9,1001},{5,21,1}, +{5,21,1},{5,21,1},{5,15,5},{13,0,1152},{0,17,109},{0,17,109},{0,10,145},{20,1,1152},{0,10,145},{23,0,1568},{1,28,2},{7,18,5},{0,18,8},{23,0,1568},{30,5,1568},{0,18,8},{0,14,1586},{30,5,1568},{0,14,1586},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{0,14,1},{0,14,1},{0,14,1},{0,8,1},{0,6,468},{0,6,468},{4,31,3146},{3,28,1262},{4,19,1743}, +{3,18,1297},{1,31,5484},{0,23,2096},{0,19,69},{0,14,2251},{0,18,8669},{0,14,4100},{6,31,1569},{6,25,131},{7,19,69},{6,18,181},{18,3,5419},{0,23,2096},{0,19,69},{0,14,2251},{28,3,5419},{0,14,2251},{3,27,1252},{3,27,1252},{3,27,1252},{3,17,1256},{0,24,1152},{0,18,61},{0,18,61},{0,11,100},{0,12,2859},{0,10,1157},{6,22,1},{6,22,1},{6,22,1},{6,16,5},{14,1,1152}, +{0,18,61},{0,18,61},{0,11,100},{24,0,1152},{0,11,100},{24,1,1568},{2,29,2},{8,19,5},{0,19,5},{24,1,1568},{31,6,1568},{0,19,5},{0,15,1586},{31,6,1568},{0,15,1586},{3,0,1252},{3,0,1252},{3,0,1252},{3,0,1252},{0,16,1},{0,16,1},{0,16,1},{0,10,1},{0,8,657},{0,8,657},{5,31,3716},{4,29,1603},{4,21,2148},{4,19,1631},{2,31,5655},{0,25,2005},{0,20,31}, +{0,15,2138},{0,19,8963},{0,15,4070},{7,31,1587},{7,26,131},{8,20,82},{7,19,181},{20,2,5419},{0,25,2001},{0,20,27},{0,15,2134},{24,7,5419},{0,15,2134},{4,28,1587},{4,28,1587},{4,28,1587},{4,18,1590},{0,27,1158},{0,20,22},{0,20,22},{0,12,62},{0,14,3075},{0,11,1221},{7,23,1},{7,23,1},{7,23,1},{7,17,5},{16,0,1152},{0,20,18},{0,20,18},{0,12,58},{25,1,1152}, +{0,12,58},{25,2,1568},{3,30,2},{9,20,13},{1,20,9},{25,2,1568},{27,10,1568},{1,20,9},{0,16,1576},{27,10,1568},{0,16,1576},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{0,19,4},{0,19,4},{0,19,4},{0,11,8},{0,9,769},{0,9,769},{6,31,3890},{5,30,1603},{5,22,2148},{5,20,1627},{3,31,5748},{0,27,1989},{1,21,31},{0,17,2117},{0,21,8560},{0,16,3545},{9,31,1634}, +{8,27,149},{8,21,73},{8,20,194},{21,3,5419},{0,27,1889},{1,21,27},{0,17,2017},{28,6,5419},{0,17,2017},{5,29,1587},{5,29,1587},{5,29,1587},{5,19,1590},{1,28,1158},{1,21,22},{1,21,22},{1,13,62},{0,16,2801},{0,13,949},{8,24,1},{8,24,1},{8,24,1},{8,17,4},{17,1,1152},{0,22,2},{0,22,2},{0,14,26},{26,2,1152},{0,14,26},{26,3,1568},{4,31,5},{10,21,13}, +{2,21,9},{26,3,1568},{28,11,1568},{2,21,9},{0,17,1576},{28,11,1568},{0,17,1576},{5,0,1586},{5,0,1586},{5,0,1586},{5,0,1586},{1,20,4},{1,20,4},{1,20,4},{1,12,8},{0,10,625},{0,10,625},{7,31,4136},{6,31,1589},{7,23,2157},{6,21,1621},{4,31,5895},{1,28,1977},{2,22,33},{1,18,2107},{0,23,8196},{0,17,3043},{10,31,1667},{9,28,131},{10,22,69},{9,21,181},{24,1,5419}, +{0,29,1772},{2,22,24},{0,18,1875},{31,6,5419},{0,18,1875},{6,30,1576},{6,30,1576},{6,30,1576},{6,20,1580},{2,29,1161},{2,22,29},{2,22,29},{2,15,58},{0,17,2529},{0,14,656},{9,25,1},{9,25,1},{9,25,1},{9,19,5},{17,4,1152},{0,24,1},{0,24,1},{0,15,1},{29,2,1152},{0,15,1},{27,4,1568},{6,31,13},{11,22,5},{3,22,5},{27,4,1568},{31,11,1568},{3,22,5}, +{0,18,1586},{31,11,1568},{0,18,1586},{6,0,1576},{6,0,1576},{6,0,1576},{6,0,1576},{2,21,10},{2,21,10},{2,21,10},{2,14,13},{0,12,520},{0,12,520},{8,31,4436},{7,31,1625},{8,23,2175},{7,22,1621},{6,31,6079},{3,28,1973},{3,23,33},{2,19,2107},{0,24,7969},{0,18,2675},{11,31,1745},{10,29,131},{11,23,69},{10,22,181},{25,2,5419},{0,30,1699},{3,23,24},{0,19,1782},{27,10,5419}, +{0,19,1782},{7,31,1576},{7,31,1576},{7,31,1576},{7,21,1580},{3,30,1161},{3,23,29},{3,23,29},{3,16,74},{0,19,2313},{0,15,474},{10,26,1},{10,26,1},{10,26,1},{10,20,5},{18,5,1152},{1,25,1},{1,25,1},{0,16,2},{30,3,1152},{0,16,2},{31,0,1568},{8,31,34},{12,23,5},{4,23,5},{31,0,1568},{30,13,1568},{4,23,5},{0,19,1586},{30,13,1568},{0,19,1586},{7,0,1576}, +{7,0,1576},{7,0,1576},{7,0,1576},{3,22,10},{3,22,10},{3,22,10},{3,15,13},{0,14,400},{0,14,400},{9,31,4730},{8,31,1716},{8,25,2148},{8,23,1631},{7,31,6244},{3,30,1977},{4,24,31},{4,19,2138},{0,26,7669},{0,19,2375},{12,31,1832},{11,30,131},{12,24,82},{11,23,181},{26,3,5419},{1,31,1699},{4,24,27},{0,20,1720},{28,11,5419},{0,20,1720},{8,31,1595},{8,31,1595},{8,31,1595}, +{8,22,1590},{4,31,1158},{4,24,22},{4,24,22},{4,16,62},{0,21,2091},{0,17,306},{11,27,1},{11,27,1},{11,27,1},{11,21,5},{20,4,1152},{2,26,1},{2,26,1},{1,17,2},{29,5,1152},{1,17,2},{29,6,1568},{9,31,68},{13,24,13},{5,24,9},{29,6,1568},{31,14,1568},{5,24,9},{0,20,1576},{31,14,1568},{0,20,1576},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{4,23,4}, +{4,23,4},{4,23,4},{4,15,8},{0,16,277},{0,16,277},{11,31,5010},{9,31,1878},{9,26,2148},{9,24,1627},{8,31,6508},{4,31,1989},{5,25,31},{4,21,2117},{0,28,7364},{0,21,2098},{14,31,1952},{12,31,149},{12,25,73},{12,24,194},{28,2,5419},{3,31,1787},{5,25,27},{0,21,1657},{27,13,5419},{0,21,1657},{9,31,1622},{9,31,1622},{9,31,1622},{9,23,1590},{5,31,1164},{5,25,22},{5,25,22}, +{5,17,62},{0,22,1928},{0,18,194},{12,28,1},{12,28,1},{12,28,1},{12,21,4},{24,0,1152},{3,27,1},{3,27,1},{2,18,2},{30,6,1152},{2,18,2},{30,7,1568},{11,31,116},{14,25,13},{6,25,9},{30,7,1568},{30,16,1568},{6,25,9},{0,21,1576},{30,16,1568},{0,21,1576},{9,0,1586},{9,0,1586},{9,0,1586},{9,0,1586},{5,24,4},{5,24,4},{5,24,4},{5,16,8},{0,18,193}, +{0,18,193},{12,31,5316},{11,31,2154},{11,27,2157},{10,25,1621},{10,31,6800},{6,31,1999},{6,26,33},{5,22,2107},{0,29,7068},{0,22,1836},{15,31,2081},{13,31,206},{14,26,69},{13,25,181},{31,0,5419},{5,31,1937},{6,26,24},{0,22,1611},{30,13,5419},{0,22,1611},{10,31,1676},{10,31,1676},{10,31,1676},{10,24,1580},{7,31,1179},{6,26,29},{6,26,29},{6,19,58},{0,24,1798},{0,19,157},{13,29,1}, +{13,29,1},{13,29,1},{13,23,5},{24,3,1152},{4,28,1},{4,28,1},{4,19,1},{28,9,1152},{4,19,1},{31,8,1568},{13,31,205},{15,26,5},{7,26,5},{31,8,1568},{28,19,1568},{7,26,5},{0,22,1586},{28,19,1568},{0,22,1586},{10,0,1576},{10,0,1576},{10,0,1576},{10,0,1576},{6,25,10},{6,25,10},{6,25,10},{6,18,13},{0,20,106},{0,20,106},{13,31,5658},{12,31,2435},{12,27,2175}, +{11,26,1621},{11,31,7055},{7,31,2090},{7,27,33},{6,23,2107},{0,31,6820},{0,23,1690},{16,31,2216},{14,31,334},{15,27,69},{14,26,181},{29,6,5419},{7,31,2081},{7,27,24},{0,23,1590},{31,14,5419},{0,23,1590},{11,31,1745},{11,31,1745},{11,31,1745},{11,25,1580},{8,31,1220},{7,27,29},{7,27,29},{7,20,74},{0,26,1650},{1,20,137},{14,30,1},{14,30,1},{14,30,1},{14,24,5},{22,9,1152}, +{5,29,1},{5,29,1},{4,20,2},{29,10,1152},{4,20,2},{29,14,1568},{15,31,289},{16,27,5},{8,27,5},{29,14,1568},{29,20,1568},{8,27,5},{0,23,1586},{29,20,1568},{0,23,1586},{11,0,1576},{11,0,1576},{11,0,1576},{11,0,1576},{7,26,10},{7,26,10},{7,26,10},{7,19,13},{0,22,58},{0,22,58},{14,31,6036},{13,31,2751},{12,29,2148},{12,27,1631},{12,31,7316},{8,31,2228},{8,28,31}, +{8,23,2138},{0,31,6884},{0,24,1613},{17,31,2402},{16,31,500},{16,28,82},{15,27,181},{30,7,5419},{9,31,2195},{8,28,27},{0,24,1577},{30,16,5419},{0,24,1577},{12,31,1811},{12,31,1811},{12,31,1811},{12,26,1590},{9,31,1286},{8,28,22},{8,28,22},{8,20,62},{0,28,1508},{2,21,137},{15,31,1},{15,31,1},{15,31,1},{15,25,5},{24,8,1152},{6,30,1},{6,30,1},{5,21,2},{30,11,1152}, +{5,21,2},{30,15,1568},{17,31,410},{17,28,13},{9,28,9},{30,15,1568},{30,21,1568},{9,28,9},{0,24,1576},{30,21,1568},{0,24,1576},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{8,27,4},{8,27,4},{8,27,4},{8,19,8},{0,24,37},{0,24,37},{15,31,6450},{14,31,3135},{13,30,2148},{13,28,1627},{13,31,7661},{10,31,2448},{9,29,31},{8,25,2117},{2,31,7196},{0,25,1593},{19,31,2594}, +{17,31,698},{16,29,73},{16,28,194},{29,11,5419},{11,31,2379},{9,29,27},{1,25,1577},{31,17,5419},{1,25,1577},{13,31,1910},{13,31,1910},{13,31,1910},{13,27,1590},{10,31,1388},{9,29,22},{9,29,22},{9,21,62},{0,30,1416},{3,22,137},{16,31,4},{16,31,4},{16,31,4},{16,25,4},{28,4,1152},{7,31,1},{7,31,1},{6,22,2},{29,13,1152},{6,22,2},{31,16,1568},{19,31,530},{18,29,13}, +{10,29,9},{31,16,1568},{31,22,1568},{10,29,9},{0,25,1576},{31,22,1568},{0,25,1576},{13,0,1586},{13,0,1586},{13,0,1586},{13,0,1586},{9,28,4},{9,28,4},{9,28,4},{9,20,8},{0,25,17},{0,25,17},{16,31,6900},{15,31,3657},{15,31,2157},{14,29,1621},{15,31,8023},{11,31,2845},{10,30,33},{9,26,2107},{5,31,7651},{1,26,1611},{20,31,2866},{18,31,1011},{18,30,69},{17,29,181},{29,14,5419}, +{13,31,2657},{10,30,24},{3,26,1587},{29,20,5419},{3,26,1587},{15,31,2057},{15,31,2057},{15,31,2057},{14,28,1580},{12,31,1476},{10,30,29},{10,30,29},{10,23,58},{0,31,1324},{4,23,157},{17,31,37},{17,31,37},{17,31,37},{17,27,5},{31,2,1152},{9,31,4},{9,31,4},{8,23,1},{27,16,1152},{8,23,1},{31,19,1568},{21,31,637},{19,30,5},{11,30,5},{31,19,1568},{27,26,1568},{11,30,5}, +{0,26,1586},{27,26,1568},{0,26,1586},{14,0,1576},{14,0,1576},{14,0,1576},{14,0,1576},{10,29,10},{10,29,10},{10,29,10},{10,22,13},{1,27,9},{1,27,9},{18,31,7332},{16,31,4196},{16,31,2175},{15,30,1621},{16,31,8348},{13,31,3285},{11,31,33},{10,27,2107},{8,31,8004},{2,27,1611},{21,31,3112},{20,31,1281},{19,31,69},{18,30,181},{30,15,5419},{15,31,2897},{11,31,24},{3,27,1590},{30,21,5419}, +{3,27,1590},{16,31,2171},{16,31,2171},{16,31,2171},{15,29,1580},{13,31,1590},{11,31,29},{11,31,29},{11,24,74},{2,31,1424},{5,24,137},{19,31,65},{19,31,65},{19,31,65},{18,28,5},{26,13,1152},{11,31,20},{11,31,20},{8,24,2},{21,21,1152},{8,24,2},{30,23,1568},{23,31,785},{20,31,5},{12,31,5},{30,23,1568},{28,27,1568},{12,31,5},{0,27,1586},{28,27,1568},{0,27,1586},{15,0,1576}, +{15,0,1576},{15,0,1576},{15,0,1576},{11,30,10},{11,30,10},{11,30,10},{11,23,13},{1,28,8},{1,28,8},{19,31,7014},{17,31,4230},{17,31,2294},{16,31,1595},{17,31,7865},{14,31,3114},{12,31,85},{12,27,1706},{8,31,7436},{3,28,1268},{22,31,2794},{21,31,1221},{20,31,113},{19,30,114},{30,17,4803},{17,31,2648},{13,31,61},{4,28,1253},{25,25,4803},{4,28,1253},{17,31,2294},{17,31,2294},{17,31,2294}, +{16,30,1590},{14,31,1740},{12,31,85},{12,31,85},{12,24,62},{3,31,1571},{6,25,137},{20,31,113},{20,31,113},{20,31,113},{19,29,5},{28,12,1152},{13,31,61},{13,31,61},{9,25,2},{22,22,1152},{9,25,2},{31,23,1250},{24,31,680},{21,31,4},{15,31,0},{31,23,1250},{23,31,1250},{15,31,0},{0,28,1252},{23,31,1250},{0,28,1252},{16,0,1586},{16,0,1586},{16,0,1586},{16,0,1586},{12,31,4}, +{12,31,4},{12,31,4},{12,23,8},{2,29,8},{2,29,8},{19,31,6534},{18,31,4116},{18,31,2435},{17,31,1590},{18,31,7164},{15,31,2809},{14,31,161},{12,28,1256},{10,31,6748},{5,28,945},{23,31,2340},{22,31,1065},{21,31,164},{20,31,64},{31,17,4056},{18,31,2211},{15,31,113},{7,28,900},{25,26,4056},{7,28,900},{18,31,2435},{18,31,2435},{18,31,2435},{17,31,1590},{16,31,1923},{14,31,161},{14,31,161}, +{13,25,62},{6,31,1729},{7,26,137},{21,31,164},{21,31,164},{21,31,164},{20,29,4},{29,13,1152},{15,31,113},{15,31,113},{10,26,2},{28,20,1152},{10,26,2},{30,26,882},{25,31,482},{23,31,0},{18,31,1},{30,26,882},{31,27,882},{18,31,1},{0,28,900},{31,27,882},{0,28,900},{17,0,1586},{17,0,1586},{17,0,1586},{17,0,1586},{13,31,13},{13,31,13},{13,31,13},{13,24,8},{3,30,8}, +{3,30,8},{21,31,6091},{20,31,4022},{19,31,2609},{18,31,1640},{19,31,6490},{16,31,2617},{15,31,318},{14,28,835},{11,31,6135},{6,29,598},{24,31,1881},{23,31,931},{22,31,245},{21,31,5},{31,19,3318},{20,31,1733},{17,31,202},{8,29,545},{27,26,3318},{8,29,545},{19,31,2609},{19,31,2609},{19,31,2609},{18,31,1640},{17,31,2086},{15,31,318},{15,31,318},{14,27,58},{8,31,1868},{8,27,157},{22,31,245}, +{22,31,245},{22,31,245},{21,31,5},{29,16,1152},{17,31,202},{17,31,202},{12,27,1},{31,20,1152},{12,27,1},{31,26,545},{26,31,305},{25,31,4},{20,31,1},{31,26,545},{29,29,545},{20,31,1},{0,29,545},{29,29,545},{0,29,545},{18,0,1576},{18,0,1576},{18,0,1576},{18,0,1576},{15,31,29},{15,31,29},{15,31,29},{14,26,13},{5,31,9},{5,31,9},{22,31,5719},{21,31,3980},{20,31,2834}, +{19,31,1745},{20,31,6050},{18,31,2457},{16,31,536},{15,29,515},{14,31,5674},{7,30,406},{25,31,1573},{24,31,861},{23,31,338},{22,31,10},{30,22,2753},{21,31,1438},{19,31,290},{11,29,338},{27,27,2753},{11,29,338},{20,31,2834},{20,31,2834},{20,31,2834},{19,31,1745},{18,31,2284},{16,31,536},{16,31,536},{15,28,74},{10,31,2064},{9,28,137},{23,31,338},{23,31,338},{23,31,338},{22,31,10},{30,17,1152}, +{19,31,290},{19,31,290},{12,28,2},{25,25,1152},{12,28,2},{31,27,313},{28,31,181},{26,31,1},{23,31,0},{31,27,313},{30,29,313},{23,31,0},{0,29,337},{30,29,313},{0,29,337},{19,0,1576},{19,0,1576},{19,0,1576},{19,0,1576},{16,31,52},{16,31,52},{16,31,52},{15,27,13},{6,31,25},{6,31,25},{22,31,5399},{22,31,3974},{21,31,3035},{20,31,1875},{21,31,5619},{19,31,2378},{18,31,776}, +{16,30,318},{15,31,5258},{9,30,225},{26,31,1333},{25,31,813},{24,31,425},{23,31,65},{30,24,2273},{23,31,1218},{20,31,353},{12,30,146},{29,27,2273},{12,30,146},{21,31,3035},{21,31,3035},{21,31,3035},{20,31,1875},{19,31,2518},{18,31,776},{18,31,776},{16,28,62},{11,31,2323},{10,29,137},{24,31,425},{24,31,425},{24,31,425},{23,31,65},{31,18,1152},{20,31,353},{20,31,353},{13,29,2},{26,26,1152}, +{13,29,2},{31,28,145},{28,31,85},{28,31,4},{26,31,1},{31,28,145},{30,30,145},{26,31,1},{0,30,145},{30,30,145},{0,30,145},{20,0,1586},{20,0,1586},{20,0,1586},{20,0,1586},{17,31,85},{17,31,85},{17,31,85},{16,27,8},{8,31,40},{8,31,40},{23,31,5143},{23,31,4004},{22,31,3254},{21,31,2070},{22,31,5274},{20,31,2310},{19,31,1062},{17,30,133},{17,31,5011},{10,31,161},{27,31,1161}, +{26,31,801},{26,31,545},{25,31,164},{31,24,1878},{24,31,1094},{22,31,461},{14,30,66},{24,31,1878},{14,30,66},{22,31,3254},{22,31,3254},{22,31,3254},{21,31,2070},{20,31,2833},{19,31,1062},{19,31,1062},{17,29,62},{14,31,2577},{11,30,137},{26,31,545},{26,31,545},{26,31,545},{25,31,164},{30,22,1152},{22,31,461},{22,31,461},{14,30,2},{27,27,1152},{14,30,2},{30,31,41},{30,31,25},{29,31,1}, +{28,31,0},{30,31,41},{31,30,41},{28,31,0},{0,30,65},{31,30,41},{0,30,65},{21,0,1586},{21,0,1586},{21,0,1586},{21,0,1586},{18,31,136},{18,31,136},{18,31,136},{17,28,8},{10,31,80},{10,31,80},{24,31,4882},{24,31,4070},{23,31,3532},{22,31,2360},{24,31,4945},{21,31,2422},{20,31,1433},{18,31,58},{20,31,4717},{12,31,157},{28,31,1026},{27,31,835},{27,31,666},{26,31,305},{31,26,1536}, +{26,31,996},{24,31,628},{16,31,1},{29,29,1536},{16,31,1},{23,31,3532},{23,31,3532},{23,31,3532},{22,31,2360},{22,31,3110},{20,31,1433},{20,31,1433},{18,31,58},{16,31,2939},{12,31,157},{27,31,666},{27,31,666},{27,31,666},{26,31,305},{30,25,1152},{24,31,628},{24,31,628},{16,31,1},{30,27,1152},{16,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0}, +{0,31,0},{31,31,0},{0,31,0},{22,0,1576},{22,0,1576},{22,0,1576},{22,0,1576},{19,31,221},{19,31,221},{19,31,221},{18,30,13},{12,31,157},{12,31,157},{25,31,4212},{24,31,3590},{24,31,3106},{23,31,2201},{24,31,4129},{22,31,2101},{21,31,1301},{19,31,13},{20,31,3869},{14,31,233},{28,31,706},{28,31,562},{28,31,481},{27,31,218},{31,27,1067},{27,31,699},{25,31,442},{18,31,1},{30,29,1067}, +{18,31,1},{24,31,3106},{24,31,3106},{24,31,3106},{23,31,2201},{23,31,2668},{21,31,1301},{21,31,1301},{19,31,13},{18,31,2523},{14,31,233},{28,31,481},{28,31,481},{28,31,481},{27,31,218},{31,25,802},{25,31,442},{25,31,442},{18,31,1},{31,27,802},{18,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,1576}, +{23,0,1576},{23,0,1576},{23,0,1576},{20,31,325},{20,31,325},{20,31,325},{19,31,13},{14,31,233},{14,31,233},{26,31,3642},{25,31,3132},{25,31,2771},{24,31,2070},{25,31,3444},{23,31,1834},{22,31,1205},{20,31,8},{21,31,3219},{16,31,346},{29,31,456},{28,31,370},{28,31,289},{28,31,145},{30,29,683},{28,31,451},{27,31,290},{21,31,1},{29,30,683},{21,31,1},{25,31,2771},{25,31,2771},{25,31,2771}, +{24,31,2070},{24,31,2273},{22,31,1205},{22,31,1205},{20,31,8},{20,31,2121},{16,31,346},{28,31,289},{28,31,289},{28,31,289},{28,31,145},{31,26,512},{27,31,290},{27,31,290},{21,31,1},{29,29,512},{21,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,1586},{24,0,1586},{24,0,1586},{24,0,1586},{22,31,421}, +{22,31,421},{22,31,421},{20,31,8},{16,31,346},{16,31,346},{26,31,3162},{26,31,2742},{26,31,2486},{25,31,1947},{26,31,2877},{24,31,1641},{23,31,1145},{22,31,52},{22,31,2673},{18,31,458},{29,31,264},{29,31,200},{29,31,164},{28,31,81},{30,30,384},{28,31,243},{28,31,162},{23,31,1},{30,30,384},{23,31,1},{26,31,2486},{26,31,2486},{26,31,2486},{25,31,1947},{24,31,1969},{23,31,1145},{23,31,1145}, +{22,31,52},{20,31,1785},{18,31,458},{29,31,164},{29,31,164},{29,31,164},{28,31,81},{31,27,290},{28,31,162},{28,31,162},{23,31,1},{30,29,290},{23,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,1586},{25,0,1586},{25,0,1586},{25,0,1586},{23,31,520},{23,31,520},{23,31,520},{22,31,52},{18,31,458}, +{18,31,458},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{0,15,5885},{0,11,4118},{0,10,1800},{0,7,4202},{0,8,6546},{0,7,4643},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{9,0,5885},{0,11,4118},{0,10,1800},{0,7,4202},{15,0,5885},{0,7,4202},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,549},{0,5,289},{0,5,289},{0,3,306},{0,3,630},{0,3,387},{0,11,0}, +{0,11,0},{0,11,0},{0,7,4},{2,2,545},{0,5,289},{0,5,289},{0,3,306},{4,1,545},{0,3,306},{13,1,2665},{0,18,680},{0,13,50},{0,11,785},{13,1,2665},{23,0,2665},{0,11,785},{0,8,2689},{23,0,2665},{0,8,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,2665},{0,20,521},{0,14,5}, +{0,12,625},{0,17,6669},{0,13,4529},{0,11,1890},{0,8,4610},{0,9,7494},{0,7,5171},{0,25,2665},{0,20,521},{0,14,5},{0,12,625},{9,2,6669},{0,13,4529},{0,11,1890},{0,8,4610},{17,0,6669},{0,8,4610},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,7,841},{0,6,445},{0,6,445},{0,4,464},{0,3,982},{0,3,595},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{4,0,841}, +{0,6,445},{0,6,445},{0,4,464},{7,0,841},{0,4,464},{14,2,2665},{0,20,521},{0,14,5},{0,12,625},{14,2,2665},{25,0,2665},{0,12,625},{0,9,2689},{25,0,2665},{0,9,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{0,19,7541},{0,14,4934},{0,12,2042}, +{0,9,5045},{0,10,8546},{0,8,5682},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{10,2,7538},{0,14,4934},{0,12,2042},{0,9,5045},{17,1,7538},{0,9,5045},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,8,1201},{0,7,637},{0,7,637},{0,4,656},{0,4,1385},{0,4,800},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{5,0,1201},{0,7,637},{0,7,637},{0,4,656},{8,0,1201}, +{0,4,656},{16,1,2665},{0,22,405},{1,15,5},{0,13,514},{16,1,2665},{28,0,2665},{0,13,514},{0,10,2689},{28,0,2665},{0,10,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,30,2669},{0,23,313},{0,16,68},{0,15,410},{0,20,8498},{0,16,5330},{0,13,2210},{0,10,5530},{0,11,9702},{0,9,6270},{0,30,2669}, +{0,23,313},{0,16,68},{0,15,410},{11,2,8493},{0,16,5330},{0,13,2210},{0,10,5530},{17,2,8493},{0,10,5530},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,9,1629},{0,8,832},{0,8,832},{0,5,881},{0,5,1874},{0,5,1106},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{5,1,1625},{0,8,832},{0,8,832},{0,5,881},{8,1,1625},{0,5,881},{17,2,2665},{0,23,313},{2,16,8}, +{0,15,410},{17,2,2665},{29,1,2665},{0,15,410},{0,11,2689},{29,1,2665},{0,11,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2777},{0,26,232},{0,17,197},{0,16,305},{0,22,9674},{0,17,5849},{0,14,2450},{0,10,6106},{0,12,11199},{0,10,7006},{1,31,2741},{0,26,232},{1,17,146},{0,16,305},{11,4,9669}, +{0,17,5849},{0,14,2450},{0,10,6106},{19,2,9669},{0,10,6106},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,11,2178},{0,10,1125},{0,10,1125},{0,6,1189},{0,6,2520},{0,5,1475},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{6,1,2178},{0,10,1125},{0,10,1125},{0,6,1189},{11,0,2178},{0,6,1189},{20,0,2665},{0,26,232},{3,17,2},{0,16,305},{20,0,2665},{30,2,2665},{0,16,305}, +{0,12,2689},{30,2,2665},{0,12,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,31,2949},{0,28,217},{1,18,261},{0,17,282},{0,25,9670},{0,19,5529},{0,16,1970},{0,12,5738},{0,13,11589},{0,11,6898},{2,31,2789},{0,28,217},{2,18,146},{0,17,282},{15,0,9669},{0,19,5529},{0,16,1970},{0,12,5738},{20,3,9669}, +{0,12,5738},{0,24,64},{0,24,64},{0,24,64},{1,14,64},{0,13,2180},{0,11,949},{0,11,949},{0,7,1018},{0,7,2691},{0,6,1433},{1,23,1},{1,23,1},{1,23,1},{1,14,0},{8,0,2178},{0,11,949},{0,11,949},{0,7,1018},{5,5,2178},{0,7,1018},{21,1,2665},{0,28,153},{4,18,5},{0,17,218},{21,1,2665},{31,3,2665},{0,17,218},{0,13,2689},{31,3,2665},{0,13,2689},{0,0,64}, +{0,0,64},{0,0,64},{0,0,64},{0,3,1},{0,3,1},{0,3,1},{0,2,4},{0,1,18},{0,1,18},{2,31,3285},{1,28,273},{2,19,453},{1,18,346},{0,27,9674},{0,20,5170},{0,17,1546},{0,13,5429},{0,15,11993},{0,12,6819},{3,31,2873},{1,28,209},{3,19,146},{1,18,282},{14,4,9669},{0,20,5170},{0,17,1546},{0,13,5429},{24,2,9669},{0,13,5429},{1,25,128},{1,25,128},{1,25,128}, +{1,15,137},{0,16,2178},{0,13,832},{0,13,832},{0,8,881},{0,8,2882},{0,7,1427},{2,23,4},{2,23,4},{2,23,4},{2,15,0},{9,1,2178},{0,13,832},{0,13,832},{0,8,881},{16,0,2178},{0,8,881},{23,0,2665},{0,29,85},{5,19,5},{0,18,149},{23,0,2665},{30,5,2665},{0,18,149},{0,14,2689},{30,5,2665},{0,14,2689},{1,0,128},{1,0,128},{1,0,128},{1,0,128},{0,5,1}, +{0,5,1},{0,5,1},{0,3,1},{0,2,72},{0,2,72},{3,31,3785},{1,30,405},{2,21,676},{1,19,469},{0,30,9669},{0,22,4878},{0,18,1190},{0,14,5138},{0,16,12390},{0,13,6789},{4,31,2966},{2,29,209},{4,20,149},{2,19,282},{18,0,9669},{0,22,4878},{0,18,1190},{0,14,5138},{30,0,9669},{0,14,5138},{2,26,320},{2,26,320},{2,26,320},{1,17,320},{0,19,2180},{0,15,680},{0,15,680}, +{0,9,740},{0,9,3149},{0,8,1441},{3,24,1},{3,24,1},{3,24,1},{3,16,1},{10,2,2178},{0,15,680},{0,15,680},{0,9,740},{17,1,2178},{0,9,740},{24,1,2665},{0,31,41},{6,20,8},{0,19,98},{24,1,2665},{31,6,2665},{0,19,98},{0,15,2689},{31,6,2665},{0,15,2689},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,160}, +{0,4,160},{4,31,4514},{2,31,630},{3,22,1027},{2,20,694},{1,31,9738},{0,23,4646},{0,20,849},{0,15,4826},{0,18,12955},{0,14,6798},{6,31,3101},{3,31,218},{5,21,146},{3,20,299},{18,3,9669},{0,23,4646},{0,20,849},{0,15,4826},{28,3,9669},{0,15,4826},{2,29,545},{2,29,545},{2,29,545},{2,18,546},{0,22,2180},{0,17,505},{0,17,505},{0,11,610},{0,11,3467},{0,10,1513},{4,26,1}, +{4,26,1},{4,26,1},{4,17,0},{13,0,2178},{0,17,505},{0,17,505},{0,11,610},{20,1,2178},{0,11,610},{26,1,2665},{2,31,85},{7,21,2},{0,20,65},{26,1,2665},{31,8,2665},{0,20,65},{0,16,2689},{31,8,2665},{0,16,2689},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289},{0,5,289},{4,31,5330},{3,31,1018},{3,23,1430}, +{2,21,979},{2,31,9981},{0,26,4406},{0,21,579},{0,16,4610},{0,19,13489},{0,15,6846},{7,31,3233},{4,31,226},{6,22,146},{4,21,282},{20,2,9669},{0,26,4406},{0,21,579},{0,16,4610},{24,7,9669},{0,16,4610},{3,30,865},{3,30,865},{3,30,865},{3,19,866},{0,24,2178},{0,19,389},{0,19,389},{0,12,464},{0,12,3885},{0,11,1603},{5,27,1},{5,27,1},{5,27,1},{5,18,0},{14,1,2178}, +{0,19,389},{0,19,389},{0,12,464},{24,0,2178},{0,12,464},{28,0,2665},{3,31,153},{8,22,5},{0,22,37},{28,0,2665},{30,10,2665},{0,22,37},{0,17,2689},{30,10,2665},{0,17,2689},{3,0,865},{3,0,865},{3,0,865},{3,0,865},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,6,445},{0,6,445},{5,31,6270},{3,31,1626},{4,24,1886},{3,22,1299},{2,31,10381},{0,28,4146},{0,22,377}, +{0,17,4373},{0,20,14006},{0,16,6915},{8,31,3434},{6,31,242},{7,23,146},{5,22,282},{21,3,9669},{0,28,4146},{0,22,377},{0,17,4373},{28,6,9669},{0,17,4373},{3,31,1226},{3,31,1226},{3,31,1226},{3,21,1205},{0,27,2180},{0,21,274},{0,21,274},{0,13,353},{0,14,4269},{0,11,1763},{6,27,4},{6,27,4},{6,27,4},{6,19,0},{16,0,2178},{0,21,274},{0,21,274},{0,13,353},{25,1,2178}, +{0,13,353},{29,1,2665},{5,31,232},{9,23,5},{0,23,10},{29,1,2665},{31,11,2665},{0,23,10},{0,18,2689},{31,11,2665},{0,18,2689},{3,0,1201},{3,0,1201},{3,0,1201},{3,0,1201},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,7,637},{0,7,637},{6,31,7374},{4,31,2339},{4,25,2441},{3,23,1730},{3,31,10950},{0,29,3909},{0,23,243},{0,18,4154},{0,22,14614},{0,17,7029},{9,31,3638}, +{7,31,320},{8,24,149},{6,23,282},{22,4,9669},{0,29,3909},{0,23,243},{0,18,4154},{29,7,9669},{0,18,4154},{4,31,1714},{4,31,1714},{4,31,1714},{3,22,1666},{0,29,2180},{0,23,194},{0,23,194},{0,14,260},{0,15,4686},{0,13,1937},{7,28,1},{7,28,1},{7,28,1},{7,20,1},{17,1,2178},{0,23,194},{0,23,194},{0,14,260},{26,2,2178},{0,14,260},{31,0,2665},{8,31,313},{10,24,8}, +{0,24,4},{31,0,2665},{30,13,2665},{0,24,4},{0,19,2689},{30,13,2665},{0,19,2689},{3,0,1665},{3,0,1665},{3,0,1665},{3,0,1665},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,8,832},{0,8,832},{7,31,8807},{5,31,3388},{5,26,3116},{4,24,2243},{4,31,11766},{0,31,3686},{0,25,138},{0,19,3938},{0,23,15369},{0,18,7206},{11,31,3853},{8,31,457},{9,25,146},{7,24,299},{25,2,9669}, +{0,31,3686},{0,25,138},{0,19,3938},{27,10,9669},{0,19,3938},{5,31,2427},{5,31,2427},{5,31,2427},{4,23,2182},{0,31,2210},{0,25,137},{0,25,137},{0,15,181},{0,16,5157},{0,14,2163},{8,30,1},{8,30,1},{8,30,1},{8,21,0},{17,4,2178},{0,25,137},{0,25,137},{0,15,181},{29,2,2178},{0,15,181},{31,3,2665},{9,31,405},{11,25,2},{1,25,2},{31,3,2665},{30,15,2665},{1,25,2}, +{0,20,2689},{30,15,2665},{0,20,2689},{4,0,2178},{4,0,2178},{4,0,2178},{4,0,2178},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,10,1125},{0,10,1125},{7,31,10230},{6,31,4421},{6,27,3739},{4,26,2742},{5,31,12634},{0,31,3719},{0,26,87},{0,20,3771},{0,25,16061},{0,19,7283},{12,31,4050},{10,31,629},{10,26,146},{8,25,282},{26,3,9669},{0,31,3718},{0,26,86},{0,20,3770},{28,11,9669}, +{0,20,3770},{5,31,3050},{5,31,3050},{5,31,3050},{5,24,2690},{1,31,2325},{0,26,86},{0,26,86},{0,16,129},{0,18,5544},{0,15,2318},{9,31,1},{9,31,1},{9,31,1},{9,22,0},{18,5,2178},{0,26,85},{0,26,85},{0,16,128},{30,3,2178},{0,16,128},{31,6,2665},{11,31,521},{12,26,5},{2,26,2},{31,6,2665},{29,17,2665},{2,26,2},{0,21,2689},{29,17,2665},{0,21,2689},{5,0,2689}, +{5,0,2689},{5,0,2689},{5,0,2689},{0,24,1},{0,24,1},{0,24,1},{0,15,5},{0,11,1348},{0,11,1348},{9,31,10738},{7,31,4899},{7,28,3705},{5,27,2742},{6,31,13045},{1,31,4002},{1,27,87},{0,21,3686},{0,27,15601},{0,20,6570},{13,31,4302},{11,31,857},{11,27,146},{9,26,282},{28,2,9669},{2,31,3954},{1,27,86},{0,21,3605},{27,13,9669},{0,21,3605},{6,31,3173},{6,31,3173},{6,31,3173}, +{6,25,2690},{2,31,2427},{1,28,83},{1,28,83},{1,17,129},{0,20,5170},{0,16,1856},{10,31,4},{10,31,4},{10,31,4},{10,23,0},{20,4,2178},{0,28,32},{0,28,32},{0,17,89},{29,5,2178},{0,17,89},{31,8,2665},{13,31,680},{13,27,5},{3,27,2},{31,8,2665},{30,18,2665},{3,27,2},{0,22,2689},{30,18,2665},{0,22,2689},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{1,25,1}, +{1,25,1},{1,25,1},{1,15,10},{0,13,1217},{0,13,1217},{10,31,11278},{8,31,5402},{7,29,3750},{6,28,2745},{7,31,13510},{3,31,4314},{2,28,77},{1,22,3686},{0,28,15046},{0,21,5958},{14,31,4590},{12,31,1171},{12,28,149},{10,27,282},{29,3,9669},{3,31,4265},{2,28,76},{0,22,3458},{28,14,9669},{0,22,3458},{7,31,3314},{7,31,3314},{7,31,3314},{7,26,2690},{4,31,2532},{2,28,73},{2,28,73}, +{2,18,129},{0,21,4837},{0,17,1490},{11,31,25},{11,31,25},{11,31,25},{11,24,1},{24,0,2178},{0,30,8},{0,30,8},{0,19,49},{30,6,2178},{0,19,49},{31,11,2665},{15,31,832},{14,28,8},{4,28,4},{31,11,2665},{31,19,2665},{4,28,4},{0,23,2689},{31,19,2665},{0,23,2689},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{2,26,1},{2,26,1},{2,26,1},{2,16,5},{0,14,1037}, +{0,14,1037},{11,31,11942},{10,31,6090},{9,30,3739},{7,29,2751},{9,31,14053},{4,31,4863},{3,29,79},{2,24,3689},{0,30,14558},{0,23,5274},{16,31,4858},{14,31,1556},{13,29,146},{11,28,299},{29,6,9669},{6,31,4594},{3,29,75},{0,24,3265},{31,14,9669},{0,24,3265},{9,31,3505},{9,31,3505},{9,31,3505},{8,27,2693},{5,31,2645},{3,30,72},{3,30,72},{3,19,134},{0,23,4506},{0,19,1109},{12,31,64}, +{12,31,64},{12,31,64},{12,25,0},{24,3,2178},{1,31,10},{1,31,10},{0,20,16},{28,9,2178},{0,20,16},{31,14,2665},{17,31,1053},{15,29,2},{5,29,2},{31,14,2665},{29,22,2665},{5,29,2},{0,24,2689},{29,22,2665},{0,24,2689},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{3,27,5},{3,27,5},{3,27,5},{3,18,8},{0,16,818},{0,16,818},{12,31,12466},{11,31,6718},{10,31,3739}, +{8,30,2742},{10,31,14554},{6,31,5363},{4,30,87},{3,24,3654},{0,31,14190},{0,24,4785},{17,31,5158},{15,31,1938},{14,30,146},{12,29,282},{30,7,9669},{8,31,4806},{4,30,86},{0,25,3130},{30,16,9669},{0,25,3130},{10,31,3658},{10,31,3658},{10,31,3658},{9,28,2690},{6,31,2795},{4,30,86},{4,30,86},{4,20,129},{0,25,4315},{0,20,809},{14,31,100},{14,31,100},{14,31,100},{13,26,0},{22,9,2178}, +{3,31,34},{3,31,34},{0,21,1},{29,10,2178},{0,21,1},{30,18,2665},{19,31,1241},{16,30,5},{6,30,2},{30,18,2665},{30,23,2665},{6,30,2},{0,25,2689},{30,23,2665},{0,25,2689},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{4,28,1},{4,28,1},{4,28,1},{4,19,5},{0,18,666},{0,18,666},{14,31,13094},{12,31,7445},{11,31,3830},{9,31,2742},{12,31,14998},{8,31,5926},{5,31,87}, +{4,25,3686},{0,31,14254},{0,25,4323},{18,31,5494},{16,31,2414},{15,31,146},{13,30,282},{29,11,9669},{10,31,5138},{5,31,86},{0,26,3013},{31,17,9669},{0,26,3013},{11,31,3829},{11,31,3829},{11,31,3829},{10,29,2690},{7,31,2981},{5,31,86},{5,31,86},{5,21,129},{0,27,4059},{0,21,597},{15,31,145},{15,31,145},{15,31,145},{14,27,0},{24,8,2178},{5,31,85},{5,31,85},{1,22,1},{30,11,2178}, +{1,22,1},{31,19,2665},{20,31,1378},{17,31,5},{7,31,2},{31,19,2665},{29,25,2665},{7,31,2},{0,26,2689},{29,25,2665},{0,26,2689},{10,0,2689},{10,0,2689},{10,0,2689},{10,0,2689},{5,29,1},{5,29,1},{5,29,1},{5,19,10},{0,20,505},{0,20,505},{15,31,12507},{13,31,7370},{12,31,4001},{11,31,2705},{13,31,14148},{8,31,5491},{6,31,154},{5,26,3063},{1,31,13399},{0,26,3306},{19,31,4949}, +{17,31,2261},{16,31,202},{15,30,185},{29,13,8712},{11,31,4644},{7,31,145},{0,27,2403},{28,20,8712},{0,27,2403},{12,31,4001},{12,31,4001},{12,31,4001},{11,30,2690},{9,31,3204},{6,31,154},{6,31,154},{6,22,129},{0,28,3762},{0,23,425},{16,31,202},{16,31,202},{16,31,202},{15,28,1},{28,4,2178},{7,31,145},{7,31,145},{2,23,1},{29,13,2178},{2,23,1},{30,22,2178},{22,31,1145},{18,31,1}, +{10,31,1},{30,22,2178},{27,27,2178},{10,31,1},{0,27,2178},{27,27,2178},{0,27,2178},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{6,30,1},{6,30,1},{6,30,1},{6,20,5},{0,22,389},{0,22,389},{16,31,11658},{14,31,7195},{13,31,4225},{12,31,2693},{14,31,13066},{10,31,5014},{8,31,261},{6,27,2390},{3,31,12366},{0,27,2277},{20,31,4338},{18,31,2037},{17,31,289},{16,30,89},{29,15,7578}, +{13,31,4037},{9,31,202},{0,27,1701},{30,20,7578},{0,27,1701},{13,31,4225},{13,31,4225},{13,31,4225},{12,31,2693},{10,31,3429},{8,31,261},{8,31,261},{7,23,134},{0,30,3509},{0,24,306},{17,31,289},{17,31,289},{17,31,289},{16,29,0},{31,2,2178},{9,31,202},{9,31,202},{3,24,0},{27,16,2178},{3,24,0},{31,22,1625},{23,31,850},{20,31,0},{13,31,1},{31,22,1625},{30,26,1625},{13,31,1}, +{0,27,1665},{30,26,1625},{0,27,1665},{12,0,2689},{12,0,2689},{12,0,2689},{12,0,2689},{7,31,5},{7,31,5},{7,31,5},{7,22,8},{0,24,306},{0,24,306},{16,31,11002},{15,31,7081},{14,31,4450},{13,31,2738},{15,31,12205},{11,31,4663},{9,31,411},{7,27,1845},{4,31,11643},{0,28,1578},{21,31,3802},{20,31,1845},{18,31,388},{17,31,25},{30,15,6661},{15,31,3525},{11,31,290},{0,28,1217},{30,21,6661}, +{0,28,1217},{14,31,4450},{14,31,4450},{14,31,4450},{13,31,2738},{11,31,3675},{9,31,411},{9,31,411},{8,24,129},{0,31,3354},{0,25,244},{18,31,388},{18,31,388},{18,31,388},{17,30,0},{26,13,2178},{11,31,290},{11,31,290},{4,25,1},{21,21,2178},{4,25,1},{31,23,1201},{24,31,653},{22,31,4},{15,31,1},{31,23,1201},{30,27,1201},{15,31,1},{0,28,1201},{30,27,1201},{0,28,1201},{13,0,2689}, +{13,0,2689},{13,0,2689},{13,0,2689},{8,31,17},{8,31,17},{8,31,17},{8,23,5},{0,26,218},{0,26,218},{17,31,10434},{16,31,7010},{15,31,4693},{14,31,2833},{16,31,11374},{12,31,4462},{10,31,629},{8,28,1387},{6,31,10895},{0,28,1002},{22,31,3334},{20,31,1701},{19,31,505},{18,31,0},{30,17,5829},{16,31,3145},{12,31,405},{1,28,866},{25,25,5829},{1,28,866},{15,31,4693},{15,31,4693},{15,31,4693}, +{14,31,2833},{12,31,3906},{10,31,629},{10,31,629},{9,25,129},{1,31,3525},{0,27,228},{19,31,505},{19,31,505},{19,31,505},{18,31,0},{28,12,2178},{12,31,405},{12,31,405},{5,26,1},{22,22,2178},{5,26,1},{30,26,841},{25,31,461},{23,31,1},{18,31,0},{30,26,841},{31,27,841},{18,31,0},{0,28,865},{31,27,841},{0,28,865},{14,0,2689},{14,0,2689},{14,0,2689},{14,0,2689},{9,31,50}, +{9,31,50},{9,31,50},{9,23,10},{0,28,137},{0,28,137},{18,31,9934},{17,31,6962},{16,31,4913},{15,31,2978},{17,31,10683},{13,31,4277},{11,31,915},{9,28,994},{8,31,10078},{0,29,630},{23,31,2934},{22,31,1605},{21,31,650},{19,31,25},{31,17,5082},{18,31,2769},{14,31,521},{2,29,546},{25,26,5082},{2,29,546},{16,31,4913},{16,31,4913},{16,31,4913},{15,31,2978},{14,31,4170},{11,31,915},{11,31,915}, +{10,26,129},{3,31,3789},{1,28,226},{21,31,650},{21,31,650},{21,31,650},{19,31,25},{29,13,2178},{14,31,521},{14,31,521},{6,27,1},{28,20,2178},{6,27,1},{31,26,545},{26,31,305},{25,31,4},{20,31,1},{31,26,545},{29,29,545},{20,31,1},{0,29,545},{29,29,545},{0,29,545},{15,0,2689},{15,0,2689},{15,0,2689},{15,0,2689},{11,31,74},{11,31,74},{11,31,74},{10,24,5},{0,29,85}, +{0,29,85},{19,31,9465},{18,31,6955},{17,31,5233},{16,31,3218},{18,31,10003},{14,31,4183},{13,31,1258},{10,29,645},{9,31,9445},{1,30,409},{24,31,2529},{23,31,1525},{22,31,785},{20,31,100},{31,19,4344},{20,31,2345},{16,31,698},{5,29,321},{27,26,4344},{5,29,321},{17,31,5233},{17,31,5233},{17,31,5233},{16,31,3218},{15,31,4491},{13,31,1258},{13,31,1258},{11,27,134},{5,31,4171},{2,29,213},{22,31,785}, +{22,31,785},{22,31,785},{20,31,100},{29,16,2178},{16,31,698},{16,31,698},{7,28,0},{31,20,2178},{7,28,0},{31,27,290},{28,31,162},{26,31,4},{23,31,1},{31,27,290},{30,29,290},{23,31,1},{0,29,320},{30,29,290},{0,29,320},{16,0,2689},{16,0,2689},{16,0,2689},{16,0,2689},{12,31,113},{12,31,113},{12,31,113},{11,26,8},{0,31,45},{0,31,45},{20,31,9219},{19,31,6985},{18,31,5530}, +{17,31,3473},{19,31,9496},{15,31,4186},{14,31,1630},{12,29,426},{11,31,8961},{3,30,277},{25,31,2275},{24,31,1509},{23,31,932},{22,31,208},{30,22,3779},{21,31,2086},{18,31,850},{6,30,129},{27,27,3779},{6,30,129},{18,31,5530},{18,31,5530},{18,31,5530},{17,31,3473},{16,31,4770},{14,31,1630},{14,31,1630},{12,28,129},{8,31,4442},{3,30,213},{23,31,932},{23,31,932},{23,31,932},{22,31,208},{30,17,2178}, +{18,31,850},{18,31,850},{8,29,1},{25,25,2178},{8,29,1},{30,30,128},{29,31,72},{28,31,1},{26,31,0},{30,30,128},{30,30,128},{26,31,0},{0,30,128},{30,30,128},{0,30,128},{17,0,2689},{17,0,2689},{17,0,2689},{17,0,2689},{13,31,170},{13,31,170},{13,31,170},{12,27,5},{2,31,89},{2,31,89},{21,31,8929},{20,31,7062},{19,31,5845},{18,31,3778},{20,31,9188},{17,31,4260},{15,31,2070}, +{13,30,234},{13,31,8680},{4,31,228},{26,31,2089},{25,31,1515},{24,31,1073},{23,31,353},{30,24,3299},{22,31,1913},{20,31,965},{9,30,65},{29,27,3299},{9,30,65},{19,31,5845},{19,31,5845},{19,31,5845},{18,31,3778},{17,31,5124},{15,31,2070},{15,31,2070},{13,29,129},{9,31,4725},{4,31,228},{24,31,1073},{24,31,1073},{24,31,1073},{23,31,353},{31,18,2178},{20,31,965},{20,31,965},{9,30,1},{26,26,2178}, +{9,30,1},{31,30,34},{30,31,18},{29,31,4},{28,31,1},{31,30,34},{31,30,34},{28,31,1},{0,30,64},{31,30,34},{0,30,64},{18,0,2689},{18,0,2689},{18,0,2689},{18,0,2689},{14,31,245},{14,31,245},{14,31,245},{13,27,10},{4,31,164},{4,31,164},{22,31,8707},{21,31,7170},{21,31,6209},{19,31,4133},{21,31,8853},{18,31,4387},{17,31,2548},{14,31,170},{14,31,8388},{6,31,244},{27,31,1971}, +{26,31,1557},{25,31,1250},{24,31,565},{31,24,2904},{23,31,1826},{22,31,1145},{10,31,1},{24,31,2904},{10,31,1},{21,31,6209},{21,31,6209},{21,31,6209},{19,31,4133},{19,31,5460},{17,31,2548},{17,31,2548},{14,30,129},{11,31,5085},{6,31,244},{25,31,1250},{25,31,1250},{25,31,1250},{24,31,565},{30,22,2178},{22,31,1145},{22,31,1145},{10,31,1},{27,27,2178},{10,31,1},{31,31,0},{31,31,0},{31,31,0}, +{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{19,0,2689},{19,0,2689},{19,0,2689},{19,0,2689},{15,31,338},{15,31,338},{15,31,338},{14,28,5},{6,31,244},{6,31,244},{23,31,7705},{22,31,6418},{21,31,5633},{20,31,3845},{22,31,7654},{19,31,3874},{18,31,2310},{15,31,53},{15,31,7258},{8,31,317},{27,31,1458},{27,31,1186},{26,31,932},{25,31,425},{31,25,2166}, +{25,31,1398},{23,31,850},{13,31,1},{28,29,2166},{13,31,1},{21,31,5633},{21,31,5633},{21,31,5633},{20,31,3845},{19,31,4830},{18,31,2310},{18,31,2310},{15,31,53},{13,31,4506},{8,31,317},{26,31,932},{26,31,932},{26,31,932},{25,31,425},{31,22,1625},{23,31,850},{23,31,850},{13,31,1},{30,26,1625},{13,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0}, +{0,31,0},{31,31,0},{0,31,0},{20,0,2689},{20,0,2689},{20,0,2689},{20,0,2689},{16,31,449},{16,31,449},{16,31,449},{15,30,8},{8,31,317},{8,31,317},{24,31,6881},{23,31,5814},{22,31,5138},{21,31,3650},{23,31,6713},{20,31,3400},{19,31,2142},{16,31,5},{17,31,6397},{9,31,425},{28,31,1075},{27,31,866},{27,31,697},{26,31,320},{31,26,1601},{26,31,1041},{24,31,653},{15,31,1},{29,29,1601}, +{15,31,1},{22,31,5138},{22,31,5138},{22,31,5138},{21,31,3650},{21,31,4313},{19,31,2142},{19,31,2142},{16,31,5},{14,31,3981},{9,31,425},{27,31,697},{27,31,697},{27,31,697},{26,31,320},{31,23,1201},{24,31,653},{24,31,653},{15,31,1},{30,27,1201},{15,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{21,0,2689}, +{21,0,2689},{21,0,2689},{21,0,2689},{18,31,549},{18,31,549},{18,31,549},{16,31,5},{9,31,425},{9,31,425},{24,31,6097},{24,31,5285},{23,31,4693},{22,31,3473},{23,31,5833},{21,31,3067},{20,31,1988},{17,31,10},{18,31,5571},{11,31,541},{28,31,739},{28,31,595},{27,31,505},{27,31,233},{30,28,1121},{26,31,737},{25,31,461},{18,31,0},{28,30,1121},{18,31,0},{23,31,4693},{23,31,4693},{23,31,4693}, +{22,31,3473},{22,31,3845},{20,31,1988},{20,31,1988},{17,31,10},{15,31,3542},{11,31,541},{27,31,505},{27,31,505},{27,31,505},{27,31,233},{30,26,841},{25,31,461},{25,31,461},{18,31,0},{31,27,841},{18,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{22,0,2689},{22,0,2689},{22,0,2689},{22,0,2689},{19,31,666}, +{19,31,666},{19,31,666},{17,31,10},{11,31,541},{11,31,541},{25,31,5427},{24,31,4757},{24,31,4273},{23,31,3314},{24,31,5002},{22,31,2788},{21,31,1898},{18,31,65},{20,31,4714},{13,31,698},{29,31,489},{28,31,387},{28,31,306},{28,31,162},{30,29,726},{27,31,482},{26,31,305},{20,31,1},{29,30,726},{20,31,1},{24,31,4273},{24,31,4273},{24,31,4273},{23,31,3314},{22,31,3429},{21,31,1898},{21,31,1898}, +{18,31,65},{17,31,3213},{13,31,698},{28,31,306},{28,31,306},{28,31,306},{28,31,162},{31,26,545},{26,31,305},{26,31,305},{20,31,1},{29,29,545},{20,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,2689},{23,0,2689},{23,0,2689},{23,0,2689},{20,31,832},{20,31,832},{20,31,832},{18,31,65},{13,31,698}, +{13,31,698},{4,31,33740},{0,31,5184},{0,22,420},{0,21,4221},{3,31,45594},{0,29,24105},{0,21,8317},{0,18,24790},{0,21,63990},{0,16,38959},{2,31,9704},{0,30,2866},{0,21,389},{0,19,3229},{14,2,18065},{0,20,13257},{0,17,6153},{0,12,13481},{25,0,18065},{0,12,13481},{0,15,1},{0,15,1},{0,15,1},{0,9,1},{0,8,1105},{0,7,585},{0,7,585},{0,4,596},{0,4,1273},{0,4,740},{0,15,1}, +{0,15,1},{0,15,1},{0,9,1},{4,1,1105},{0,7,585},{0,7,585},{0,4,596},{8,0,1105},{0,4,596},{20,4,9248},{0,30,2866},{0,21,389},{0,19,3229},{20,4,9248},{29,5,9248},{0,19,3229},{0,14,9248},{29,5,9248},{0,14,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,38380},{1,31,6614},{0,23,245}, +{0,22,3864},{4,31,50747},{0,31,24961},{0,22,8353},{0,19,25735},{0,22,65535},{0,17,41319},{2,31,10152},{0,31,2624},{0,23,229},{0,20,2980},{16,0,19334},{0,20,13769},{0,18,6243},{0,13,14116},{25,1,19334},{0,13,14116},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{0,9,1513},{0,8,772},{0,8,772},{0,5,821},{0,5,1750},{0,4,1028},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{5,1,1513}, +{0,8,772},{0,8,772},{0,5,821},{9,0,1513},{0,5,821},{24,0,9248},{0,31,2624},{0,23,229},{0,20,2980},{24,0,9248},{30,6,9248},{0,20,2980},{0,15,9248},{30,6,9248},{0,15,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,43788},{1,31,8598},{0,24,126},{0,23,3525},{4,31,56155},{0,31,26241},{0,23,8425}, +{0,20,26793},{0,23,65535},{0,18,43819},{3,31,10706},{0,31,2624},{0,24,122},{0,21,2701},{17,0,20689},{0,22,14385},{0,19,6369},{0,13,14756},{25,2,20689},{0,13,14756},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{0,10,1989},{0,9,1018},{0,9,1018},{0,6,1096},{0,5,2294},{0,5,1334},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{5,2,1985},{0,9,1018},{0,9,1018},{0,6,1096},{9,1,1985}, +{0,6,1096},{25,1,9248},{0,31,2624},{0,24,122},{0,21,2701},{25,1,9248},{31,7,9248},{0,21,2701},{0,16,9250},{31,7,9248},{0,16,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,31,49566},{1,31,11350},{0,25,41},{0,24,3109},{4,31,62331},{0,31,28289},{0,24,8585},{0,21,27848},{0,23,65535},{0,19,46459},{4,31,11395}, +{0,31,2880},{0,25,37},{0,22,2440},{17,2,22129},{0,23,15030},{0,20,6509},{0,14,15441},{27,2,22129},{0,14,15441},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{0,12,2525},{0,10,1300},{0,10,1300},{0,6,1384},{0,6,2905},{0,6,1708},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{7,0,2521},{0,10,1300},{0,10,1300},{0,6,1384},{10,1,2521},{0,6,1384},{26,2,9248},{1,31,2866},{0,25,37}, +{0,22,2440},{26,2,9248},{27,11,9248},{0,22,2440},{0,17,9250},{27,11,9248},{0,17,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,31,56892},{2,31,15166},{0,26,20},{0,25,2804},{5,31,65535},{0,31,31511},{0,25,8733},{0,22,29095},{0,26,65535},{0,20,49444},{4,31,12385},{1,31,3380},{0,26,4},{0,23,2173},{17,4,23851}, +{0,23,15948},{0,21,6729},{0,15,16274},{29,2,23851},{0,15,16274},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{0,13,3200},{0,11,1665},{0,11,1665},{0,7,1754},{0,7,3691},{0,6,2185},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{2,10,3200},{0,11,1665},{0,11,1665},{0,7,1754},{13,0,3200},{0,7,1754},{24,8,9248},{3,31,3204},{0,26,4},{0,23,2173},{24,8,9248},{30,11,9248},{0,23,2173}, +{0,18,9248},{30,11,9248},{0,18,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,31,63870},{2,31,19230},{0,27,45},{0,27,2520},{5,31,65535},{1,31,35016},{0,26,8925},{0,23,30250},{0,28,65535},{0,21,52374},{5,31,13379},{2,31,4026},{0,27,29},{0,24,1901},{18,4,25472},{0,26,16706},{0,22,6963},{0,16,17124},{29,3,25472}, +{0,16,17124},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{0,14,3874},{0,13,2084},{0,13,2084},{0,8,2165},{0,8,4466},{0,7,2627},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{8,1,3872},{0,13,2084},{0,13,2084},{0,8,2165},{6,5,3872},{0,8,2165},{28,4,9248},{5,31,3589},{1,27,4},{0,24,1901},{28,4,9248},{29,13,9248},{0,24,1901},{0,19,9248},{29,13,9248},{0,19,9248},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,31,65535},{2,31,24002},{0,28,109},{0,27,2268},{6,31,65535},{1,31,38780},{0,27,8825},{0,24,30825},{0,28,65535},{0,22,54996},{6,31,14345},{2,31,4766},{1,28,62},{0,26,1697},{18,6,26744},{0,28,17104},{0,23,6957},{0,17,17625},{31,3,26744},{0,17,17625},{0,31,5},{0,31,5},{0,31,5}, +{0,19,5},{0,16,4418},{0,14,2306},{0,14,2306},{0,9,2420},{0,8,5122},{0,8,2997},{0,31,5},{0,31,5},{0,31,5},{0,19,5},{9,1,4418},{0,14,2306},{0,14,2306},{0,9,2420},{16,0,4418},{0,9,2420},{29,5,9248},{8,31,3904},{2,28,1},{0,26,1693},{29,5,9248},{30,14,9248},{0,26,1693},{0,20,9250},{30,14,9248},{0,20,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1}, +{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{7,31,65535},{3,31,29032},{0,29,330},{0,28,2105},{6,31,65535},{2,31,42151},{0,28,7781},{0,25,30108},{0,29,65535},{0,22,56388},{7,31,14819},{3,31,5416},{2,29,62},{0,27,1580},{23,0,26744},{0,29,16547},{0,24,6221},{0,18,17124},{30,5,26744},{0,18,17124},{1,31,84},{1,31,84},{1,31,84},{1,20,72},{0,19,4420},{0,16,2005},{0,16,2005}, +{0,10,2165},{0,9,5389},{0,9,2925},{1,31,20},{1,31,20},{1,31,20},{1,20,8},{10,2,4418},{0,16,2005},{0,16,2005},{0,10,2165},{17,1,4418},{0,10,2165},{30,6,9248},{8,31,4160},{3,29,1},{0,27,1480},{30,6,9248},{31,15,9248},{0,27,1480},{0,21,9250},{31,15,9248},{0,21,9250},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{0,3,1},{0,3,1},{0,3,1},{0,2,0},{0,1,34}, +{0,1,34},{7,31,65535},{3,31,35719},{1,30,717},{0,30,2062},{7,31,65535},{2,31,46660},{0,29,6696},{0,26,29322},{0,31,65535},{0,23,58077},{9,31,15473},{5,31,6173},{3,30,65},{1,28,1601},{23,3,26744},{0,31,15992},{0,26,5346},{0,19,16582},{28,8,26744},{0,19,16582},{2,31,329},{2,31,329},{2,31,329},{1,21,189},{0,22,4420},{0,18,1737},{0,18,1737},{0,11,1898},{0,11,5707},{0,10,2885},{3,31,34}, +{3,31,34},{3,31,34},{2,21,10},{13,0,4418},{0,18,1737},{0,18,1737},{0,11,1898},{20,1,4418},{0,11,1898},{28,12,9248},{10,31,4570},{4,30,4},{0,28,1285},{28,12,9248},{22,22,9248},{0,28,1285},{0,22,9248},{22,22,9248},{0,22,9248},{1,0,185},{1,0,185},{1,0,185},{1,0,185},{0,6,1},{0,6,1},{0,6,1},{0,4,1},{0,3,97},{0,3,97},{7,31,65535},{4,31,40786},{1,31,1122}, +{0,30,2138},{7,31,65535},{2,31,49800},{0,30,5634},{0,27,27967},{0,31,65535},{0,24,58770},{10,31,15531},{6,31,6593},{4,31,61},{2,29,1533},{25,2,26259},{0,31,15284},{0,27,4514},{0,20,15812},{27,10,26259},{0,20,15812},{2,31,633},{2,31,633},{2,31,633},{2,22,381},{0,24,4418},{0,20,1480},{0,20,1480},{0,12,1640},{0,12,6125},{0,11,2891},{4,31,61},{4,31,61},{4,31,61},{3,22,10},{14,1,4418}, +{0,20,1480},{0,20,1480},{0,12,1640},{24,0,4418},{0,12,1640},{30,11,8978},{11,31,4744},{5,31,0},{0,29,1040},{30,11,8978},{31,18,8978},{0,29,1040},{0,23,8980},{31,18,8978},{0,23,8980},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,9,0},{0,9,0},{0,9,0},{0,5,4},{0,4,193},{0,4,193},{8,31,65535},{4,31,40898},{1,31,1890},{0,31,2125},{7,31,65535},{3,31,47871},{0,30,4194}, +{0,27,24703},{0,31,65535},{0,24,56130},{11,31,14325},{8,31,6051},{5,31,100},{3,29,1218},{22,9,24371},{0,31,13716},{0,28,3402},{0,21,13989},{29,10,24371},{0,21,13989},{3,31,1058},{3,31,1058},{3,31,1058},{2,24,617},{0,27,4420},{0,22,1280},{0,22,1280},{0,13,1445},{0,14,6509},{0,12,2945},{5,31,100},{5,31,100},{5,31,100},{4,23,5},{16,0,4418},{0,22,1280},{0,22,1280},{0,13,1445},{25,1,4418}, +{0,13,1445},{29,14,7938},{13,31,4225},{7,31,4},{0,29,656},{29,14,7938},{29,20,7938},{0,29,656},{0,23,7956},{29,20,7938},{0,23,7956},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,11,4},{0,11,4},{0,11,4},{0,7,0},{0,5,325},{0,5,325},{8,31,65535},{4,31,41266},{1,31,2914},{1,31,2170},{7,31,65535},{3,31,46175},{0,30,3010},{0,27,21695},{0,31,65535},{0,25,53636},{12,31,13140}, +{8,31,5571},{6,31,157},{4,29,932},{24,7,22568},{0,31,12404},{0,28,2474},{0,21,12245},{29,11,22568},{0,21,12245},{4,31,1630},{4,31,1630},{4,31,1630},{3,25,937},{0,29,4420},{0,23,1090},{0,23,1090},{0,14,1268},{0,15,6926},{0,13,3029},{6,31,157},{6,31,157},{6,31,157},{5,24,8},{17,1,4418},{0,23,1090},{0,23,1090},{0,14,1268},{26,2,4418},{0,14,1268},{31,12,6962},{14,31,3709},{8,31,1}, +{0,30,353},{31,12,6962},{27,22,6962},{0,30,353},{0,24,6970},{27,22,6962},{0,24,6970},{3,0,937},{3,0,937},{3,0,937},{3,0,937},{0,14,0},{0,14,0},{0,14,0},{0,8,4},{0,6,493},{0,6,493},{9,31,65535},{5,31,41956},{2,31,4257},{1,31,2512},{7,31,65535},{3,31,44573},{0,30,1984},{0,28,18569},{0,31,65535},{0,25,51026},{13,31,11930},{10,31,5125},{7,31,250},{5,29,701},{27,4,20642}, +{1,31,11209},{0,29,1634},{0,22,10422},{31,11,20642},{0,22,10422},{4,31,2350},{4,31,2350},{4,31,2350},{3,27,1361},{0,31,4450},{0,25,949},{0,25,949},{0,16,1096},{0,16,7397},{0,14,3171},{7,31,250},{7,31,250},{7,31,250},{6,25,10},{17,4,4418},{0,25,949},{0,25,949},{0,16,1096},{29,2,4418},{0,16,1096},{30,15,5941},{15,31,3176},{10,31,0},{0,30,128},{30,15,5941},{30,21,5941},{0,30,128}, +{0,24,5953},{30,21,5941},{0,24,5953},{3,0,1360},{3,0,1360},{3,0,1360},{3,0,1360},{0,17,0},{0,17,0},{0,17,0},{0,10,1},{0,8,697},{0,8,697},{9,31,65535},{5,31,42660},{2,31,5617},{1,31,3088},{8,31,65535},{3,31,43421},{0,31,1250},{0,28,15865},{0,31,65535},{0,25,48978},{13,31,10922},{11,31,4753},{8,31,360},{6,30,509},{28,4,19021},{2,31,10246},{0,30,1088},{0,23,8945},{29,13,19021}, +{0,23,8945},{5,31,3131},{5,31,3131},{5,31,3131},{4,28,1822},{1,31,4580},{0,28,776},{0,28,776},{0,17,925},{0,18,7893},{0,15,3333},{8,31,360},{8,31,360},{8,31,360},{7,26,10},{18,5,4418},{0,28,776},{0,28,776},{0,17,925},{30,3,4418},{0,17,925},{31,15,5101},{17,31,2777},{11,31,9},{0,31,25},{31,15,5101},{30,22,5101},{0,31,25},{0,25,5105},{30,22,5101},{0,25,5105},{4,0,1818}, +{4,0,1818},{4,0,1818},{4,0,1818},{0,20,1},{0,20,1},{0,20,1},{0,12,1},{0,9,925},{0,9,925},{9,31,65535},{5,31,43620},{2,31,7233},{1,31,3920},{8,31,65535},{3,31,42525},{0,31,738},{0,28,13417},{0,31,65535},{0,25,47186},{14,31,9978},{11,31,4449},{10,31,452},{7,30,354},{31,1,17485},{3,31,9369},{0,30,704},{0,24,7570},{31,13,17485},{0,24,7570},{6,31,4058},{6,31,4058},{6,31,4058}, +{4,29,2315},{2,31,4874},{0,29,610},{0,29,610},{0,18,772},{0,20,8427},{0,16,3497},{10,31,452},{10,31,452},{10,31,452},{8,27,5},{20,4,4418},{0,29,610},{0,29,610},{0,18,772},{29,5,4418},{0,18,772},{31,16,4325},{18,31,2357},{13,31,0},{1,31,0},{31,16,4325},{31,22,4325},{1,31,0},{0,25,4337},{31,22,4325},{0,25,4337},{4,0,2314},{4,0,2314},{4,0,2314},{4,0,2314},{0,22,1}, +{0,22,1},{0,22,1},{0,13,4},{0,10,1189},{0,10,1189},{9,31,65535},{5,31,44836},{2,31,9105},{2,31,4905},{8,31,65535},{3,31,41885},{0,31,482},{0,28,11225},{0,31,65535},{0,26,45590},{15,31,9102},{13,31,4161},{11,31,557},{9,30,212},{29,6,16034},{5,31,8602},{0,31,482},{0,24,6242},{31,14,16034},{0,24,6242},{6,31,5066},{6,31,5066},{6,31,5066},{5,30,2907},{2,31,5322},{0,31,482},{0,31,482}, +{0,19,637},{0,20,8939},{0,17,3725},{11,31,557},{11,31,557},{11,31,557},{9,28,8},{24,0,4418},{0,31,482},{0,31,482},{0,19,637},{30,6,4418},{0,19,637},{30,19,3613},{20,31,1940},{15,31,4},{4,31,1},{30,19,3613},{31,23,3613},{4,31,1},{0,26,3617},{31,23,3613},{0,26,3617},{5,0,2906},{5,0,2906},{5,0,2906},{5,0,2906},{0,25,1},{0,25,1},{0,25,1},{0,15,0},{0,11,1489}, +{0,11,1489},{9,31,65535},{5,31,46510},{3,31,11362},{2,31,6237},{9,31,65535},{3,31,41471},{0,31,500},{0,29,8976},{0,31,65535},{0,26,43934},{16,31,8139},{14,31,3853},{12,31,680},{10,30,109},{26,13,14504},{8,31,7667},{0,31,500},{0,25,4979},{21,21,14504},{0,25,4979},{7,31,6337},{7,31,6337},{7,31,6337},{5,31,3642},{3,31,5962},{0,31,500},{0,31,500},{0,20,520},{0,22,9629},{0,18,4035},{12,31,680}, +{12,31,680},{12,31,680},{10,29,10},{24,3,4418},{0,31,500},{0,31,500},{0,20,520},{28,9,4418},{0,20,520},{31,19,2888},{20,31,1517},{16,31,1},{7,31,1},{31,19,2888},{27,26,2888},{7,31,1},{0,26,2906},{27,26,2888},{0,26,2906},{5,0,3617},{5,0,3617},{5,0,3617},{5,0,3617},{0,28,1},{0,28,1},{0,28,1},{0,17,4},{0,11,1930},{0,11,1930},{10,31,65535},{6,31,48082},{3,31,13570}, +{2,31,7693},{9,31,65535},{3,31,41375},{0,31,788},{0,29,7120},{0,31,65535},{0,26,42734},{17,31,7409},{15,31,3625},{13,31,821},{11,31,45},{28,11,13235},{8,31,6899},{2,31,628},{0,25,3987},{31,16,13235},{0,25,3987},{7,31,7681},{7,31,7681},{7,31,7681},{6,31,4437},{4,31,6659},{1,31,738},{1,31,738},{0,21,421},{0,23,10286},{0,20,4305},{13,31,821},{13,31,821},{13,31,821},{11,30,10},{22,9,4418}, +{2,31,628},{2,31,628},{0,21,421},{29,10,4418},{0,21,421},{31,20,2312},{21,31,1217},{18,31,1},{9,31,0},{31,20,2312},{30,25,2312},{9,31,0},{0,27,2314},{30,25,2312},{0,27,2314},{6,0,4337},{6,0,4337},{6,0,4337},{6,0,4337},{0,30,1},{0,30,1},{0,30,1},{0,18,1},{0,13,2329},{0,13,2329},{10,31,65535},{6,31,49890},{3,31,16034},{2,31,9405},{9,31,65535},{4,31,41526},{0,31,1332}, +{0,29,5520},{0,31,65535},{0,26,41790},{18,31,6747},{16,31,3459},{14,31,980},{12,31,5},{31,8,12051},{10,31,6275},{4,31,801},{0,26,3066},{28,19,12051},{0,26,3066},{8,31,9062},{8,31,9062},{8,31,9062},{7,31,5410},{4,31,7555},{1,31,1154},{1,31,1154},{0,23,325},{0,23,11118},{0,20,4625},{14,31,980},{14,31,980},{14,31,980},{12,31,5},{24,8,4418},{4,31,801},{4,31,801},{0,23,325},{30,11,4418}, +{0,23,325},{30,23,1800},{23,31,949},{19,31,4},{12,31,1},{30,23,1800},{28,27,1800},{12,31,1},{0,27,1818},{28,27,1800},{0,27,1818},{6,0,5105},{6,0,5105},{6,0,5105},{6,0,5105},{0,31,36},{0,31,36},{0,31,36},{0,20,4},{0,15,2741},{0,15,2741},{10,31,65535},{6,31,51954},{3,31,18754},{3,31,11330},{9,31,65535},{4,31,41798},{1,31,2082},{0,29,4176},{0,31,65535},{0,27,41092},{19,31,6153}, +{17,31,3297},{16,31,1154},{13,31,20},{29,13,10952},{11,31,5708},{6,31,965},{0,27,2291},{28,20,10952},{0,27,2291},{9,31,10545},{9,31,10545},{9,31,10545},{7,31,6482},{5,31,8549},{2,31,1716},{2,31,1716},{0,24,221},{0,26,11876},{0,22,4989},{16,31,1154},{16,31,1154},{16,31,1154},{13,31,20},{28,4,4418},{6,31,965},{6,31,965},{0,24,221},{29,13,4418},{0,24,221},{29,26,1352},{23,31,725},{21,31,0}, +{14,31,1},{29,26,1352},{31,26,1352},{14,31,1},{0,28,1360},{31,26,1352},{0,28,1360},{7,0,5953},{7,0,5953},{7,0,5953},{7,0,5953},{1,31,145},{1,31,145},{1,31,145},{0,21,1},{0,16,3130},{0,16,3130},{10,31,65535},{6,31,54582},{4,31,21886},{3,31,13652},{9,31,65535},{4,31,42410},{1,31,3144},{0,30,2841},{0,31,65535},{0,27,40390},{19,31,5649},{18,31,3157},{17,31,1325},{15,31,74},{29,15,9818}, +{13,31,5241},{8,31,1108},{0,27,1589},{30,20,9818},{0,27,1589},{10,31,12376},{10,31,12376},{10,31,12376},{8,31,7844},{6,31,9861},{3,31,2576},{3,31,2576},{0,25,136},{0,28,12696},{0,23,5429},{17,31,1325},{17,31,1325},{17,31,1325},{15,31,74},{31,2,4418},{8,31,1108},{8,31,1108},{0,25,136},{27,16,4418},{0,25,136},{31,24,925},{25,31,505},{23,31,1},{17,31,1},{31,24,925},{31,27,925},{17,31,1}, +{0,28,937},{31,27,925},{0,28,937},{7,0,6970},{7,0,6970},{7,0,6970},{7,0,6970},{1,31,388},{1,31,388},{1,31,388},{0,23,0},{0,17,3665},{0,17,3665},{10,31,65535},{7,31,57052},{4,31,24910},{3,31,15988},{9,31,65535},{4,31,43226},{1,31,4360},{0,30,1833},{0,31,65535},{0,27,40038},{21,31,5202},{19,31,3073},{18,31,1508},{16,31,180},{30,15,8901},{14,31,4814},{10,31,1300},{0,28,1021},{30,21,8901}, +{0,28,1021},{10,31,14136},{10,31,14136},{10,31,14136},{8,31,9252},{7,31,11195},{3,31,3536},{3,31,3536},{0,26,85},{0,29,13491},{0,23,5925},{18,31,1508},{18,31,1508},{18,31,1508},{16,31,180},{26,13,4418},{10,31,1300},{10,31,1300},{0,26,85},{21,21,4418},{0,26,85},{30,27,613},{26,31,337},{24,31,1},{20,31,1},{30,27,613},{30,28,613},{20,31,1},{0,29,617},{30,28,613},{0,29,617},{8,0,7956}, +{8,0,7956},{8,0,7956},{8,0,7956},{2,31,697},{2,31,697},{2,31,697},{0,25,4},{0,18,4181},{0,18,4181},{11,31,65535},{7,31,59708},{4,31,28190},{3,31,18580},{10,31,65535},{5,31,44295},{1,31,5832},{0,30,1081},{0,31,65535},{0,27,39942},{22,31,4818},{20,31,3017},{19,31,1709},{17,31,325},{30,17,8069},{15,31,4473},{11,31,1514},{0,29,602},{25,25,8069},{0,29,602},{11,31,15965},{11,31,15965},{11,31,15965}, +{9,31,10757},{7,31,12667},{4,31,4662},{4,31,4662},{0,27,52},{0,30,14340},{0,25,6449},{19,31,1709},{19,31,1709},{19,31,1709},{17,31,325},{28,12,4418},{11,31,1514},{11,31,1514},{0,27,52},{22,22,4418},{0,27,52},{31,27,365},{27,31,205},{26,31,1},{22,31,1},{31,27,365},{30,29,365},{22,31,1},{0,29,377},{30,29,365},{0,29,377},{8,0,8980},{8,0,8980},{8,0,8980},{8,0,8980},{2,31,1097}, +{2,31,1097},{2,31,1097},{0,26,1},{0,20,4682},{0,20,4682},{11,31,65535},{8,31,58981},{5,31,29551},{4,31,19751},{10,31,65535},{5,31,43215},{2,31,6910},{1,30,686},{0,31,65535},{0,28,34909},{23,31,4502},{21,31,3011},{20,31,1973},{18,31,520},{31,17,7322},{17,31,4242},{13,31,1769},{0,29,314},{25,26,7322},{0,29,314},{12,31,16739},{12,31,16739},{12,31,16739},{10,31,11492},{8,31,13636},{5,31,5510},{5,31,5510}, +{1,28,54},{0,31,14139},{0,26,6041},{20,31,1973},{20,31,1973},{20,31,1973},{18,31,520},{29,13,4418},{13,31,1769},{13,31,1769},{0,28,29},{28,20,4418},{0,28,29},{31,28,181},{28,31,97},{27,31,4},{25,31,0},{31,28,181},{31,29,181},{25,31,0},{0,30,185},{31,29,181},{0,30,185},{9,0,9248},{9,0,9248},{9,0,9248},{9,0,9248},{3,31,1348},{3,31,1348},{3,31,1348},{1,27,5},{0,21,4520}, +{0,21,4520},{12,31,65535},{9,31,57270},{6,31,30345},{5,31,20521},{11,31,65535},{6,31,41449},{3,31,8015},{2,31,301},{0,31,65535},{0,28,28330},{24,31,4181},{22,31,3053},{21,31,2248},{20,31,772},{31,19,6584},{20,31,3941},{15,31,2041},{0,30,77},{27,26,6584},{0,30,77},{13,31,17289},{13,31,17289},{13,31,17289},{11,31,12050},{10,31,14315},{7,31,6389},{7,31,6389},{2,29,53},{0,31,13860},{0,28,5286},{21,31,2248}, +{21,31,2248},{21,31,2248},{20,31,772},{29,16,4418},{15,31,2041},{15,31,2041},{0,30,13},{31,20,4418},{0,30,13},{30,31,50},{30,31,34},{29,31,0},{28,31,1},{30,31,50},{31,30,50},{28,31,1},{0,30,68},{31,30,50},{0,30,68},{10,0,9250},{10,0,9250},{10,0,9250},{10,0,9250},{4,31,1549},{4,31,1549},{4,31,1549},{2,28,2},{0,23,4114},{0,23,4114},{13,31,65535},{9,31,55894},{7,31,31068}, +{6,31,21256},{12,31,65535},{8,31,39740},{4,31,9073},{3,31,90},{0,31,65535},{0,29,23356},{24,31,3973},{23,31,3125},{23,31,2500},{21,31,1037},{30,22,6019},{20,31,3701},{17,31,2340},{0,31,4},{27,27,6019},{0,31,4},{14,31,17796},{14,31,17796},{14,31,17796},{12,31,12625},{11,31,14957},{8,31,7139},{8,31,7139},{3,30,53},{0,31,14020},{0,29,4652},{23,31,2500},{23,31,2500},{23,31,2500},{21,31,1037},{30,17,4418}, +{17,31,2340},{17,31,2340},{0,31,4},{25,25,4418},{0,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{31,31,4},{30,31,1},{0,31,4},{31,31,4},{0,31,4},{11,0,9250},{11,0,9250},{11,0,9250},{11,0,9250},{6,31,1765},{6,31,1765},{6,31,1765},{3,29,2},{0,25,3877},{0,25,3877},{13,31,65535},{10,31,53236},{8,31,30487},{7,31,21105},{13,31,65535},{8,31,37332},{5,31,9177}, +{4,31,36},{1,31,65535},{0,29,18680},{25,31,3443},{24,31,2741},{23,31,2248},{22,31,980},{29,25,5163},{21,31,3218},{20,31,2117},{3,31,1},{30,26,5163},{3,31,1},{15,31,17289},{15,31,17289},{15,31,17289},{13,31,12512},{12,31,14328},{9,31,7149},{9,31,7149},{4,31,20},{0,31,13376},{0,29,3944},{23,31,2248},{23,31,2248},{23,31,2248},{22,31,980},{31,17,3872},{20,31,2117},{20,31,2117},{3,31,1},{25,26,3872}, +{3,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{12,0,9248},{12,0,9248},{12,0,9248},{12,0,9248},{7,31,1972},{7,31,1972},{7,31,1972},{4,30,5},{0,27,3545},{0,27,3545},{14,31,65535},{11,31,50266},{9,31,29322},{8,31,20567},{13,31,65535},{9,31,35025},{6,31,8985},{5,31,21},{2,31,65535},{0,29,14712},{26,31,2873}, +{25,31,2283},{24,31,1825},{22,31,820},{30,24,4267},{22,31,2657},{20,31,1685},{5,31,1},{29,27,4267},{5,31,1},{16,31,16427},{16,31,16427},{16,31,16427},{14,31,12185},{13,31,13442},{10,31,6915},{10,31,6915},{5,31,5},{1,31,12539},{0,30,3314},{24,31,1825},{24,31,1825},{24,31,1825},{22,31,820},{28,23,3200},{20,31,1685},{20,31,1685},{5,31,1},{28,25,3200},{5,31,1},{31,31,0},{31,31,0},{31,31,0}, +{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{13,0,9248},{13,0,9248},{13,0,9248},{13,0,9248},{8,31,2250},{8,31,2250},{8,31,2250},{5,31,5},{0,28,3170},{0,28,3170},{15,31,65535},{12,31,47239},{10,31,28065},{9,31,20104},{14,31,65535},{10,31,32574},{7,31,8839},{6,31,54},{3,31,64890},{0,30,10964},{26,31,2252},{25,31,1806},{25,31,1445},{23,31,650},{30,25,3361}, +{23,31,2091},{21,31,1322},{8,31,0},{30,27,3361},{8,31,0},{17,31,15584},{17,31,15584},{17,31,15584},{15,31,11846},{14,31,12522},{11,31,6697},{11,31,6697},{6,31,50},{3,31,11669},{0,31,2834},{25,31,1445},{25,31,1445},{25,31,1445},{23,31,650},{30,21,2521},{21,31,1322},{21,31,1322},{8,31,0},{31,24,2521},{8,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0}, +{0,31,0},{31,31,0},{0,31,0},{14,0,9250},{14,0,9250},{14,0,9250},{14,0,9250},{9,31,2525},{9,31,2525},{9,31,2525},{6,31,50},{0,31,2834},{0,31,2834},{16,31,65535},{13,31,44559},{11,31,27000},{10,31,19705},{15,31,64179},{11,31,30525},{8,31,8677},{7,31,149},{3,31,60570},{0,30,8308},{27,31,1782},{26,31,1416},{25,31,1157},{24,31,520},{30,26,2646},{23,31,1691},{22,31,1040},{11,31,1},{31,27,2646}, +{11,31,1},{18,31,14889},{18,31,14889},{18,31,14889},{16,31,11585},{15,31,11778},{12,31,6555},{12,31,6555},{7,31,145},{3,31,11061},{0,31,2610},{25,31,1157},{25,31,1157},{25,31,1157},{24,31,520},{31,21,1985},{22,31,1040},{22,31,1040},{11,31,1},{31,25,1985},{11,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{15,0,9250}, +{15,0,9250},{15,0,9250},{15,0,9250},{10,31,2792},{10,31,2792},{10,31,2792},{7,31,145},{0,31,2610},{0,31,2610},{16,31,63318},{14,31,42019},{12,31,25930},{11,31,19324},{16,31,59178},{11,31,28845},{9,31,8605},{8,31,276},{6,31,56253},{0,30,6420},{27,31,1366},{27,31,1094},{26,31,872},{25,31,397},{30,27,2017},{25,31,1298},{23,31,794},{13,31,1},{30,28,2017},{13,31,1},{19,31,14244},{19,31,14244},{19,31,14244}, +{17,31,11312},{16,31,11037},{13,31,6429},{13,31,6429},{8,31,260},{6,31,10457},{0,31,2642},{26,31,872},{26,31,872},{26,31,872},{25,31,397},{31,22,1513},{23,31,794},{23,31,794},{13,31,1},{29,27,1513},{13,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{16,0,9248},{16,0,9248},{16,0,9248},{16,0,9248},{12,31,3074}, +{12,31,3074},{12,31,3074},{8,31,260},{0,31,2642},{0,31,2642},{17,31,58848},{15,31,39619},{13,31,24975},{12,31,19007},{16,31,54474},{13,31,27057},{10,31,8569},{9,31,461},{8,31,51302},{0,31,5046},{28,31,979},{27,31,806},{27,31,637},{26,31,292},{31,26,1473},{26,31,953},{24,31,605},{16,31,0},{29,29,1473},{16,31,0},{19,31,13604},{19,31,13604},{19,31,13604},{18,31,11057},{16,31,10429},{14,31,6339},{14,31,6339}, +{10,31,424},{8,31,9713},{1,31,2900},{27,31,637},{27,31,637},{27,31,637},{26,31,292},{30,25,1105},{24,31,605},{24,31,605},{16,31,0},{30,27,1105},{16,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{17,0,9248},{17,0,9248},{17,0,9248},{17,0,9248},{12,31,3330},{12,31,3330},{12,31,3330},{10,31,424},{1,31,2900}, +{1,31,2900}, diff --git a/ext/basis_universal/basisu_transcoder_tables_atc_56.inc b/ext/basis_universal/basisu_transcoder_tables_atc_56.inc new file mode 100644 index 0000000000..2b56c0944c --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_atc_56.inc @@ -0,0 +1,481 @@ +{0,3,20},{0,3,5},{0,2,1},{0,2,9},{0,2,35},{0,2,27},{0,1,17},{0,1,24},{0,1,41},{0,1,25},{0,3,20},{0,3,5},{0,2,1},{0,2,9},{0,2,35},{0,2,27},{0,1,17},{0,1,24},{1,0,35},{0,1,24},{0,1,1},{0,1,1},{0,1,1},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,1,1}, +{0,1,1},{0,1,1},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{1,0,18},{0,3,5},{0,2,1},{0,2,9},{1,0,18},{1,1,18},{0,2,9},{0,1,20},{1,1,18},{0,1,20},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,9,54},{0,7,37},{0,4,52}, +{0,4,36},{0,7,52},{0,5,21},{0,4,0},{0,3,21},{0,4,88},{0,3,37},{1,5,24},{1,5,9},{1,4,5},{1,4,13},{2,1,51},{0,5,21},{0,4,0},{0,3,21},{3,1,51},{0,3,21},{0,7,36},{0,7,36},{0,7,36},{0,4,36},{0,5,10},{0,4,0},{0,4,0},{0,2,5},{0,3,26},{0,2,14},{1,3,5},{1,3,5},{1,3,5},{1,3,4},{1,2,8}, +{0,4,0},{0,4,0},{0,2,5},{2,1,8},{0,2,5},{2,2,18},{0,7,1},{1,4,1},{0,4,0},{2,2,18},{2,3,18},{0,4,0},{0,3,20},{2,3,18},{0,3,20},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,10},{0,2,10},{1,11,54},{1,9,37},{1,6,52},{1,6,36},{1,9,52},{1,7,21},{1,6,0}, +{1,5,21},{0,7,63},{0,5,25},{2,7,24},{2,7,9},{2,6,5},{2,6,13},{3,3,51},{1,7,21},{1,6,0},{1,5,21},{4,3,51},{1,5,21},{1,9,36},{1,9,36},{1,9,36},{1,6,36},{1,7,10},{1,6,0},{1,6,0},{1,4,5},{0,6,11},{0,5,9},{2,5,5},{2,5,5},{2,5,5},{2,5,4},{3,1,8},{1,6,0},{1,6,0},{1,4,5},{3,3,8}, +{1,4,5},{3,4,18},{1,9,1},{2,6,1},{1,6,0},{3,4,18},{7,0,18},{1,6,0},{0,5,20},{7,0,18},{0,5,20},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,6,0},{1,6,0},{1,6,0},{1,4,1},{0,6,2},{0,6,2},{2,13,54},{2,11,37},{2,8,52},{2,8,36},{2,11,52},{2,9,21},{2,8,0},{2,7,21},{0,11,51},{1,7,25},{3,9,24}, +{3,9,9},{3,8,5},{3,8,13},{5,1,51},{2,9,21},{2,8,0},{2,7,21},{9,0,51},{2,7,21},{2,11,36},{2,11,36},{2,11,36},{2,8,36},{2,9,10},{2,8,0},{2,8,0},{2,6,5},{1,8,11},{1,7,9},{3,7,5},{3,7,5},{3,7,5},{3,7,4},{3,6,8},{2,8,0},{2,8,0},{2,6,5},{8,0,8},{2,6,5},{4,6,18},{2,11,1},{3,8,1}, +{2,8,0},{4,6,18},{8,2,18},{2,8,0},{0,7,20},{8,2,18},{0,7,20},{2,0,36},{2,0,36},{2,0,36},{2,0,36},{2,8,0},{2,8,0},{2,8,0},{2,6,1},{1,8,2},{1,8,2},{3,15,70},{3,13,51},{4,10,69},{3,10,52},{3,14,52},{3,12,25},{3,10,4},{3,9,27},{1,13,53},{2,10,26},{4,12,22},{4,11,12},{4,10,5},{4,10,9},{6,4,51}, +{2,13,22},{3,10,3},{3,9,26},{11,1,51},{3,9,26},{3,13,51},{3,13,51},{3,13,51},{3,10,51},{3,12,9},{3,11,2},{3,11,2},{3,9,2},{2,11,9},{3,9,10},{4,10,4},{4,10,4},{4,10,4},{4,9,5},{6,2,8},{3,11,1},{3,11,1},{3,9,1},{11,0,8},{3,9,1},{7,2,18},{3,13,1},{4,10,1},{3,10,2},{7,2,18},{11,2,18},{3,10,2}, +{0,9,26},{11,2,18},{0,9,26},{3,0,50},{3,0,50},{3,0,50},{3,0,50},{3,11,1},{3,11,1},{3,11,1},{3,9,1},{2,10,0},{2,10,0},{4,17,54},{4,15,36},{4,13,54},{4,12,38},{4,15,52},{4,14,24},{4,12,3},{4,11,26},{2,15,53},{3,12,26},{5,14,22},{5,13,12},{5,12,5},{5,12,9},{8,2,51},{3,15,22},{4,12,3},{4,11,26},{12,3,51}, +{4,11,26},{4,15,36},{4,15,36},{4,15,36},{4,12,37},{4,14,8},{4,12,2},{4,12,2},{4,11,1},{3,13,9},{3,11,14},{5,12,4},{5,12,4},{5,12,4},{5,11,5},{8,0,8},{4,12,2},{4,12,2},{4,11,1},{11,3,8},{4,11,1},{9,0,18},{4,15,0},{5,12,1},{4,12,2},{9,0,18},{15,0,18},{4,12,2},{0,11,26},{15,0,18},{0,11,26},{4,0,36}, +{4,0,36},{4,0,36},{4,0,36},{4,12,1},{4,12,1},{4,12,1},{4,11,0},{3,12,0},{3,12,0},{5,19,54},{5,17,37},{5,15,54},{5,14,38},{5,17,52},{5,15,27},{5,14,3},{5,13,26},{3,17,52},{4,14,26},{6,15,24},{6,15,12},{6,14,5},{6,14,9},{10,1,51},{4,17,21},{5,14,3},{5,13,26},{17,0,51},{5,13,26},{5,17,36},{5,17,36},{5,17,36}, +{5,14,37},{5,15,10},{5,14,2},{5,14,2},{5,13,1},{4,15,12},{4,13,11},{6,14,4},{6,14,4},{6,14,4},{6,13,5},{9,2,8},{5,14,2},{5,14,2},{5,13,1},{16,0,8},{5,13,1},{10,2,18},{5,17,1},{6,14,1},{5,14,2},{10,2,18},{16,2,18},{5,14,2},{0,13,26},{16,2,18},{0,13,26},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,14,1}, +{5,14,1},{5,14,1},{5,13,0},{4,14,0},{4,14,0},{6,21,54},{6,19,37},{6,16,52},{6,16,36},{6,19,52},{6,17,21},{6,16,0},{6,15,26},{4,19,51},{5,15,36},{7,17,24},{7,17,9},{7,16,5},{7,16,13},{11,3,51},{6,17,21},{6,16,0},{6,15,26},{18,2,51},{6,15,26},{6,19,36},{6,19,36},{6,19,36},{6,16,36},{6,17,10},{6,16,0},{6,16,0}, +{6,15,1},{5,16,11},{5,15,11},{7,15,5},{7,15,5},{7,15,5},{7,15,5},{11,1,8},{6,16,0},{6,16,0},{6,15,1},{17,2,8},{6,15,1},{11,4,18},{6,19,1},{7,16,1},{6,16,0},{11,4,18},{17,4,18},{6,16,0},{0,15,26},{17,4,18},{0,15,26},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,16,0},{6,16,0},{6,16,0},{6,15,0},{5,16,2}, +{5,16,2},{7,23,70},{7,21,51},{8,18,69},{7,18,52},{7,22,52},{7,20,25},{7,18,4},{7,17,27},{5,21,53},{6,18,26},{8,20,22},{8,19,12},{8,18,5},{8,18,9},{13,2,51},{6,21,22},{7,18,3},{7,17,26},{21,2,51},{7,17,26},{7,21,51},{7,21,51},{7,21,51},{7,18,51},{7,20,9},{7,19,2},{7,19,2},{7,17,2},{6,19,9},{7,17,10},{8,18,4}, +{8,18,4},{8,18,4},{8,17,5},{13,0,8},{7,19,1},{7,19,1},{7,17,1},{20,2,8},{7,17,1},{14,0,18},{7,21,1},{8,18,1},{7,18,2},{14,0,18},{20,4,18},{7,18,2},{0,17,26},{20,4,18},{0,17,26},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,19,1},{7,19,1},{7,19,1},{7,17,1},{6,18,0},{6,18,0},{8,25,54},{8,23,36},{8,21,54}, +{8,20,38},{8,24,51},{8,22,24},{8,20,3},{8,19,26},{6,23,53},{7,20,26},{9,22,22},{9,21,12},{9,20,5},{9,20,9},{14,4,51},{7,23,22},{8,20,3},{8,19,26},{25,0,51},{8,19,26},{8,23,36},{8,23,36},{8,23,36},{8,20,37},{8,22,8},{8,20,2},{8,20,2},{8,19,1},{7,21,9},{7,19,14},{9,20,4},{9,20,4},{9,20,4},{9,19,5},{14,2,8}, +{8,20,2},{8,20,2},{8,19,1},{24,0,8},{8,19,1},{15,2,18},{8,23,0},{9,20,1},{8,20,2},{15,2,18},{25,1,18},{8,20,2},{0,19,26},{25,1,18},{0,19,26},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,20,1},{8,20,1},{8,20,1},{8,19,0},{7,20,0},{7,20,0},{9,27,54},{9,25,36},{9,23,54},{9,22,38},{9,26,51},{9,24,24},{9,22,3}, +{9,21,26},{7,25,53},{8,22,26},{10,24,22},{10,23,12},{10,22,5},{10,22,9},{16,2,51},{8,25,19},{9,22,3},{9,21,26},{27,1,51},{9,21,26},{9,25,36},{9,25,36},{9,25,36},{9,22,37},{9,24,8},{9,22,2},{9,22,2},{9,21,1},{8,23,12},{8,21,11},{10,22,4},{10,22,4},{10,22,4},{10,21,5},{16,0,8},{9,22,2},{9,22,2},{9,21,1},{26,1,8}, +{9,21,1},{17,0,18},{9,25,0},{10,22,1},{9,22,2},{17,0,18},{26,3,18},{9,22,2},{0,21,26},{26,3,18},{0,21,26},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,22,1},{9,22,1},{9,22,1},{9,21,0},{8,22,0},{8,22,0},{10,29,54},{10,27,36},{10,25,54},{10,24,38},{10,28,51},{10,26,24},{10,24,3},{10,23,26},{8,27,52},{9,24,26},{11,26,22}, +{11,25,12},{11,24,5},{11,24,9},{17,4,51},{9,27,19},{10,24,3},{10,23,26},{27,4,51},{10,23,26},{10,27,36},{10,27,36},{10,27,36},{10,24,37},{10,26,8},{10,24,2},{10,24,2},{10,23,1},{9,25,12},{9,23,11},{11,24,4},{11,24,4},{11,24,4},{11,23,5},{17,2,8},{10,24,2},{10,24,2},{10,23,1},{27,3,8},{10,23,1},{18,2,18},{10,27,0},{11,24,1}, +{10,24,2},{18,2,18},{31,0,18},{10,24,2},{0,23,26},{31,0,18},{0,23,26},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,24,1},{10,24,1},{10,24,1},{10,23,0},{9,24,0},{9,24,0},{11,31,70},{11,29,52},{11,27,70},{11,27,54},{11,30,53},{11,28,20},{11,27,5},{11,26,25},{10,28,56},{10,26,22},{12,28,22},{12,27,9},{12,26,8},{12,26,9},{19,3,51}, +{11,28,19},{11,27,4},{10,26,21},{30,4,51},{10,26,21},{11,30,50},{11,30,50},{11,30,50},{11,27,50},{11,28,11},{11,27,1},{11,27,1},{11,25,2},{10,27,11},{11,25,10},{12,26,4},{12,26,4},{12,26,4},{12,25,5},{19,1,8},{11,27,0},{11,27,0},{11,25,1},{29,4,8},{11,25,1},{20,1,18},{11,29,2},{12,26,4},{11,27,4},{20,1,18},{29,6,18},{11,27,4}, +{0,26,20},{29,6,18},{0,26,20},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,27,1},{11,27,1},{11,27,1},{11,25,2},{10,26,2},{10,26,2},{12,33,54},{12,31,37},{12,29,56},{12,29,41},{12,32,51},{12,30,22},{12,29,5},{12,28,24},{11,30,56},{11,28,22},{13,30,22},{13,29,9},{13,28,8},{13,28,9},{20,5,51},{12,30,22},{12,29,5},{11,28,21},{31,6,51}, +{11,28,21},{12,31,37},{12,31,37},{12,31,37},{12,29,37},{12,30,8},{12,29,1},{12,29,1},{12,27,0},{11,29,11},{12,27,9},{13,28,4},{13,28,4},{13,28,4},{13,27,5},{20,3,8},{12,29,1},{12,29,1},{12,27,0},{30,6,8},{12,27,0},{21,3,18},{12,31,1},{13,28,4},{13,28,5},{21,3,18},{30,8,18},{13,28,5},{0,28,20},{30,8,18},{0,28,20},{12,0,36}, +{12,0,36},{12,0,36},{12,0,36},{12,29,0},{12,29,0},{12,29,0},{12,27,0},{11,28,2},{11,28,2},{13,35,54},{13,33,36},{13,31,56},{13,31,41},{13,34,51},{13,32,24},{13,31,5},{13,30,24},{11,33,53},{12,30,21},{14,32,22},{14,31,9},{14,30,8},{14,30,9},{23,0,51},{12,33,19},{13,31,5},{12,30,21},{31,9,51},{12,30,21},{13,33,36},{13,33,36},{13,33,36}, +{13,31,37},{13,32,8},{13,31,1},{13,31,1},{13,29,0},{12,31,9},{13,29,9},{14,30,4},{14,30,4},{14,30,4},{14,29,5},{21,5,8},{13,31,1},{13,31,1},{13,29,0},{31,8,8},{13,29,0},{22,5,18},{13,33,0},{14,30,4},{14,30,5},{22,5,18},{31,10,18},{14,30,5},{0,30,20},{31,10,18},{0,30,20},{13,0,36},{13,0,36},{13,0,36},{13,0,36},{13,31,0}, +{13,31,0},{13,31,0},{13,29,0},{12,30,1},{12,30,1},{14,37,54},{14,35,36},{14,33,54},{14,32,38},{14,36,51},{14,34,24},{14,32,3},{14,32,35},{12,35,52},{13,32,26},{15,34,22},{15,33,12},{15,32,5},{15,32,9},{24,2,51},{13,35,19},{14,32,3},{13,32,26},{27,17,51},{13,32,26},{14,35,36},{14,35,36},{14,35,36},{14,32,37},{14,34,8},{14,32,2},{14,32,2}, +{14,31,0},{13,33,12},{14,31,9},{15,32,4},{15,32,4},{15,32,4},{15,31,5},{24,0,8},{14,32,2},{14,32,2},{14,31,0},{31,11,8},{14,31,0},{25,0,18},{14,35,0},{15,32,1},{14,32,2},{25,0,18},{31,13,18},{14,32,2},{0,32,26},{31,13,18},{0,32,26},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,32,1},{14,32,1},{14,32,1},{14,31,0},{13,32,0}, +{13,32,0},{15,40,68},{15,37,52},{15,35,70},{15,35,54},{15,38,53},{15,36,20},{15,35,5},{15,34,25},{14,36,56},{14,34,22},{16,36,22},{16,35,9},{16,34,8},{16,34,9},{26,1,51},{15,36,19},{15,35,4},{14,34,21},{30,17,51},{14,34,21},{15,38,50},{15,38,50},{15,38,50},{15,35,50},{15,36,11},{15,35,1},{15,35,1},{15,33,2},{14,35,11},{15,33,10},{16,34,4}, +{16,34,4},{16,34,4},{16,33,5},{24,6,8},{15,35,0},{15,35,0},{15,33,1},{29,17,8},{15,33,1},{25,6,18},{15,37,2},{16,34,4},{15,35,4},{25,6,18},{29,19,18},{15,35,4},{0,34,20},{29,19,18},{0,34,20},{15,0,50},{15,0,50},{15,0,50},{15,0,50},{15,35,1},{15,35,1},{15,35,1},{15,33,2},{14,34,2},{14,34,2},{16,41,56},{16,39,37},{16,37,56}, +{16,37,41},{16,40,51},{16,38,22},{16,37,5},{16,36,24},{15,38,56},{15,36,22},{17,38,22},{17,37,9},{17,36,8},{17,36,9},{27,3,51},{16,38,22},{16,37,5},{15,36,21},{31,19,51},{15,36,21},{16,39,37},{16,39,37},{16,39,37},{16,37,37},{16,38,8},{16,37,1},{16,37,1},{16,35,0},{15,37,11},{16,35,9},{17,36,4},{17,36,4},{17,36,4},{17,35,5},{27,1,8}, +{16,37,1},{16,37,1},{16,35,0},{30,19,8},{16,35,0},{28,1,18},{16,39,1},{17,36,4},{17,36,5},{28,1,18},{30,21,18},{17,36,5},{0,36,20},{30,21,18},{0,36,20},{16,0,36},{16,0,36},{16,0,36},{16,0,36},{16,37,0},{16,37,0},{16,37,0},{16,35,0},{15,36,2},{15,36,2},{17,43,56},{17,41,37},{17,39,56},{17,39,41},{17,42,51},{17,40,22},{17,39,5}, +{17,38,24},{15,42,56},{16,38,21},{18,40,22},{18,39,9},{18,38,8},{18,38,9},{28,5,51},{17,40,22},{17,39,5},{16,38,21},{31,22,51},{16,38,21},{17,41,37},{17,41,37},{17,41,37},{17,39,37},{17,40,8},{17,39,1},{17,39,1},{17,37,0},{16,39,9},{17,37,9},{18,38,4},{18,38,4},{18,38,4},{18,37,5},{28,3,8},{17,39,1},{17,39,1},{17,37,0},{31,21,8}, +{17,37,0},{29,3,18},{17,41,1},{18,38,4},{18,38,5},{29,3,18},{31,23,18},{18,38,5},{0,38,20},{31,23,18},{0,38,20},{17,0,36},{17,0,36},{17,0,36},{17,0,36},{17,39,0},{17,39,0},{17,39,0},{17,37,0},{16,38,1},{16,38,1},{18,45,56},{18,43,37},{18,41,56},{18,41,41},{18,44,51},{18,42,22},{18,41,5},{18,40,24},{16,43,53},{17,40,21},{19,42,22}, +{19,41,9},{19,40,8},{19,40,9},{31,0,51},{18,42,22},{18,41,5},{17,40,21},{28,29,51},{17,40,21},{18,43,37},{18,43,37},{18,43,37},{18,41,37},{18,42,8},{18,41,1},{18,41,1},{18,39,0},{17,41,9},{18,39,9},{19,40,4},{19,40,4},{19,40,4},{19,39,5},{29,5,8},{18,41,1},{18,41,1},{18,39,0},{31,24,8},{18,39,0},{30,5,18},{18,43,1},{19,40,4}, +{19,40,5},{30,5,18},{31,26,18},{19,40,5},{0,40,20},{31,26,18},{0,40,20},{18,0,36},{18,0,36},{18,0,36},{18,0,36},{18,41,0},{18,41,0},{18,41,0},{18,39,0},{17,40,1},{17,40,1},{19,48,68},{19,46,51},{20,43,70},{19,43,51},{19,47,52},{19,44,22},{19,43,3},{19,42,20},{17,46,51},{18,42,23},{20,44,24},{20,44,8},{20,43,6},{20,42,14},{31,6,51}, +{19,44,21},{19,43,2},{19,42,19},{31,29,51},{19,42,19},{19,46,50},{19,46,50},{19,46,50},{19,43,50},{19,45,9},{19,43,2},{19,43,2},{19,41,3},{18,43,10},{19,41,6},{20,42,5},{20,42,5},{20,42,5},{20,42,5},{31,4,8},{19,43,1},{19,43,1},{19,41,2},{30,29,8},{19,41,2},{30,11,18},{19,46,1},{20,43,2},{19,43,1},{30,11,18},{30,31,18},{19,43,1}, +{0,42,18},{30,31,18},{0,42,18},{19,0,50},{19,0,50},{19,0,50},{19,0,50},{19,43,2},{19,43,2},{19,43,2},{19,41,2},{18,43,1},{18,43,1},{20,49,56},{20,47,38},{20,45,53},{20,45,37},{20,48,51},{20,46,19},{20,45,1},{20,44,22},{18,48,56},{19,44,23},{21,46,24},{21,46,8},{21,45,6},{21,44,14},{30,15,51},{20,46,19},{20,45,1},{19,44,22},{31,32,51}, +{19,44,22},{20,47,37},{20,47,37},{20,47,37},{20,45,36},{20,46,10},{20,45,0},{20,45,0},{20,43,2},{19,45,10},{20,43,11},{21,44,5},{21,44,5},{21,44,5},{21,44,5},{30,13,8},{20,45,0},{20,45,0},{20,43,2},{31,31,8},{20,43,2},{31,13,18},{20,47,2},{21,45,2},{20,45,1},{31,13,18},{30,34,18},{20,45,1},{0,44,18},{30,34,18},{0,44,18},{20,0,36}, +{20,0,36},{20,0,36},{20,0,36},{20,45,0},{20,45,0},{20,45,0},{20,43,1},{19,45,1},{19,45,1},{21,51,56},{21,49,37},{21,47,53},{21,47,37},{21,50,51},{21,48,22},{21,47,1},{21,46,22},{19,50,56},{20,46,20},{22,48,22},{22,48,13},{22,47,6},{22,46,14},{30,20,51},{21,48,22},{21,47,1},{20,46,19},{31,35,51},{20,46,19},{21,49,37},{21,49,37},{21,49,37}, +{21,47,36},{21,48,8},{21,47,0},{21,47,0},{21,45,2},{20,47,11},{21,45,11},{22,46,5},{22,46,5},{22,46,5},{22,46,5},{31,15,8},{21,47,0},{21,47,0},{21,45,2},{31,34,8},{21,45,2},{31,18,18},{21,49,1},{22,47,2},{21,47,1},{31,18,18},{31,36,18},{21,47,1},{0,46,18},{31,36,18},{0,46,18},{21,0,36},{21,0,36},{21,0,36},{21,0,36},{21,47,0}, +{21,47,0},{21,47,0},{21,45,1},{20,46,2},{20,46,2},{22,53,56},{22,51,37},{22,49,56},{22,49,41},{22,52,51},{22,50,22},{22,49,5},{22,48,24},{20,51,53},{21,48,21},{23,50,22},{23,49,9},{23,48,8},{23,48,9},{31,22,51},{22,50,22},{22,49,5},{21,48,21},{28,42,51},{21,48,21},{22,51,37},{22,51,37},{22,51,37},{22,49,37},{22,50,8},{22,49,1},{22,49,1}, +{22,47,2},{21,49,9},{22,47,11},{23,48,4},{23,48,4},{23,48,4},{23,48,5},{31,20,8},{22,49,1},{22,49,1},{22,47,2},{31,37,8},{22,47,2},{31,23,18},{22,51,1},{23,48,4},{23,48,5},{31,23,18},{31,39,18},{23,48,5},{0,48,20},{31,39,18},{0,48,20},{22,0,36},{22,0,36},{22,0,36},{22,0,36},{22,49,0},{22,49,0},{22,49,0},{22,47,1},{21,48,1}, +{21,48,1},{23,56,68},{23,54,51},{24,51,70},{23,51,51},{23,55,52},{23,52,22},{23,51,3},{23,50,20},{21,54,51},{22,50,23},{24,52,24},{24,52,8},{24,51,6},{24,50,14},{31,28,51},{23,52,21},{23,51,2},{23,50,19},{31,42,51},{23,50,19},{23,54,50},{23,54,50},{23,54,50},{23,51,50},{23,53,9},{23,51,2},{23,51,2},{23,49,3},{22,51,10},{23,49,6},{24,50,5}, +{24,50,5},{24,50,5},{24,50,5},{31,26,8},{23,51,1},{23,51,1},{23,49,2},{30,42,8},{23,49,2},{31,29,18},{23,54,1},{24,51,2},{23,51,1},{31,29,18},{30,44,18},{23,51,1},{0,50,18},{30,44,18},{0,50,18},{23,0,50},{23,0,50},{23,0,50},{23,0,50},{23,51,2},{23,51,2},{23,51,2},{23,49,2},{22,51,1},{22,51,1},{24,58,54},{24,55,38},{24,53,53}, +{24,53,37},{24,56,52},{24,54,19},{24,53,1},{24,52,22},{22,56,51},{23,52,23},{25,54,24},{25,54,8},{25,53,6},{25,52,14},{31,33,51},{24,54,19},{24,53,1},{23,52,22},{31,45,51},{23,52,22},{24,56,36},{24,56,36},{24,56,36},{24,53,36},{24,54,10},{24,53,0},{24,53,0},{24,51,2},{23,53,10},{24,51,11},{25,52,5},{25,52,5},{25,52,5},{25,52,5},{31,31,8}, +{24,53,0},{24,53,0},{24,51,2},{31,44,8},{24,51,2},{31,34,18},{24,55,2},{25,53,2},{24,53,1},{31,34,18},{31,46,18},{24,53,1},{0,52,18},{31,46,18},{0,52,18},{24,0,36},{24,0,36},{24,0,36},{24,0,36},{24,53,0},{24,53,0},{24,53,0},{24,51,1},{23,53,1},{23,53,1},{25,60,54},{25,57,38},{25,55,53},{25,55,37},{25,58,52},{25,56,19},{25,55,1}, +{25,54,22},{23,58,51},{24,54,20},{26,56,24},{26,56,8},{26,55,6},{26,54,14},{31,38,51},{25,56,19},{25,55,1},{24,54,19},{31,48,51},{24,54,19},{25,58,36},{25,58,36},{25,58,36},{25,55,36},{25,56,10},{25,55,0},{25,55,0},{25,53,2},{24,55,11},{25,53,11},{26,54,5},{26,54,5},{26,54,5},{26,54,5},{31,36,8},{25,55,0},{25,55,0},{25,53,2},{31,47,8}, +{25,53,2},{30,43,18},{25,57,2},{26,55,2},{25,55,1},{30,43,18},{30,50,18},{25,55,1},{0,54,18},{30,50,18},{0,54,18},{25,0,36},{25,0,36},{25,0,36},{25,0,36},{25,55,0},{25,55,0},{25,55,0},{25,53,1},{24,54,2},{24,54,2},{26,62,54},{26,59,38},{26,57,53},{26,57,37},{26,60,52},{26,58,19},{26,57,1},{26,56,22},{25,58,56},{25,56,20},{27,58,24}, +{27,58,8},{27,57,6},{27,56,14},{30,47,51},{26,58,19},{26,57,1},{25,56,19},{31,51,51},{25,56,19},{26,60,36},{26,60,36},{26,60,36},{26,57,36},{26,58,10},{26,57,0},{26,57,0},{26,55,2},{25,57,11},{26,55,11},{27,56,5},{27,56,5},{27,56,5},{27,56,5},{30,45,8},{26,57,0},{26,57,0},{26,55,2},{31,50,8},{26,55,2},{31,45,18},{26,59,2},{27,57,2}, +{26,57,1},{31,45,18},{31,52,18},{26,57,1},{0,56,18},{31,52,18},{0,56,18},{26,0,36},{26,0,36},{26,0,36},{26,0,36},{26,57,0},{26,57,0},{26,57,0},{26,55,1},{25,56,2},{25,56,2},{27,63,76},{27,62,52},{28,59,69},{27,59,51},{27,63,52},{27,60,21},{27,59,3},{27,58,22},{25,62,52},{26,58,28},{28,60,24},{28,60,9},{28,59,5},{28,59,13},{31,49,51}, +{27,60,20},{27,59,2},{27,58,21},{30,56,51},{27,58,21},{27,62,51},{27,62,51},{27,62,51},{27,59,51},{27,61,9},{27,59,3},{27,59,3},{27,58,6},{26,60,11},{27,57,12},{28,58,5},{28,58,5},{28,58,5},{28,58,4},{29,54,8},{27,59,2},{27,59,2},{27,58,5},{29,56,8},{27,58,5},{30,54,18},{27,62,2},{28,59,1},{27,59,1},{30,54,18},{29,58,18},{27,59,1}, +{0,58,20},{29,58,18},{0,58,20},{27,0,50},{27,0,50},{27,0,50},{27,0,50},{27,60,1},{27,60,1},{27,60,1},{27,58,2},{26,59,0},{26,59,0},{28,63,86},{28,63,38},{28,61,52},{28,61,36},{28,63,59},{28,62,21},{28,61,0},{28,60,21},{27,62,60},{27,60,28},{29,62,24},{29,62,9},{29,61,5},{29,61,13},{30,58,51},{28,62,21},{28,61,0},{28,60,21},{31,58,51}, +{28,60,21},{28,63,37},{28,63,37},{28,63,37},{28,61,36},{28,62,10},{28,61,0},{28,61,0},{28,59,5},{27,62,11},{27,60,12},{29,60,5},{29,60,5},{29,60,5},{29,60,4},{30,56,8},{28,61,0},{28,61,0},{28,59,5},{30,58,8},{28,59,5},{31,56,18},{28,63,2},{29,61,1},{28,61,0},{31,56,18},{30,60,18},{28,61,0},{0,60,20},{30,60,18},{0,60,20},{28,0,36}, +{28,0,36},{28,0,36},{28,0,36},{28,61,0},{28,61,0},{28,61,0},{28,59,1},{27,61,0},{27,61,0},{30,63,94},{30,63,78},{29,63,52},{29,63,36},{30,63,115},{29,63,36},{29,63,0},{29,62,21},{29,63,88},{28,62,25},{30,63,30},{30,63,14},{30,63,5},{30,63,13},{31,60,51},{29,63,36},{29,63,0},{29,62,21},{31,61,51},{29,62,21},{29,63,52},{29,63,52},{29,63,52}, +{29,63,36},{29,63,16},{29,63,0},{29,63,0},{29,61,5},{28,63,11},{28,62,9},{30,62,5},{30,62,5},{30,62,5},{30,62,4},{31,58,8},{29,63,0},{29,63,0},{29,61,5},{31,60,8},{29,61,5},{31,61,18},{30,63,10},{30,63,1},{29,63,0},{31,61,18},{31,62,18},{29,63,0},{0,62,20},{31,62,18},{0,62,20},{29,0,36},{29,0,36},{29,0,36},{29,0,36},{29,63,0}, +{29,63,0},{29,63,0},{29,61,1},{28,63,2},{28,63,2},{31,63,68},{31,63,68},{30,63,61},{30,63,45},{30,63,59},{30,63,27},{30,63,18},{30,63,1},{30,63,28},{30,63,10},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{30,63,1},{31,63,4},{30,63,1},{30,63,61},{30,63,61},{30,63,61},{30,63,45},{30,63,34},{30,63,18},{30,63,18}, +{30,63,1},{30,63,19},{30,63,10},{31,63,4},{31,63,4},{31,63,4},{31,63,4},{31,62,4},{31,63,4},{31,63,4},{30,63,1},{31,63,4},{30,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{30,0,36},{30,0,36},{30,0,36},{30,0,36},{30,63,9},{30,63,9},{30,63,9},{30,63,1},{30,63,10}, +{30,63,10},{0,7,74},{0,6,20},{0,4,2},{0,4,26},{0,5,153},{0,4,110},{0,3,45},{0,2,115},{0,3,169},{0,2,124},{0,7,74},{0,6,20},{0,4,2},{0,4,26},{0,5,153},{0,4,110},{0,3,45},{0,2,115},{0,3,153},{0,2,115},{0,3,1},{0,3,1},{0,3,1},{0,2,0},{0,2,13},{0,2,9},{0,2,9},{0,1,5},{0,1,14},{0,1,6},{0,3,1}, +{0,3,1},{0,3,1},{0,2,0},{0,2,13},{0,2,9},{0,2,9},{0,1,5},{1,0,13},{0,1,5},{2,1,72},{0,6,20},{0,4,2},{0,4,26},{2,1,72},{3,1,72},{0,4,26},{0,3,74},{3,1,72},{0,3,74},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,13,81},{0,10,13},{0,6,26}, +{0,6,14},{0,9,244},{0,7,129},{0,6,41},{0,4,139},{0,5,300},{0,4,175},{0,13,81},{0,10,13},{0,6,26},{0,6,14},{2,3,243},{0,7,129},{0,6,41},{0,4,139},{4,1,243},{0,4,139},{0,9,9},{0,9,9},{0,9,9},{0,5,10},{0,5,52},{0,5,17},{0,5,17},{0,3,17},{0,3,68},{0,3,33},{0,9,9},{0,9,9},{0,9,9},{0,5,10},{1,2,50}, +{0,5,17},{0,5,17},{0,3,17},{2,1,50},{0,3,17},{3,3,72},{0,10,4},{1,6,2},{0,6,5},{3,3,72},{4,3,72},{0,6,5},{0,5,74},{4,3,72},{0,5,74},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,2},{0,1,2},{1,15,145},{1,12,77},{1,8,90},{1,8,78},{0,15,243},{0,10,96},{0,8,3}, +{0,6,106},{0,8,395},{0,6,187},{1,15,81},{1,12,13},{1,8,26},{1,8,14},{4,1,243},{0,10,96},{0,8,3},{0,6,106},{5,3,243},{0,6,106},{1,11,73},{1,11,73},{1,11,73},{1,7,74},{0,11,50},{0,8,2},{0,8,2},{0,5,2},{0,5,131},{0,5,51},{1,11,9},{1,11,9},{1,11,9},{1,7,10},{3,1,50},{0,8,2},{0,8,2},{0,5,2},{3,3,50}, +{0,5,2},{5,1,72},{1,12,4},{2,8,2},{0,8,2},{5,1,72},{9,0,72},{0,8,2},{0,7,74},{9,0,72},{0,7,74},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,7,1},{0,7,1},{0,7,1},{0,4,1},{0,3,32},{0,3,32},{2,17,162},{2,14,94},{2,10,107},{2,10,95},{1,17,244},{1,12,97},{1,10,4},{1,8,107},{0,11,345},{0,8,116},{2,17,81}, +{2,14,13},{2,10,26},{2,10,14},{6,0,243},{0,14,76},{1,10,3},{0,9,83},{10,0,243},{0,9,83},{2,13,90},{2,13,90},{2,13,90},{2,9,91},{1,13,51},{1,10,3},{1,10,3},{1,7,3},{0,9,94},{0,7,14},{2,13,9},{2,13,9},{2,13,9},{2,9,10},{3,6,50},{1,10,2},{1,10,2},{1,7,2},{8,0,50},{1,7,2},{7,0,72},{2,14,4},{3,10,2}, +{1,10,2},{7,0,72},{10,2,72},{1,10,2},{0,9,74},{10,2,72},{0,9,74},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{1,9,2},{1,9,2},{1,9,2},{1,6,2},{0,7,13},{0,7,13},{3,19,154},{3,16,82},{3,13,100},{3,12,85},{2,19,244},{2,15,90},{2,13,5},{2,11,97},{0,15,287},{0,11,73},{3,19,90},{3,16,18},{4,12,29},{3,12,21},{6,6,243}, +{1,16,75},{2,13,5},{0,11,73},{12,1,243},{0,11,73},{3,15,81},{3,15,81},{3,15,81},{3,12,81},{2,15,52},{2,13,1},{2,13,1},{2,9,4},{0,13,61},{0,10,14},{3,15,17},{3,15,17},{3,15,17},{3,12,17},{6,2,50},{2,13,1},{2,13,1},{2,9,4},{11,0,50},{2,9,4},{8,2,72},{3,16,2},{4,12,4},{2,13,4},{8,2,72},{12,3,72},{2,13,4}, +{0,11,72},{12,3,72},{0,11,72},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{2,12,0},{2,12,0},{2,12,0},{2,9,0},{0,11,1},{0,11,1},{4,21,162},{4,18,94},{4,15,103},{4,14,95},{3,21,244},{3,17,88},{3,15,5},{3,13,97},{0,18,260},{1,13,73},{4,21,81},{4,18,13},{4,15,22},{4,14,14},{9,1,243},{2,18,75},{3,15,5},{1,13,73},{13,3,243}, +{1,13,73},{4,17,90},{4,17,90},{4,17,90},{4,14,91},{3,17,52},{3,15,1},{3,15,1},{3,11,4},{0,16,52},{1,12,14},{4,17,9},{4,17,9},{4,17,9},{4,14,10},{8,0,50},{3,15,1},{3,15,1},{3,11,4},{11,3,50},{3,11,4},{10,1,72},{3,20,2},{5,14,4},{3,15,4},{10,1,72},{17,0,72},{3,15,4},{0,13,72},{17,0,72},{0,13,72},{4,0,90}, +{4,0,90},{4,0,90},{4,0,90},{3,14,0},{3,14,0},{3,14,0},{3,11,0},{1,13,1},{1,13,1},{5,23,162},{5,20,94},{5,16,107},{5,16,95},{4,23,244},{4,18,97},{4,16,4},{4,15,98},{0,22,244},{2,15,73},{5,23,81},{5,20,13},{5,16,26},{5,16,14},{10,3,243},{3,20,75},{4,16,3},{2,15,73},{18,0,243},{2,15,73},{5,19,90},{5,19,90},{5,19,90}, +{5,15,94},{4,19,51},{4,16,3},{4,16,3},{4,13,5},{1,18,52},{2,14,14},{5,19,9},{5,19,9},{5,19,9},{5,15,13},{9,2,50},{4,16,2},{4,16,2},{4,13,4},{16,0,50},{4,13,4},{11,3,72},{5,20,4},{6,16,2},{4,16,2},{11,3,72},{18,2,72},{4,16,2},{0,15,72},{18,2,72},{0,15,72},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,15,2}, +{4,15,2},{4,15,2},{4,13,1},{2,15,1},{2,15,1},{6,25,162},{6,22,94},{6,18,107},{6,18,95},{5,25,244},{5,20,97},{5,18,4},{5,16,107},{1,24,244},{3,17,74},{6,25,81},{6,22,13},{6,18,26},{6,18,14},{12,1,243},{3,24,75},{5,18,3},{3,17,74},{19,2,243},{3,17,74},{6,21,90},{6,21,90},{6,21,90},{6,17,91},{5,21,51},{5,18,3},{5,18,3}, +{5,15,5},{2,20,52},{3,16,19},{6,21,9},{6,21,9},{6,21,9},{6,17,10},{11,1,50},{5,18,2},{5,18,2},{5,15,4},{17,2,50},{5,15,4},{13,1,72},{6,22,4},{7,18,2},{5,18,2},{13,1,72},{19,4,72},{5,18,2},{0,17,74},{19,4,72},{0,17,74},{6,0,90},{6,0,90},{6,0,90},{6,0,90},{5,17,2},{5,17,2},{5,17,2},{5,15,1},{3,17,0}, +{3,17,0},{7,27,154},{7,24,82},{7,21,100},{7,20,85},{6,27,244},{6,23,90},{6,21,5},{6,19,97},{2,26,244},{4,19,73},{7,27,90},{7,24,18},{8,20,29},{7,20,21},{13,4,243},{5,24,75},{6,21,5},{4,19,73},{22,2,243},{4,19,73},{7,23,81},{7,23,81},{7,23,81},{7,20,81},{6,23,52},{6,21,1},{6,21,1},{6,17,4},{3,23,52},{4,18,14},{7,23,17}, +{7,23,17},{7,23,17},{7,20,17},{13,0,50},{6,21,1},{6,21,1},{6,17,4},{20,2,50},{6,17,4},{14,4,72},{7,24,2},{8,20,4},{6,21,4},{14,4,72},{25,0,72},{6,21,4},{0,19,72},{25,0,72},{0,19,72},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{6,20,0},{6,20,0},{6,20,0},{6,17,0},{4,19,1},{4,19,1},{8,29,162},{8,26,92},{8,23,103}, +{8,22,95},{7,29,244},{7,25,90},{7,23,5},{7,21,97},{3,28,244},{5,21,73},{8,29,81},{8,26,11},{8,23,22},{8,22,14},{14,6,243},{6,26,75},{7,23,5},{5,21,73},{26,0,243},{5,21,73},{8,25,90},{8,25,90},{8,25,90},{8,22,91},{7,25,52},{7,23,1},{7,23,1},{7,19,4},{4,24,52},{5,20,14},{8,25,9},{8,25,9},{8,25,9},{8,22,10},{14,2,50}, +{7,23,1},{7,23,1},{7,19,4},{24,0,50},{7,19,4},{16,2,72},{8,26,2},{9,22,4},{7,23,4},{16,2,72},{27,1,72},{7,23,4},{0,21,72},{27,1,72},{0,21,72},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{7,22,0},{7,22,0},{7,22,0},{7,19,0},{5,21,1},{5,21,1},{9,31,162},{9,28,92},{9,25,103},{9,24,95},{8,31,244},{8,26,100},{8,24,9}, +{8,23,98},{4,30,244},{6,23,73},{9,31,81},{9,28,11},{9,25,22},{9,24,14},{16,4,243},{7,28,75},{8,24,8},{6,23,73},{27,2,243},{6,23,73},{9,27,90},{9,27,90},{9,27,90},{9,24,91},{8,27,51},{8,24,5},{8,24,5},{8,21,5},{5,26,52},{6,22,14},{9,27,9},{9,27,9},{9,27,9},{9,24,10},{16,0,50},{8,24,4},{8,24,4},{8,21,4},{26,1,50}, +{8,21,4},{17,4,72},{9,28,2},{10,24,4},{8,25,4},{17,4,72},{27,4,72},{8,25,4},{0,23,72},{27,4,72},{0,23,72},{9,0,90},{9,0,90},{9,0,90},{9,0,90},{8,24,1},{8,24,1},{8,24,1},{8,21,1},{6,23,1},{6,23,1},{10,33,162},{10,30,92},{10,27,103},{10,26,95},{9,33,244},{9,28,100},{9,26,9},{9,25,98},{5,32,244},{7,25,73},{10,33,81}, +{10,30,11},{10,27,22},{10,26,14},{17,6,243},{8,30,75},{9,26,8},{7,25,73},{28,4,243},{7,25,73},{10,29,90},{10,29,90},{10,29,90},{10,26,91},{9,29,51},{9,26,5},{9,26,5},{9,23,5},{6,28,52},{7,24,14},{10,29,9},{10,29,9},{10,29,9},{10,26,10},{17,2,50},{9,26,4},{9,26,4},{9,23,4},{27,3,50},{9,23,4},{18,6,72},{10,30,2},{11,26,4}, +{9,27,4},{18,6,72},{28,6,72},{9,27,4},{0,25,72},{28,6,72},{0,25,72},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,26,1},{9,26,1},{9,26,1},{9,23,1},{7,25,1},{7,25,1},{11,35,154},{11,32,82},{11,29,97},{11,29,85},{10,35,244},{10,31,96},{10,29,3},{10,27,90},{6,34,244},{8,27,78},{11,35,90},{11,32,18},{12,29,27},{11,29,21},{19,5,243}, +{9,32,75},{10,29,3},{9,27,75},{31,4,243},{9,27,75},{11,31,81},{11,31,81},{11,31,81},{11,28,80},{10,31,52},{10,29,2},{10,29,2},{10,26,5},{7,31,50},{9,26,11},{11,31,17},{11,31,17},{11,31,17},{11,28,16},{19,1,50},{10,29,2},{10,29,2},{9,26,2},{29,4,50},{9,26,2},{20,5,72},{11,32,2},{12,29,2},{10,29,2},{20,5,72},{31,6,72},{10,29,2}, +{0,27,74},{31,6,72},{0,27,74},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,28,1},{10,28,1},{10,28,1},{10,25,1},{8,28,2},{8,28,2},{12,37,162},{12,34,92},{12,31,107},{12,30,99},{11,37,244},{11,33,90},{11,31,3},{11,29,90},{7,36,244},{9,29,78},{12,37,81},{12,34,11},{12,31,26},{12,30,18},{22,0,243},{10,34,75},{11,31,3},{10,29,75},{31,7,243}, +{10,29,75},{12,33,90},{12,33,90},{12,33,90},{12,30,90},{11,33,52},{11,31,2},{11,31,2},{11,28,5},{8,32,52},{10,28,11},{12,33,9},{12,33,9},{12,33,9},{12,30,9},{20,3,50},{11,31,2},{11,31,2},{10,28,2},{30,6,50},{10,28,2},{23,0,72},{12,34,2},{13,31,2},{11,31,2},{23,0,72},{31,9,72},{11,31,2},{0,29,74},{31,9,72},{0,29,74},{12,0,90}, +{12,0,90},{12,0,90},{12,0,90},{11,30,1},{11,30,1},{11,30,1},{11,27,1},{9,30,2},{9,30,2},{13,39,162},{13,36,92},{13,33,103},{13,32,95},{12,39,244},{12,34,100},{12,32,9},{12,31,100},{8,38,244},{10,31,78},{13,39,81},{13,36,11},{13,33,22},{13,32,14},{23,2,243},{11,36,75},{12,32,8},{11,31,75},{28,14,243},{11,31,75},{13,35,90},{13,35,90},{13,35,90}, +{13,32,91},{12,35,51},{12,32,5},{12,32,5},{12,30,6},{9,34,52},{11,30,11},{13,35,9},{13,35,9},{13,35,9},{13,32,10},{21,5,50},{12,32,4},{12,32,4},{11,30,2},{31,8,50},{11,30,2},{24,2,72},{13,36,2},{14,32,4},{12,33,4},{24,2,72},{27,17,72},{12,33,4},{0,31,74},{27,17,72},{0,31,74},{13,0,90},{13,0,90},{13,0,90},{13,0,90},{12,32,1}, +{12,32,1},{12,32,1},{12,29,1},{10,31,4},{10,31,4},{14,41,162},{14,38,92},{14,35,103},{14,34,95},{13,41,244},{13,36,100},{13,34,9},{13,33,98},{9,40,244},{11,33,73},{14,41,81},{14,38,11},{14,35,22},{14,34,14},{24,4,243},{12,38,75},{13,34,8},{11,33,73},{28,17,243},{11,33,73},{14,37,90},{14,37,90},{14,37,90},{14,34,91},{13,37,51},{13,34,5},{13,34,5}, +{13,31,10},{10,36,52},{11,32,14},{14,37,9},{14,37,9},{14,37,9},{14,34,10},{24,0,50},{13,34,4},{13,34,4},{12,32,4},{31,11,50},{12,32,4},{25,4,72},{14,38,2},{15,34,4},{13,35,4},{25,4,72},{28,19,72},{13,35,4},{0,33,72},{28,19,72},{0,33,72},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{13,34,1},{13,34,1},{13,34,1},{13,31,1},{11,33,1}, +{11,33,1},{15,44,152},{15,40,84},{15,37,97},{15,37,85},{14,44,243},{14,39,96},{14,37,3},{14,35,90},{10,42,244},{12,35,78},{15,44,88},{15,40,20},{16,37,27},{15,37,21},{27,0,243},{13,41,76},{14,37,3},{13,35,75},{31,17,243},{13,35,75},{15,40,80},{15,40,80},{15,40,80},{15,36,80},{14,40,50},{14,37,2},{14,37,2},{14,34,5},{11,39,50},{13,34,11},{15,40,16}, +{15,40,16},{15,40,16},{15,36,16},{24,6,50},{14,37,2},{14,37,2},{13,34,2},{29,17,50},{13,34,2},{27,3,72},{15,40,4},{16,37,2},{14,37,2},{27,3,72},{31,19,72},{14,37,2},{0,35,74},{31,19,72},{0,35,74},{15,0,80},{15,0,80},{15,0,80},{15,0,80},{14,36,1},{14,36,1},{14,36,1},{14,33,1},{12,36,2},{12,36,2},{16,45,164},{16,42,95},{16,39,107}, +{16,38,99},{15,46,243},{15,41,96},{15,39,3},{15,37,90},{11,44,244},{13,37,78},{16,45,83},{16,42,14},{16,39,26},{16,38,18},{27,5,243},{14,43,76},{15,39,3},{14,37,75},{31,20,243},{14,37,75},{16,41,91},{16,41,91},{16,41,91},{16,38,90},{15,42,50},{15,39,2},{15,39,2},{15,36,5},{12,41,51},{14,36,11},{16,41,10},{16,41,10},{16,41,10},{16,38,9},{27,1,50}, +{15,39,2},{15,39,2},{14,36,2},{30,19,50},{14,36,2},{28,5,72},{15,44,4},{17,39,2},{15,39,2},{28,5,72},{31,22,72},{15,39,2},{0,37,74},{31,22,72},{0,37,74},{16,0,90},{16,0,90},{16,0,90},{16,0,90},{15,38,1},{15,38,1},{15,38,1},{15,35,1},{13,38,2},{13,38,2},{17,47,164},{17,44,95},{17,41,107},{17,40,99},{16,47,245},{16,43,91},{16,41,3}, +{16,39,100},{12,46,244},{14,39,78},{17,47,83},{17,44,14},{17,41,26},{17,40,18},{30,0,243},{15,45,76},{16,41,2},{15,39,75},{28,27,243},{15,39,75},{17,43,91},{17,43,91},{17,43,91},{17,40,90},{16,43,53},{16,41,2},{16,41,2},{16,38,6},{13,43,51},{15,38,11},{17,43,10},{17,43,10},{17,43,10},{17,40,9},{28,3,50},{16,41,1},{16,41,1},{15,38,2},{31,21,50}, +{15,38,2},{31,0,72},{16,46,1},{18,41,2},{16,41,1},{31,0,72},{28,29,72},{16,41,1},{0,39,74},{28,29,72},{0,39,74},{17,0,90},{17,0,90},{17,0,90},{17,0,90},{16,40,1},{16,40,1},{16,40,1},{16,37,1},{14,40,2},{14,40,2},{18,49,162},{18,46,95},{18,43,107},{18,42,99},{17,49,244},{17,45,91},{17,43,3},{17,41,100},{13,48,244},{15,41,78},{18,49,81}, +{18,46,14},{18,43,26},{18,42,18},{31,2,243},{15,48,75},{17,43,2},{15,41,78},{29,29,243},{15,41,78},{18,45,91},{18,45,91},{18,45,91},{18,42,90},{17,45,53},{17,43,2},{17,43,2},{17,40,6},{14,45,51},{16,40,18},{18,45,10},{18,45,10},{18,45,10},{18,42,9},{29,5,50},{17,43,1},{17,43,1},{16,40,2},{31,24,50},{16,40,2},{30,9,72},{17,48,2},{19,43,2}, +{17,43,1},{30,9,72},{29,31,72},{17,43,1},{0,41,74},{29,31,72},{0,41,74},{18,0,90},{18,0,90},{18,0,90},{18,0,90},{17,42,1},{17,42,1},{17,42,1},{17,39,1},{15,42,2},{15,42,2},{19,52,152},{19,48,84},{19,45,105},{19,45,84},{18,52,243},{18,47,89},{18,45,1},{18,43,96},{14,50,244},{16,44,81},{19,52,88},{19,48,20},{20,45,26},{19,45,20},{31,8,243}, +{17,49,76},{18,45,1},{16,44,80},{31,30,243},{16,44,80},{19,48,80},{19,48,80},{19,48,80},{19,44,81},{18,48,50},{18,45,1},{18,45,1},{18,42,1},{15,47,52},{17,42,13},{19,48,16},{19,48,16},{19,48,16},{19,44,17},{31,4,50},{18,45,1},{18,45,1},{18,42,1},{30,29,50},{18,42,1},{30,15,72},{19,48,4},{20,45,1},{18,45,1},{30,15,72},{31,32,72},{18,45,1}, +{0,43,80},{31,32,72},{0,43,80},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,45,0},{18,45,0},{18,45,0},{18,41,1},{16,44,1},{16,44,1},{20,53,164},{20,50,95},{20,47,106},{20,47,94},{19,54,243},{19,49,96},{19,47,1},{19,45,96},{15,52,244},{17,46,81},{20,53,83},{20,50,14},{20,47,25},{20,47,13},{29,20,243},{18,51,76},{19,47,1},{17,46,80},{31,33,243}, +{17,46,80},{20,49,91},{20,49,91},{20,49,91},{20,46,90},{19,50,50},{19,47,1},{19,47,1},{19,44,1},{16,49,51},{18,44,13},{20,49,10},{20,49,10},{20,49,10},{20,46,9},{30,13,50},{19,47,1},{19,47,1},{19,44,1},{31,31,50},{19,44,1},{30,20,72},{19,52,4},{21,47,1},{19,47,1},{30,20,72},{31,35,72},{19,47,1},{0,45,80},{31,35,72},{0,45,80},{20,0,90}, +{20,0,90},{20,0,90},{20,0,90},{19,47,0},{19,47,0},{19,47,0},{19,43,1},{17,46,1},{17,46,1},{21,55,164},{21,52,95},{21,49,107},{21,48,99},{20,55,245},{20,51,91},{20,49,3},{20,47,97},{16,54,244},{18,47,85},{21,55,83},{21,52,14},{21,49,26},{21,48,18},{30,22,243},{19,53,76},{20,49,2},{19,47,81},{28,40,243},{19,47,81},{21,51,91},{21,51,91},{21,51,91}, +{21,48,90},{20,51,53},{20,49,2},{20,49,2},{20,46,5},{17,51,51},{19,46,13},{21,51,10},{21,51,10},{21,51,10},{21,48,9},{31,15,50},{20,49,1},{20,49,1},{19,46,4},{31,34,50},{19,46,4},{31,22,72},{20,54,1},{22,49,2},{20,49,1},{31,22,72},{28,42,72},{20,49,1},{0,47,80},{28,42,72},{0,47,80},{21,0,90},{21,0,90},{21,0,90},{21,0,90},{20,48,1}, +{20,48,1},{20,48,1},{20,45,2},{18,48,2},{18,48,2},{22,57,164},{22,54,95},{22,51,107},{22,50,99},{21,57,245},{21,53,91},{21,51,3},{21,49,100},{17,56,244},{19,49,78},{22,57,83},{22,54,14},{22,51,26},{22,50,18},{31,24,243},{19,56,76},{21,51,2},{19,49,78},{29,42,243},{19,49,78},{22,53,91},{22,53,91},{22,53,91},{22,50,90},{21,53,53},{21,51,2},{21,51,2}, +{21,48,6},{18,53,51},{20,48,18},{22,53,10},{22,53,10},{22,53,10},{22,50,9},{31,20,50},{21,51,1},{21,51,1},{20,48,2},{31,37,50},{20,48,2},{31,27,72},{21,56,1},{23,51,2},{21,51,1},{31,27,72},{29,44,72},{21,51,1},{0,49,74},{29,44,72},{0,49,74},{22,0,90},{22,0,90},{22,0,90},{22,0,90},{21,50,1},{21,50,1},{21,50,1},{21,47,2},{19,50,2}, +{19,50,2},{23,60,152},{23,57,81},{23,53,105},{23,53,84},{22,60,243},{22,55,89},{22,53,1},{22,51,96},{18,59,244},{20,52,81},{23,60,88},{23,57,17},{24,53,26},{23,53,20},{31,30,243},{21,57,73},{22,53,1},{20,52,80},{31,43,243},{20,52,80},{23,56,80},{23,56,80},{23,56,80},{23,52,81},{22,56,50},{22,53,1},{22,53,1},{22,50,1},{19,55,52},{21,50,13},{23,56,16}, +{23,56,16},{23,56,16},{23,52,17},{31,26,50},{22,53,1},{22,53,1},{22,50,1},{30,42,50},{22,50,1},{31,33,72},{23,57,1},{24,53,1},{22,53,1},{31,33,72},{31,45,72},{22,53,1},{0,51,80},{31,45,72},{0,51,80},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{22,53,0},{22,53,0},{22,53,0},{22,49,1},{20,52,1},{20,52,1},{24,62,162},{24,58,94},{24,55,106}, +{24,55,94},{23,62,243},{23,57,89},{23,55,1},{23,53,96},{19,61,244},{21,54,81},{24,62,81},{24,58,13},{24,55,25},{24,55,13},{31,35,243},{22,59,73},{23,55,1},{21,54,80},{27,51,243},{21,54,80},{24,58,90},{24,58,90},{24,58,90},{24,54,90},{23,58,50},{23,55,1},{23,55,1},{23,52,1},{20,57,50},{22,52,13},{24,58,9},{24,58,9},{24,58,9},{24,54,9},{31,31,50}, +{23,55,1},{23,55,1},{23,52,1},{31,44,50},{23,52,1},{31,38,72},{24,58,4},{25,55,1},{23,55,1},{31,38,72},{31,48,72},{23,55,1},{0,53,80},{31,48,72},{0,53,80},{24,0,90},{24,0,90},{24,0,90},{24,0,90},{23,55,0},{23,55,0},{23,55,0},{23,51,1},{21,54,1},{21,54,1},{25,63,164},{25,60,94},{25,57,106},{25,57,94},{24,63,245},{24,59,97},{24,57,3}, +{24,55,97},{20,63,249},{22,56,81},{25,63,83},{25,60,13},{25,57,25},{25,57,13},{31,40,243},{23,61,73},{24,57,2},{22,56,80},{31,49,243},{22,56,80},{25,60,90},{25,60,90},{25,60,90},{25,56,90},{24,60,51},{24,57,3},{24,57,3},{24,54,5},{21,59,50},{23,54,13},{25,60,9},{25,60,9},{25,60,9},{25,56,9},{31,36,50},{24,57,2},{24,57,2},{23,54,4},{31,47,50}, +{23,54,4},{30,47,72},{25,60,4},{26,57,1},{24,57,1},{30,47,72},{31,51,72},{24,57,1},{0,55,80},{31,51,72},{0,55,80},{25,0,90},{25,0,90},{25,0,90},{25,0,90},{24,56,2},{24,56,2},{24,56,2},{24,53,2},{22,56,1},{22,56,1},{26,63,194},{26,62,94},{26,59,106},{26,59,94},{25,63,284},{25,61,97},{25,59,3},{25,57,97},{22,63,253},{23,58,81},{27,62,99}, +{26,62,13},{26,59,25},{26,59,13},{29,52,243},{24,63,76},{25,59,2},{23,58,80},{28,56,243},{23,58,80},{26,62,90},{26,62,90},{26,62,90},{26,58,90},{25,62,51},{25,59,3},{25,59,3},{25,56,5},{22,61,50},{24,56,10},{26,62,9},{26,62,9},{26,62,9},{26,58,9},{30,45,50},{25,59,2},{25,59,2},{24,56,1},{31,50,50},{24,56,1},{30,52,72},{26,62,4},{27,59,1}, +{25,59,1},{30,52,72},{28,58,72},{25,59,1},{0,57,80},{28,58,72},{0,57,80},{26,0,90},{26,0,90},{26,0,90},{26,0,90},{25,58,2},{25,58,2},{25,58,2},{25,55,2},{23,58,1},{23,58,1},{27,63,280},{27,63,120},{27,62,105},{27,61,82},{27,63,328},{26,63,99},{26,61,5},{26,59,99},{24,63,308},{24,60,74},{28,63,105},{28,63,45},{28,61,27},{27,61,18},{31,51,243}, +{26,63,99},{26,61,5},{24,60,74},{31,56,243},{24,60,74},{27,63,84},{27,63,84},{27,63,84},{27,60,81},{26,63,58},{26,62,2},{26,62,2},{26,58,2},{23,63,53},{25,58,9},{27,63,20},{27,63,20},{27,63,20},{27,60,17},{29,54,50},{26,62,2},{26,62,2},{26,58,2},{29,56,50},{26,58,2},{30,58,72},{28,63,20},{28,61,2},{27,61,2},{30,58,72},{31,58,72},{27,61,2}, +{0,60,74},{31,58,72},{0,60,74},{27,0,80},{27,0,80},{27,0,80},{27,0,80},{26,61,0},{26,61,0},{26,61,0},{26,58,1},{24,60,0},{24,60,0},{28,63,331},{28,63,187},{28,63,106},{28,63,94},{28,63,358},{27,63,173},{27,63,4},{27,61,82},{26,63,355},{25,62,65},{29,63,126},{29,63,62},{28,63,25},{28,63,13},{31,56,221},{28,63,121},{27,63,4},{25,62,65},{30,60,221}, +{25,62,65},{28,63,106},{28,63,106},{28,63,106},{28,62,91},{27,63,100},{27,63,4},{27,63,4},{27,60,2},{25,63,72},{26,60,9},{28,63,25},{28,63,25},{28,63,25},{28,62,10},{30,56,50},{27,63,4},{27,63,4},{27,60,2},{30,58,50},{27,60,2},{31,59,61},{29,63,37},{29,63,1},{27,63,4},{31,59,61},{31,61,61},{27,63,4},{0,62,65},{31,61,61},{0,62,65},{28,0,90}, +{28,0,90},{28,0,90},{28,0,90},{27,63,0},{27,63,0},{27,63,0},{27,60,1},{25,62,0},{25,62,0},{29,63,239},{29,63,175},{29,63,139},{29,63,99},{29,63,239},{28,63,122},{28,63,41},{28,62,19},{28,63,233},{26,63,19},{30,63,54},{30,63,38},{30,63,29},{29,63,18},{31,60,93},{29,63,54},{29,63,18},{27,63,9},{31,61,93},{27,63,9},{29,63,139},{29,63,139},{29,63,139}, +{29,63,99},{29,63,139},{28,63,41},{28,63,41},{28,62,3},{27,63,116},{27,62,9},{30,63,29},{30,63,29},{30,63,29},{29,63,18},{31,58,50},{29,63,18},{29,63,18},{28,62,2},{31,60,50},{28,62,2},{31,62,5},{31,63,9},{30,63,4},{30,63,0},{31,62,5},{31,62,9},{30,63,0},{0,63,9},{31,62,9},{0,63,9},{29,0,90},{29,0,90},{29,0,90},{29,0,90},{28,63,5}, +{28,63,5},{28,63,5},{28,61,2},{27,62,8},{27,62,8},{30,63,140},{30,63,124},{30,63,115},{30,63,99},{30,63,131},{29,63,98},{29,63,62},{29,63,2},{29,63,122},{28,63,20},{31,63,25},{31,63,25},{31,63,25},{30,63,18},{31,62,17},{30,63,18},{30,63,9},{29,63,1},{31,62,22},{29,63,1},{30,63,115},{30,63,115},{30,63,115},{30,63,99},{30,63,106},{29,63,62},{29,63,62}, +{29,63,2},{29,63,86},{28,63,20},{31,63,25},{31,63,25},{31,63,25},{30,63,18},{31,61,13},{30,63,9},{30,63,9},{29,63,1},{31,62,13},{29,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{30,0,90},{30,0,90},{30,0,90},{30,0,90},{29,63,26},{29,63,26},{29,63,26},{29,63,2},{28,63,20}, +{28,63,20},{0,13,200},{0,10,52},{0,7,2},{0,6,61},{0,9,441},{0,7,308},{0,5,139},{0,4,318},{0,5,491},{0,4,354},{0,13,200},{0,10,52},{0,7,2},{0,6,61},{2,2,441},{0,7,308},{0,5,139},{0,4,318},{2,3,441},{0,4,318},{0,6,0},{0,6,0},{0,6,0},{0,4,1},{0,3,41},{0,3,20},{0,3,20},{0,2,26},{0,2,50},{0,1,30},{0,6,0}, +{0,6,0},{0,6,0},{0,4,1},{1,0,41},{0,3,20},{0,3,20},{0,2,26},{1,1,41},{0,2,26},{3,3,200},{0,10,52},{0,7,2},{0,6,61},{3,3,200},{4,3,200},{0,6,61},{0,5,202},{4,3,200},{0,5,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,18,200},{0,14,20},{0,10,13}, +{0,9,26},{0,12,686},{0,9,419},{0,8,178},{0,5,442},{0,7,789},{0,5,491},{0,18,200},{0,14,20},{0,10,13},{0,9,26},{3,2,686},{0,9,419},{0,8,178},{0,5,442},{6,0,686},{0,5,442},{0,11,1},{0,11,1},{0,11,1},{0,7,0},{0,6,145},{0,5,74},{0,5,74},{0,3,74},{0,3,165},{0,3,90},{0,11,1},{0,11,1},{0,11,1},{0,7,0},{1,2,145}, +{0,5,74},{0,5,74},{0,3,74},{3,0,145},{0,3,74},{5,1,200},{0,14,20},{1,9,2},{0,9,26},{5,1,200},{9,0,200},{0,9,26},{0,7,202},{9,0,200},{0,7,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,23,251},{0,17,53},{1,12,78},{0,11,54},{0,17,724},{0,13,362},{0,11,86}, +{0,8,387},{0,9,932},{0,7,498},{1,20,201},{1,16,21},{1,12,14},{1,11,27},{4,4,723},{0,13,362},{0,11,86},{0,8,387},{7,2,723},{0,8,387},{0,17,49},{0,17,49},{0,17,49},{0,10,49},{0,11,162},{0,9,45},{0,9,45},{0,5,50},{0,5,243},{0,5,99},{1,13,2},{1,13,2},{1,13,2},{1,9,1},{3,1,162},{0,9,45},{0,9,45},{0,5,50},{3,3,162}, +{0,5,50},{7,0,200},{0,17,4},{2,11,2},{0,11,5},{7,0,200},{10,2,200},{0,11,5},{0,9,202},{10,2,200},{0,9,202},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,13},{0,2,13},{1,25,315},{1,19,117},{1,14,171},{1,13,118},{0,23,723},{0,16,299},{0,13,18},{0,10,318},{0,12,1087},{0,9,516},{2,22,201}, +{2,17,21},{2,14,14},{2,13,27},{5,6,723},{0,16,299},{0,13,18},{0,10,318},{8,4,723},{0,10,318},{1,19,113},{1,19,113},{1,19,113},{1,12,113},{0,16,162},{0,13,17},{0,13,17},{0,8,26},{0,8,338},{0,7,129},{2,15,2},{2,15,2},{2,15,2},{2,11,1},{3,6,162},{0,13,17},{0,13,17},{0,8,26},{8,0,162},{0,8,26},{7,5,200},{1,19,4},{3,13,2}, +{0,13,2},{7,5,200},{14,0,200},{0,13,2},{0,11,202},{14,0,200},{0,11,202},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,10,0},{0,10,0},{0,10,0},{0,6,0},{0,5,58},{0,5,58},{2,28,408},{2,22,210},{2,16,281},{2,15,213},{0,29,739},{0,20,260},{0,16,29},{0,13,280},{0,15,1143},{0,12,464},{3,25,200},{3,21,16},{3,16,18},{3,15,20},{7,5,723}, +{0,20,244},{0,16,13},{0,13,264},{14,0,723},{0,13,264},{2,21,209},{2,21,209},{2,21,209},{2,14,209},{1,19,178},{0,17,18},{0,17,18},{0,10,21},{0,12,376},{0,9,121},{3,18,0},{3,18,0},{3,18,0},{3,13,1},{6,2,162},{0,17,2},{0,17,2},{0,10,5},{11,0,162},{0,10,5},{10,1,200},{2,22,2},{4,15,5},{2,15,5},{10,1,200},{17,0,200},{2,15,5}, +{0,13,200},{17,0,200},{0,13,200},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{1,13,16},{1,13,16},{1,13,16},{1,8,17},{0,8,80},{0,8,80},{3,30,408},{3,24,210},{3,18,281},{3,17,213},{1,31,739},{1,22,260},{2,17,27},{1,15,280},{0,19,1000},{0,14,322},{4,26,201},{4,22,21},{4,18,14},{4,17,27},{10,0,723},{0,23,212},{2,17,11},{0,15,225},{15,2,723}, +{0,15,225},{3,23,209},{3,23,209},{3,23,209},{3,16,209},{2,21,178},{1,19,18},{1,19,18},{1,12,21},{0,15,294},{0,12,44},{4,19,2},{4,19,2},{4,19,2},{4,15,2},{8,0,162},{1,19,2},{1,19,2},{0,13,4},{11,3,162},{0,13,4},{11,3,200},{3,24,2},{5,17,2},{2,17,2},{11,3,200},{18,2,200},{2,17,2},{0,15,200},{18,2,200},{0,15,200},{3,0,208}, +{3,0,208},{3,0,208},{3,0,208},{2,15,16},{2,15,16},{2,15,16},{2,10,17},{0,12,40},{0,12,40},{4,31,420},{4,26,222},{4,20,276},{4,19,223},{3,29,740},{2,24,260},{3,19,27},{2,16,270},{0,23,920},{0,16,234},{5,28,201},{5,24,21},{5,20,14},{5,19,27},{11,2,723},{0,27,200},{3,19,11},{0,17,211},{16,4,723},{0,17,211},{4,25,218},{4,25,218},{4,25,218}, +{4,18,218},{3,23,178},{2,21,18},{2,21,18},{2,14,21},{0,19,228},{0,15,17},{5,21,2},{5,21,2},{5,21,2},{5,17,1},{9,2,162},{2,21,2},{2,21,2},{1,15,4},{16,0,162},{1,15,4},{13,1,200},{3,28,2},{6,19,2},{3,19,2},{13,1,200},{19,4,200},{3,19,2},{0,17,202},{19,4,200},{0,17,202},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{3,17,16}, +{3,17,16},{3,17,16},{3,12,17},{0,15,13},{0,15,13},{5,33,420},{5,28,222},{5,22,276},{5,21,223},{3,34,740},{3,26,260},{3,22,29},{3,18,270},{0,25,844},{0,19,202},{6,30,201},{6,26,21},{6,22,14},{6,21,27},{12,4,723},{1,29,200},{3,22,13},{0,19,202},{22,0,723},{0,19,202},{5,27,218},{5,27,218},{5,27,218},{5,20,218},{3,28,178},{3,23,18},{3,23,18}, +{3,16,18},{0,22,195},{1,17,17},{6,23,2},{6,23,2},{6,23,2},{6,19,1},{11,1,162},{3,23,2},{3,23,2},{3,16,2},{17,2,162},{3,16,2},{15,0,200},{5,28,4},{7,21,2},{4,21,2},{15,0,200},{24,1,200},{4,21,2},{0,19,202},{24,1,200},{0,19,202},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{3,22,16},{3,22,16},{3,22,16},{3,16,17},{0,19,0}, +{0,19,0},{6,36,408},{6,30,210},{6,24,276},{6,23,213},{4,37,739},{4,28,260},{4,24,24},{4,21,280},{0,29,780},{1,21,202},{7,33,200},{7,29,17},{7,24,13},{7,23,20},{15,0,723},{2,31,203},{4,24,8},{1,21,201},{24,1,723},{1,21,201},{6,29,209},{6,29,209},{6,29,209},{6,22,209},{5,27,178},{4,25,17},{4,25,17},{4,18,21},{0,26,168},{2,19,14},{7,26,0}, +{7,26,0},{7,26,0},{7,21,1},{13,0,162},{4,25,1},{4,25,1},{3,19,4},{20,2,162},{3,19,4},{16,2,200},{6,30,2},{8,23,5},{6,23,5},{16,2,200},{27,1,200},{6,23,5},{0,21,200},{27,1,200},{0,21,200},{6,0,208},{6,0,208},{6,0,208},{6,0,208},{5,21,16},{5,21,16},{5,21,16},{5,16,17},{1,21,2},{1,21,2},{7,38,408},{7,32,210},{7,26,276}, +{7,25,213},{5,39,739},{5,30,260},{5,26,24},{5,23,280},{0,33,749},{2,23,202},{8,34,201},{8,30,19},{8,26,14},{8,25,21},{16,1,723},{3,33,202},{5,26,8},{2,23,201},{25,3,723},{2,23,201},{7,31,209},{7,31,209},{7,31,209},{7,24,209},{6,29,178},{5,27,17},{5,27,17},{5,20,21},{0,30,164},{3,21,14},{8,28,1},{8,28,1},{8,28,1},{8,23,2},{14,2,162}, +{5,27,1},{5,27,1},{4,21,4},{24,0,162},{4,21,4},{17,4,200},{7,32,2},{9,25,5},{7,25,5},{17,4,200},{27,4,200},{7,25,5},{0,23,200},{27,4,200},{0,23,200},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{6,23,16},{6,23,16},{6,23,16},{6,18,17},{2,23,2},{2,23,2},{8,39,420},{8,34,222},{8,28,286},{8,27,223},{6,41,739},{6,32,260},{6,28,24}, +{6,25,280},{0,36,725},{3,25,202},{9,36,201},{9,32,21},{9,28,14},{9,27,21},{18,0,723},{4,35,200},{6,28,8},{3,25,201},{30,0,723},{3,25,201},{8,33,218},{8,33,218},{8,33,218},{8,26,219},{7,31,178},{6,29,17},{6,29,17},{6,22,21},{2,30,168},{4,23,17},{9,30,1},{9,30,1},{9,30,1},{9,25,2},{16,0,162},{6,29,1},{6,29,1},{5,23,4},{26,1,162}, +{5,23,4},{18,6,200},{7,36,2},{10,27,5},{8,27,5},{18,6,200},{28,6,200},{8,27,5},{0,25,200},{28,6,200},{0,25,200},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{7,25,16},{7,25,16},{7,25,16},{7,20,17},{3,25,2},{3,25,2},{9,41,420},{9,36,222},{9,30,286},{9,29,223},{7,43,739},{7,34,260},{7,30,24},{7,27,280},{1,38,725},{4,27,201},{10,38,201}, +{10,34,21},{10,30,14},{10,29,21},{19,2,723},{5,37,200},{7,30,8},{4,27,201},{31,2,723},{4,27,201},{9,35,218},{9,35,218},{9,35,218},{9,28,219},{7,36,178},{7,31,17},{7,31,17},{7,24,21},{2,33,165},{5,25,17},{10,31,2},{10,31,2},{10,31,2},{10,27,2},{17,2,162},{7,31,1},{7,31,1},{6,25,4},{27,3,162},{6,25,4},{21,1,200},{9,36,4},{11,29,5}, +{9,29,5},{21,1,200},{29,8,200},{9,29,5},{0,27,200},{29,8,200},{0,27,200},{9,0,218},{9,0,218},{9,0,218},{9,0,218},{7,30,16},{7,30,16},{7,30,16},{7,24,17},{4,27,1},{4,27,1},{10,44,408},{10,38,210},{10,32,276},{10,31,217},{8,45,739},{8,36,260},{8,32,24},{8,29,267},{2,41,727},{5,29,207},{11,41,200},{11,37,17},{11,32,13},{11,31,18},{21,1,723}, +{6,39,203},{8,32,8},{6,29,203},{29,8,723},{6,29,203},{10,37,209},{10,37,209},{10,37,209},{10,31,208},{9,35,178},{8,33,17},{8,33,17},{8,27,21},{3,36,165},{6,27,18},{11,34,0},{11,34,0},{11,34,0},{11,30,1},{19,1,162},{8,33,1},{8,33,1},{7,27,2},{29,4,162},{7,27,2},{23,0,200},{10,38,2},{12,32,8},{9,32,5},{23,0,200},{31,9,200},{9,32,5}, +{0,29,202},{31,9,200},{0,29,202},{10,0,208},{10,0,208},{10,0,208},{10,0,208},{9,29,16},{9,29,16},{9,29,16},{9,25,16},{5,30,2},{5,30,2},{11,46,408},{11,40,210},{11,34,276},{11,33,213},{9,47,739},{9,38,260},{9,34,24},{9,31,267},{3,43,727},{6,31,207},{12,42,203},{12,38,19},{12,34,14},{12,33,21},{22,3,723},{7,41,203},{9,34,8},{7,31,203},{30,10,723}, +{7,31,203},{11,39,209},{11,39,209},{11,39,209},{11,32,209},{10,37,178},{9,35,17},{9,35,17},{9,29,21},{4,38,164},{7,29,18},{12,36,1},{12,36,1},{12,36,1},{12,31,2},{20,3,162},{9,35,1},{9,35,1},{8,29,2},{30,6,162},{8,29,2},{24,2,200},{11,40,2},{13,33,5},{11,33,5},{24,2,200},{27,17,200},{11,33,5},{0,31,202},{27,17,200},{0,31,202},{11,0,208}, +{11,0,208},{11,0,208},{11,0,208},{10,31,16},{10,31,16},{10,31,16},{10,27,16},{6,32,2},{6,32,2},{12,47,420},{12,42,220},{12,36,286},{12,35,223},{10,49,739},{10,40,260},{10,36,24},{10,33,280},{3,46,727},{7,33,202},{13,44,203},{13,40,19},{13,36,14},{13,35,21},{24,1,723},{8,43,202},{10,36,8},{7,33,201},{31,12,723},{7,33,201},{12,41,218},{12,41,218},{12,41,218}, +{12,34,219},{11,39,178},{10,37,17},{10,37,17},{10,31,21},{5,40,164},{8,31,21},{13,38,1},{13,38,1},{13,38,1},{13,33,2},{21,5,162},{10,37,1},{10,37,1},{9,31,2},{31,8,162},{9,31,2},{25,4,200},{12,42,2},{14,35,5},{12,35,5},{25,4,200},{28,19,200},{12,35,5},{0,33,200},{28,19,200},{0,33,200},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{11,33,16}, +{11,33,16},{11,33,16},{11,29,16},{7,33,2},{7,33,2},{13,49,420},{13,44,220},{13,38,286},{13,37,223},{11,51,739},{11,42,260},{11,38,24},{11,35,280},{4,48,729},{8,35,201},{14,46,203},{14,42,19},{14,38,14},{14,37,21},{26,0,723},{9,45,202},{11,38,8},{8,35,201},{31,15,723},{8,35,201},{13,43,218},{13,43,218},{13,43,218},{13,36,219},{11,44,178},{11,39,17},{11,39,17}, +{11,32,21},{6,42,164},{9,33,17},{14,40,1},{14,40,1},{14,40,1},{14,35,2},{24,0,162},{11,39,1},{11,39,1},{10,33,4},{31,11,162},{10,33,4},{26,6,200},{13,44,2},{15,37,5},{13,37,5},{26,6,200},{29,21,200},{13,37,5},{0,35,200},{29,21,200},{0,35,200},{13,0,218},{13,0,218},{13,0,218},{13,0,218},{11,38,16},{11,38,16},{11,38,16},{11,32,17},{8,35,1}, +{8,35,1},{14,52,408},{14,46,212},{14,41,282},{14,39,217},{12,53,739},{12,44,259},{12,40,27},{12,37,267},{6,49,727},{9,37,207},{15,49,200},{15,44,20},{15,40,17},{15,39,18},{26,6,723},{10,48,203},{12,40,11},{10,37,203},{29,21,723},{10,37,203},{14,46,208},{14,46,208},{14,46,208},{14,39,208},{13,43,178},{12,41,18},{12,41,18},{12,35,21},{7,44,163},{10,35,18},{15,42,1}, +{15,42,1},{15,42,1},{15,38,1},{24,6,162},{12,41,2},{12,41,2},{11,35,2},{29,17,162},{11,35,2},{28,5,200},{13,48,2},{16,40,5},{13,40,1},{28,5,200},{31,22,200},{13,40,1},{0,37,202},{31,22,200},{0,37,202},{14,0,208},{14,0,208},{14,0,208},{14,0,208},{13,37,16},{13,37,16},{13,37,16},{13,33,16},{9,38,2},{9,38,2},{15,54,408},{15,48,210},{15,43,282}, +{15,41,217},{13,55,739},{13,46,259},{13,42,27},{13,39,267},{7,51,727},{10,39,207},{16,50,203},{16,47,18},{16,42,11},{16,41,26},{29,1,723},{11,49,203},{13,42,11},{11,39,203},{30,23,723},{11,39,203},{15,47,209},{15,47,209},{15,47,209},{15,41,208},{14,45,178},{13,43,18},{13,43,18},{13,37,21},{8,46,164},{11,37,18},{16,44,1},{16,44,1},{16,44,1},{16,39,2},{27,1,162}, +{13,43,2},{13,43,2},{12,37,2},{30,19,162},{12,37,2},{31,0,200},{15,48,2},{17,42,5},{14,42,1},{31,0,200},{28,29,200},{14,42,1},{0,39,202},{28,29,200},{0,39,202},{15,0,208},{15,0,208},{15,0,208},{15,0,208},{14,39,16},{14,39,16},{14,39,16},{14,35,16},{10,40,2},{10,40,2},{16,56,418},{16,50,220},{16,44,283},{16,43,228},{14,57,739},{14,48,260},{14,44,27}, +{14,41,267},{7,54,727},{11,41,207},{17,52,203},{17,48,19},{17,44,11},{17,43,26},{30,3,723},{12,51,202},{14,44,11},{12,41,203},{31,25,723},{12,41,203},{16,49,218},{16,49,218},{16,49,218},{16,43,219},{15,47,178},{14,45,18},{14,45,18},{14,39,21},{9,48,164},{12,39,21},{17,46,1},{17,46,1},{17,46,1},{17,41,2},{28,3,162},{14,45,2},{14,45,2},{13,39,2},{31,21,162}, +{13,39,2},{30,9,200},{16,50,2},{18,44,5},{15,44,1},{30,9,200},{29,31,200},{15,44,1},{0,41,202},{29,31,200},{0,41,202},{16,0,218},{16,0,218},{16,0,218},{16,0,218},{15,41,16},{15,41,16},{15,41,16},{15,37,16},{11,42,2},{11,42,2},{17,58,418},{17,52,220},{17,46,283},{17,45,228},{15,59,739},{15,50,260},{15,46,27},{15,43,267},{8,56,724},{12,43,206},{18,54,203}, +{18,50,19},{18,46,11},{18,45,26},{31,5,723},{13,53,202},{15,46,11},{13,43,203},{31,28,723},{13,43,203},{17,51,218},{17,51,218},{17,51,218},{17,45,219},{15,52,178},{15,47,18},{15,47,18},{15,41,21},{10,50,164},{13,41,21},{18,48,1},{18,48,1},{18,48,1},{18,43,2},{29,5,162},{15,47,2},{15,47,2},{14,41,2},{31,24,162},{14,41,2},{31,11,200},{17,52,2},{19,46,5}, +{16,46,1},{31,11,200},{29,34,200},{16,46,1},{0,43,202},{29,34,200},{0,43,202},{17,0,218},{17,0,218},{17,0,218},{17,0,218},{15,46,17},{15,46,17},{15,46,17},{15,40,16},{12,44,2},{12,44,2},{18,60,410},{18,54,212},{18,49,282},{18,48,218},{17,58,739},{16,52,259},{16,48,27},{16,45,273},{10,57,724},{13,46,208},{19,57,200},{19,52,20},{19,48,17},{19,47,25},{31,11,723}, +{14,56,203},{16,48,11},{14,45,208},{29,34,723},{14,45,208},{18,54,208},{18,54,208},{18,54,208},{18,47,208},{17,51,178},{16,49,18},{16,49,18},{16,43,20},{11,52,163},{14,44,24},{19,50,1},{19,50,1},{19,50,1},{19,46,0},{31,4,162},{16,49,2},{16,49,2},{15,43,4},{30,29,162},{15,43,4},{30,20,200},{18,54,4},{20,48,5},{17,48,1},{30,20,200},{31,35,200},{17,48,1}, +{0,45,208},{31,35,200},{0,45,208},{18,0,208},{18,0,208},{18,0,208},{18,0,208},{17,45,17},{17,45,17},{17,45,17},{17,41,16},{13,46,0},{13,46,0},{19,62,410},{19,56,212},{19,51,282},{19,49,217},{18,60,739},{17,54,259},{17,50,27},{17,47,273},{11,59,724},{14,47,218},{20,59,201},{20,55,18},{20,50,11},{20,49,26},{31,16,723},{15,58,203},{17,50,11},{15,47,208},{30,36,723}, +{15,47,208},{19,56,208},{19,56,208},{19,56,208},{19,49,208},{18,53,178},{17,51,18},{17,51,18},{17,45,20},{12,54,164},{15,46,24},{20,52,1},{20,52,1},{20,52,1},{20,48,2},{30,13,162},{17,51,2},{17,51,2},{16,45,1},{31,31,162},{16,45,1},{31,22,200},{19,56,4},{21,50,5},{18,50,1},{31,22,200},{28,42,200},{18,50,1},{0,47,208},{28,42,200},{0,47,208},{19,0,208}, +{19,0,208},{19,0,208},{19,0,208},{18,47,17},{18,47,17},{18,47,17},{18,43,16},{14,48,2},{14,48,2},{20,63,426},{20,58,223},{20,52,283},{20,51,228},{19,62,739},{18,56,259},{18,52,27},{18,49,267},{12,61,727},{15,49,207},{21,61,201},{21,57,18},{21,52,11},{21,51,26},{31,21,723},{16,60,203},{18,52,11},{16,49,203},{31,38,723},{16,49,203},{20,57,219},{20,57,219},{20,57,219}, +{20,51,219},{19,55,178},{18,53,18},{18,53,18},{18,47,20},{13,56,164},{16,47,17},{21,54,1},{21,54,1},{21,54,1},{21,49,2},{31,15,162},{18,53,2},{18,53,2},{17,47,1},{31,34,162},{17,47,1},{31,27,200},{19,60,4},{22,52,5},{19,52,1},{31,27,200},{29,44,200},{19,52,1},{0,49,202},{29,44,200},{0,49,202},{20,0,218},{20,0,218},{20,0,218},{20,0,218},{19,49,16}, +{19,49,16},{19,49,16},{19,45,16},{15,50,2},{15,50,2},{21,63,468},{21,60,223},{21,54,283},{21,53,228},{20,63,749},{19,58,259},{19,54,27},{19,51,267},{13,63,727},{16,51,206},{22,63,201},{22,59,18},{22,54,11},{22,53,26},{30,30,723},{17,62,203},{19,54,11},{17,51,203},{31,41,723},{17,51,203},{21,59,219},{21,59,219},{21,59,219},{21,53,219},{19,60,180},{19,55,18},{19,55,18}, +{19,49,21},{14,58,164},{17,49,21},{22,56,1},{22,56,1},{22,56,1},{22,51,2},{31,20,162},{19,55,2},{19,55,2},{18,49,2},{31,37,162},{18,49,2},{31,32,200},{20,62,1},{23,54,5},{20,54,1},{31,32,200},{30,46,200},{20,54,1},{0,51,202},{30,46,200},{0,51,202},{21,0,218},{21,0,218},{21,0,218},{21,0,218},{19,54,17},{19,54,17},{19,54,17},{19,48,16},{16,52,2}, +{16,52,2},{22,63,570},{22,63,209},{22,57,288},{22,56,212},{21,63,804},{20,61,254},{20,56,33},{20,53,273},{15,63,753},{17,54,208},{23,63,232},{23,61,13},{23,56,16},{23,55,25},{31,32,723},{19,62,212},{20,56,17},{18,53,208},{30,46,723},{18,53,208},{22,62,208},{22,62,208},{22,62,208},{22,55,208},{20,63,178},{20,57,17},{20,57,17},{20,51,20},{15,60,163},{18,52,24},{23,59,0}, +{23,59,0},{23,59,0},{23,54,0},{31,26,162},{20,57,1},{20,57,1},{19,51,4},{30,42,162},{19,51,4},{31,38,200},{22,63,1},{24,56,1},{21,56,1},{31,38,200},{31,48,200},{21,56,1},{0,53,208},{31,48,200},{0,53,208},{22,0,208},{22,0,208},{22,0,208},{22,0,208},{20,57,16},{20,57,16},{20,57,16},{21,49,16},{17,54,0},{17,54,0},{23,63,696},{23,63,237},{23,59,288}, +{23,58,212},{23,63,888},{21,63,254},{21,58,33},{21,55,273},{17,63,824},{18,56,208},{24,63,273},{24,62,21},{24,58,17},{24,57,26},{30,41,723},{20,63,233},{21,58,17},{19,55,208},{29,50,723},{19,55,208},{23,63,212},{23,63,212},{23,63,212},{23,57,208},{22,61,180},{21,59,17},{21,59,17},{21,53,20},{16,62,163},{19,54,24},{24,60,2},{24,60,2},{24,60,2},{24,56,2},{31,31,162}, +{21,59,1},{21,59,1},{20,53,1},{31,44,162},{20,53,1},{30,47,200},{24,62,20},{25,58,1},{22,58,1},{30,47,200},{31,51,200},{22,58,1},{0,55,208},{31,51,200},{0,55,208},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{21,59,16},{21,59,16},{21,59,16},{22,51,16},{18,56,0},{18,56,0},{25,63,804},{24,63,334},{24,61,283},{24,60,227},{24,63,957},{22,63,297},{22,60,33}, +{22,57,273},{20,63,913},{19,58,208},{26,63,313},{25,63,51},{25,60,17},{25,59,26},{31,43,723},{22,63,281},{22,60,17},{19,58,208},{30,52,723},{19,58,208},{24,63,234},{24,63,234},{24,63,234},{24,59,218},{23,63,180},{22,61,17},{22,61,17},{22,55,20},{18,62,171},{20,55,17},{25,62,2},{25,62,2},{25,62,2},{25,58,2},{31,36,162},{22,61,1},{22,61,1},{21,55,1},{31,47,162}, +{21,55,1},{30,52,200},{25,63,50},{26,60,1},{23,60,1},{30,52,200},{28,58,200},{23,60,1},{0,57,208},{28,58,200},{0,57,208},{24,0,218},{24,0,218},{24,0,218},{24,0,218},{22,61,16},{22,61,16},{22,61,16},{23,53,16},{19,58,0},{19,58,0},{26,63,930},{25,63,492},{25,63,283},{25,62,227},{25,63,1068},{24,63,389},{23,62,33},{23,59,273},{21,63,999},{20,60,209},{27,63,379}, +{26,63,149},{26,62,17},{26,61,26},{31,48,723},{24,63,364},{24,62,16},{20,60,208},{31,54,723},{20,60,208},{25,63,267},{25,63,267},{25,63,267},{25,61,218},{24,63,205},{23,63,17},{23,63,17},{23,57,20},{20,63,189},{21,57,17},{26,63,5},{26,63,5},{26,63,5},{26,60,2},{30,45,162},{23,63,1},{23,63,1},{22,57,1},{31,50,162},{22,57,1},{31,54,200},{27,63,90},{27,62,1}, +{24,62,0},{31,54,200},{29,60,200},{24,62,0},{0,59,208},{29,60,200},{0,59,208},{25,0,218},{25,0,218},{25,0,218},{25,0,218},{23,63,16},{23,63,16},{23,63,16},{23,56,17},{20,60,1},{20,60,1},{27,63,877},{26,63,585},{26,63,329},{26,63,209},{26,63,990},{25,63,397},{25,63,36},{24,61,165},{23,63,910},{22,61,122},{28,63,306},{28,63,162},{27,63,36},{27,63,4},{30,56,546}, +{26,63,306},{25,63,20},{22,61,113},{30,58,546},{22,61,113},{26,63,329},{26,63,329},{26,63,329},{26,63,209},{25,63,276},{25,63,36},{25,63,36},{24,59,18},{22,63,230},{22,60,22},{27,63,36},{27,63,36},{27,63,36},{27,62,0},{29,54,162},{25,63,20},{25,63,20},{24,59,2},{29,56,162},{24,59,2},{31,58,113},{29,63,61},{28,63,0},{26,63,1},{31,58,113},{31,60,113},{26,63,1}, +{0,61,113},{31,60,113},{0,61,113},{26,0,208},{26,0,208},{26,0,208},{26,0,208},{25,62,16},{25,62,16},{25,62,16},{25,57,17},{21,62,1},{21,62,1},{28,63,731},{27,63,573},{27,63,404},{27,63,244},{27,63,797},{26,63,354},{26,63,98},{25,62,57},{25,63,737},{23,62,38},{29,63,190},{29,63,126},{28,63,65},{28,63,5},{31,56,333},{28,63,185},{27,63,52},{24,62,26},{30,60,333}, +{24,62,26},{27,63,404},{27,63,404},{27,63,404},{27,63,244},{27,63,356},{26,63,98},{26,63,98},{25,61,18},{24,63,315},{23,62,22},{28,63,65},{28,63,65},{28,63,65},{28,63,5},{30,56,162},{27,63,52},{27,63,52},{25,61,2},{30,58,162},{25,61,2},{31,61,25},{30,63,13},{30,63,4},{29,63,1},{31,61,25},{31,62,25},{29,63,1},{0,62,25},{31,62,25},{0,62,25},{27,0,208}, +{27,0,208},{27,0,208},{27,0,208},{26,63,17},{26,63,17},{26,63,17},{26,59,17},{23,63,9},{23,63,9},{29,63,642},{28,63,524},{28,63,443},{28,63,299},{28,63,623},{28,63,335},{27,63,201},{26,63,17},{27,63,610},{24,63,26},{30,63,131},{30,63,115},{29,63,101},{29,63,37},{31,59,193},{29,63,121},{28,63,85},{26,63,1},{30,62,193},{26,63,1},{28,63,443},{28,63,443},{28,63,443}, +{28,63,299},{28,63,398},{27,63,201},{27,63,201},{26,63,17},{26,63,378},{24,63,26},{29,63,101},{29,63,101},{29,63,101},{29,63,37},{31,57,145},{28,63,85},{28,63,85},{26,63,1},{31,60,145},{26,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{28,0,218},{28,0,218},{28,0,218},{28,0,218},{27,63,32}, +{27,63,32},{27,63,32},{27,61,17},{24,63,26},{24,63,26},{29,63,418},{29,63,354},{29,63,318},{29,63,254},{29,63,370},{28,63,223},{28,63,142},{28,63,25},{28,63,358},{26,63,58},{30,63,51},{30,63,35},{30,63,26},{30,63,10},{31,61,54},{30,63,34},{30,63,25},{28,63,0},{31,62,54},{28,63,0},{29,63,318},{29,63,318},{29,63,318},{29,63,254},{29,63,270},{28,63,142},{28,63,142}, +{28,63,25},{27,63,249},{26,63,58},{30,63,26},{30,63,26},{30,63,26},{30,63,10},{31,60,41},{30,63,25},{30,63,25},{28,63,0},{31,61,41},{28,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{29,0,218},{29,0,218},{29,0,218},{29,0,218},{28,63,61},{28,63,61},{28,63,61},{28,63,25},{26,63,58}, +{26,63,58},{0,18,421},{0,15,106},{0,10,8},{0,9,117},{0,12,925},{0,9,650},{0,9,286},{0,6,670},{0,7,1030},{0,5,726},{0,18,421},{0,15,106},{0,10,8},{0,9,117},{3,2,925},{0,9,650},{0,9,286},{0,6,670},{6,0,925},{0,6,670},{0,9,0},{0,9,0},{0,9,0},{0,5,1},{0,4,85},{0,4,45},{0,4,45},{0,2,50},{0,2,98},{0,2,59},{0,9,0}, +{0,9,0},{0,9,0},{0,5,1},{1,1,85},{0,4,45},{0,4,45},{0,2,50},{2,0,85},{0,2,50},{5,1,421},{0,15,106},{0,10,8},{0,9,117},{5,1,421},{9,0,421},{0,9,117},{0,7,421},{9,0,421},{0,7,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,24,421},{0,19,53},{0,13,8}, +{0,11,72},{0,16,1261},{0,12,805},{0,11,328},{0,7,822},{0,9,1438},{0,7,922},{0,24,421},{0,19,53},{0,13,8},{0,11,72},{3,6,1261},{0,12,805},{0,11,328},{0,7,822},{8,0,1261},{0,7,822},{0,14,0},{0,14,0},{0,14,0},{0,8,1},{0,7,221},{0,7,116},{0,7,116},{0,4,125},{0,4,257},{0,3,146},{0,14,0},{0,14,0},{0,14,0},{0,8,1},{2,0,221}, +{0,7,116},{0,7,116},{0,4,125},{3,1,221},{0,4,125},{7,0,421},{0,19,53},{1,12,8},{0,11,72},{7,0,421},{11,1,421},{0,11,72},{0,9,421},{11,1,421},{0,9,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,29,430},{0,22,34},{0,15,62},{0,14,49},{0,20,1514},{0,15,866},{0,13,301}, +{0,9,894},{0,11,1797},{0,9,1063},{0,29,430},{0,22,34},{1,15,33},{0,14,49},{6,0,1514},{0,15,866},{0,13,301},{0,9,894},{10,0,1514},{0,9,894},{0,19,10},{0,19,10},{0,19,10},{0,12,10},{0,11,338},{0,9,149},{0,9,149},{0,5,162},{0,5,419},{0,5,211},{0,19,10},{0,19,10},{0,19,10},{0,12,10},{3,1,338},{0,9,149},{0,9,149},{0,5,162},{3,3,338}, +{0,5,162},{8,2,421},{0,22,25},{2,14,8},{0,14,40},{8,2,421},{14,0,421},{0,14,40},{0,11,421},{14,0,421},{0,11,421},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,2},{0,1,2},{1,31,494},{1,24,98},{1,17,131},{1,16,110},{0,25,1517},{0,19,734},{0,15,157},{0,11,789},{0,14,1982},{0,11,1045},{1,31,430}, +{1,24,34},{2,16,35},{1,16,46},{7,2,1514},{0,19,734},{0,15,157},{0,11,789},{11,2,1514},{0,11,789},{1,21,74},{1,21,74},{1,21,74},{1,14,74},{0,16,338},{0,13,89},{0,13,89},{0,8,106},{0,8,514},{0,7,217},{1,21,10},{1,21,10},{1,21,10},{1,14,10},{3,6,338},{0,13,89},{0,13,89},{0,8,106},{8,0,338},{0,8,106},{10,0,421},{0,26,5},{3,16,5}, +{0,16,10},{10,0,421},{17,0,421},{0,16,10},{0,13,421},{17,0,421},{0,13,421},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,7,1},{0,7,1},{0,7,1},{0,4,1},{0,3,32},{0,3,32},{1,37,629},{1,28,213},{2,19,340},{1,18,216},{0,31,1517},{0,23,629},{0,18,54},{0,14,686},{0,17,2187},{0,13,1070},{3,30,437},{2,27,33},{3,19,29},{2,18,45},{9,1,1514}, +{0,23,629},{0,18,54},{0,14,686},{13,3,1514},{0,14,686},{1,27,209},{1,27,209},{1,27,209},{1,17,208},{0,22,338},{0,17,34},{0,17,34},{0,11,53},{0,11,666},{0,9,273},{3,21,16},{3,21,16},{3,21,16},{3,15,16},{6,2,338},{0,17,34},{0,17,34},{0,11,53},{11,0,338},{0,11,53},{12,0,421},{0,30,1},{4,18,8},{0,18,5},{12,0,421},{20,0,421},{0,18,5}, +{0,15,421},{20,0,421},{0,15,421},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,6,106},{0,6,106},{2,39,821},{2,30,405},{2,22,557},{2,20,408},{0,36,1517},{0,25,562},{0,21,14},{0,16,589},{0,19,2445},{0,15,1130},{3,35,437},{3,29,33},{4,21,33},{3,20,45},{10,3,1514},{0,25,562},{0,21,14},{0,16,589},{18,0,1514}, +{0,16,589},{2,29,401},{2,29,401},{2,29,401},{2,19,400},{0,27,340},{0,21,10},{0,21,10},{0,13,20},{0,14,851},{0,11,357},{3,26,16},{3,26,16},{3,26,16},{3,18,16},{8,0,338},{0,21,10},{0,21,10},{0,13,20},{11,3,338},{0,13,20},{13,1,421},{1,32,2},{5,20,8},{1,20,5},{13,1,421},{21,2,421},{1,20,5},{0,17,421},{21,2,421},{0,17,421},{2,0,400}, +{2,0,400},{2,0,400},{2,0,400},{0,19,0},{0,19,0},{0,19,0},{0,11,1},{0,9,205},{0,9,205},{3,41,854},{3,32,435},{3,24,590},{3,22,441},{1,38,1518},{0,29,543},{1,23,15},{0,18,575},{0,23,2318},{0,17,906},{4,37,430},{4,30,34},{5,23,33},{4,22,49},{12,1,1514},{0,29,494},{1,23,14},{0,18,526},{19,2,1514},{0,18,526},{3,31,434},{3,31,434},{3,31,434}, +{3,21,433},{1,29,341},{1,23,11},{1,23,11},{1,15,21},{0,17,734},{0,15,230},{4,27,10},{4,27,10},{4,27,10},{4,20,10},{9,2,338},{0,25,2},{0,25,2},{0,15,5},{16,0,338},{0,15,5},{15,0,421},{3,32,2},{6,22,8},{2,22,5},{15,0,421},{25,0,421},{2,22,5},{0,19,421},{25,0,421},{0,19,421},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{1,21,1}, +{1,21,1},{1,21,1},{1,13,2},{0,12,157},{0,12,157},{4,42,866},{4,34,450},{4,26,581},{4,24,458},{2,40,1518},{1,31,543},{2,25,15},{1,20,575},{0,27,2166},{0,20,706},{5,39,430},{5,32,34},{6,25,33},{5,24,49},{14,0,1514},{0,32,461},{2,25,14},{0,20,481},{20,4,1514},{0,20,481},{4,33,445},{4,33,445},{4,33,445},{4,23,445},{2,31,341},{2,25,11},{2,25,11}, +{2,17,27},{0,21,626},{0,17,102},{5,29,10},{5,29,10},{5,29,10},{5,22,10},{11,1,338},{1,27,2},{1,27,2},{0,17,2},{17,2,338},{0,17,2},{16,1,421},{3,36,2},{7,24,8},{3,24,5},{16,1,421},{27,1,421},{3,24,5},{0,21,421},{27,1,421},{0,21,421},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{2,23,1},{2,23,1},{2,23,1},{2,15,2},{0,16,97}, +{0,16,97},{5,45,854},{5,36,438},{5,28,579},{5,26,446},{3,43,1514},{3,32,545},{3,27,9},{3,22,582},{0,31,2010},{0,22,546},{7,38,437},{6,35,33},{7,27,26},{6,26,50},{14,6,1514},{0,37,430},{3,27,9},{0,23,446},{26,0,1514},{0,23,446},{5,35,434},{5,35,434},{5,35,434},{5,25,434},{3,34,338},{3,27,8},{3,27,8},{3,19,20},{0,25,525},{0,19,45},{7,29,16}, +{7,29,16},{7,29,16},{7,23,16},{13,0,338},{2,29,0},{2,29,0},{1,20,4},{20,2,338},{1,20,4},{18,1,421},{4,38,1},{8,26,10},{4,27,2},{18,1,421},{29,2,421},{4,27,2},{0,23,421},{29,2,421},{0,23,421},{5,0,433},{5,0,433},{5,0,433},{5,0,433},{3,25,1},{3,25,1},{3,25,1},{3,17,1},{0,19,41},{0,19,41},{6,47,854},{6,38,438},{6,30,579}, +{6,28,446},{4,45,1515},{3,36,553},{4,29,15},{3,24,589},{0,34,1887},{0,25,450},{7,44,437},{7,37,33},{8,29,30},{7,28,50},{16,4,1514},{0,40,422},{4,29,14},{0,25,425},{27,2,1514},{0,25,425},{6,37,434},{6,37,434},{6,37,434},{6,27,434},{4,35,341},{4,29,14},{4,29,14},{4,21,21},{0,29,461},{0,22,41},{7,34,16},{7,34,16},{7,34,16},{7,26,16},{14,2,338}, +{3,31,0},{3,31,0},{2,22,4},{24,0,338},{2,22,4},{19,3,421},{5,40,1},{8,29,5},{5,29,2},{19,3,421},{30,4,421},{5,29,2},{0,25,421},{30,4,421},{0,25,421},{6,0,433},{6,0,433},{6,0,433},{6,0,433},{4,27,1},{4,27,1},{4,27,1},{4,19,2},{0,23,13},{0,23,13},{7,49,854},{7,40,438},{7,32,590},{7,30,446},{5,47,1515},{4,37,543},{5,31,15}, +{4,26,591},{0,36,1785},{0,27,422},{8,45,430},{8,38,34},{9,31,30},{8,30,43},{17,6,1514},{1,42,422},{5,31,14},{0,27,422},{28,4,1514},{0,27,422},{7,39,434},{7,39,434},{7,39,434},{7,29,434},{5,37,341},{5,31,14},{5,31,14},{5,23,21},{0,32,404},{1,24,41},{8,35,10},{8,35,10},{8,35,10},{8,28,9},{16,0,338},{4,33,2},{4,33,2},{3,24,4},{26,1,338}, +{3,24,4},{21,1,421},{6,42,1},{9,31,5},{6,31,2},{21,1,421},{31,6,421},{6,31,2},{0,27,421},{31,6,421},{0,27,421},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{5,29,1},{5,29,1},{5,29,1},{5,21,2},{0,27,1},{0,27,1},{8,50,866},{8,42,450},{8,34,581},{8,32,458},{6,48,1518},{5,39,543},{6,33,15},{5,28,591},{0,40,1685},{1,29,422},{9,47,430}, +{9,40,34},{10,33,33},{9,32,49},{20,1,1514},{2,44,422},{6,33,14},{1,29,422},{29,6,1514},{1,29,422},{8,41,445},{8,41,445},{8,41,445},{8,31,446},{6,39,341},{6,33,11},{6,33,11},{6,25,21},{0,35,371},{2,26,41},{9,37,10},{9,37,10},{9,37,10},{9,30,9},{17,2,338},{5,35,2},{5,35,2},{5,25,5},{27,3,338},{5,25,5},{23,0,421},{7,44,1},{11,32,8}, +{7,32,5},{23,0,421},{31,9,421},{7,32,5},{0,29,421},{31,9,421},{0,29,421},{8,0,445},{8,0,445},{8,0,445},{8,0,445},{6,31,1},{6,31,1},{6,31,1},{6,23,2},{1,29,1},{1,29,1},{9,53,854},{9,45,437},{9,36,579},{9,34,446},{7,51,1514},{7,41,546},{7,35,9},{6,31,589},{0,44,1607},{2,31,430},{11,46,437},{10,43,36},{11,35,26},{10,34,50},{22,0,1514}, +{3,47,421},{7,35,9},{3,31,426},{31,7,1514},{3,31,426},{9,43,434},{9,43,434},{9,43,434},{9,33,434},{7,42,338},{7,35,8},{7,35,8},{7,27,18},{0,39,344},{3,29,42},{11,37,16},{11,37,16},{11,37,16},{10,32,16},{19,1,338},{6,37,0},{6,37,0},{5,28,1},{29,4,338},{5,28,1},{24,2,421},{8,46,1},{12,34,10},{8,35,2},{24,2,421},{30,14,421},{8,35,2}, +{0,31,425},{30,14,421},{0,31,425},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{7,33,1},{7,33,1},{7,33,1},{7,26,1},{2,32,2},{2,32,2},{10,55,854},{10,47,437},{10,38,579},{10,36,446},{8,53,1515},{7,43,561},{8,37,15},{7,32,589},{0,47,1577},{3,33,425},{11,52,437},{11,45,36},{12,37,30},{11,36,50},{23,2,1514},{4,48,422},{8,37,14},{3,33,425},{28,14,1514}, +{3,33,425},{10,45,434},{10,45,434},{10,45,434},{10,35,434},{8,43,341},{8,37,14},{8,37,14},{8,29,19},{0,43,340},{4,30,38},{11,42,16},{11,42,16},{11,42,16},{11,34,16},{20,3,338},{7,39,0},{7,39,0},{6,30,1},{30,6,338},{6,30,1},{26,1,421},{9,48,1},{12,37,5},{9,37,2},{26,1,421},{30,17,421},{9,37,2},{0,33,421},{30,17,421},{0,33,421},{10,0,433}, +{10,0,433},{10,0,433},{10,0,433},{8,35,1},{8,35,1},{8,35,1},{8,28,2},{3,34,2},{3,34,2},{11,57,854},{11,48,438},{11,40,579},{11,38,446},{9,55,1515},{8,46,555},{9,39,15},{8,34,591},{0,51,1530},{4,35,422},{12,53,430},{12,46,34},{13,39,30},{12,38,43},{24,4,1514},{5,50,422},{9,39,14},{4,35,422},{28,17,1514},{4,35,422},{11,47,434},{11,47,434},{11,47,434}, +{11,37,434},{9,45,341},{9,39,14},{9,39,14},{9,31,19},{1,45,340},{5,32,41},{12,44,9},{12,44,9},{12,44,9},{12,36,9},{21,5,338},{8,41,1},{8,41,1},{7,32,4},{31,8,338},{7,32,4},{27,3,421},{10,50,1},{13,39,5},{10,39,2},{27,3,421},{31,19,421},{10,39,2},{0,35,421},{31,19,421},{0,35,421},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{9,37,1}, +{9,37,1},{9,37,1},{9,30,2},{4,35,1},{4,35,1},{12,58,866},{12,50,450},{12,41,590},{12,40,458},{10,57,1515},{9,48,555},{10,41,15},{9,36,591},{0,54,1518},{5,37,422},{13,55,430},{13,48,34},{14,41,30},{13,40,43},{25,6,1514},{6,52,422},{10,41,14},{5,37,422},{29,19,1514},{5,37,422},{12,49,445},{12,49,445},{12,49,445},{12,39,446},{10,47,341},{10,41,14},{10,41,14}, +{10,33,21},{2,47,340},{6,34,41},{13,46,9},{13,46,9},{13,46,9},{13,38,9},{24,0,338},{9,43,1},{9,43,1},{9,33,5},{31,11,338},{9,33,5},{29,1,421},{11,52,1},{14,41,5},{11,41,2},{29,1,421},{31,22,421},{11,41,2},{0,37,421},{31,22,421},{0,37,421},{12,0,445},{12,0,445},{12,0,445},{12,0,445},{10,39,1},{10,39,1},{10,39,1},{10,31,5},{5,37,1}, +{5,37,1},{13,61,854},{13,53,437},{13,44,593},{13,43,442},{11,59,1517},{11,49,546},{11,43,13},{10,39,589},{1,57,1518},{6,39,430},{15,54,437},{14,51,36},{15,43,25},{14,42,48},{27,5,1514},{7,55,421},{11,43,13},{7,39,426},{31,20,1514},{7,39,426},{13,51,434},{13,51,434},{13,51,434},{13,42,434},{11,50,338},{11,43,13},{11,43,13},{11,35,18},{4,47,341},{7,37,42},{15,45,16}, +{15,45,16},{15,45,16},{15,39,17},{24,6,338},{10,45,1},{10,45,1},{9,36,1},{29,17,338},{9,36,1},{31,0,421},{12,54,1},{16,43,4},{12,43,0},{31,0,421},{30,27,421},{12,43,0},{0,39,425},{30,27,421},{0,39,425},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{11,41,1},{11,41,1},{11,41,1},{11,34,1},{6,40,1},{6,40,1},{14,63,854},{14,55,437},{14,46,593}, +{14,45,442},{12,61,1515},{11,51,561},{12,45,19},{11,41,589},{2,59,1518},{7,41,430},{15,60,437},{15,53,36},{16,45,34},{15,44,48},{30,0,1514},{9,55,425},{12,45,18},{8,41,426},{28,27,1514},{8,41,426},{14,53,434},{14,53,434},{14,53,434},{14,44,434},{12,51,341},{12,46,17},{12,46,17},{12,37,19},{4,51,340},{8,38,38},{15,50,16},{15,50,16},{15,50,16},{15,42,17},{27,1,338}, +{11,47,1},{11,47,1},{10,38,1},{30,19,338},{10,38,1},{31,6,421},{13,56,1},{17,45,4},{13,45,0},{31,6,421},{31,29,421},{13,45,0},{0,41,425},{31,29,421},{0,41,425},{14,0,433},{14,0,433},{14,0,433},{14,0,433},{12,43,1},{12,43,1},{12,43,1},{12,36,2},{7,42,1},{7,42,1},{15,63,878},{15,57,437},{15,48,579},{15,47,442},{13,63,1515},{12,54,555},{13,47,19}, +{12,43,574},{3,61,1518},{8,43,429},{16,61,430},{16,54,34},{17,47,34},{16,46,41},{31,2,1514},{10,57,425},{13,47,18},{9,43,426},{29,29,1514},{9,43,426},{15,55,434},{15,55,434},{15,55,434},{15,46,434},{13,53,341},{13,47,19},{13,47,19},{13,39,19},{5,53,340},{9,40,38},{16,52,9},{16,52,9},{16,52,9},{16,44,10},{28,3,338},{12,49,1},{12,49,1},{11,40,1},{31,21,338}, +{11,40,1},{31,11,421},{14,58,1},{18,47,4},{14,47,0},{31,11,421},{31,32,421},{14,47,0},{0,43,425},{31,32,421},{0,43,425},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{13,45,1},{13,45,1},{13,45,1},{13,38,2},{8,43,4},{8,43,4},{16,63,926},{16,58,450},{16,49,590},{16,48,458},{14,63,1542},{13,56,555},{14,49,15},{13,45,574},{4,62,1517},{9,45,429},{17,63,430}, +{17,56,34},{18,49,30},{17,48,43},{30,11,1514},{11,59,425},{14,49,14},{10,45,426},{30,31,1514},{10,45,426},{16,57,445},{16,57,445},{16,57,445},{16,47,446},{14,55,341},{14,49,14},{14,49,14},{14,41,19},{6,55,340},{10,42,38},{17,54,9},{17,54,9},{17,54,9},{17,46,10},{29,5,338},{13,51,1},{13,51,1},{12,42,1},{31,24,338},{12,42,1},{31,16,421},{15,60,1},{18,49,5}, +{15,49,2},{31,16,421},{31,35,421},{15,49,2},{0,45,425},{31,35,421},{0,45,425},{16,0,445},{16,0,445},{16,0,445},{16,0,445},{14,47,1},{14,47,1},{14,47,1},{14,40,2},{9,45,4},{9,45,4},{17,63,1034},{17,61,438},{17,52,593},{17,51,442},{16,63,1598},{15,57,554},{15,51,13},{15,47,577},{6,63,1535},{10,48,434},{19,63,437},{18,59,41},{19,51,25},{18,50,48},{29,20,1514}, +{11,63,422},{15,51,13},{11,47,433},{31,33,1514},{11,47,433},{17,60,433},{17,60,433},{17,60,433},{17,50,434},{15,58,338},{15,51,13},{15,51,13},{15,43,20},{7,57,339},{12,44,41},{19,53,16},{19,53,16},{19,53,16},{19,47,17},{31,4,338},{14,53,1},{14,53,1},{13,44,1},{30,29,338},{13,44,1},{31,22,421},{16,63,1},{20,51,4},{16,51,0},{31,22,421},{30,40,421},{16,51,0}, +{0,47,433},{30,40,421},{0,47,433},{17,0,433},{17,0,433},{17,0,433},{17,0,433},{15,49,1},{15,49,1},{15,49,1},{15,42,0},{10,48,1},{10,48,1},{18,63,1166},{18,63,438},{18,54,593},{18,53,442},{17,63,1643},{15,60,561},{16,53,19},{15,49,589},{8,63,1566},{11,49,430},{20,63,458},{19,61,41},{20,53,34},{19,52,48},{30,22,1514},{13,63,429},{16,53,18},{12,49,426},{28,40,1514}, +{12,49,426},{18,62,433},{18,62,433},{18,62,433},{18,52,434},{16,60,339},{16,54,17},{16,54,17},{16,45,26},{9,57,341},{13,46,41},{19,58,17},{19,58,17},{19,58,17},{19,50,17},{30,13,338},{15,55,1},{15,55,1},{14,46,1},{31,31,338},{14,46,1},{31,27,421},{18,63,5},{21,53,4},{17,53,0},{31,27,421},{31,42,421},{17,53,0},{0,49,425},{31,42,421},{0,49,425},{18,0,433}, +{18,0,433},{18,0,433},{18,0,433},{16,51,1},{16,51,1},{16,51,1},{16,44,1},{11,50,1},{11,50,1},{20,63,1326},{19,63,470},{19,56,593},{19,55,442},{18,63,1742},{16,62,546},{17,55,19},{16,51,574},{10,63,1638},{12,51,429},{21,63,506},{20,63,29},{21,55,34},{20,54,41},{31,24,1514},{15,63,461},{17,55,18},{13,51,426},{29,42,1514},{13,51,426},{19,63,434},{19,63,434},{19,63,434}, +{19,54,434},{17,62,339},{17,56,17},{17,56,17},{17,47,26},{10,59,341},{13,48,38},{20,60,9},{20,60,9},{20,60,9},{20,52,10},{31,15,338},{16,57,2},{16,57,2},{15,48,1},{31,34,338},{15,48,1},{31,32,421},{20,63,20},{22,55,4},{18,55,0},{31,32,421},{31,45,421},{18,55,0},{0,51,425},{31,45,421},{0,51,425},{19,0,433},{19,0,433},{19,0,433},{19,0,433},{17,53,1}, +{17,53,1},{17,53,1},{17,46,1},{12,51,4},{12,51,4},{21,63,1470},{20,63,561},{20,58,582},{20,57,461},{19,63,1895},{18,62,562},{18,57,19},{17,53,574},{12,63,1761},{13,53,429},{22,63,590},{21,63,59},{22,57,34},{21,56,41},{31,29,1514},{17,63,530},{18,57,18},{14,53,426},{30,44,1514},{14,53,426},{20,63,461},{20,63,461},{20,63,461},{20,55,446},{18,63,341},{18,58,17},{18,58,17}, +{18,49,19},{11,61,341},{14,50,38},{21,62,9},{21,62,9},{21,62,9},{21,54,10},{31,20,338},{17,59,2},{17,59,2},{16,50,1},{31,37,338},{16,50,1},{31,38,421},{21,63,50},{23,57,4},{19,57,0},{31,38,421},{31,48,421},{19,57,0},{0,53,425},{31,48,421},{0,53,425},{20,0,445},{20,0,445},{20,0,445},{20,0,445},{18,55,1},{18,55,1},{18,55,1},{18,48,2},{13,53,4}, +{13,53,4},{22,63,1674},{21,63,753},{21,60,586},{21,59,443},{21,63,2046},{19,63,629},{19,60,19},{19,55,577},{15,63,1917},{14,56,426},{24,63,674},{23,63,120},{23,60,29},{22,58,50},{31,35,1514},{19,63,629},{19,60,19},{14,56,425},{27,51,1514},{14,56,425},{21,63,497},{21,63,497},{21,63,497},{21,58,433},{19,63,388},{19,60,10},{19,60,10},{19,51,20},{12,63,347},{16,52,41},{23,61,17}, +{23,61,17},{23,61,17},{23,55,17},{31,26,338},{18,62,2},{18,62,2},{17,52,1},{30,42,338},{17,52,1},{31,44,421},{23,63,104},{24,59,5},{20,59,1},{31,44,421},{31,51,421},{20,59,1},{0,56,425},{31,51,421},{0,56,425},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{19,58,0},{19,58,0},{19,58,0},{19,50,0},{14,56,1},{14,56,1},{23,63,1902},{22,63,995},{22,62,586}, +{22,61,443},{22,63,2235},{20,63,759},{20,61,15},{19,57,578},{17,63,2118},{15,58,426},{25,63,770},{24,63,250},{24,61,35},{23,60,50},{31,40,1514},{21,63,701},{20,61,14},{15,58,425},{31,49,1514},{15,58,425},{22,63,554},{22,63,554},{22,63,554},{22,60,433},{21,63,437},{20,61,14},{20,61,14},{20,53,26},{14,63,379},{17,54,41},{24,63,25},{24,63,25},{24,63,25},{23,59,17},{31,31,338}, +{19,63,4},{19,63,4},{18,54,1},{31,44,338},{18,54,1},{31,49,421},{25,63,169},{25,61,5},{21,61,1},{31,49,421},{30,56,421},{21,61,1},{0,58,425},{30,56,421},{0,58,425},{22,0,433},{22,0,433},{22,0,433},{22,0,433},{20,59,2},{20,59,2},{20,59,2},{20,52,1},{15,58,1},{15,58,1},{24,63,2045},{24,63,1233},{23,63,629},{23,63,442},{24,63,2360},{22,63,914},{21,63,14}, +{20,59,549},{19,63,2241},{16,60,401},{26,63,849},{25,63,395},{25,63,34},{24,62,41},{29,52,1459},{23,63,778},{21,63,13},{17,59,400},{28,56,1459},{17,59,400},{23,63,629},{23,63,629},{23,63,629},{23,62,433},{22,63,491},{21,63,14},{21,63,14},{21,55,26},{16,63,446},{18,56,41},{25,63,34},{25,63,34},{25,63,34},{24,60,10},{31,36,338},{21,63,13},{21,63,13},{19,56,1},{31,47,338}, +{19,56,1},{31,54,392},{27,63,218},{26,63,4},{22,63,0},{31,54,392},{29,60,392},{22,63,0},{0,59,400},{29,60,392},{0,59,400},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{21,61,2},{21,61,2},{21,61,2},{21,54,1},{16,60,1},{16,60,1},{25,63,1767},{25,63,1167},{24,63,701},{24,63,449},{24,63,1976},{23,63,747},{22,63,66},{21,60,306},{20,63,1820},{17,61,217},{27,63,611}, +{26,63,317},{26,63,61},{25,63,10},{30,52,1064},{25,63,587},{23,63,41},{18,61,208},{28,58,1064},{18,61,208},{24,63,701},{24,63,701},{24,63,701},{24,63,449},{23,63,581},{22,63,66},{22,63,66},{22,57,26},{18,63,530},{19,58,41},{26,63,61},{26,63,61},{26,63,61},{25,62,10},{30,45,338},{23,63,41},{23,63,41},{20,58,1},{31,50,338},{20,58,1},{30,60,200},{28,63,106},{27,63,1}, +{25,63,1},{30,60,200},{31,59,200},{25,63,1},{0,60,208},{31,59,200},{0,60,208},{24,0,445},{24,0,445},{24,0,445},{24,0,445},{22,63,2},{22,63,2},{22,63,2},{22,56,1},{17,62,1},{17,62,1},{26,63,1542},{26,63,1122},{25,63,833},{25,63,497},{26,63,1647},{24,63,687},{24,63,203},{23,61,122},{22,63,1515},{19,62,78},{28,63,410},{28,63,266},{27,63,116},{27,63,20},{30,56,722}, +{26,63,402},{25,63,100},{20,62,65},{30,58,722},{20,62,65},{25,63,833},{25,63,833},{25,63,833},{25,63,497},{24,63,707},{24,63,203},{24,63,203},{23,60,17},{20,63,619},{19,61,46},{27,63,116},{27,63,116},{27,63,116},{27,63,20},{29,54,338},{25,63,100},{25,63,100},{22,60,2},{29,56,338},{22,60,2},{31,59,61},{29,63,37},{29,63,1},{27,63,4},{31,59,61},{31,61,61},{27,63,4}, +{0,62,65},{31,61,61},{0,62,65},{25,0,433},{25,0,433},{25,0,433},{25,0,433},{23,63,25},{23,63,25},{23,63,25},{23,58,1},{19,62,13},{19,62,13},{27,63,1406},{27,63,1134},{26,63,962},{26,63,602},{27,63,1454},{25,63,702},{25,63,341},{24,62,43},{24,63,1378},{20,63,35},{29,63,318},{28,63,250},{28,63,169},{28,63,61},{31,56,509},{28,63,313},{27,63,164},{22,63,10},{30,60,509}, +{22,63,10},{26,63,962},{26,63,962},{26,63,962},{26,63,602},{26,63,827},{25,63,341},{25,63,341},{24,62,27},{22,63,747},{20,63,35},{28,63,169},{28,63,169},{28,63,169},{28,63,61},{30,56,338},{27,63,164},{27,63,164},{23,62,2},{30,58,338},{23,62,2},{31,62,5},{31,63,9},{30,63,4},{30,63,0},{31,62,5},{31,62,9},{30,63,0},{0,63,9},{31,62,9},{0,63,9},{26,0,433}, +{26,0,433},{26,0,433},{26,0,433},{24,63,50},{24,63,50},{24,63,50},{24,60,1},{20,63,26},{20,63,26},{28,63,1135},{28,63,991},{27,63,874},{27,63,602},{28,63,1162},{26,63,618},{26,63,362},{25,63,5},{25,63,1087},{22,63,58},{30,63,219},{29,63,161},{29,63,125},{29,63,61},{30,62,294},{29,63,193},{28,63,117},{24,63,1},{31,60,297},{24,63,1},{27,63,874},{27,63,874},{27,63,874}, +{27,63,602},{27,63,730},{26,63,362},{26,63,362},{25,63,5},{24,63,681},{22,63,58},{29,63,125},{29,63,125},{29,63,125},{29,63,61},{31,56,221},{28,63,117},{28,63,117},{24,63,1},{31,59,221},{24,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{27,0,433},{27,0,433},{27,0,433},{27,0,433},{25,63,101}, +{25,63,101},{25,63,101},{25,62,1},{22,63,58},{22,63,58},{29,63,885},{28,63,751},{28,63,670},{28,63,526},{28,63,778},{27,63,483},{27,63,314},{26,63,10},{26,63,777},{24,63,117},{30,63,75},{30,63,59},{30,63,50},{30,63,34},{31,60,114},{29,63,81},{29,63,45},{27,63,0},{31,61,114},{27,63,0},{28,63,670},{28,63,670},{28,63,670},{28,63,526},{28,63,553},{27,63,314},{27,63,314}, +{26,63,10},{25,63,518},{24,63,117},{30,63,50},{30,63,50},{30,63,50},{30,63,34},{31,59,85},{29,63,45},{29,63,45},{27,63,0},{30,62,85},{27,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{28,0,445},{28,0,445},{28,0,445},{28,0,445},{27,63,145},{27,63,145},{27,63,145},{26,63,10},{24,63,117}, +{24,63,117},{0,26,882},{0,21,218},{0,15,16},{0,13,260},{0,17,1899},{0,13,1341},{0,11,593},{0,8,1380},{0,9,2113},{0,7,1513},{0,26,882},{0,21,218},{0,15,16},{0,13,260},{4,4,1896},{0,13,1341},{0,11,593},{0,8,1380},{7,2,1896},{0,8,1380},{0,12,0},{0,12,0},{0,12,0},{0,7,1},{0,6,162},{0,5,85},{0,5,85},{0,3,85},{0,3,186},{0,3,101},{0,12,0}, +{0,12,0},{0,12,0},{0,7,1},{1,3,162},{0,5,85},{0,5,85},{0,3,85},{3,0,162},{0,3,85},{6,6,882},{0,21,218},{0,15,16},{0,13,260},{6,6,882},{12,1,882},{0,13,260},{0,10,884},{12,1,882},{0,10,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,884},{0,25,146},{0,17,2}, +{0,15,185},{0,21,2355},{0,17,1539},{0,13,653},{0,10,1605},{0,11,2667},{0,9,1777},{0,31,884},{0,25,146},{0,17,2},{0,15,185},{5,4,2355},{0,17,1539},{0,13,653},{0,10,1605},{7,4,2355},{0,10,1605},{0,17,1},{0,17,1},{0,17,1},{0,10,1},{0,9,338},{0,8,180},{0,8,180},{0,5,180},{0,5,389},{0,5,229},{0,17,1},{0,17,1},{0,17,1},{0,10,1},{2,2,338}, +{0,8,180},{0,8,180},{0,5,180},{2,3,338},{0,5,180},{9,1,882},{0,25,146},{0,17,2},{0,15,185},{9,1,882},{13,3,882},{0,15,185},{0,12,884},{13,3,882},{0,12,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,36,884},{0,29,90},{0,19,37},{0,17,130},{0,25,2899},{0,19,1764},{0,16,733}, +{0,11,1853},{0,13,3325},{0,11,2109},{0,36,884},{0,29,90},{0,19,37},{0,17,130},{7,1,2899},{0,19,1764},{0,16,733},{0,11,1853},{12,0,2899},{0,11,1853},{0,23,0},{0,23,0},{0,23,0},{0,14,1},{0,11,580},{0,11,305},{0,11,305},{0,6,325},{0,6,667},{0,5,389},{0,23,0},{0,23,0},{0,23,0},{0,14,1},{2,5,578},{0,11,305},{0,11,305},{0,6,325},{5,1,578}, +{0,6,325},{10,3,882},{0,29,90},{1,19,2},{0,17,130},{10,3,882},{18,0,882},{0,17,130},{0,14,884},{18,0,882},{0,14,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,42,918},{0,32,81},{1,21,105},{0,20,109},{0,29,3051},{0,21,1707},{0,19,569},{0,13,1800},{0,16,3672},{0,13,2161},{1,38,888}, +{0,32,81},{1,21,41},{0,20,109},{8,2,3048},{0,21,1707},{0,19,569},{0,13,1800},{12,3,3048},{0,13,1800},{0,28,36},{0,28,36},{0,28,36},{0,17,37},{0,16,648},{0,13,269},{0,13,269},{0,9,292},{0,8,824},{0,7,417},{1,25,4},{1,25,4},{1,25,4},{1,16,5},{3,6,648},{0,13,269},{0,13,269},{0,9,292},{8,0,648},{0,9,292},{12,1,882},{0,32,45},{2,21,2}, +{0,20,73},{12,1,882},{19,2,882},{0,20,73},{0,16,890},{19,2,882},{0,16,890},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,10},{0,2,10},{1,44,997},{1,34,154},{1,24,229},{1,22,178},{0,35,3048},{0,25,1528},{0,21,324},{0,16,1605},{0,19,3907},{0,15,2138},{2,41,883},{2,32,86},{2,24,42},{1,22,114},{9,5,3048}, +{0,25,1528},{0,21,324},{0,16,1605},{15,3,3048},{0,16,1605},{1,31,113},{1,31,113},{1,31,113},{1,19,113},{0,22,648},{0,17,164},{0,17,164},{0,11,193},{0,11,976},{0,9,443},{2,27,2},{2,27,2},{2,27,2},{2,18,1},{6,2,648},{0,17,164},{0,17,164},{0,11,193},{11,0,648},{0,11,193},{13,4,882},{0,36,13},{3,23,4},{0,22,32},{13,4,882},{22,2,882},{0,22,32}, +{0,18,884},{22,2,882},{0,18,884},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,10,0},{0,10,0},{0,10,0},{0,6,0},{0,5,58},{0,5,58},{1,49,1173},{1,38,302},{2,26,421},{1,24,321},{0,40,3051},{0,29,1380},{0,23,186},{0,18,1464},{0,21,4201},{0,17,2149},{3,43,883},{3,34,86},{3,26,42},{2,24,114},{12,0,3048},{0,29,1380},{0,23,186},{0,18,1464},{20,0,3048}, +{0,18,1464},{1,36,289},{1,36,289},{1,36,289},{1,22,290},{0,27,650},{0,21,100},{0,21,100},{0,13,130},{0,14,1161},{0,13,491},{3,29,2},{3,29,2},{3,29,2},{3,20,1},{8,0,648},{0,21,100},{0,21,100},{0,13,130},{11,3,648},{0,13,130},{14,6,882},{0,40,1},{4,25,1},{0,25,16},{14,6,882},{26,0,882},{0,25,16},{0,20,884},{26,0,882},{0,20,884},{1,0,289}, +{1,0,289},{1,0,289},{1,0,289},{0,15,1},{0,15,1},{0,15,1},{0,9,1},{0,7,136},{0,7,136},{2,51,1365},{2,40,494},{2,28,722},{2,26,513},{0,46,3048},{0,32,1269},{0,27,82},{0,20,1341},{0,25,4525},{0,19,2197},{4,45,886},{3,38,90},{4,28,36},{3,26,114},{13,2,3048},{0,32,1269},{0,27,82},{0,20,1341},{21,2,3048},{0,20,1341},{2,38,481},{2,38,481},{2,38,481}, +{2,24,482},{0,32,650},{0,25,52},{0,25,52},{0,15,85},{0,17,1345},{0,15,569},{4,31,4},{4,31,4},{4,31,4},{4,22,5},{9,2,648},{0,25,52},{0,25,52},{0,15,85},{16,0,648},{0,15,85},{16,4,882},{1,42,1},{5,27,1},{0,27,1},{16,4,882},{27,2,882},{0,27,1},{0,22,884},{27,2,882},{0,22,884},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,21,0}, +{0,21,0},{0,21,0},{0,12,1},{0,9,250},{0,9,250},{2,57,1667},{2,44,786},{3,30,1042},{2,29,801},{0,51,3048},{0,36,1157},{0,29,20},{0,22,1236},{0,27,4891},{0,21,2281},{5,47,886},{4,41,86},{5,30,36},{4,28,116},{14,4,3048},{0,36,1157},{0,29,20},{0,22,1236},{25,0,3048},{0,22,1236},{2,43,785},{2,43,785},{2,43,785},{2,27,786},{0,38,648},{0,29,20},{0,29,20}, +{0,18,40},{0,19,1594},{0,16,677},{5,33,4},{5,33,4},{5,33,4},{5,24,5},{11,1,648},{0,29,20},{0,29,20},{0,18,40},{17,2,648},{0,18,40},{17,6,882},{2,44,1},{6,29,1},{1,29,1},{17,6,882},{28,4,882},{1,29,1},{0,24,884},{28,4,882},{0,24,884},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{0,26,0},{0,26,0},{0,26,0},{0,16,1},{0,11,400}, +{0,11,400},{3,59,1784},{3,46,901},{4,32,1195},{3,31,910},{1,53,3055},{0,40,1094},{1,31,23},{0,25,1175},{0,31,4840},{0,23,2054},{6,49,883},{6,41,81},{6,32,42},{5,30,123},{14,10,3048},{0,40,1058},{1,31,19},{0,25,1139},{28,0,3048},{0,25,1139},{3,46,900},{3,46,900},{3,46,900},{3,30,900},{1,40,654},{1,31,22},{1,31,22},{1,20,38},{0,23,1560},{0,19,533},{6,35,2}, +{6,35,2},{6,35,2},{6,26,1},{13,0,648},{0,33,5},{0,33,5},{0,20,13},{20,2,648},{0,20,13},{19,5,882},{3,46,1},{7,31,5},{2,31,1},{19,5,882},{31,4,882},{2,31,1},{0,26,882},{31,4,882},{0,26,882},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{1,29,4},{1,29,4},{1,29,4},{1,18,4},{0,15,377},{0,15,377},{4,61,1772},{4,48,891},{5,34,1195}, +{4,33,906},{2,55,3055},{1,42,1094},{2,33,29},{1,27,1175},{0,34,4609},{0,26,1716},{7,51,883},{7,43,81},{7,34,42},{6,32,114},{18,1,3048},{0,44,990},{2,33,25},{0,27,1058},{29,2,3048},{0,27,1058},{4,47,891},{4,47,891},{4,47,891},{4,32,891},{2,42,654},{2,33,29},{2,33,29},{2,22,38},{0,27,1396},{0,21,347},{7,37,2},{7,37,2},{7,37,2},{7,28,1},{14,2,648}, +{0,37,1},{0,37,1},{0,23,5},{24,0,648},{0,23,5},{22,0,882},{4,48,1},{8,33,1},{3,33,0},{22,0,882},{31,7,882},{3,33,0},{0,28,882},{31,7,882},{0,28,882},{4,0,890},{4,0,890},{4,0,890},{4,0,890},{2,31,4},{2,31,4},{2,31,4},{2,20,4},{0,19,260},{0,19,260},{5,63,1772},{5,50,891},{6,36,1195},{5,35,906},{3,57,3055},{2,44,1094},{3,35,29}, +{2,29,1175},{0,38,4381},{0,29,1436},{8,53,886},{7,47,89},{8,36,36},{7,34,114},{19,3,3048},{0,47,949},{3,35,25},{0,29,995},{30,4,3048},{0,29,995},{5,49,890},{5,49,890},{5,49,890},{5,33,891},{3,44,654},{3,35,29},{3,35,29},{3,24,38},{0,29,1251},{0,24,221},{8,39,4},{8,39,4},{8,39,4},{8,30,4},{16,0,648},{1,39,1},{1,39,1},{0,25,2},{26,1,648}, +{0,25,2},{23,2,882},{5,50,1},{9,35,1},{4,35,1},{23,2,882},{28,14,882},{4,35,1},{0,30,882},{28,14,882},{0,30,882},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{3,32,5},{3,32,5},{3,32,5},{3,22,4},{0,23,180},{0,23,180},{6,63,1790},{6,52,891},{7,38,1195},{6,37,906},{4,59,3057},{3,46,1094},{4,37,29},{3,31,1175},{0,42,4185},{0,31,1206},{9,55,886}, +{8,49,86},{9,38,36},{8,36,116},{20,5,3048},{0,51,907},{4,37,20},{0,31,950},{31,6,3048},{0,31,950},{6,51,890},{6,51,890},{6,51,890},{6,35,891},{4,46,657},{4,37,29},{4,37,29},{3,26,49},{0,34,1121},{0,27,117},{9,41,4},{9,41,4},{9,41,4},{9,32,5},{17,2,648},{2,41,1},{2,41,1},{1,27,2},{27,3,648},{1,27,2},{24,4,882},{6,52,1},{10,37,1}, +{5,37,1},{24,4,882},{28,17,882},{5,37,1},{0,32,884},{28,17,882},{0,32,884},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{4,34,9},{4,34,9},{4,34,9},{4,24,10},{0,27,116},{0,27,116},{8,63,1844},{7,54,901},{8,40,1188},{7,39,910},{5,62,3052},{4,48,1094},{5,39,23},{4,33,1175},{0,44,3969},{0,33,1039},{10,57,885},{10,49,81},{10,40,35},{9,38,123},{23,1,3048}, +{0,55,888},{5,39,19},{0,34,907},{29,12,3048},{0,34,907},{7,54,900},{7,54,900},{7,54,900},{7,38,900},{5,48,654},{5,39,22},{5,39,22},{5,28,45},{0,38,990},{0,29,80},{10,43,2},{10,43,2},{10,43,2},{10,34,1},{19,1,648},{3,43,1},{3,43,1},{3,29,1},{29,4,648},{3,29,1},{27,0,882},{7,54,1},{11,39,5},{6,39,1},{27,0,882},{31,17,882},{6,39,1}, +{0,34,882},{31,17,882},{0,34,882},{7,0,900},{7,0,900},{7,0,900},{7,0,900},{5,37,4},{5,37,4},{5,37,4},{5,26,4},{0,31,58},{0,31,58},{9,63,1886},{8,56,892},{9,42,1188},{8,41,900},{6,63,3055},{5,50,1094},{6,41,23},{5,35,1175},{0,49,3804},{0,36,935},{11,59,885},{11,51,81},{11,42,35},{10,40,123},{23,6,3048},{0,58,883},{6,41,19},{0,36,886},{30,14,3048}, +{0,36,886},{8,55,891},{8,55,891},{8,55,891},{8,40,891},{6,50,654},{6,41,22},{6,41,22},{6,30,45},{0,40,889},{1,31,80},{11,45,2},{11,45,2},{11,45,2},{11,36,1},{20,3,648},{5,43,2},{5,43,2},{4,31,1},{30,6,648},{4,31,1},{27,5,882},{8,56,2},{12,41,2},{7,41,1},{27,5,882},{31,20,882},{7,41,1},{0,36,882},{31,20,882},{0,36,882},{8,0,890}, +{8,0,890},{8,0,890},{8,0,890},{6,39,4},{6,39,4},{6,39,4},{6,28,4},{0,34,25},{0,34,25},{10,63,1964},{9,58,892},{10,44,1188},{9,43,900},{7,63,3100},{6,52,1094},{7,43,23},{6,37,1175},{0,51,3640},{0,38,887},{12,61,886},{11,55,89},{12,44,38},{11,42,123},{26,1,3048},{1,60,883},{7,43,19},{0,38,883},{30,17,3048},{0,38,883},{9,57,891},{9,57,891},{9,57,891}, +{9,42,891},{7,52,654},{7,43,22},{7,43,22},{7,32,38},{0,44,801},{2,34,86},{12,47,4},{12,47,4},{12,47,4},{12,38,4},{21,5,648},{6,45,2},{6,45,2},{4,33,2},{31,8,648},{4,33,2},{30,0,882},{9,58,2},{13,43,2},{8,43,1},{30,0,882},{28,27,882},{8,43,1},{0,38,882},{28,27,882},{0,38,882},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{7,41,4}, +{7,41,4},{7,41,4},{7,30,4},{0,38,5},{0,38,5},{11,63,2078},{10,60,892},{11,46,1188},{10,45,900},{9,63,3181},{7,54,1094},{8,45,35},{7,39,1175},{0,55,3496},{1,40,887},{13,63,886},{12,56,88},{13,46,38},{12,44,110},{27,3,3048},{2,62,883},{7,46,25},{1,40,883},{31,19,3048},{1,40,883},{10,59,891},{10,59,891},{10,59,891},{10,44,891},{8,54,657},{8,45,34},{8,45,34}, +{7,34,49},{0,48,756},{3,36,86},{13,49,4},{13,49,4},{13,49,4},{13,40,4},{24,0,648},{6,49,1},{6,49,1},{5,35,2},{31,11,648},{5,35,2},{31,2,882},{10,60,2},{14,45,2},{9,45,1},{31,2,882},{29,29,882},{9,45,1},{0,40,882},{29,29,882},{0,40,882},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{8,42,9},{8,42,9},{8,42,9},{8,32,10},{0,42,1}, +{0,42,1},{12,63,2228},{11,63,902},{12,48,1188},{11,47,908},{10,63,3256},{8,57,1095},{9,47,33},{8,41,1164},{0,59,3364},{2,42,889},{14,63,915},{14,57,90},{14,48,35},{13,47,117},{29,2,3048},{4,63,886},{8,48,25},{3,42,885},{29,25,3048},{3,42,885},{11,62,900},{11,62,900},{11,62,900},{11,46,900},{9,57,652},{9,47,29},{9,47,29},{9,36,45},{0,51,691},{4,37,80},{14,51,2}, +{14,51,2},{14,51,2},{14,42,2},{24,6,648},{7,51,1},{7,51,1},{7,37,1},{29,17,648},{7,37,1},{31,8,882},{11,63,2},{15,47,8},{10,47,5},{31,8,882},{31,30,882},{10,47,5},{0,42,884},{31,30,882},{0,42,884},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{9,45,4},{9,45,4},{9,45,4},{9,34,4},{1,44,1},{1,44,1},{13,63,2414},{12,63,907},{13,50,1188}, +{12,49,900},{11,63,3391},{9,59,1095},{10,49,23},{9,43,1164},{0,63,3276},{3,44,889},{15,63,981},{15,59,90},{15,50,35},{14,48,123},{31,1,3048},{6,63,906},{10,49,19},{4,44,885},{30,27,3048},{4,44,885},{12,63,891},{12,63,891},{12,63,891},{12,48,891},{10,59,652},{10,49,22},{10,49,22},{10,38,45},{0,55,659},{5,39,80},{15,53,2},{15,53,2},{15,53,2},{15,44,2},{27,1,648}, +{9,51,2},{9,51,2},{8,39,1},{30,19,648},{8,39,1},{29,20,882},{12,63,17},{16,49,2},{11,49,1},{29,20,882},{31,33,882},{11,49,1},{0,44,884},{31,33,882},{0,44,884},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{10,47,4},{10,47,4},{10,47,4},{10,36,4},{2,46,1},{2,46,1},{15,63,2606},{13,63,987},{14,52,1188},{13,51,900},{13,63,3517},{10,61,1095},{11,51,23}, +{10,45,1164},{1,63,3300},{4,46,892},{17,63,1014},{15,63,94},{16,52,38},{15,50,123},{31,6,3048},{8,63,936},{11,51,19},{5,46,885},{31,29,3048},{5,46,885},{13,63,906},{13,63,906},{13,63,906},{13,50,891},{11,61,652},{11,51,22},{11,51,22},{11,40,45},{0,59,651},{6,41,80},{16,55,4},{16,55,4},{16,55,4},{16,46,5},{28,3,648},{10,53,2},{10,53,2},{9,41,1},{31,21,648}, +{9,41,1},{30,22,882},{14,63,37},{17,51,2},{12,51,1},{30,22,882},{28,40,882},{12,51,1},{0,46,884},{28,40,882},{0,46,884},{13,0,890},{13,0,890},{13,0,890},{13,0,890},{11,49,4},{11,49,4},{11,49,4},{11,38,4},{3,48,0},{3,48,0},{16,63,2792},{15,63,1079},{15,54,1188},{14,53,900},{14,63,3652},{11,63,1095},{12,53,35},{11,47,1164},{3,63,3436},{5,48,887},{18,63,1080}, +{17,62,102},{17,54,38},{16,52,110},{30,15,3048},{10,63,996},{11,54,25},{5,48,883},{31,32,3048},{5,48,883},{14,63,939},{14,63,939},{14,63,939},{14,52,891},{12,62,657},{12,53,34},{12,53,34},{12,42,50},{1,61,651},{7,43,80},{17,57,4},{17,57,4},{17,57,4},{17,48,4},{29,5,648},{11,55,2},{11,55,2},{10,43,1},{31,24,648},{10,43,1},{31,24,882},{16,63,80},{18,53,2}, +{13,53,1},{31,24,882},{29,42,882},{13,53,1},{0,48,882},{29,42,882},{0,48,882},{14,0,890},{14,0,890},{14,0,890},{14,0,890},{12,50,9},{12,50,9},{12,50,9},{12,40,9},{4,50,1},{4,50,1},{17,63,3038},{16,63,1268},{16,57,1186},{15,55,908},{15,63,3879},{12,63,1146},{13,55,33},{12,49,1164},{5,63,3667},{6,50,889},{19,63,1205},{18,63,147},{18,56,41},{17,55,117},{31,17,3048}, +{12,63,1110},{12,56,20},{7,50,885},{29,38,3048},{7,50,885},{16,63,979},{16,63,979},{16,63,979},{15,54,900},{13,63,670},{13,55,29},{13,55,29},{13,45,41},{2,63,648},{8,46,81},{18,60,1},{18,60,1},{18,60,1},{18,50,2},{31,4,648},{11,59,4},{11,59,4},{11,45,1},{30,29,648},{11,45,1},{31,30,882},{18,63,146},{19,56,5},{14,55,5},{31,30,882},{31,43,882},{14,55,5}, +{0,50,884},{31,43,882},{0,50,884},{15,0,900},{15,0,900},{15,0,900},{15,0,900},{13,53,4},{13,53,4},{13,53,4},{13,42,5},{5,52,1},{5,52,1},{18,63,3308},{17,63,1502},{17,59,1186},{16,57,898},{17,63,4077},{14,63,1230},{14,57,33},{13,51,1164},{8,63,3820},{7,52,889},{21,63,1368},{19,63,261},{19,58,41},{18,57,117},{30,26,3048},{14,63,1226},{13,58,20},{8,52,885},{30,40,3048}, +{8,52,885},{17,63,1018},{17,63,1018},{17,63,1018},{16,56,890},{14,63,724},{14,57,29},{14,57,29},{14,47,41},{4,63,665},{9,48,88},{19,62,1},{19,62,1},{19,62,1},{19,52,2},{30,13,648},{12,61,1},{12,61,1},{12,47,1},{31,31,648},{12,47,1},{31,35,882},{20,63,193},{20,58,4},{15,57,5},{31,35,882},{27,51,882},{15,57,5},{0,52,884},{27,51,882},{0,52,884},{16,0,890}, +{16,0,890},{16,0,890},{16,0,890},{14,55,4},{14,55,4},{14,55,4},{14,44,5},{6,54,1},{6,54,1},{19,63,3614},{18,63,1804},{18,61,1186},{17,59,898},{18,63,4284},{15,63,1417},{15,59,33},{14,53,1164},{9,63,4036},{8,54,892},{22,63,1494},{20,63,405},{20,60,33},{19,59,117},{31,28,3048},{16,63,1395},{14,60,20},{9,54,885},{31,42,3048},{9,54,885},{18,63,1075},{18,63,1075},{18,63,1075}, +{17,58,890},{16,63,787},{15,59,29},{15,59,29},{15,48,45},{6,63,705},{10,49,80},{20,63,5},{20,63,5},{20,63,5},{20,54,5},{31,15,648},{13,63,1},{13,63,1},{13,49,1},{31,34,648},{13,49,1},{31,40,882},{22,63,277},{21,60,4},{16,59,5},{31,40,882},{31,49,882},{16,59,5},{0,54,884},{31,49,882},{0,54,884},{17,0,890},{17,0,890},{17,0,890},{17,0,890},{15,57,4}, +{15,57,4},{15,57,4},{15,46,5},{7,56,1},{7,56,1},{20,63,4014},{19,63,2174},{19,63,1186},{18,61,898},{19,63,4545},{17,63,1725},{16,62,39},{15,55,1164},{11,63,4300},{9,56,892},{23,63,1656},{22,63,585},{21,62,33},{20,60,108},{31,33,3048},{18,63,1563},{15,62,20},{10,56,885},{31,45,3048},{10,56,885},{19,63,1150},{19,63,1150},{19,63,1150},{18,60,890},{17,63,841},{16,62,35},{16,62,35}, +{16,50,50},{8,63,747},{11,51,80},{21,63,20},{21,63,20},{21,63,20},{21,56,5},{31,20,648},{15,63,5},{15,63,5},{14,51,1},{31,37,648},{14,51,1},{29,52,882},{23,63,397},{22,62,4},{17,61,5},{29,52,882},{28,56,882},{17,61,5},{0,56,884},{28,56,882},{0,56,884},{18,0,890},{18,0,890},{18,0,890},{18,0,890},{16,58,10},{16,58,10},{16,58,10},{16,48,9},{8,58,0}, +{8,58,0},{22,63,4123},{21,63,2404},{20,63,1278},{19,63,901},{20,63,4626},{18,63,1849},{17,63,38},{16,57,1006},{14,63,4330},{10,58,771},{24,63,1629},{23,63,715},{22,63,65},{22,62,81},{31,38,2814},{20,63,1505},{17,63,34},{11,58,761},{31,48,2814},{11,58,761},{20,63,1278},{20,63,1278},{20,63,1278},{19,62,901},{18,63,948},{17,63,38},{17,63,38},{17,53,41},{10,63,840},{12,54,81},{22,63,65}, +{22,63,65},{22,63,65},{22,59,2},{31,26,648},{17,63,34},{17,63,34},{15,53,1},{30,42,648},{15,53,1},{31,50,761},{25,63,425},{23,63,9},{19,63,1},{31,50,761},{31,55,761},{19,63,1},{0,58,761},{31,55,761},{0,58,761},{19,0,900},{19,0,900},{19,0,900},{19,0,900},{17,61,4},{17,61,4},{17,61,4},{17,50,5},{9,60,2},{9,60,2},{23,63,3735},{22,63,2314},{21,63,1395}, +{20,63,899},{22,63,4090},{19,63,1618},{18,63,104},{17,58,678},{15,63,3826},{11,59,507},{25,63,1285},{24,63,609},{23,63,122},{23,62,26},{30,45,2249},{21,63,1186},{19,63,74},{13,59,482},{31,50,2249},{13,59,482},{21,63,1395},{21,63,1395},{21,63,1395},{20,63,899},{19,63,1086},{18,63,104},{18,63,104},{18,55,41},{12,63,969},{13,56,81},{23,63,122},{23,63,122},{23,63,122},{23,61,2},{31,31,648}, +{19,63,74},{19,63,74},{16,55,1},{31,44,648},{16,55,1},{31,53,481},{27,63,269},{25,63,0},{21,63,0},{31,53,481},{31,57,481},{21,63,0},{0,59,481},{31,57,481},{0,59,481},{20,0,890},{20,0,890},{20,0,890},{20,0,890},{18,63,4},{18,63,4},{18,63,4},{18,52,5},{10,62,2},{10,62,2},{23,63,3399},{23,63,2260},{22,63,1530},{21,63,954},{23,63,3639},{20,63,1402},{19,63,238}, +{18,59,405},{17,63,3443},{13,60,297},{26,63,1009},{25,63,525},{25,63,164},{24,63,5},{29,52,1769},{23,63,918},{21,63,113},{14,60,266},{28,56,1769},{14,60,266},{22,63,1530},{22,63,1530},{22,63,1530},{21,63,954},{21,63,1251},{19,63,238},{19,63,238},{19,57,41},{14,63,1105},{14,58,81},{25,63,164},{25,63,164},{25,63,164},{24,62,5},{31,36,648},{21,63,113},{21,63,113},{17,57,1},{31,47,648}, +{17,57,1},{31,55,265},{28,63,145},{27,63,4},{24,63,1},{31,55,265},{30,60,265},{24,63,1},{0,60,265},{30,60,265},{0,60,265},{21,0,890},{21,0,890},{21,0,890},{21,0,890},{19,63,13},{19,63,13},{19,63,13},{19,54,5},{12,62,8},{12,62,8},{24,63,3069},{24,63,2257},{23,63,1683},{23,63,1054},{24,63,3258},{22,63,1330},{21,63,378},{19,61,213},{20,63,3102},{14,61,166},{27,63,801}, +{26,63,477},{26,63,221},{25,63,20},{30,52,1374},{24,63,758},{23,63,181},{16,61,114},{28,58,1374},{16,61,114},{23,63,1683},{23,63,1683},{23,63,1683},{23,63,1054},{22,63,1401},{21,63,378},{21,63,378},{19,59,46},{16,63,1296},{15,60,81},{26,63,221},{26,63,221},{26,63,221},{25,63,20},{30,45,648},{23,63,181},{23,63,181},{18,59,1},{31,50,648},{18,59,1},{31,58,113},{29,63,61},{28,63,0}, +{26,63,1},{31,58,113},{31,60,113},{26,63,1},{0,61,113},{31,60,113},{0,61,113},{22,0,890},{22,0,890},{22,0,890},{22,0,890},{20,63,45},{20,63,45},{20,63,45},{20,56,10},{13,63,25},{13,63,25},{25,63,2860},{25,63,2260},{24,63,1854},{24,63,1210},{25,63,2932},{23,63,1310},{22,63,609},{20,62,81},{21,63,2731},{16,62,94},{28,63,630},{27,63,475},{27,63,306},{26,63,101},{30,56,1032}, +{26,63,612},{25,63,290},{18,62,21},{30,58,1032},{18,62,21},{24,63,1854},{24,63,1854},{24,63,1854},{24,63,1210},{23,63,1620},{22,63,609},{22,63,609},{21,61,44},{18,63,1515},{16,62,78},{27,63,306},{27,63,306},{27,63,306},{26,63,101},{29,54,648},{25,63,290},{25,63,290},{19,61,5},{29,56,648},{19,61,5},{31,61,18},{30,63,10},{30,63,1},{29,63,0},{31,61,18},{31,62,18},{29,63,0}, +{0,62,20},{31,62,18},{0,62,20},{23,0,900},{23,0,900},{23,0,900},{23,0,900},{21,63,104},{21,63,104},{21,63,104},{21,59,5},{15,63,65},{15,63,65},{26,63,2626},{26,63,2206},{25,63,1915},{25,63,1315},{26,63,2641},{24,63,1333},{23,63,789},{22,63,40},{22,63,2445},{17,63,116},{29,63,524},{28,63,406},{28,63,325},{27,63,170},{31,56,771},{27,63,507},{26,63,320},{20,63,0},{30,60,771}, +{20,63,0},{25,63,1915},{25,63,1915},{25,63,1915},{25,63,1315},{24,63,1661},{23,63,789},{23,63,789},{22,62,29},{20,63,1517},{17,63,116},{28,63,325},{28,63,325},{28,63,325},{27,63,170},{31,52,578},{26,63,320},{26,63,320},{20,63,0},{28,60,578},{20,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{24,0,890}, +{24,0,890},{24,0,890},{24,0,890},{23,63,164},{23,63,164},{23,63,164},{22,61,5},{17,63,116},{17,63,116},{27,63,2156},{27,63,1884},{26,63,1630},{26,63,1210},{26,63,2081},{25,63,1108},{24,63,705},{23,63,5},{23,63,1927},{19,63,180},{29,63,300},{29,63,236},{29,63,200},{28,63,85},{31,57,451},{28,63,283},{27,63,194},{23,63,1},{29,62,451},{23,63,1},{26,63,1630},{26,63,1630},{26,63,1630}, +{26,63,1210},{25,63,1347},{24,63,705},{24,63,705},{23,63,5},{22,63,1229},{19,63,180},{29,63,200},{29,63,200},{29,63,200},{28,63,85},{30,58,338},{27,63,194},{27,63,194},{23,63,1},{31,58,338},{23,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{24,63,221}, +{24,63,221},{24,63,221},{23,63,5},{19,63,180},{19,63,180},{28,63,1782},{27,63,1564},{27,63,1395},{27,63,1123},{27,63,1620},{26,63,937},{25,63,651},{24,63,25},{24,63,1560},{21,63,233},{30,63,150},{30,63,134},{29,63,104},{29,63,40},{31,59,216},{29,63,136},{28,63,90},{25,63,1},{30,62,216},{25,63,1},{27,63,1395},{27,63,1395},{27,63,1395},{27,63,1123},{26,63,1101},{25,63,651},{25,63,651}, +{24,63,25},{23,63,998},{21,63,233},{29,63,104},{29,63,104},{29,63,104},{29,63,40},{31,57,162},{28,63,90},{28,63,90},{25,63,1},{29,62,162},{25,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{25,63,290},{25,63,290},{25,63,290},{24,63,25},{21,63,233}, +{21,63,233},{0,34,1570},{0,27,400},{0,19,25},{0,16,481},{0,23,3372},{0,17,2355},{0,15,1053},{0,11,2425},{0,13,3753},{0,11,2681},{0,34,1570},{0,27,400},{0,19,25},{0,16,481},{7,0,3371},{0,17,2355},{0,15,1053},{0,11,2425},{10,2,3371},{0,11,2425},{0,16,0},{0,16,0},{0,16,0},{0,10,1},{0,8,288},{0,7,149},{0,7,149},{0,5,160},{0,4,332},{0,4,200},{0,16,0}, +{0,16,0},{0,16,0},{0,10,1},{1,5,288},{0,7,149},{0,7,149},{0,5,160},{4,0,288},{0,5,160},{10,1,1568},{0,27,400},{0,19,25},{0,16,481},{10,1,1568},{17,0,1568},{0,16,481},{0,13,1568},{17,0,1568},{0,13,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,40,1568},{0,31,296},{0,22,2}, +{0,20,373},{0,27,3968},{0,21,2627},{0,17,1107},{0,13,2720},{0,15,4479},{0,11,3065},{0,40,1568},{0,31,296},{0,22,2},{0,20,373},{7,3,3968},{0,21,2627},{0,17,1107},{0,13,2720},{13,0,3968},{0,13,2720},{0,21,1},{0,21,1},{0,21,1},{0,13,0},{0,11,512},{0,9,269},{0,9,269},{0,5,288},{0,5,593},{0,5,337},{0,21,1},{0,21,1},{0,21,1},{0,13,0},{3,1,512}, +{0,9,269},{0,9,269},{0,5,288},{3,3,512},{0,5,288},{11,3,1568},{0,31,296},{0,22,2},{0,20,373},{11,3,1568},{18,2,1568},{0,20,373},{0,15,1568},{18,2,1568},{0,15,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,45,1568},{0,34,221},{0,24,17},{0,22,274},{0,30,4651},{0,23,2924},{0,19,1209}, +{0,15,3065},{0,17,5292},{0,13,3465},{0,45,1568},{0,34,221},{0,24,17},{0,22,274},{8,3,4651},{0,23,2924},{0,19,1209},{0,15,3065},{14,1,4651},{0,15,3065},{0,27,0},{0,27,0},{0,27,0},{0,16,0},{0,13,802},{0,12,424},{0,12,424},{0,7,433},{0,7,918},{0,7,533},{0,27,0},{0,27,0},{0,27,0},{0,16,0},{4,0,800},{0,12,424},{0,12,424},{0,7,433},{6,1,800}, +{0,7,433},{13,1,1568},{0,34,221},{1,24,2},{0,22,274},{13,1,1568},{19,4,1568},{0,22,274},{0,17,1570},{19,4,1568},{0,17,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,50,1568},{0,38,145},{0,26,82},{0,24,193},{0,34,5419},{0,25,3275},{0,21,1347},{0,16,3410},{0,17,6220},{0,15,3933},{0,50,1568}, +{0,38,145},{1,26,81},{0,24,193},{10,0,5419},{0,25,3275},{0,21,1347},{0,16,3410},{15,2,5419},{0,16,3410},{0,32,0},{0,32,0},{0,32,0},{0,19,0},{0,16,1152},{0,15,605},{0,15,605},{0,9,628},{0,8,1328},{0,7,789},{0,32,0},{0,32,0},{0,32,0},{0,19,0},{3,6,1152},{0,15,605},{0,15,605},{0,9,628},{8,0,1152},{0,9,628},{15,0,1568},{0,38,145},{2,26,2}, +{0,24,193},{15,0,1568},{24,1,1568},{0,24,193},{0,19,1570},{24,1,1568},{0,19,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,53,1633},{0,42,166},{1,29,162},{0,26,209},{0,40,5419},{0,29,3012},{0,25,964},{0,18,3152},{0,21,6513},{0,17,3861},{1,53,1569},{1,42,138},{2,28,74},{1,26,186},{11,3,5419}, +{0,29,3012},{0,25,964},{0,18,3152},{18,2,5419},{0,18,3152},{1,34,66},{1,34,66},{1,34,66},{1,21,66},{0,22,1152},{0,19,442},{0,19,442},{0,11,493},{0,11,1480},{0,11,749},{1,34,2},{1,34,2},{1,34,2},{1,21,2},{6,2,1152},{0,19,442},{0,19,442},{0,11,493},{11,0,1152},{0,11,493},{16,2,1568},{0,42,85},{3,28,0},{0,26,128},{16,2,1568},{27,1,1568},{0,26,128}, +{0,21,1568},{27,1,1568},{0,21,1568},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,6,0},{0,6,0},{0,6,0},{0,4,1},{0,3,20},{0,3,20},{1,58,1713},{1,44,230},{2,31,354},{1,28,273},{0,45,5419},{0,32,2817},{0,27,682},{0,20,2945},{0,25,6853},{0,19,3825},{2,55,1569},{2,44,138},{3,30,74},{2,28,186},{13,1,5419},{0,32,2817},{0,27,682},{0,20,2945},{19,4,5419}, +{0,20,2945},{1,40,145},{1,40,145},{1,40,145},{1,25,146},{0,27,1154},{0,23,338},{0,23,338},{0,13,394},{0,14,1665},{0,13,755},{2,36,2},{2,36,2},{2,36,2},{2,23,2},{8,0,1152},{0,23,338},{0,23,338},{0,13,394},{11,3,1152},{0,13,394},{17,4,1568},{0,46,41},{4,30,1},{0,29,80},{17,4,1568},{27,4,1568},{0,29,80},{0,23,1568},{27,4,1568},{0,23,1568},{1,0,145}, +{1,0,145},{1,0,145},{1,0,145},{0,11,1},{0,11,1},{0,11,1},{0,7,0},{0,5,74},{0,5,74},{2,60,1905},{1,49,393},{2,33,531},{1,31,433},{0,50,5419},{0,36,2609},{0,29,468},{0,22,2756},{0,27,7195},{0,21,3825},{3,57,1569},{3,46,138},{4,32,81},{3,30,186},{15,0,5419},{0,36,2609},{0,29,468},{0,22,2756},{24,1,5419},{0,22,2756},{2,42,337},{2,42,337},{2,42,337}, +{2,27,338},{0,32,1154},{0,25,244},{0,25,244},{0,16,289},{0,17,1849},{0,15,797},{3,38,2},{3,38,2},{3,38,2},{3,25,2},{9,2,1152},{0,25,244},{0,25,244},{0,16,289},{16,0,1152},{0,16,289},{18,6,1568},{0,51,16},{5,32,2},{0,31,41},{18,6,1568},{28,6,1568},{0,31,41},{0,25,1568},{28,6,1568},{0,25,1568},{2,0,337},{2,0,337},{2,0,337},{2,0,337},{0,17,0}, +{0,17,0},{0,17,0},{0,10,0},{0,7,164},{0,7,164},{2,63,2145},{2,51,585},{3,35,851},{2,33,618},{0,55,5420},{0,40,2425},{0,32,274},{0,24,2585},{0,29,7609},{0,23,3861},{4,58,1570},{4,47,136},{5,34,81},{4,32,193},{16,1,5419},{0,40,2425},{0,32,274},{0,24,2585},{25,3,5419},{0,24,2585},{2,47,545},{2,47,545},{2,47,545},{2,30,545},{0,38,1152},{0,29,164},{0,29,164}, +{0,18,208},{0,19,2098},{0,17,869},{4,40,0},{4,40,0},{4,40,0},{4,27,1},{11,1,1152},{0,29,164},{0,29,164},{0,18,208},{17,2,1152},{0,18,208},{21,1,1568},{0,54,2},{6,34,2},{0,33,13},{21,1,1568},{29,8,1568},{0,33,13},{0,27,1568},{29,8,1568},{0,27,1568},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,22,0},{0,22,0},{0,22,0},{0,13,1},{0,10,289}, +{0,10,289},{3,63,2596},{3,53,934},{3,37,1277},{2,35,964},{0,61,5420},{0,44,2242},{0,35,141},{0,28,2402},{0,32,8131},{0,25,3956},{5,61,1569},{5,50,138},{6,36,74},{5,34,186},{17,4,5419},{0,44,2242},{0,35,141},{0,28,2402},{27,4,5419},{0,28,2402},{3,49,901},{3,49,901},{3,49,901},{3,32,900},{0,44,1152},{0,34,97},{0,34,97},{0,20,145},{0,23,2436},{0,19,989},{5,43,1}, +{5,43,1},{5,43,1},{5,30,2},{13,0,1152},{0,34,97},{0,34,97},{0,20,145},{20,2,1152},{0,20,145},{23,0,1568},{1,57,2},{7,36,0},{0,36,1},{23,0,1568},{31,9,1568},{0,36,1},{0,29,1570},{31,9,1568},{0,29,1570},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{0,28,0},{0,28,0},{0,28,0},{0,17,1},{0,13,461},{0,13,461},{4,63,3146},{3,57,1262},{4,40,1731}, +{3,37,1284},{1,63,5484},{0,46,2129},{0,38,53},{0,30,2243},{0,36,8615},{0,27,4070},{6,63,1569},{6,52,138},{7,38,74},{6,36,186},{18,6,5419},{0,46,2129},{0,38,53},{0,30,2243},{28,6,5419},{0,30,2243},{3,55,1252},{3,55,1252},{3,55,1252},{3,35,1253},{0,49,1152},{0,38,53},{0,38,53},{0,23,89},{0,25,2763},{0,21,1139},{6,45,1},{6,45,1},{6,45,1},{6,32,2},{14,2,1152}, +{0,38,53},{0,38,53},{0,23,89},{24,0,1152},{0,23,89},{24,2,1568},{2,59,2},{8,38,1},{1,38,1},{24,2,1568},{27,17,1568},{1,38,1},{0,31,1570},{27,17,1568},{0,31,1570},{3,0,1252},{3,0,1252},{3,0,1252},{3,0,1252},{0,33,0},{0,33,0},{0,33,0},{0,20,0},{0,15,653},{0,15,653},{5,63,3716},{4,58,1599},{4,42,2134},{4,39,1627},{2,63,5655},{0,51,1983},{0,40,33}, +{0,32,2133},{0,38,8925},{0,30,4044},{7,63,1587},{7,54,138},{8,40,80},{7,38,186},{21,1,5419},{0,51,1979},{0,40,29},{0,32,2129},{29,8,5419},{0,32,2129},{4,56,1587},{4,56,1587},{4,56,1587},{4,37,1586},{0,54,1156},{0,41,29},{0,41,29},{0,25,54},{0,27,2988},{0,23,1193},{7,47,1},{7,47,1},{7,47,1},{7,33,2},{16,0,1152},{0,41,25},{0,41,25},{0,25,50},{26,1,1152}, +{0,25,50},{25,4,1568},{3,61,2},{9,40,1},{2,40,1},{25,4,1568},{28,19,1568},{2,40,1},{0,33,1568},{28,19,1568},{0,33,1568},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{0,38,5},{0,38,5},{0,38,5},{0,23,4},{0,17,754},{0,17,754},{6,63,3890},{5,60,1599},{5,44,2134},{5,41,1627},{3,63,5748},{0,55,1975},{1,42,33},{0,33,2085},{0,42,8569},{0,32,3525},{9,63,1634}, +{8,55,136},{9,42,80},{8,40,208},{22,3,5419},{0,55,1875},{1,42,29},{0,33,1985},{30,10,5419},{0,33,1985},{5,58,1587},{5,58,1587},{5,58,1587},{5,39,1586},{1,56,1156},{1,43,29},{1,43,29},{1,27,54},{0,31,2736},{0,25,907},{8,48,0},{8,48,0},{8,48,0},{8,35,1},{17,2,1152},{0,45,5},{0,45,5},{0,28,17},{27,3,1152},{0,28,17},{26,6,1568},{4,62,1},{10,42,1}, +{3,42,1},{26,6,1568},{29,21,1568},{3,42,1},{0,35,1568},{29,21,1568},{0,35,1568},{5,0,1586},{5,0,1586},{5,0,1586},{5,0,1586},{1,40,5},{1,40,5},{1,40,5},{1,25,4},{0,21,610},{0,21,610},{7,63,4136},{6,63,1589},{7,46,2141},{6,44,1613},{4,63,5895},{2,55,1973},{2,45,43},{2,35,2100},{0,46,8199},{0,34,3051},{10,63,1667},{9,57,131},{10,45,74},{9,43,195},{24,2,5419}, +{0,59,1772},{2,45,34},{0,36,1874},{27,17,5419},{0,36,1874},{6,61,1576},{6,61,1576},{6,61,1576},{6,41,1577},{2,59,1161},{2,46,26},{2,46,26},{2,30,49},{0,36,2505},{0,29,616},{9,51,1},{9,51,1},{9,51,1},{9,38,2},{19,1,1152},{0,49,2},{0,49,2},{0,30,4},{29,4,1152},{0,30,4},{28,5,1568},{6,63,13},{11,44,1},{4,44,1},{28,5,1568},{31,22,1568},{4,44,1}, +{0,37,1570},{31,22,1568},{0,37,1570},{6,0,1576},{6,0,1576},{6,0,1576},{6,0,1576},{2,43,9},{2,43,9},{2,43,9},{2,27,10},{0,25,468},{0,25,468},{8,63,4436},{7,63,1625},{7,49,2161},{7,46,1613},{6,63,6079},{3,57,1973},{3,47,43},{3,37,2100},{0,49,7908},{0,37,2671},{11,63,1745},{10,59,131},{11,47,74},{10,45,195},{25,4,5419},{0,61,1699},{3,47,34},{0,38,1787},{28,19,5419}, +{0,38,1787},{7,63,1576},{7,63,1576},{7,63,1576},{7,43,1577},{3,61,1161},{3,47,34},{3,47,34},{3,32,59},{0,38,2294},{0,31,422},{10,53,1},{10,53,1},{10,53,1},{10,40,2},{20,3,1152},{2,49,2},{2,49,2},{1,32,2},{30,6,1152},{1,32,2},{31,0,1568},{8,63,34},{12,46,1},{5,46,1},{31,0,1568},{28,29,1568},{5,46,1},{0,39,1570},{28,29,1568},{0,39,1570},{7,0,1576}, +{7,0,1576},{7,0,1576},{7,0,1576},{3,45,9},{3,45,9},{3,45,9},{3,29,10},{0,29,356},{0,29,356},{9,63,4730},{8,63,1716},{8,50,2134},{8,47,1627},{7,63,6244},{3,61,1977},{4,48,33},{3,40,2100},{0,53,7620},{0,40,2343},{12,63,1832},{11,61,131},{12,48,80},{11,47,195},{26,6,5419},{1,63,1699},{4,48,29},{0,41,1714},{29,21,5419},{0,41,1714},{8,63,1595},{8,63,1595},{8,63,1595}, +{8,45,1587},{4,62,1158},{4,49,29},{4,49,29},{4,33,54},{0,42,2098},{0,34,282},{11,55,1},{11,55,1},{11,55,1},{11,42,2},{21,5,1152},{3,51,2},{3,51,2},{2,34,2},{31,8,1152},{2,34,2},{30,9,1568},{9,63,68},{13,48,1},{6,48,1},{30,9,1568},{29,31,1568},{6,48,1},{0,41,1570},{29,31,1568},{0,41,1570},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{4,47,4}, +{4,47,4},{4,47,4},{4,31,5},{0,32,269},{0,32,269},{11,63,5010},{9,63,1878},{9,52,2134},{9,49,1627},{8,63,6508},{4,62,1965},{5,50,33},{4,42,2079},{0,55,7360},{0,42,2067},{14,63,1952},{12,63,149},{13,50,80},{12,48,208},{29,1,5419},{3,63,1787},{5,50,29},{0,43,1651},{30,23,5419},{0,43,1651},{9,63,1622},{9,63,1622},{9,63,1622},{9,47,1587},{5,63,1164},{5,51,29},{5,51,29}, +{5,35,54},{0,46,1926},{0,36,186},{12,56,0},{12,56,0},{12,56,0},{12,44,1},{24,0,1152},{3,55,2},{3,55,2},{3,36,2},{31,11,1152},{3,36,2},{31,11,1568},{11,63,116},{14,50,1},{7,50,1},{31,11,1568},{29,34,1568},{7,50,1},{0,43,1570},{29,34,1568},{0,43,1570},{9,0,1586},{9,0,1586},{9,0,1586},{9,0,1586},{5,48,5},{5,48,5},{5,48,5},{5,33,4},{0,36,185}, +{0,36,185},{12,63,5316},{11,63,2154},{11,54,2141},{10,52,1613},{10,63,6800},{6,62,1995},{6,53,43},{5,44,2085},{0,59,7068},{0,44,1845},{15,63,2081},{13,63,206},{14,53,74},{13,51,195},{31,0,5419},{5,63,1937},{6,53,34},{0,45,1601},{28,29,5419},{0,45,1601},{10,63,1676},{10,63,1676},{10,63,1676},{10,49,1577},{7,63,1179},{6,54,26},{6,54,26},{6,38,49},{0,49,1764},{0,40,149},{13,59,1}, +{13,59,1},{13,59,1},{13,46,1},{24,6,1152},{4,57,1},{4,57,1},{4,38,4},{29,17,1152},{4,38,4},{30,20,1568},{13,63,205},{15,52,1},{8,52,1},{30,20,1568},{31,35,1568},{8,52,1},{0,45,1576},{31,35,1568},{0,45,1576},{10,0,1576},{10,0,1576},{10,0,1576},{10,0,1576},{6,51,9},{6,51,9},{6,51,9},{6,35,10},{0,40,113},{0,40,113},{13,63,5658},{12,63,2435},{12,56,2148}, +{11,54,1613},{11,63,7055},{7,63,2090},{7,55,43},{6,46,2085},{0,63,6820},{0,47,1701},{16,63,2216},{14,63,334},{15,55,74},{14,53,195},{30,9,5419},{7,63,2081},{7,55,34},{0,47,1580},{29,31,5419},{0,47,1580},{11,63,1745},{11,63,1745},{11,63,1745},{11,51,1577},{8,63,1220},{7,56,26},{7,56,26},{7,40,49},{0,53,1624},{0,42,145},{14,61,1},{14,61,1},{14,61,1},{14,48,2},{27,1,1152}, +{5,59,1},{5,59,1},{5,40,4},{30,19,1152},{5,40,4},{31,22,1568},{15,63,289},{16,54,1},{9,54,1},{31,22,1568},{28,42,1568},{9,54,1},{0,47,1576},{28,42,1568},{0,47,1576},{11,0,1576},{11,0,1576},{11,0,1576},{11,0,1576},{7,53,9},{7,53,9},{7,53,9},{7,37,10},{0,44,61},{0,44,61},{14,63,6036},{13,63,2751},{12,58,2119},{12,55,1627},{12,63,7316},{8,63,2228},{8,57,31}, +{7,48,2100},{0,63,6884},{0,49,1606},{17,63,2402},{16,63,500},{16,57,82},{15,55,195},{31,11,5419},{9,63,2195},{8,57,27},{0,49,1570},{29,34,5419},{0,49,1570},{12,63,1811},{12,63,1811},{12,63,1811},{12,53,1587},{9,63,1286},{8,57,22},{8,57,22},{8,41,56},{0,57,1508},{1,44,145},{15,63,1},{15,63,1},{15,63,1},{15,50,2},{28,3,1152},{6,61,1},{6,61,1},{6,42,4},{31,21,1152}, +{6,42,4},{31,27,1568},{17,63,410},{17,56,1},{10,56,1},{31,27,1568},{29,44,1568},{10,56,1},{0,49,1570},{29,44,1568},{0,49,1570},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{8,55,4},{8,55,4},{8,55,4},{8,39,5},{0,48,34},{0,48,34},{15,63,6450},{14,63,3135},{13,60,2119},{13,57,1627},{13,63,7661},{10,63,2448},{9,59,31},{8,50,2079},{2,63,7196},{0,51,1580},{19,63,2594}, +{17,63,698},{16,59,73},{16,57,194},{31,16,5419},{11,63,2379},{9,59,27},{1,51,1570},{30,36,5419},{1,51,1570},{13,63,1910},{13,63,1910},{13,63,1910},{13,55,1587},{10,63,1388},{9,59,22},{9,59,22},{9,43,56},{0,61,1416},{2,46,145},{16,63,4},{16,63,4},{16,63,4},{16,52,1},{29,5,1152},{7,63,1},{7,63,1},{7,44,4},{31,24,1152},{7,44,4},{31,32,1568},{19,63,530},{18,58,1}, +{11,58,1},{31,32,1568},{30,46,1568},{11,58,1},{0,51,1570},{30,46,1568},{0,51,1570},{13,0,1586},{13,0,1586},{13,0,1586},{13,0,1586},{9,57,4},{9,57,4},{9,57,4},{9,41,5},{0,51,10},{0,51,10},{16,63,6900},{15,63,3657},{15,62,2128},{14,60,1616},{15,63,8023},{11,63,2845},{10,61,33},{9,52,2085},{5,63,7651},{1,54,1584},{20,63,2866},{18,63,1011},{18,61,69},{17,59,181},{31,22,5419}, +{13,63,2657},{10,61,24},{2,53,1577},{28,42,5419},{2,53,1577},{15,63,2057},{15,63,2057},{15,63,2057},{14,58,1577},{12,63,1476},{10,61,29},{10,61,29},{10,46,54},{0,63,1324},{4,47,137},{17,63,37},{17,63,37},{17,63,37},{17,54,1},{31,4,1152},{9,63,4},{9,63,4},{7,47,2},{30,29,1152},{7,47,2},{31,38,1568},{21,63,637},{19,60,5},{12,60,4},{31,38,1568},{31,48,1568},{12,60,4}, +{0,53,1576},{31,48,1568},{0,53,1576},{14,0,1576},{14,0,1576},{14,0,1576},{14,0,1576},{10,59,10},{10,59,10},{10,59,10},{10,44,10},{0,56,0},{0,56,0},{18,63,7332},{16,63,4196},{16,63,2175},{15,62,1616},{16,63,8348},{13,63,3285},{11,63,33},{10,54,2085},{8,63,8004},{2,56,1584},{21,63,3112},{20,63,1281},{19,63,69},{18,61,181},{31,27,5419},{15,63,2897},{11,63,24},{3,55,1577},{29,44,5419}, +{3,55,1577},{16,63,2171},{16,63,2171},{16,63,2171},{15,60,1577},{13,63,1590},{11,63,29},{11,63,29},{11,48,49},{2,63,1424},{4,50,145},{19,63,65},{19,63,65},{19,63,65},{18,56,1},{30,13,1152},{11,63,20},{11,63,20},{9,48,4},{31,31,1152},{9,48,4},{30,47,1568},{23,63,785},{20,62,4},{13,62,4},{30,47,1568},{31,51,1568},{13,62,4},{0,55,1576},{31,51,1568},{0,55,1576},{15,0,1576}, +{15,0,1576},{15,0,1576},{15,0,1576},{11,61,10},{11,61,10},{11,61,10},{11,46,10},{1,58,0},{1,58,0},{19,63,7014},{17,63,4230},{17,63,2294},{16,63,1595},{17,63,7865},{14,63,3114},{12,63,85},{12,55,1713},{8,63,7436},{3,57,1268},{22,63,2794},{21,63,1221},{20,63,113},{19,61,114},{31,31,4803},{17,63,2648},{13,63,61},{4,57,1253},{31,44,4803},{4,57,1253},{17,63,2294},{17,63,2294},{17,63,2294}, +{16,62,1587},{14,63,1740},{12,63,85},{12,63,85},{12,49,56},{3,63,1571},{5,52,145},{20,63,113},{20,63,113},{20,63,113},{19,58,1},{31,15,1152},{13,63,61},{13,63,61},{10,50,4},{31,34,1152},{10,50,4},{31,47,1250},{24,63,680},{21,63,4},{15,63,0},{31,47,1250},{31,53,1250},{15,63,0},{0,57,1252},{31,53,1250},{0,57,1252},{16,0,1586},{16,0,1586},{16,0,1586},{16,0,1586},{12,63,4}, +{12,63,4},{12,63,4},{12,47,8},{2,60,0},{2,60,0},{19,63,6534},{18,63,4116},{18,63,2435},{17,63,1590},{18,63,7164},{15,63,2809},{14,63,161},{12,57,1256},{10,63,6748},{5,58,909},{23,63,2340},{22,63,1065},{21,63,164},{20,62,41},{31,34,4056},{18,63,2211},{15,63,113},{6,58,884},{31,46,4056},{6,58,884},{18,63,2435},{18,63,2435},{18,63,2435},{17,63,1590},{16,63,1923},{14,63,161},{14,63,161}, +{13,51,56},{6,63,1729},{6,54,145},{21,63,164},{21,63,164},{21,63,164},{20,60,0},{31,20,1152},{15,63,113},{15,63,113},{11,52,4},{31,37,1152},{11,52,4},{31,49,882},{25,63,482},{23,63,0},{18,63,1},{31,49,882},{30,56,882},{18,63,1},{0,58,884},{30,56,882},{0,58,884},{17,0,1586},{17,0,1586},{17,0,1586},{17,0,1586},{13,63,13},{13,63,13},{13,63,13},{13,49,5},{3,62,0}, +{3,62,0},{21,63,6091},{20,63,4022},{19,63,2609},{18,63,1640},{19,63,6490},{16,63,2617},{15,63,318},{14,58,834},{11,63,6135},{6,59,598},{24,63,1881},{23,63,931},{22,63,245},{21,63,5},{31,38,3318},{20,63,1733},{17,63,202},{8,59,545},{31,48,3318},{8,59,545},{19,63,2609},{19,63,2609},{19,63,2609},{18,63,1640},{17,63,2086},{15,63,318},{15,63,318},{14,54,54},{8,63,1868},{8,55,137},{22,63,245}, +{22,63,245},{22,63,245},{21,62,2},{31,26,1152},{17,63,202},{17,63,202},{11,55,2},{30,42,1152},{11,55,2},{31,52,545},{26,63,305},{25,63,4},{20,63,1},{31,52,545},{30,58,545},{20,63,1},{0,59,545},{30,58,545},{0,59,545},{18,0,1576},{18,0,1576},{18,0,1576},{18,0,1576},{15,63,29},{15,63,29},{15,63,29},{14,52,10},{5,62,5},{5,62,5},{22,63,5719},{21,63,3980},{20,63,2834}, +{19,63,1745},{20,63,6050},{18,63,2457},{16,63,536},{15,59,515},{14,63,5674},{8,60,385},{25,63,1573},{24,63,861},{23,63,338},{22,63,10},{30,45,2753},{21,63,1438},{19,63,290},{10,60,313},{31,50,2753},{10,60,313},{20,63,2834},{20,63,2834},{20,63,2834},{19,63,1745},{18,63,2284},{16,63,536},{16,63,536},{15,56,54},{10,63,2064},{9,57,137},{23,63,338},{23,63,338},{23,63,338},{22,63,10},{31,31,1152}, +{19,63,290},{19,63,290},{12,57,2},{31,44,1152},{12,57,2},{31,55,313},{28,63,181},{26,63,1},{23,63,0},{31,55,313},{31,58,313},{23,63,0},{0,60,313},{31,58,313},{0,60,313},{19,0,1576},{19,0,1576},{19,0,1576},{19,0,1576},{16,63,52},{16,63,52},{16,63,52},{15,54,10},{7,62,25},{7,62,25},{22,63,5399},{22,63,3974},{21,63,3035},{20,63,1875},{21,63,5619},{19,63,2378},{18,63,776}, +{16,60,294},{15,63,5258},{9,61,225},{26,63,1333},{25,63,813},{24,63,425},{23,63,65},{29,52,2273},{23,63,1218},{20,63,353},{12,61,146},{28,56,2273},{12,61,146},{21,63,3035},{21,63,3035},{21,63,3035},{20,63,1875},{19,63,2518},{18,63,776},{18,63,776},{16,58,49},{11,63,2323},{10,59,137},{24,63,425},{24,63,425},{24,63,425},{23,63,65},{31,36,1152},{20,63,353},{20,63,353},{13,59,2},{31,47,1152}, +{13,59,2},{31,57,145},{28,63,85},{28,63,4},{26,63,1},{31,57,145},{31,60,145},{26,63,1},{0,61,145},{31,60,145},{0,61,145},{20,0,1586},{20,0,1586},{20,0,1586},{20,0,1586},{17,63,85},{17,63,85},{17,63,85},{16,56,5},{8,63,40},{8,63,40},{23,63,5143},{23,63,4004},{22,63,3254},{21,63,2070},{22,63,5274},{20,63,2310},{19,63,1062},{17,61,133},{17,63,5011},{10,63,161},{27,63,1161}, +{26,63,801},{26,63,545},{25,63,164},{30,52,1878},{24,63,1094},{22,63,461},{13,62,42},{28,58,1878},{13,62,42},{22,63,3254},{22,63,3254},{22,63,3254},{21,63,2070},{20,63,2833},{19,63,1062},{19,63,1062},{17,60,49},{14,63,2577},{11,61,137},{26,63,545},{26,63,545},{26,63,545},{25,63,164},{30,45,1152},{22,63,461},{22,63,461},{14,61,2},{31,50,1152},{14,61,2},{31,60,41},{30,63,25},{29,63,1}, +{28,63,0},{31,60,41},{31,61,41},{28,63,0},{0,62,41},{31,61,41},{0,62,41},{21,0,1586},{21,0,1586},{21,0,1586},{21,0,1586},{18,63,136},{18,63,136},{18,63,136},{17,58,5},{10,63,80},{10,63,80},{24,63,4882},{24,63,4070},{23,63,3532},{22,63,2360},{24,63,4945},{21,63,2422},{20,63,1433},{18,63,58},{20,63,4717},{12,63,157},{28,63,1026},{27,63,835},{27,63,666},{26,63,305},{30,56,1536}, +{26,63,996},{24,63,628},{16,63,1},{30,58,1536},{16,63,1},{23,63,3532},{23,63,3532},{23,63,3532},{22,63,2360},{22,63,3110},{20,63,1433},{20,63,1433},{18,62,50},{16,63,2939},{12,63,157},{27,63,666},{27,63,666},{27,63,666},{26,63,305},{29,54,1152},{24,63,628},{24,63,628},{16,63,1},{29,56,1152},{16,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0}, +{0,63,0},{31,63,0},{0,63,0},{22,0,1576},{22,0,1576},{22,0,1576},{22,0,1576},{19,63,221},{19,63,221},{19,63,221},{18,60,9},{12,63,157},{12,63,157},{25,63,4212},{24,63,3590},{24,63,3106},{23,63,2201},{24,63,4129},{22,63,2101},{21,63,1301},{19,63,13},{20,63,3869},{14,63,233},{28,63,706},{28,63,562},{28,63,481},{27,63,218},{30,58,1067},{27,63,699},{25,63,442},{18,63,1},{31,58,1067}, +{18,63,1},{24,63,3106},{24,63,3106},{24,63,3106},{23,63,2201},{23,63,2668},{21,63,1301},{21,63,1301},{19,63,13},{18,63,2523},{14,63,233},{28,63,481},{28,63,481},{28,63,481},{27,63,218},{31,50,800},{25,63,442},{25,63,442},{18,63,1},{31,55,800},{18,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{23,0,1576}, +{23,0,1576},{23,0,1576},{23,0,1576},{20,63,325},{20,63,325},{20,63,325},{19,62,9},{14,63,233},{14,63,233},{26,63,3642},{25,63,3132},{25,63,2771},{24,63,2070},{25,63,3444},{23,63,1834},{22,63,1205},{20,63,8},{21,63,3219},{16,63,346},{29,63,456},{28,63,370},{28,63,289},{28,63,145},{31,56,683},{28,63,451},{27,63,290},{21,63,1},{30,60,683},{21,63,1},{25,63,2771},{25,63,2771},{25,63,2771}, +{24,63,2070},{24,63,2273},{22,63,1205},{22,63,1205},{20,63,8},{20,63,2121},{16,63,346},{28,63,289},{28,63,289},{28,63,289},{28,63,145},{30,56,512},{27,63,290},{27,63,290},{21,63,1},{30,58,512},{21,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{24,0,1586},{24,0,1586},{24,0,1586},{24,0,1586},{22,63,421}, +{22,63,421},{22,63,421},{20,63,8},{16,63,346},{16,63,346},{26,63,3162},{26,63,2742},{26,63,2486},{25,63,1947},{26,63,2877},{24,63,1641},{23,63,1145},{22,63,52},{22,63,2673},{18,63,458},{29,63,264},{29,63,200},{29,63,164},{28,63,81},{31,58,384},{28,63,243},{28,63,162},{23,63,1},{31,60,384},{23,63,1},{26,63,2486},{26,63,2486},{26,63,2486},{25,63,1947},{24,63,1969},{23,63,1145},{23,63,1145}, +{22,63,52},{20,63,1785},{18,63,458},{29,63,164},{29,63,164},{29,63,164},{28,63,81},{31,55,288},{28,63,162},{28,63,162},{23,63,1},{28,62,288},{23,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{25,0,1586},{25,0,1586},{25,0,1586},{25,0,1586},{23,63,520},{23,63,520},{23,63,520},{22,63,52},{18,63,458}, +{18,63,458},{0,46,2665},{0,36,666},{0,26,37},{0,22,773},{0,31,5885},{0,23,4085},{0,21,1802},{0,15,4214},{0,17,6543},{0,13,4662},{0,46,2665},{0,36,666},{0,26,37},{0,22,773},{9,0,5885},{0,23,4085},{0,21,1802},{0,15,4214},{15,0,5885},{0,15,4214},{0,22,0},{0,22,0},{0,22,0},{0,13,1},{0,11,545},{0,10,289},{0,10,289},{0,6,306},{0,6,630},{0,5,362},{0,22,0}, +{0,22,0},{0,22,0},{0,13,1},{3,1,545},{0,10,289},{0,10,289},{0,6,306},{5,1,545},{0,6,306},{13,2,2665},{0,36,666},{0,26,37},{0,22,773},{13,2,2665},{23,0,2665},{0,22,773},{0,17,2665},{23,0,2665},{0,17,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,51,2665},{0,40,530},{0,28,2}, +{0,24,650},{0,34,6670},{0,27,4445},{0,23,1886},{0,16,4577},{0,19,7493},{0,15,5130},{0,51,2665},{0,40,530},{0,28,2},{0,24,650},{10,1,6669},{0,27,4445},{0,23,1886},{0,16,4577},{17,0,6669},{0,16,4577},{0,27,1},{0,27,1},{0,27,1},{0,16,1},{0,14,841},{0,13,442},{0,13,442},{0,7,458},{0,7,965},{0,7,558},{0,27,1},{0,27,1},{0,27,1},{0,16,1},{4,0,841}, +{0,13,442},{0,13,442},{0,7,458},{7,0,841},{0,7,458},{15,1,2665},{0,40,530},{0,28,2},{0,24,650},{15,1,2665},{25,0,2665},{0,24,650},{0,19,2665},{25,0,2665},{0,19,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,56,2665},{0,44,410},{0,30,17},{0,28,522},{0,38,7538},{0,29,4826},{0,25,2006}, +{0,18,5002},{0,21,8547},{0,16,5681},{0,56,2665},{0,44,410},{0,30,17},{0,28,522},{11,1,7538},{0,29,4826},{0,25,2006},{0,18,5002},{17,2,7538},{0,18,5002},{0,32,1},{0,32,1},{0,32,1},{0,19,1},{0,16,1201},{0,15,628},{0,15,628},{0,9,653},{0,9,1382},{0,9,822},{0,32,1},{0,32,1},{0,32,1},{0,19,1},{5,0,1201},{0,15,628},{0,15,628},{0,9,653},{8,0,1201}, +{0,9,653},{16,2,2665},{0,44,410},{1,30,2},{0,28,522},{16,2,2665},{28,0,2665},{0,28,522},{0,21,2665},{28,0,2665},{0,21,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,62,2665},{0,49,325},{0,33,65},{0,30,405},{0,41,8493},{0,31,5261},{0,27,2162},{0,20,5477},{0,23,9705},{0,18,6259},{0,62,2665}, +{0,49,325},{0,33,65},{0,30,405},{11,4,8493},{0,31,5261},{0,27,2162},{0,20,5477},{17,4,8493},{0,20,5477},{0,38,0},{0,38,0},{0,38,0},{0,23,1},{0,19,1625},{0,17,821},{0,17,821},{0,11,898},{0,10,1874},{0,9,1094},{0,38,0},{0,38,0},{0,38,0},{0,23,1},{5,2,1625},{0,17,821},{0,17,821},{0,11,898},{8,2,1625},{0,11,898},{18,1,2665},{0,49,325},{2,32,1}, +{0,30,405},{18,1,2665},{29,2,2665},{0,30,405},{0,23,2665},{29,2,2665},{0,23,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,63,2777},{0,51,221},{0,35,178},{0,32,306},{0,45,9669},{0,34,5810},{0,29,2382},{0,22,6054},{0,25,11123},{0,20,6989},{1,63,2741},{0,51,221},{1,35,137},{0,32,306},{13,1,9669}, +{0,34,5810},{0,29,2382},{0,22,6054},{19,4,9669},{0,22,6054},{0,44,0},{0,44,0},{0,44,0},{0,26,1},{0,22,2178},{0,19,1108},{0,19,1108},{0,11,1213},{0,11,2506},{0,11,1469},{0,44,0},{0,44,0},{0,44,0},{0,26,1},{6,2,2178},{0,19,1108},{0,19,1108},{0,11,1213},{11,0,2178},{0,11,1213},{20,0,2665},{0,51,221},{3,34,1},{0,32,306},{20,0,2665},{31,3,2665},{0,32,306}, +{0,25,2669},{31,3,2665},{0,25,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,63,2949},{0,55,209},{1,37,242},{0,35,285},{0,50,9669},{0,38,5486},{0,32,1938},{0,24,5733},{0,27,11477},{0,22,6887},{2,63,2789},{0,55,209},{2,37,137},{0,35,285},{15,0,9669},{0,38,5486},{0,32,1938},{0,24,5733},{24,1,9669}, +{0,24,5733},{1,46,64},{1,46,64},{1,46,64},{1,28,65},{0,27,2180},{0,23,932},{0,23,932},{0,15,1037},{0,14,2691},{0,13,1421},{1,46,0},{1,46,0},{1,46,0},{1,28,1},{8,0,2178},{0,23,932},{0,23,932},{0,15,1037},{11,3,2178},{0,15,1037},{21,2,2665},{0,55,145},{4,36,2},{0,35,221},{21,2,2665},{31,6,2665},{0,35,221},{0,27,2669},{31,6,2665},{0,27,2669},{0,0,64}, +{0,0,64},{0,0,64},{0,0,64},{0,5,1},{0,5,1},{0,5,1},{0,3,1},{0,3,17},{0,3,17},{2,63,3285},{1,57,273},{2,39,434},{1,37,349},{0,56,9670},{0,42,5186},{0,34,1530},{0,26,5430},{0,29,11903},{0,24,6821},{3,63,2873},{1,57,209},{3,39,137},{1,37,285},{16,1,9669},{0,42,5186},{0,34,1530},{0,26,5430},{25,3,9669},{0,26,5430},{1,51,128},{1,51,128},{1,51,128}, +{1,31,129},{0,32,2180},{0,27,772},{0,27,772},{0,16,865},{0,17,2875},{0,15,1409},{2,47,1},{2,47,1},{2,47,1},{2,30,1},{9,2,2178},{0,27,772},{0,27,772},{0,16,865},{16,0,2178},{0,16,865},{23,0,2665},{0,59,85},{5,38,2},{0,37,146},{23,0,2665},{31,9,2665},{0,37,146},{0,29,2669},{31,9,2665},{0,29,2669},{1,0,128},{1,0,128},{1,0,128},{1,0,128},{0,11,0}, +{0,11,0},{0,11,0},{0,6,1},{0,5,65},{0,5,65},{3,63,3785},{1,61,405},{2,41,653},{1,39,466},{0,61,9669},{0,44,4909},{0,36,1190},{0,28,5145},{0,32,12358},{0,26,6791},{4,63,2966},{2,59,209},{4,41,154},{2,39,285},{18,0,9669},{0,44,4909},{0,36,1190},{0,28,5145},{30,0,9669},{0,28,5145},{2,53,320},{2,53,320},{2,53,320},{2,33,321},{0,38,2178},{0,31,628},{0,31,628}, +{0,18,730},{0,19,3124},{0,17,1427},{3,49,1},{3,49,1},{3,49,1},{3,32,0},{11,1,2178},{0,31,628},{0,31,628},{0,18,730},{17,2,2178},{0,18,730},{24,2,2665},{0,63,41},{6,40,2},{0,39,89},{24,2,2665},{30,14,2665},{0,39,89},{0,31,2669},{30,14,2665},{0,31,2669},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,16,0},{0,16,0},{0,16,0},{0,10,1},{0,7,149}, +{0,7,149},{4,63,4514},{2,63,630},{3,45,1013},{2,41,681},{1,63,9738},{0,49,4610},{0,40,833},{0,30,4849},{0,36,12905},{0,29,6798},{6,63,3101},{4,60,208},{5,43,149},{3,41,286},{18,6,9669},{0,49,4610},{0,40,833},{0,30,4849},{28,6,9669},{0,30,4849},{2,59,545},{2,59,545},{2,59,545},{2,37,545},{0,44,2178},{0,34,493},{0,34,493},{0,22,584},{0,23,3462},{0,19,1493},{4,52,0}, +{4,52,0},{4,52,0},{4,34,1},{13,0,2178},{0,34,493},{0,34,493},{0,22,584},{20,2,2178},{0,22,584},{26,1,2665},{2,63,85},{7,42,4},{0,41,52},{26,1,2665},{31,16,2665},{0,41,52},{0,33,2669},{31,16,2665},{0,33,2669},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,22,0},{0,22,0},{0,22,0},{0,13,1},{0,10,289},{0,10,289},{4,63,5330},{3,63,1018},{3,47,1406}, +{2,43,966},{2,63,9981},{0,53,4366},{0,42,585},{0,33,4609},{0,38,13451},{0,31,6834},{7,63,3233},{5,62,208},{6,45,149},{4,42,285},{21,1,9669},{0,53,4366},{0,42,585},{0,33,4609},{29,8,9669},{0,33,4609},{3,61,865},{3,61,865},{3,61,865},{3,39,865},{0,49,2178},{0,38,377},{0,38,377},{0,24,461},{0,25,3789},{0,21,1589},{5,54,0},{5,54,0},{5,54,0},{5,36,1},{14,2,2178}, +{0,38,377},{0,38,377},{0,24,461},{24,0,2178},{0,24,461},{28,0,2665},{3,63,153},{8,44,5},{0,44,20},{28,0,2665},{31,19,2665},{0,44,20},{0,35,2669},{31,19,2665},{0,35,2669},{3,0,865},{3,0,865},{3,0,865},{3,0,865},{0,27,1},{0,27,1},{0,27,1},{0,16,1},{0,13,442},{0,13,442},{5,63,6270},{3,63,1626},{4,49,1866},{3,45,1286},{2,63,10381},{0,55,4133},{0,45,401}, +{0,35,4366},{0,42,14023},{0,32,6917},{8,63,3434},{6,63,242},{7,47,149},{5,44,285},{22,3,9669},{0,55,4133},{0,45,401},{0,35,4366},{30,10,9669},{0,35,4366},{3,63,1226},{3,63,1226},{3,63,1226},{3,42,1201},{0,54,2178},{0,42,277},{0,42,277},{0,26,356},{0,27,4170},{0,23,1721},{6,56,0},{6,56,0},{6,56,0},{6,38,1},{16,0,2178},{0,42,277},{0,42,277},{0,26,356},{26,1,2178}, +{0,26,356},{29,2,2665},{5,63,232},{9,46,5},{0,46,5},{29,2,2665},{31,22,2665},{0,46,5},{0,37,2669},{31,22,2665},{0,37,2669},{3,0,1201},{3,0,1201},{3,0,1201},{3,0,1201},{0,32,1},{0,32,1},{0,32,1},{0,19,1},{0,15,628},{0,15,628},{6,63,7374},{4,63,2339},{4,51,2411},{3,48,1715},{3,63,10950},{0,59,3909},{0,47,257},{0,37,4141},{0,44,14641},{0,34,7031},{9,63,3638}, +{7,63,320},{8,49,154},{6,46,285},{24,1,9669},{0,59,3909},{0,47,257},{0,37,4141},{31,12,9669},{0,37,4141},{4,63,1714},{4,63,1714},{4,63,1714},{4,44,1665},{0,59,2180},{0,46,193},{0,46,193},{0,28,269},{0,31,4582},{0,25,1889},{7,58,0},{7,58,0},{7,58,0},{7,40,1},{17,2,2178},{0,46,193},{0,46,193},{0,28,269},{27,3,2178},{0,28,269},{31,0,2665},{8,63,313},{10,48,2}, +{1,48,2},{31,0,2665},{30,27,2665},{1,48,2},{0,39,2669},{30,27,2665},{0,39,2669},{3,0,1665},{3,0,1665},{3,0,1665},{3,0,1665},{0,38,0},{0,38,0},{0,38,0},{0,23,1},{0,17,821},{0,17,821},{7,63,8807},{5,63,3388},{5,53,3082},{4,49,2230},{4,63,11766},{0,63,3686},{0,51,134},{0,39,3909},{0,46,15438},{0,37,7214},{11,63,3853},{8,63,457},{9,51,149},{7,49,286},{25,4,9669}, +{0,63,3686},{0,51,134},{0,39,3909},{28,19,9669},{0,39,3909},{5,63,2427},{5,63,2427},{5,63,2427},{4,47,2179},{0,63,2210},{0,49,128},{0,49,128},{0,31,193},{0,34,5117},{0,29,2123},{8,60,0},{8,60,0},{8,60,0},{8,42,1},{19,1,2178},{0,49,128},{0,49,128},{0,31,193},{29,4,2178},{0,31,193},{31,6,2665},{9,63,405},{11,50,4},{2,50,4},{31,6,2665},{31,29,2665},{2,50,4}, +{0,42,2669},{31,29,2665},{0,42,2669},{4,0,2178},{4,0,2178},{4,0,2178},{4,0,2178},{0,44,0},{0,44,0},{0,44,0},{0,26,1},{0,19,1108},{0,19,1108},{7,63,10230},{6,63,4421},{6,55,3705},{4,52,2725},{5,63,12634},{0,63,3719},{0,53,77},{0,41,3727},{0,51,15978},{0,39,7289},{12,63,4050},{10,63,629},{10,53,149},{8,50,285},{26,6,9669},{0,63,3718},{0,53,76},{0,41,3726},{29,21,9669}, +{0,41,3726},{5,63,3050},{5,63,3050},{5,63,3050},{5,49,2690},{1,63,2325},{0,53,73},{0,53,73},{0,33,118},{0,36,5499},{0,31,2266},{9,62,0},{9,62,0},{9,62,0},{9,44,1},{20,3,2178},{0,53,72},{0,53,72},{0,33,117},{30,6,2178},{0,33,117},{31,12,2665},{11,63,521},{12,52,5},{3,52,4},{31,12,2665},{31,32,2665},{3,52,4},{0,44,2669},{31,32,2665},{0,44,2669},{5,0,2689}, +{5,0,2689},{5,0,2689},{5,0,2689},{0,49,1},{0,49,1},{0,49,1},{0,29,2},{0,21,1341},{0,21,1341},{9,63,10738},{7,63,4899},{7,57,3705},{5,54,2725},{6,63,13045},{1,63,4002},{1,55,77},{0,43,3642},{0,53,15510},{0,42,6577},{13,63,4302},{11,63,857},{11,55,149},{9,52,285},{29,1,9669},{2,63,3954},{1,55,76},{0,43,3561},{30,23,9669},{0,43,3561},{6,63,3173},{6,63,3173},{6,63,3173}, +{6,51,2690},{2,63,2427},{1,55,73},{1,55,73},{1,35,118},{0,40,5171},{0,32,1846},{10,63,4},{10,63,4},{10,63,4},{10,46,1},{21,5,2178},{0,57,32},{0,57,32},{0,35,72},{31,8,2178},{0,35,72},{31,17,2665},{13,63,680},{13,54,5},{3,55,4},{31,17,2665},{31,35,2665},{3,55,4},{0,46,2669},{31,35,2665},{0,46,2669},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{1,51,1}, +{1,51,1},{1,51,1},{1,31,2},{0,25,1145},{0,25,1145},{10,63,11278},{8,63,5402},{8,58,3742},{6,56,2725},{7,63,13510},{3,63,4314},{2,57,77},{1,45,3642},{0,57,15046},{0,44,5927},{14,63,4590},{12,63,1171},{12,57,149},{10,54,285},{30,3,9669},{3,63,4265},{2,57,76},{0,45,3414},{31,25,9669},{0,45,3414},{7,63,3314},{7,63,3314},{7,63,3314},{7,53,2690},{4,63,2532},{2,57,73},{2,57,73}, +{2,37,118},{0,44,4867},{0,36,1470},{11,63,25},{11,63,25},{11,63,25},{11,48,1},{24,0,2178},{0,61,8},{0,61,8},{0,38,40},{31,11,2178},{0,38,40},{31,22,2665},{15,63,832},{14,56,5},{4,57,4},{31,22,2665},{30,40,2665},{4,57,4},{0,47,2677},{30,40,2665},{0,47,2677},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{2,53,1},{2,53,1},{2,53,1},{2,33,2},{0,29,965}, +{0,29,965},{11,63,11942},{10,63,6090},{9,62,3723},{8,58,2734},{9,63,14053},{4,63,4863},{3,59,79},{2,48,3633},{0,61,14558},{0,46,5283},{16,63,4858},{14,63,1556},{13,60,138},{11,57,299},{30,9,9669},{6,63,4594},{3,59,75},{0,48,3233},{29,31,9669},{0,48,3233},{9,63,3505},{9,63,3505},{9,63,3505},{8,55,2690},{5,63,2645},{3,61,72},{3,61,72},{3,39,117},{0,46,4539},{0,38,1091},{12,63,64}, +{12,63,64},{12,63,64},{12,50,1},{24,6,2178},{1,63,10},{1,63,10},{0,40,13},{29,17,2178},{0,40,13},{31,28,2665},{17,63,1053},{15,59,2},{5,59,2},{31,28,2665},{31,42,2665},{5,59,2},{0,50,2669},{31,42,2665},{0,50,2669},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{3,55,5},{3,55,5},{3,55,5},{3,36,5},{0,34,794},{0,34,794},{12,63,12466},{11,63,6718},{10,62,3738}, +{8,60,2723},{10,63,14554},{6,63,5363},{4,61,87},{3,50,3633},{0,63,14190},{0,49,4774},{17,63,5158},{15,63,1938},{14,62,138},{12,59,282},{31,11,9669},{8,63,4806},{4,61,86},{0,50,3110},{29,34,9669},{0,50,3110},{10,63,3658},{10,63,3658},{10,63,3658},{9,57,2690},{6,63,2795},{4,62,66},{4,62,66},{4,41,131},{0,51,4269},{0,40,833},{14,63,100},{14,63,100},{14,63,100},{13,52,1},{27,1,2178}, +{3,63,34},{3,63,34},{0,43,2},{30,19,2178},{0,43,2},{31,33,2665},{19,63,1241},{16,61,5},{6,61,2},{31,33,2665},{31,45,2665},{6,61,2},{0,52,2669},{31,45,2665},{0,52,2669},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{4,57,1},{4,57,1},{4,57,1},{4,37,2},{0,38,650},{0,38,650},{14,63,13094},{12,63,7445},{11,63,3830},{9,62,2723},{12,63,14998},{8,63,5926},{5,63,87}, +{4,51,3642},{0,63,14254},{0,51,4306},{18,63,5494},{16,63,2414},{15,63,146},{13,61,282},{31,16,9669},{10,63,5138},{5,63,86},{0,52,3005},{30,36,9669},{0,52,3005},{11,63,3829},{11,63,3829},{11,63,3829},{10,59,2690},{7,63,2981},{5,63,86},{5,63,86},{5,43,131},{0,53,4014},{0,44,601},{15,63,145},{15,63,145},{15,63,145},{14,54,1},{28,3,2178},{5,63,85},{5,63,85},{1,45,2},{31,21,2178}, +{1,45,2},{31,38,2665},{20,63,1378},{17,63,5},{7,63,2},{31,38,2665},{31,48,2665},{7,63,2},{0,54,2669},{31,48,2665},{0,54,2669},{10,0,2689},{10,0,2689},{10,0,2689},{10,0,2689},{5,59,1},{5,59,1},{5,59,1},{5,39,2},{0,40,520},{0,40,520},{15,63,12507},{13,63,7370},{12,63,4001},{11,63,2705},{13,63,14148},{8,63,5491},{6,63,154},{5,53,3033},{1,63,13399},{0,53,3297},{19,63,4949}, +{17,63,2261},{16,63,202},{15,61,185},{31,20,8712},{11,63,4644},{7,63,145},{0,54,2365},{31,37,8712},{0,54,2365},{12,63,4001},{12,63,4001},{12,63,4001},{11,61,2690},{9,63,3204},{6,63,154},{6,63,154},{6,45,131},{0,57,3762},{0,46,419},{16,63,202},{16,63,202},{16,63,202},{15,56,1},{29,5,2178},{7,63,145},{7,63,145},{2,47,2},{31,24,2178},{2,47,2},{30,45,2178},{22,63,1145},{18,63,1}, +{10,63,1},{30,45,2178},{31,50,2178},{10,63,1},{0,55,2180},{31,50,2178},{0,55,2180},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{6,61,1},{6,61,1},{6,61,1},{6,41,2},{0,44,400},{0,44,400},{16,63,11658},{14,63,7195},{13,63,4225},{12,63,2693},{14,63,13066},{10,63,5014},{8,63,261},{6,54,2366},{3,63,12366},{0,55,2274},{20,63,4338},{18,63,2037},{17,63,289},{16,62,80},{31,24,7578}, +{13,63,4037},{9,63,202},{0,55,1698},{29,42,7578},{0,55,1698},{13,63,4225},{13,63,4225},{13,63,4225},{12,63,2693},{10,63,3429},{8,63,261},{8,63,261},{7,47,132},{0,61,3509},{0,49,290},{17,63,289},{17,63,289},{17,63,289},{16,59,0},{31,4,2178},{9,63,202},{9,63,202},{3,49,2},{30,29,2178},{3,49,2},{31,44,1625},{23,63,850},{20,63,0},{13,63,1},{31,44,1625},{31,52,1625},{13,63,1}, +{0,56,1625},{31,52,1625},{0,56,1625},{12,0,2689},{12,0,2689},{12,0,2689},{12,0,2689},{7,63,5},{7,63,5},{7,63,5},{7,44,4},{0,49,289},{0,49,289},{16,63,11002},{15,63,7081},{14,63,4450},{13,63,2738},{15,63,12205},{11,63,4663},{9,63,411},{7,55,1813},{4,63,11643},{0,56,1550},{21,63,3802},{20,63,1845},{18,63,388},{17,62,25},{31,27,6661},{15,63,3525},{11,63,290},{0,57,1217},{29,44,6661}, +{0,57,1217},{14,63,4450},{14,63,4450},{14,63,4450},{13,63,2738},{11,63,3675},{9,63,411},{9,63,411},{8,49,131},{0,63,3354},{0,51,222},{18,63,388},{18,63,388},{18,63,388},{17,61,0},{30,13,2178},{11,63,290},{11,63,290},{4,51,2},{31,31,2178},{4,51,2},{31,47,1201},{24,63,653},{22,63,4},{15,63,1},{31,47,1201},{31,53,1201},{15,63,1},{0,57,1201},{31,53,1201},{0,57,1201},{13,0,2689}, +{13,0,2689},{13,0,2689},{13,0,2689},{8,63,17},{8,63,17},{8,63,17},{8,46,2},{0,53,205},{0,53,205},{17,63,10434},{16,63,7010},{15,63,4693},{14,63,2833},{16,63,11374},{12,63,4462},{10,63,629},{8,56,1358},{6,63,10895},{0,57,1002},{22,63,3334},{20,63,1701},{19,63,505},{18,63,0},{31,31,5829},{16,63,3145},{12,63,405},{1,58,842},{31,44,5829},{1,58,842},{15,63,4693},{15,63,4693},{15,63,4693}, +{14,63,2833},{12,63,3906},{10,63,629},{10,63,629},{9,51,131},{1,63,3525},{0,54,218},{19,63,505},{19,63,505},{19,63,505},{18,63,0},{31,15,2178},{12,63,405},{12,63,405},{5,53,2},{31,34,2178},{5,53,2},{31,49,841},{25,63,461},{23,63,1},{18,63,0},{31,49,841},{31,55,841},{18,63,0},{0,58,841},{31,55,841},{0,58,841},{14,0,2689},{14,0,2689},{14,0,2689},{14,0,2689},{9,63,50}, +{9,63,50},{9,63,50},{9,48,2},{0,57,137},{0,57,137},{18,63,9934},{17,63,6962},{16,63,4913},{15,63,2978},{17,63,10683},{13,63,4277},{11,63,915},{9,58,974},{8,63,10078},{0,59,630},{23,63,2934},{22,63,1605},{21,63,650},{19,63,25},{31,34,5082},{18,63,2769},{14,63,521},{2,59,546},{31,46,5082},{2,59,546},{16,63,4913},{16,63,4913},{16,63,4913},{15,63,2978},{14,63,4170},{11,63,915},{11,63,915}, +{10,53,131},{3,63,3789},{1,56,218},{21,63,650},{21,63,650},{21,63,650},{19,63,25},{31,20,2178},{14,63,521},{14,63,521},{6,55,2},{31,37,2178},{6,55,2},{31,52,545},{26,63,305},{25,63,4},{20,63,1},{31,52,545},{30,58,545},{20,63,1},{0,59,545},{30,58,545},{0,59,545},{15,0,2689},{15,0,2689},{15,0,2689},{15,0,2689},{11,63,74},{11,63,74},{11,63,74},{10,49,2},{0,59,85}, +{0,59,85},{19,63,9465},{18,63,6955},{17,63,5233},{16,63,3218},{18,63,10003},{14,63,4183},{13,63,1258},{11,58,645},{9,63,9445},{1,61,409},{24,63,2529},{23,63,1525},{22,63,785},{20,63,100},{31,38,4344},{20,63,2345},{16,63,698},{4,60,289},{31,48,4344},{4,60,289},{17,63,5233},{17,63,5233},{17,63,5233},{16,63,3218},{15,63,4491},{13,63,1258},{13,63,1258},{11,56,120},{5,63,4171},{2,59,213},{22,63,785}, +{22,63,785},{22,63,785},{20,63,100},{31,26,2178},{16,63,698},{16,63,698},{7,57,0},{30,42,2178},{7,57,0},{31,55,288},{28,63,162},{26,63,4},{23,63,1},{31,55,288},{28,62,288},{23,63,1},{0,60,288},{28,62,288},{0,60,288},{16,0,2689},{16,0,2689},{16,0,2689},{16,0,2689},{12,63,113},{12,63,113},{12,63,113},{11,52,4},{0,63,45},{0,63,45},{20,63,9219},{19,63,6985},{18,63,5530}, +{17,63,3473},{19,63,9496},{15,63,4186},{14,63,1630},{11,60,404},{11,63,8961},{3,61,277},{25,63,2275},{24,63,1509},{23,63,932},{22,63,208},{30,45,3779},{21,63,2086},{18,63,850},{6,61,129},{31,50,3779},{6,61,129},{18,63,5530},{18,63,5530},{18,63,5530},{17,63,3473},{16,63,4770},{14,63,1630},{14,63,1630},{12,57,129},{8,63,4442},{3,61,213},{23,63,932},{23,63,932},{23,63,932},{22,63,208},{31,31,2178}, +{18,63,850},{18,63,850},{8,59,1},{31,44,2178},{8,59,1},{31,58,128},{29,63,72},{28,63,1},{26,63,0},{31,58,128},{31,60,128},{26,63,0},{0,61,128},{31,60,128},{0,61,128},{17,0,2689},{17,0,2689},{17,0,2689},{17,0,2689},{13,63,170},{13,63,170},{13,63,170},{12,54,2},{2,63,89},{2,63,89},{21,63,8929},{20,63,7062},{19,63,5845},{18,63,3778},{20,63,9188},{17,63,4260},{15,63,2070}, +{13,61,234},{13,63,8680},{4,62,212},{26,63,2089},{25,63,1515},{24,63,1073},{23,63,353},{29,52,3299},{22,63,1913},{20,63,965},{8,62,32},{28,56,3299},{8,62,32},{19,63,5845},{19,63,5845},{19,63,5845},{18,63,3778},{17,63,5124},{15,63,2070},{15,63,2070},{13,59,129},{9,63,4725},{4,62,196},{24,63,1073},{24,63,1073},{24,63,1073},{23,63,353},{31,36,2178},{20,63,965},{20,63,965},{9,61,1},{31,47,2178}, +{9,61,1},{31,60,34},{30,63,18},{29,63,4},{28,63,1},{31,60,34},{31,61,34},{28,63,1},{0,62,32},{31,61,34},{0,62,32},{18,0,2689},{18,0,2689},{18,0,2689},{18,0,2689},{14,63,245},{14,63,245},{14,63,245},{13,56,2},{4,63,164},{4,63,164},{22,63,8707},{21,63,7170},{21,63,6209},{19,63,4133},{21,63,8853},{18,63,4387},{17,63,2548},{14,62,154},{14,63,8388},{6,63,244},{27,63,1971}, +{26,63,1557},{25,63,1250},{24,63,565},{30,52,2904},{23,63,1826},{22,63,1145},{10,63,1},{28,58,2904},{10,63,1},{21,63,6209},{21,63,6209},{21,63,6209},{19,63,4133},{19,63,5460},{17,63,2548},{17,63,2548},{14,61,129},{11,63,5085},{6,63,244},{25,63,1250},{25,63,1250},{25,63,1250},{24,63,565},{30,45,2178},{22,63,1145},{22,63,1145},{10,63,1},{31,50,2178},{10,63,1},{31,63,0},{31,63,0},{31,63,0}, +{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{19,0,2689},{19,0,2689},{19,0,2689},{19,0,2689},{15,63,338},{15,63,338},{15,63,338},{14,58,2},{6,63,244},{6,63,244},{23,63,7705},{22,63,6418},{21,63,5633},{20,63,3845},{22,63,7654},{19,63,3874},{18,63,2310},{15,63,53},{15,63,7258},{8,63,317},{27,63,1458},{27,63,1186},{26,63,932},{25,63,425},{30,54,2166}, +{25,63,1398},{23,63,850},{13,63,1},{29,58,2166},{13,63,1},{21,63,5633},{21,63,5633},{21,63,5633},{20,63,3845},{19,63,4830},{18,63,2310},{18,63,2310},{15,62,45},{13,63,4506},{8,63,317},{26,63,932},{26,63,932},{26,63,932},{25,63,425},{31,44,1625},{23,63,850},{23,63,850},{13,63,1},{31,52,1625},{13,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0}, +{0,63,0},{31,63,0},{0,63,0},{20,0,2689},{20,0,2689},{20,0,2689},{20,0,2689},{16,63,449},{16,63,449},{16,63,449},{15,60,4},{8,63,317},{8,63,317},{24,63,6881},{23,63,5814},{22,63,5138},{21,63,3650},{23,63,6713},{20,63,3400},{19,63,2142},{16,63,5},{17,63,6397},{9,63,425},{28,63,1075},{27,63,866},{27,63,697},{26,63,320},{30,56,1601},{26,63,1041},{24,63,653},{15,63,1},{30,58,1601}, +{15,63,1},{22,63,5138},{22,63,5138},{22,63,5138},{21,63,3650},{21,63,4313},{19,63,2142},{19,63,2142},{16,63,5},{14,63,3981},{9,63,425},{27,63,697},{27,63,697},{27,63,697},{26,63,320},{31,47,1201},{24,63,653},{24,63,653},{15,63,1},{31,53,1201},{15,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{21,0,2689}, +{21,0,2689},{21,0,2689},{21,0,2689},{18,63,549},{18,63,549},{18,63,549},{16,62,1},{9,63,425},{9,63,425},{24,63,6097},{24,63,5285},{23,63,4693},{22,63,3473},{23,63,5833},{21,63,3067},{20,63,1988},{17,63,10},{18,63,5571},{11,63,541},{28,63,739},{28,63,595},{27,63,505},{27,63,233},{31,54,1121},{26,63,737},{25,63,461},{18,63,0},{29,60,1121},{18,63,0},{23,63,4693},{23,63,4693},{23,63,4693}, +{22,63,3473},{22,63,3845},{20,63,1988},{20,63,1988},{17,63,10},{15,63,3542},{11,63,541},{27,63,505},{27,63,505},{27,63,505},{27,63,233},{31,49,841},{25,63,461},{25,63,461},{18,63,0},{31,55,841},{18,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{22,0,2689},{22,0,2689},{22,0,2689},{22,0,2689},{19,63,666}, +{19,63,666},{19,63,666},{17,63,10},{11,63,541},{11,63,541},{25,63,5427},{24,63,4757},{24,63,4273},{23,63,3314},{24,63,5002},{22,63,2788},{21,63,1898},{18,63,65},{20,63,4714},{13,63,698},{29,63,489},{28,63,387},{28,63,306},{28,63,162},{31,56,726},{27,63,482},{26,63,305},{20,63,1},{30,60,726},{20,63,1},{24,63,4273},{24,63,4273},{24,63,4273},{23,63,3314},{22,63,3429},{21,63,1898},{21,63,1898}, +{18,63,65},{17,63,3213},{13,63,698},{28,63,306},{28,63,306},{28,63,306},{28,63,162},{31,52,545},{26,63,305},{26,63,305},{20,63,1},{30,58,545},{20,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{23,0,2689},{23,0,2689},{23,0,2689},{23,0,2689},{20,63,832},{20,63,832},{20,63,832},{18,63,65},{13,63,698}, +{13,63,698},{4,63,33740},{0,63,5184},{0,45,446},{0,43,4126},{3,63,45594},{0,59,24105},{0,42,8295},{0,37,24703},{0,44,64117},{0,34,38807},{2,63,9704},{0,61,2866},{0,44,386},{0,37,3205},{14,4,18065},{0,38,13219},{0,34,6147},{0,24,13496},{25,0,18065},{0,24,13496},{0,31,1},{0,31,1},{0,31,1},{0,19,1},{0,16,1105},{0,15,584},{0,15,584},{0,9,605},{0,8,1273},{0,7,750},{0,31,1}, +{0,31,1},{0,31,1},{0,19,1},{4,2,1105},{0,15,584},{0,15,584},{0,9,605},{8,0,1105},{0,9,605},{21,5,9248},{0,61,2866},{0,44,386},{0,37,3205},{21,5,9248},{31,8,9248},{0,37,3205},{0,28,9256},{31,8,9248},{0,28,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,63,38380},{1,63,6614},{0,47,261}, +{0,45,3769},{4,63,50747},{0,63,24961},{0,44,8337},{0,39,25658},{0,46,65535},{0,36,41267},{2,63,10152},{0,63,2624},{0,46,221},{0,41,2929},{16,0,19334},{0,42,13795},{0,36,6237},{0,26,14121},{26,1,19334},{0,26,14121},{0,36,1},{0,36,1},{0,36,1},{0,22,0},{0,18,1513},{0,17,769},{0,17,769},{0,9,845},{0,9,1742},{0,9,1014},{0,36,1},{0,36,1},{0,36,1},{0,22,0},{5,1,1513}, +{0,17,769},{0,17,769},{0,9,845},{9,0,1513},{0,9,845},{24,0,9248},{0,63,2624},{0,46,221},{0,41,2929},{24,0,9248},{31,11,9248},{0,41,2929},{0,30,9256},{31,11,9248},{0,30,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,63,43788},{1,63,8598},{0,49,121},{0,47,3430},{4,63,56155},{0,63,26241},{0,46,8415}, +{0,41,26663},{0,46,65535},{0,36,43795},{3,63,10706},{0,63,2624},{0,48,116},{0,43,2650},{17,0,20689},{0,44,14404},{0,38,6363},{0,28,14796},{26,3,20689},{0,28,14796},{0,42,0},{0,42,0},{0,42,0},{0,25,0},{0,21,1985},{0,19,1009},{0,19,1009},{0,11,1090},{0,11,2281},{0,11,1346},{0,42,0},{0,42,0},{0,42,0},{0,25,0},{6,1,1985},{0,19,1009},{0,19,1009},{0,11,1090},{9,2,1985}, +{0,11,1090},{25,2,9248},{0,63,2624},{0,48,116},{0,43,2650},{25,2,9248},{27,19,9248},{0,43,2650},{0,32,9250},{27,19,9248},{0,32,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,63,49566},{1,63,11350},{0,51,36},{0,50,3105},{4,63,62331},{0,63,28289},{0,48,8549},{0,43,27718},{0,49,65535},{0,38,46395},{4,63,11395}, +{0,63,2880},{0,51,36},{0,45,2389},{17,4,22129},{0,46,15067},{0,40,6525},{0,28,15500},{27,4,22129},{0,28,15500},{0,47,0},{0,47,0},{0,47,0},{0,28,1},{0,24,2521},{0,21,1285},{0,21,1285},{0,13,1385},{0,12,2905},{0,11,1714},{0,47,0},{0,47,0},{0,47,0},{0,28,1},{7,0,2521},{0,21,1285},{0,21,1285},{0,13,1385},{11,1,2521},{0,13,1385},{26,4,9248},{1,63,2866},{0,51,36}, +{0,45,2389},{26,4,9248},{28,21,9248},{0,45,2389},{0,34,9250},{28,21,9248},{0,34,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,63,56892},{2,63,15166},{0,53,5},{0,52,2726},{5,63,65535},{0,63,31511},{0,51,8735},{0,45,28953},{0,53,65535},{0,40,49505},{4,63,12385},{1,63,3380},{0,53,1},{0,47,2120},{19,1,23851}, +{0,49,15876},{0,42,6761},{0,30,16331},{29,4,23851},{0,30,16331},{0,53,0},{0,53,0},{0,53,0},{0,32,1},{0,27,3200},{0,23,1640},{0,23,1640},{0,15,1769},{0,13,3689},{0,13,2169},{0,53,0},{0,53,0},{0,53,0},{0,32,1},{7,3,3200},{0,23,1640},{0,23,1640},{0,15,1769},{13,0,3200},{0,15,1769},{28,3,9248},{3,63,3204},{0,53,1},{0,47,2120},{28,3,9248},{31,21,9248},{0,47,2120}, +{0,36,9256},{31,21,9248},{0,36,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,63870},{2,63,19230},{0,55,30},{0,54,2429},{5,63,65535},{1,63,35016},{0,53,8921},{0,47,30108},{0,55,65535},{0,42,52385},{5,63,13379},{2,63,4026},{0,56,18},{0,50,1885},{20,1,25472},{0,53,16616},{0,46,6989},{0,33,17105},{29,6,25472}, +{0,33,17105},{0,58,0},{0,58,0},{0,58,0},{0,35,0},{0,29,3874},{0,25,1994},{0,25,1994},{0,16,2129},{0,15,4454},{0,15,2637},{0,58,0},{0,58,0},{0,58,0},{0,35,0},{8,2,3872},{0,25,1994},{0,25,1994},{0,16,2129},{12,3,3872},{0,16,2129},{29,5,9248},{5,63,3589},{1,55,1},{0,50,1885},{29,5,9248},{31,24,9248},{0,50,1885},{0,38,9256},{31,24,9248},{0,38,9256},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,65535},{2,63,24002},{0,57,109},{0,56,2154},{6,63,65535},{1,63,38780},{0,55,8815},{0,48,30807},{0,57,65535},{0,44,54965},{6,63,14345},{2,63,4766},{1,58,54},{0,52,1670},{20,5,26744},{0,55,17059},{0,46,7005},{0,33,17609},{31,6,26744},{0,33,17609},{0,63,5},{0,63,5},{0,63,5}, +{0,38,4},{0,32,4420},{0,29,2210},{0,29,2210},{0,18,2378},{0,17,5115},{0,16,2981},{0,63,5},{0,63,5},{0,63,5},{0,38,4},{9,2,4418},{0,29,2210},{0,29,2210},{0,18,2378},{16,0,4418},{0,18,2378},{30,7,9248},{8,63,3904},{2,57,1},{0,52,1666},{30,7,9248},{28,31,9248},{0,52,1666},{0,40,9256},{28,31,9248},{0,40,9256},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1}, +{0,1,1},{0,1,1},{0,1,0},{0,1,1},{0,1,1},{7,63,65535},{3,63,29032},{0,60,314},{0,58,1989},{6,63,65535},{2,63,42151},{0,57,7781},{0,50,30102},{0,59,65535},{0,46,56345},{7,63,14819},{3,63,5416},{2,60,54},{0,54,1565},{23,0,26744},{0,59,16547},{0,49,6177},{0,37,17105},{31,9,26744},{0,37,17105},{1,63,84},{1,63,84},{1,63,84},{1,40,68},{0,38,4418},{0,31,1972},{0,31,1972}, +{0,20,2129},{0,19,5364},{0,18,2915},{1,63,20},{1,63,20},{1,63,20},{1,40,4},{11,1,4418},{0,31,1972},{0,31,1972},{0,20,2129},{17,2,4418},{0,20,2129},{31,9,9248},{8,63,4160},{3,59,1},{0,54,1465},{31,9,9248},{28,34,9248},{0,54,1465},{0,42,9256},{28,34,9248},{0,42,9256},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{0,7,0},{0,7,0},{0,7,0},{0,4,0},{0,3,25}, +{0,3,25},{7,63,65535},{3,63,35719},{1,62,657},{0,60,1985},{7,63,65535},{2,63,46660},{0,59,6696},{0,52,29368},{0,63,65535},{0,49,58301},{9,63,15473},{5,63,6173},{3,62,45},{1,56,1566},{23,6,26744},{0,63,15992},{0,53,5318},{0,39,16547},{30,14,26744},{0,39,16547},{2,63,329},{2,63,329},{2,63,329},{1,44,186},{0,44,4418},{0,36,1709},{0,36,1709},{0,22,1872},{0,23,5702},{0,20,2885},{3,63,34}, +{3,63,34},{3,63,34},{2,42,10},{13,0,4418},{0,36,1709},{0,36,1709},{0,22,1872},{20,2,4418},{0,22,1872},{31,15,9248},{10,63,4570},{4,61,4},{0,56,1268},{31,15,9248},{31,34,9248},{0,56,1268},{0,45,9250},{31,34,9248},{0,45,9250},{1,0,185},{1,0,185},{1,0,185},{1,0,185},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{0,6,97},{0,6,97},{7,63,65535},{4,63,40786},{1,63,1122}, +{0,62,2034},{7,63,65535},{2,63,49800},{0,61,5634},{0,54,27965},{0,63,65535},{0,49,58553},{10,63,15531},{6,63,6593},{4,63,61},{2,58,1482},{25,4,26259},{0,63,15284},{0,55,4484},{0,41,15722},{28,19,26259},{0,41,15722},{2,63,633},{2,63,633},{2,63,633},{2,46,378},{0,49,4418},{0,40,1489},{0,40,1489},{0,24,1665},{0,25,6029},{0,22,2897},{4,63,61},{4,63,61},{4,63,61},{3,44,10},{14,2,4418}, +{0,40,1489},{0,40,1489},{0,24,1665},{24,0,4418},{0,24,1665},{31,19,8978},{11,63,4744},{5,63,0},{0,58,1025},{31,19,8978},{30,38,8978},{0,58,1025},{0,46,8986},{30,38,8978},{0,46,8986},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,18,0},{0,18,0},{0,18,0},{0,11,0},{0,8,193},{0,8,193},{8,63,65535},{4,63,40898},{1,63,1890},{1,62,2029},{7,63,65535},{3,63,47871},{0,61,4194}, +{0,56,24760},{0,63,65535},{0,49,55881},{11,63,14325},{8,63,6051},{5,63,100},{3,58,1197},{27,1,24371},{0,63,13716},{0,57,3402},{0,41,13914},{30,19,24371},{0,41,13914},{3,63,1058},{3,63,1058},{3,63,1058},{2,49,618},{0,54,4418},{0,44,1285},{0,44,1285},{0,26,1476},{0,27,6410},{0,25,2937},{5,63,100},{5,63,100},{5,63,100},{4,46,5},{16,0,4418},{0,44,1285},{0,44,1285},{0,26,1476},{26,1,4418}, +{0,26,1476},{31,22,7938},{13,63,4225},{7,63,4},{0,60,628},{31,22,7938},{28,42,7938},{0,60,628},{0,47,7946},{28,42,7938},{0,47,7946},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{0,11,320},{0,11,320},{8,63,65535},{4,63,41266},{1,63,2914},{1,62,2109},{7,63,65535},{3,63,46175},{0,61,3010},{0,56,21624},{0,63,65535},{0,51,53461},{12,63,13140}, +{8,63,5571},{6,63,157},{4,59,932},{28,1,22568},{0,63,12404},{0,57,2474},{0,43,12155},{30,21,22568},{0,43,12155},{4,63,1630},{4,63,1630},{4,63,1630},{3,51,938},{0,59,4420},{0,46,1117},{0,46,1117},{0,30,1280},{0,31,6822},{0,27,3009},{6,63,157},{6,63,157},{6,63,157},{5,48,4},{17,2,4418},{0,46,1117},{0,46,1117},{0,30,1280},{27,3,4418},{0,30,1280},{30,28,6962},{14,63,3709},{8,63,1}, +{0,60,340},{30,28,6962},{31,40,6962},{0,60,340},{0,48,6964},{31,40,6962},{0,48,6964},{3,0,937},{3,0,937},{3,0,937},{3,0,937},{0,29,0},{0,29,0},{0,29,0},{0,17,0},{0,13,482},{0,13,482},{9,63,65535},{5,63,41956},{2,63,4257},{1,62,2505},{7,63,65535},{3,63,44573},{0,62,1944},{0,56,18402},{0,63,65535},{0,51,50815},{13,63,11930},{10,63,5125},{7,63,250},{5,59,701},{28,5,20642}, +{1,63,11209},{0,59,1634},{0,45,10346},{31,22,20642},{0,45,10346},{4,63,2350},{4,63,2350},{4,63,2350},{3,54,1361},{0,63,4450},{0,51,914},{0,51,914},{0,32,1097},{0,34,7357},{0,29,3131},{7,63,250},{7,63,250},{7,63,250},{6,50,10},{19,1,4418},{0,51,914},{0,51,914},{0,32,1097},{29,4,4418},{0,32,1097},{31,27,5941},{15,63,3176},{10,63,0},{0,62,116},{31,27,5941},{31,42,5941},{0,62,116}, +{0,49,5945},{31,42,5941},{0,49,5945},{3,0,1360},{3,0,1360},{3,0,1360},{3,0,1360},{0,34,1},{0,34,1},{0,34,1},{0,21,1},{0,17,706},{0,17,706},{9,63,65535},{5,63,42660},{2,63,5617},{1,63,3088},{8,63,65535},{3,63,43421},{0,62,1240},{0,56,15810},{0,63,65535},{0,51,48735},{13,63,10922},{11,63,4753},{8,63,360},{6,61,509},{29,5,19021},{2,63,10246},{0,61,1088},{0,47,8885},{31,24,19021}, +{0,47,8885},{5,63,3131},{5,63,3131},{5,63,3131},{4,56,1818},{1,63,4580},{0,55,754},{0,55,754},{0,35,928},{0,36,7846},{0,31,3281},{8,63,360},{8,63,360},{8,63,360},{7,52,10},{20,3,4418},{0,55,754},{0,55,754},{0,35,928},{30,6,4418},{0,35,928},{31,30,5101},{17,63,2777},{11,63,9},{0,62,20},{31,30,5101},{31,43,5101},{0,62,20},{0,50,5105},{31,43,5101},{0,50,5105},{4,0,1818}, +{4,0,1818},{4,0,1818},{4,0,1818},{0,40,0},{0,40,0},{0,40,0},{0,24,0},{0,17,914},{0,17,914},{9,63,65535},{5,63,43620},{2,63,7233},{1,63,3920},{8,63,65535},{3,63,42525},{0,63,738},{0,58,13413},{0,63,65535},{0,51,46911},{14,63,9978},{11,63,4449},{10,63,452},{8,60,344},{31,2,17485},{3,63,9369},{0,61,704},{0,48,7498},{29,29,17485},{0,48,7498},{6,63,4058},{6,63,4058},{6,63,4058}, +{4,59,2315},{2,63,4874},{0,59,610},{0,59,610},{0,37,769},{0,38,8389},{0,32,3497},{10,63,452},{10,63,452},{10,63,452},{8,54,5},{21,5,4418},{0,59,610},{0,59,610},{0,37,769},{31,8,4418},{0,37,769},{31,32,4325},{18,63,2357},{13,63,0},{1,63,0},{31,32,4325},{31,45,4325},{1,63,0},{0,51,4329},{31,45,4325},{0,51,4329},{4,0,2314},{4,0,2314},{4,0,2314},{4,0,2314},{0,45,0}, +{0,45,0},{0,45,0},{0,27,0},{0,19,1184},{0,19,1184},{9,63,65535},{5,63,44836},{2,63,9105},{2,63,4905},{8,63,65535},{3,63,41885},{0,63,482},{0,58,11125},{0,63,65535},{0,51,45343},{15,63,9102},{13,63,4161},{11,63,557},{9,61,212},{30,9,16034},{5,63,8602},{0,63,482},{0,48,6250},{29,31,16034},{0,48,6250},{6,63,5066},{6,63,5066},{6,63,5066},{5,61,2907},{2,63,5322},{0,63,482},{0,63,482}, +{0,39,628},{0,42,8965},{0,36,3717},{11,63,557},{11,63,557},{11,63,557},{9,56,5},{24,0,4418},{0,63,482},{0,63,482},{0,39,628},{31,11,4418},{0,39,628},{31,35,3613},{20,63,1940},{15,63,4},{4,63,1},{31,35,3613},{28,50,3613},{4,63,1},{0,52,3617},{28,50,3613},{0,52,3617},{5,0,2906},{5,0,2906},{5,0,2906},{5,0,2906},{0,50,0},{0,50,0},{0,50,0},{0,30,1},{0,23,1480}, +{0,23,1480},{9,63,65535},{5,63,46510},{3,63,11362},{2,63,6237},{9,63,65535},{3,63,41471},{0,63,500},{0,58,8857},{0,63,65535},{0,53,43697},{16,63,8139},{14,63,3853},{12,63,680},{10,62,89},{30,13,14504},{8,63,7667},{0,63,500},{0,50,4961},{31,31,14504},{0,50,4961},{7,63,6337},{7,63,6337},{7,63,6337},{5,63,3642},{3,63,5962},{0,63,500},{0,63,500},{0,41,493},{0,44,9656},{0,38,3995},{12,63,680}, +{12,63,680},{12,63,680},{10,59,10},{24,6,4418},{0,63,500},{0,63,500},{0,41,493},{29,17,4418},{0,41,493},{31,38,2888},{20,63,1517},{16,63,1},{7,63,1},{31,38,2888},{31,48,2888},{7,63,1},{0,53,2896},{31,48,2888},{0,53,2896},{5,0,3617},{5,0,3617},{5,0,3617},{5,0,3617},{0,56,0},{0,56,0},{0,56,0},{0,34,1},{0,25,1853},{0,25,1853},{10,63,65535},{6,63,48082},{3,63,13570}, +{2,63,7693},{9,63,65535},{3,63,41375},{0,63,788},{0,58,7113},{0,63,65535},{0,53,42465},{17,63,7409},{15,63,3625},{13,63,821},{11,62,34},{31,13,13235},{8,63,6899},{2,63,628},{0,52,3956},{30,34,13235},{0,52,3956},{7,63,7681},{7,63,7681},{7,63,7681},{6,63,4437},{4,63,6659},{1,63,738},{1,63,738},{0,43,394},{0,46,10331},{0,40,4289},{13,63,821},{13,63,821},{13,63,821},{11,61,10},{27,1,4418}, +{2,63,628},{2,63,628},{0,43,394},{30,19,4418},{0,43,394},{31,41,2312},{21,63,1217},{18,63,1},{9,63,0},{31,41,2312},{29,52,2312},{9,63,0},{0,54,2320},{29,52,2312},{0,54,2320},{6,0,4337},{6,0,4337},{6,0,4337},{6,0,4337},{0,61,1},{0,61,1},{0,61,1},{0,37,0},{0,27,2225},{0,27,2225},{10,63,65535},{6,63,49890},{3,63,16034},{2,63,9405},{9,63,65535},{4,63,41526},{0,63,1332}, +{0,59,5520},{0,63,65535},{0,53,41489},{18,63,6747},{16,63,3459},{14,63,980},{12,63,5},{30,20,12051},{10,63,6275},{4,63,801},{0,53,3089},{31,35,12051},{0,53,3089},{8,63,9062},{8,63,9062},{8,63,9062},{7,63,5410},{4,63,7555},{1,63,1154},{1,63,1154},{0,46,306},{0,49,11046},{0,42,4619},{14,63,980},{14,63,980},{14,63,980},{12,62,5},{28,3,4418},{4,63,801},{4,63,801},{0,46,306},{31,21,4418}, +{0,46,306},{30,47,1800},{23,63,949},{19,63,4},{12,63,1},{30,47,1800},{31,51,1800},{12,63,1},{0,55,1808},{31,51,1800},{0,55,1808},{6,0,5105},{6,0,5105},{6,0,5105},{6,0,5105},{0,63,36},{0,63,36},{0,63,36},{0,40,0},{0,29,2633},{0,29,2633},{10,63,65535},{6,63,51954},{3,63,18754},{3,63,11330},{9,63,65535},{4,63,41798},{1,63,2082},{0,60,4084},{0,63,65535},{0,53,40769},{19,63,6153}, +{17,63,3297},{16,63,1154},{13,63,20},{31,20,10952},{11,63,5708},{6,63,965},{0,54,2281},{31,37,10952},{0,54,2281},{9,63,10545},{9,63,10545},{9,63,10545},{7,63,6482},{5,63,8549},{2,63,1716},{2,63,1716},{0,48,208},{0,53,11786},{0,44,4985},{16,63,1154},{16,63,1154},{16,63,1154},{13,63,20},{29,5,4418},{6,63,965},{6,63,965},{0,48,208},{31,24,4418},{0,48,208},{31,46,1352},{23,63,725},{21,63,0}, +{14,63,1},{31,46,1352},{30,54,1352},{14,63,1},{0,56,1360},{30,54,1352},{0,56,1360},{7,0,5953},{7,0,5953},{7,0,5953},{7,0,5953},{1,63,145},{1,63,145},{1,63,145},{0,43,1},{0,31,3077},{0,31,3077},{10,63,65535},{6,63,54582},{4,63,21886},{3,63,13652},{9,63,65535},{4,63,42410},{1,63,3144},{0,60,2770},{0,63,65535},{0,55,40127},{19,63,5649},{18,63,3157},{17,63,1325},{15,63,74},{31,24,9818}, +{13,63,5241},{8,63,1108},{0,56,1538},{29,42,9818},{0,56,1538},{10,63,12376},{10,63,12376},{10,63,12376},{8,63,7844},{6,63,9861},{3,63,2576},{3,63,2576},{0,50,145},{0,55,12659},{0,46,5441},{17,63,1325},{17,63,1325},{17,63,1325},{15,63,74},{31,4,4418},{8,63,1108},{8,63,1108},{0,50,145},{30,29,4418},{0,50,145},{31,49,925},{25,63,505},{23,63,1},{17,63,1},{31,49,925},{30,56,925},{17,63,1}, +{0,58,929},{30,56,925},{0,58,929},{7,0,6970},{7,0,6970},{7,0,6970},{7,0,6970},{1,63,388},{1,63,388},{1,63,388},{0,47,0},{0,34,3625},{0,34,3625},{10,63,65535},{7,63,57052},{4,63,24910},{3,63,15988},{9,63,65535},{4,63,43226},{1,63,4360},{0,61,1833},{0,63,65535},{0,55,39743},{21,63,5202},{19,63,3073},{18,63,1508},{16,63,180},{31,27,8901},{14,63,4814},{10,63,1300},{0,57,1021},{29,44,8901}, +{0,57,1021},{10,63,14136},{10,63,14136},{10,63,14136},{8,63,9252},{7,63,11195},{3,63,3536},{3,63,3536},{0,53,89},{0,59,13491},{0,49,5921},{18,63,1508},{18,63,1508},{18,63,1508},{16,63,180},{30,13,4418},{10,63,1300},{10,63,1300},{0,53,89},{31,31,4418},{0,53,89},{31,51,613},{26,63,337},{24,63,1},{20,63,1},{31,51,613},{31,56,613},{20,63,1},{0,59,617},{31,56,613},{0,59,617},{8,0,7956}, +{8,0,7956},{8,0,7956},{8,0,7956},{2,63,697},{2,63,697},{2,63,697},{0,50,0},{0,36,4141},{0,36,4141},{11,63,65535},{7,63,59708},{4,63,28190},{3,63,18580},{10,63,65535},{5,63,44295},{1,63,5832},{0,61,1081},{0,63,65535},{0,55,39615},{22,63,4818},{20,63,3017},{19,63,1709},{17,63,325},{31,31,8069},{15,63,4473},{11,63,1514},{0,58,593},{31,44,8069},{0,58,593},{11,63,15965},{11,63,15965},{11,63,15965}, +{9,63,10757},{7,63,12667},{4,63,4662},{4,63,4662},{0,55,50},{0,61,14340},{0,51,6395},{19,63,1709},{19,63,1709},{19,63,1709},{17,63,325},{31,15,4418},{11,63,1514},{11,63,1514},{0,55,50},{31,34,4418},{0,55,50},{31,54,365},{27,63,205},{26,63,1},{22,63,1},{31,54,365},{31,58,365},{22,63,1},{0,60,369},{31,58,365},{0,60,369},{8,0,8980},{8,0,8980},{8,0,8980},{8,0,8980},{2,63,1097}, +{2,63,1097},{2,63,1097},{0,53,0},{0,40,4689},{0,40,4689},{11,63,65535},{8,63,58981},{5,63,29551},{4,63,19751},{10,63,65535},{5,63,43215},{2,63,6910},{1,62,614},{0,63,65535},{0,57,34909},{23,63,4502},{21,63,3011},{20,63,1973},{18,63,520},{31,34,7322},{17,63,4242},{13,63,1769},{0,60,274},{31,46,7322},{0,60,274},{12,63,16739},{12,63,16739},{12,63,16739},{10,63,11492},{8,63,13636},{5,63,5510},{5,63,5510}, +{0,58,53},{0,63,14139},{0,53,5981},{20,63,1973},{20,63,1973},{20,63,1973},{18,63,520},{31,20,4418},{13,63,1769},{13,63,1769},{0,58,17},{31,37,4418},{0,58,17},{31,57,181},{28,63,97},{27,63,4},{25,63,0},{31,57,181},{31,59,181},{25,63,0},{0,61,185},{31,59,181},{0,61,185},{9,0,9248},{9,0,9248},{9,0,9248},{9,0,9248},{3,63,1348},{3,63,1348},{3,63,1348},{1,55,4},{0,42,4545}, +{0,42,4545},{12,63,65535},{9,63,57270},{6,63,30345},{5,63,20521},{11,63,65535},{6,63,41449},{3,63,8015},{2,62,242},{0,63,65535},{0,57,28330},{24,63,4181},{22,63,3053},{21,63,2248},{20,63,772},{31,38,6584},{20,63,3941},{15,63,2041},{0,61,77},{31,48,6584},{0,61,77},{13,63,17289},{13,63,17289},{13,63,17289},{11,63,12050},{10,63,14315},{7,63,6389},{7,63,6389},{2,60,41},{0,63,13860},{0,55,5252},{21,63,2248}, +{21,63,2248},{21,63,2248},{20,63,772},{31,26,4418},{15,63,2041},{15,63,2041},{0,60,4},{30,42,4418},{0,60,4},{31,60,50},{30,63,34},{29,63,0},{28,63,1},{31,60,50},{31,61,50},{28,63,1},{0,62,52},{31,61,50},{0,62,52},{10,0,9250},{10,0,9250},{10,0,9250},{10,0,9250},{4,63,1549},{4,63,1549},{4,63,1549},{2,57,2},{0,46,4141},{0,46,4141},{13,63,65535},{9,63,55894},{7,63,31068}, +{6,63,21256},{12,63,65535},{8,63,39740},{4,63,9073},{3,63,90},{0,63,65535},{0,59,23356},{24,63,3973},{23,63,3125},{23,63,2500},{21,63,1037},{30,45,6019},{20,63,3701},{17,63,2340},{0,63,4},{31,50,6019},{0,63,4},{14,63,17796},{14,63,17796},{14,63,17796},{12,63,12625},{11,63,14957},{8,63,7139},{8,63,7139},{3,62,41},{0,63,14020},{0,59,4652},{23,63,2500},{23,63,2500},{23,63,2500},{21,63,1037},{31,31,4418}, +{17,63,2340},{17,63,2340},{1,62,4},{31,44,4418},{1,62,4},{31,62,4},{31,63,4},{31,63,4},{30,63,1},{31,62,4},{31,63,4},{30,63,1},{0,63,4},{31,63,4},{0,63,4},{11,0,9250},{11,0,9250},{11,0,9250},{11,0,9250},{6,63,1765},{6,63,1765},{6,63,1765},{3,59,2},{0,51,3816},{0,51,3816},{13,63,65535},{10,63,53236},{8,63,30487},{7,63,21105},{13,63,65535},{8,63,37332},{5,63,9177}, +{4,63,36},{1,63,65535},{0,59,18680},{25,63,3443},{24,63,2741},{23,63,2248},{22,63,980},{31,44,5163},{21,63,3218},{20,63,2117},{3,63,1},{29,54,5163},{3,63,1},{15,63,17289},{15,63,17289},{15,63,17289},{13,63,12512},{12,63,14328},{9,63,7149},{9,63,7149},{4,63,20},{0,63,13376},{0,59,3944},{23,63,2248},{23,63,2248},{23,63,2248},{22,63,980},{31,34,3872},{20,63,2117},{20,63,2117},{3,63,1},{31,46,3872}, +{3,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{12,0,9248},{12,0,9248},{12,0,9248},{12,0,9248},{7,63,1972},{7,63,1972},{7,63,1972},{4,61,5},{0,55,3488},{0,55,3488},{14,63,65535},{11,63,50266},{9,63,29322},{8,63,20567},{13,63,65535},{9,63,35025},{6,63,8985},{5,63,21},{2,63,65535},{0,59,14712},{26,63,2873}, +{25,63,2283},{24,63,1825},{22,63,820},{29,52,4267},{22,63,2657},{20,63,1685},{5,63,1},{28,56,4267},{5,63,1},{16,63,16427},{16,63,16427},{16,63,16427},{14,63,12185},{13,63,13442},{10,63,6915},{10,63,6915},{5,63,5},{1,63,12539},{0,61,3314},{24,63,1825},{24,63,1825},{24,63,1825},{22,63,820},{31,37,3200},{20,63,1685},{20,63,1685},{5,63,1},{27,52,3200},{5,63,1},{31,63,0},{31,63,0},{31,63,0}, +{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{13,0,9248},{13,0,9248},{13,0,9248},{13,0,9248},{8,63,2250},{8,63,2250},{8,63,2250},{5,63,5},{0,57,3170},{0,57,3170},{15,63,65535},{12,63,47239},{10,63,28065},{9,63,20104},{14,63,65535},{10,63,32574},{7,63,8839},{6,63,54},{3,63,64890},{0,61,10964},{26,63,2252},{25,63,1806},{25,63,1445},{23,63,650},{29,54,3361}, +{23,63,2091},{21,63,1322},{8,63,0},{29,56,3361},{8,63,0},{17,63,15584},{17,63,15584},{17,63,15584},{15,63,11846},{14,63,12522},{11,63,6697},{11,63,6697},{6,63,50},{3,63,11669},{0,63,2834},{25,63,1445},{25,63,1445},{25,63,1445},{23,63,650},{31,40,2521},{21,63,1322},{21,63,1322},{8,63,0},{31,49,2521},{8,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0}, +{0,63,0},{31,63,0},{0,63,0},{14,0,9250},{14,0,9250},{14,0,9250},{14,0,9250},{9,63,2525},{9,63,2525},{9,63,2525},{6,63,50},{0,63,2834},{0,63,2834},{16,63,65535},{13,63,44559},{11,63,27000},{10,63,19705},{15,63,64179},{11,63,30525},{8,63,8677},{7,63,149},{3,63,60570},{0,61,8308},{27,63,1782},{26,63,1416},{25,63,1157},{24,63,520},{31,49,2646},{23,63,1691},{22,63,1040},{11,63,1},{30,56,2646}, +{11,63,1},{18,63,14889},{18,63,14889},{18,63,14889},{16,63,11585},{15,63,11778},{12,63,6555},{12,63,6555},{7,63,145},{3,63,11061},{0,63,2610},{25,63,1157},{25,63,1157},{25,63,1157},{24,63,520},{31,42,1985},{22,63,1040},{22,63,1040},{11,63,1},{30,52,1985},{11,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{15,0,9250}, +{15,0,9250},{15,0,9250},{15,0,9250},{10,63,2792},{10,63,2792},{10,63,2792},{7,63,145},{0,63,2610},{0,63,2610},{16,63,63318},{14,63,42019},{12,63,25930},{11,63,19324},{16,63,59178},{11,63,28845},{9,63,8605},{8,63,276},{6,63,56253},{0,61,6420},{27,63,1366},{27,63,1094},{26,63,872},{25,63,397},{31,51,2017},{25,63,1298},{23,63,794},{13,63,1},{31,56,2017},{13,63,1},{19,63,14244},{19,63,14244},{19,63,14244}, +{17,63,11312},{16,63,11037},{13,63,6429},{13,63,6429},{8,63,260},{6,63,10457},{0,63,2642},{26,63,872},{26,63,872},{26,63,872},{25,63,397},{31,45,1513},{23,63,794},{23,63,794},{13,63,1},{31,52,1513},{13,63,1},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{16,0,9248},{16,0,9248},{16,0,9248},{16,0,9248},{12,63,3074}, +{12,63,3074},{12,63,3074},{8,63,260},{0,63,2642},{0,63,2642},{17,63,58848},{15,63,39619},{13,63,24975},{12,63,19007},{16,63,54474},{13,63,27057},{10,63,8569},{9,63,461},{8,63,51302},{0,63,5046},{28,63,979},{27,63,806},{27,63,637},{26,63,292},{30,56,1473},{26,63,953},{24,63,605},{16,63,0},{30,58,1473},{16,63,0},{19,63,13604},{19,63,13604},{19,63,13604},{18,63,11057},{16,63,10429},{14,63,6339},{14,63,6339}, +{10,63,424},{8,63,9713},{1,63,2900},{27,63,637},{27,63,637},{27,63,637},{26,63,292},{31,48,1105},{24,63,605},{24,63,605},{16,63,0},{31,54,1105},{16,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{31,63,0},{0,63,0},{31,63,0},{0,63,0},{17,0,9248},{17,0,9248},{17,0,9248},{17,0,9248},{12,63,3330},{12,63,3330},{12,63,3330},{10,63,424},{1,63,2900}, +{1,63,2900}, diff --git a/ext/basis_universal/basisu_transcoder_tables_bc7_m5_alpha.inc b/ext/basis_universal/basisu_transcoder_tables_bc7_m5_alpha.inc new file mode 100644 index 0000000000..6669852923 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_bc7_m5_alpha.inc @@ -0,0 +1,49 @@ +{7,0,47},{7,0,44},{2,0,15},{2,0,12},{8,2,48},{0,0,0},{15,0,27},{15,1,24},{9,0,7},{15,1,24},{23,3,96},{6,0,3},{24,7,27},{24,7,24},{18,3,6},{18,5,4},{24,5,16},{21,1,6},{32,15,27},{32,15,24},{26,11,6},{26,13,4},{32,13,16},{22,3,1},{41,24,27},{41,24,24},{35,20,6},{35,22,4},{41,22,16},{31,12,1},{49,32,27}, +{49,32,24},{43,28,6},{43,30,4},{49,30,16},{39,20,1},{57,40,27},{57,40,24},{51,36,6},{51,38,4},{57,38,16},{47,28,1},{65,48,27},{65,48,24},{59,44,6},{59,46,4},{65,46,16},{55,36,1},{74,57,27},{74,57,24},{68,53,6},{68,55,4},{74,55,16},{64,45,1},{82,65,27},{82,65,24},{76,61,6},{76,63,4},{82,63,16},{72,53,1},{90,73,27},{90,73,24},{84,69,6}, +{84,71,4},{90,71,16},{80,61,1},{98,81,27},{98,81,24},{92,77,6},{92,79,4},{98,79,16},{88,69,1},{107,90,27},{107,90,24},{101,86,6},{101,88,4},{107,88,16},{97,78,1},{115,98,27},{115,98,24},{109,94,6},{109,96,4},{115,96,16},{105,86,1},{123,106,27},{123,106,24},{117,102,6},{117,104,4},{123,104,16},{113,94,1},{131,114,27},{131,114,24},{125,110,6},{125,112,4},{131,112,16}, +{121,102,1},{140,123,27},{140,123,24},{134,119,6},{134,121,4},{140,121,16},{130,111,1},{148,131,27},{148,131,24},{142,127,6},{142,129,4},{148,129,16},{138,119,1},{156,139,27},{156,139,24},{150,135,6},{150,137,4},{156,137,16},{146,127,1},{164,147,27},{164,147,24},{158,143,6},{158,145,4},{164,145,16},{154,135,1},{173,156,27},{173,156,24},{167,152,6},{167,154,4},{173,154,16},{163,144,1},{181,164,27}, +{181,164,24},{175,160,6},{175,162,4},{181,162,16},{171,152,1},{189,172,27},{189,172,24},{183,168,6},{183,170,4},{189,170,16},{179,160,1},{197,180,27},{197,180,24},{191,176,6},{191,178,4},{197,178,16},{187,168,1},{206,189,27},{206,189,24},{200,185,6},{200,187,4},{206,187,16},{196,177,1},{214,197,27},{214,197,24},{208,193,6},{208,195,4},{214,195,16},{204,185,1},{222,205,27},{222,205,24},{216,201,6}, +{216,203,4},{222,203,16},{212,193,1},{230,213,27},{230,213,24},{224,209,6},{224,211,4},{230,211,16},{220,201,1},{239,222,27},{239,222,24},{233,218,6},{233,220,4},{239,220,16},{229,210,1},{247,230,27},{247,230,24},{241,226,6},{241,228,4},{247,228,16},{237,218,1},{255,238,27},{255,238,24},{249,234,6},{249,236,4},{255,236,16},{245,226,1},{255,247,7},{255,248,4},{255,247,7},{255,248,4},{255,0,0}, +{253,234,1},{16,0,47},{16,0,44},{5,0,15},{5,0,12},{17,5,48},{0,0,0},{37,1,111},{36,2,108},{13,0,11},{13,3,12},{37,1,96},{3,0,3},{33,0,27},{33,0,24},{31,0,27},{31,1,24},{45,9,96},{11,0,3},{40,7,27},{41,8,24},{39,7,27},{29,0,4},{41,3,16},{19,1,2},{49,16,27},{50,17,24},{38,5,6},{38,6,4},{50,12,16},{40,4,6},{57,24,27}, +{58,25,24},{46,13,6},{46,14,4},{58,20,16},{36,0,1},{65,32,27},{66,33,24},{54,21,6},{54,22,4},{66,28,16},{44,6,1},{73,40,27},{74,41,24},{62,29,6},{62,30,4},{74,36,16},{52,14,1},{82,49,27},{83,50,24},{71,38,6},{71,39,4},{83,45,16},{61,23,1},{90,57,27},{91,58,24},{79,46,6},{79,47,4},{91,53,16},{69,31,1},{98,65,27},{99,66,24},{87,54,6}, +{87,55,4},{99,61,16},{77,39,1},{106,73,27},{107,74,24},{95,62,6},{95,63,4},{107,69,16},{85,47,1},{115,82,27},{116,83,24},{104,71,6},{104,72,4},{116,78,16},{94,56,1},{123,90,27},{124,91,24},{112,79,6},{112,80,4},{124,86,16},{102,64,1},{131,98,27},{132,99,24},{120,87,6},{120,88,4},{132,94,16},{110,72,1},{139,106,27},{140,107,24},{128,95,6},{128,96,4},{140,102,16}, +{118,80,1},{148,115,27},{149,116,24},{137,104,6},{137,105,4},{149,111,16},{127,89,1},{156,123,27},{157,124,24},{145,112,6},{145,113,4},{157,119,16},{135,97,1},{164,131,27},{165,132,24},{153,120,6},{153,121,4},{165,127,16},{143,105,1},{172,139,27},{173,140,24},{161,128,6},{161,129,4},{173,135,16},{151,113,1},{181,148,27},{182,149,24},{170,137,6},{170,138,4},{182,144,16},{160,122,1},{189,156,27}, +{190,157,24},{178,145,6},{178,146,4},{190,152,16},{168,130,1},{197,164,27},{198,165,24},{186,153,6},{186,154,4},{198,160,16},{176,138,1},{205,172,27},{206,173,24},{194,161,6},{194,162,4},{206,168,16},{184,146,1},{214,181,27},{215,182,24},{203,170,6},{203,171,4},{215,177,16},{193,155,1},{222,189,27},{223,190,24},{211,178,6},{211,179,4},{223,185,16},{201,163,1},{230,197,27},{231,198,24},{219,186,6}, +{219,187,4},{231,193,16},{209,171,1},{238,205,27},{239,206,24},{227,194,6},{227,195,4},{239,201,16},{217,179,1},{247,214,27},{248,215,24},{236,203,6},{236,204,4},{248,210,16},{226,188,1},{255,222,27},{255,222,24},{244,211,6},{244,212,4},{255,220,16},{234,196,1},{254,218,6},{255,242,28},{252,219,6},{252,220,4},{255,245,16},{242,204,1},{255,238,7},{255,239,4},{255,238,7},{255,239,4},{255,0,0}, +{250,212,1},{28,0,47},{28,0,44},{9,0,15},{9,0,12},{29,9,48},{0,0,0},{53,0,111},{53,0,108},{17,0,15},{17,0,12},{37,7,32},{0,0,0},{66,3,111},{63,7,108},{25,0,11},{25,7,12},{65,5,96},{7,0,3},{51,0,27},{71,15,108},{47,0,27},{33,6,8},{73,13,96},{15,0,3},{61,4,27},{80,24,108},{61,4,27},{60,6,24},{62,0,16},{24,4,3},{69,12,27}, +{88,32,108},{69,12,27},{68,14,24},{70,8,16},{32,2,2},{77,20,27},{96,40,108},{58,2,6},{58,2,4},{78,16,16},{60,0,6},{85,28,27},{104,48,108},{66,10,6},{66,10,4},{86,24,16},{68,8,6},{94,37,27},{113,57,108},{75,19,6},{75,19,4},{95,33,16},{77,17,6},{102,45,27},{121,65,108},{83,27,6},{83,27,4},{103,41,16},{65,3,1},{110,53,27},{129,73,108},{91,35,6}, +{91,35,4},{111,49,16},{73,11,1},{118,61,27},{137,81,108},{99,43,6},{99,43,4},{119,57,16},{81,19,1},{127,70,27},{146,90,108},{108,52,6},{108,52,4},{128,66,16},{90,28,1},{135,78,27},{154,98,108},{116,60,6},{116,60,4},{136,74,16},{98,36,1},{143,86,27},{162,106,108},{124,68,6},{124,68,4},{144,82,16},{106,44,1},{151,94,27},{170,114,108},{132,76,6},{132,76,4},{152,90,16}, +{114,52,1},{160,103,27},{179,123,108},{141,85,6},{141,85,4},{161,99,16},{123,61,1},{168,111,27},{187,131,108},{149,93,6},{149,93,4},{169,107,16},{131,69,1},{176,119,27},{195,139,108},{157,101,6},{157,101,4},{177,115,16},{139,77,1},{184,127,27},{203,147,108},{165,109,6},{165,109,4},{185,123,16},{147,85,1},{193,136,27},{212,156,108},{174,118,6},{174,118,4},{194,132,16},{156,94,1},{201,144,27}, +{220,164,108},{182,126,6},{182,126,4},{202,140,16},{164,102,1},{209,152,27},{228,172,108},{190,134,6},{190,134,4},{210,148,16},{172,110,1},{217,160,27},{236,180,108},{198,142,6},{198,142,4},{218,156,16},{180,118,1},{226,169,27},{245,189,108},{207,151,6},{207,151,4},{227,165,16},{189,127,1},{234,177,27},{253,197,108},{215,159,6},{215,159,4},{235,173,16},{197,135,1},{242,185,27},{243,186,24},{223,167,6}, +{223,167,4},{243,181,16},{205,143,1},{250,193,27},{251,194,24},{231,175,6},{231,175,4},{251,189,16},{213,151,1},{255,203,27},{255,206,24},{240,184,6},{240,184,4},{255,208,16},{222,160,1},{251,188,6},{255,230,28},{248,192,6},{248,192,4},{255,233,16},{230,168,1},{255,200,6},{255,202,4},{255,200,6},{255,202,4},{255,0,0},{238,176,1},{255,226,7},{255,227,4},{255,226,7},{255,227,4},{255,0,0}, +{246,184,1},{41,0,47},{41,0,44},{13,0,15},{13,0,12},{42,13,48},{0,0,0},{71,0,111},{71,0,108},{21,0,15},{21,0,12},{50,7,32},{0,0,0},{86,1,111},{85,2,108},{29,1,15},{29,3,12},{87,0,96},{3,0,3},{96,6,111},{93,10,108},{37,0,11},{37,11,12},{95,8,96},{11,0,3},{71,0,27},{102,19,108},{68,0,27},{46,7,8},{104,17,96},{20,0,3},{82,0,27}, +{110,27,108},{81,0,27},{80,2,24},{112,25,96},{28,0,3},{91,7,27},{118,35,108},{91,7,27},{88,10,24},{91,2,16},{36,7,3},{99,15,27},{126,43,108},{99,15,27},{96,18,24},{99,10,16},{44,1,2},{108,24,27},{135,52,108},{108,24,27},{79,0,4},{108,19,16},{53,10,2},{116,32,27},{143,60,108},{87,5,6},{87,7,4},{116,27,16},{90,3,6},{124,40,27},{151,68,108},{95,13,6}, +{95,15,4},{124,35,16},{98,11,6},{132,48,27},{159,76,108},{103,21,6},{103,23,4},{132,43,16},{106,19,6},{141,57,27},{168,85,108},{112,30,6},{112,32,4},{141,52,16},{115,28,6},{149,65,27},{176,93,108},{120,38,6},{120,40,4},{149,60,16},{94,5,1},{157,73,27},{184,101,108},{128,46,6},{128,48,4},{157,68,16},{102,13,1},{165,81,27},{192,109,108},{136,54,6},{136,56,4},{165,76,16}, +{110,21,1},{174,90,27},{201,118,108},{145,63,6},{145,65,4},{174,85,16},{119,30,1},{182,98,27},{209,126,108},{153,71,6},{153,73,4},{182,93,16},{127,38,1},{190,106,27},{217,134,108},{161,79,6},{161,81,4},{190,101,16},{135,46,1},{198,114,27},{225,142,108},{169,87,6},{169,89,4},{198,109,16},{143,54,1},{207,123,27},{234,151,108},{178,96,6},{178,98,4},{207,118,16},{152,63,1},{215,131,27}, +{242,159,108},{186,104,6},{186,106,4},{215,126,16},{160,71,1},{223,139,27},{250,167,108},{194,112,6},{194,114,4},{223,134,16},{168,79,1},{231,147,27},{231,147,24},{202,120,6},{202,122,4},{231,142,16},{176,87,1},{240,156,27},{240,156,24},{211,129,6},{211,131,4},{240,151,16},{185,96,1},{248,164,27},{248,164,24},{219,137,6},{219,139,4},{248,159,16},{193,104,1},{254,173,27},{255,174,24},{227,145,6}, +{227,147,4},{255,169,16},{201,112,1},{255,182,27},{255,187,24},{235,153,6},{235,155,4},{255,193,16},{209,120,1},{249,159,6},{255,218,28},{244,162,6},{244,164,4},{255,220,16},{218,129,1},{254,169,6},{254,168,4},{252,170,6},{252,172,4},{255,245,16},{226,137,1},{255,184,6},{255,190,4},{255,184,6},{255,190,4},{255,0,0},{234,145,1},{255,213,7},{255,214,4},{255,213,7},{255,214,4},{255,0,0}, +{242,153,1},{59,0,47},{59,0,44},{18,0,15},{18,0,12},{60,18,48},{0,0,0},{69,0,47},{68,2,44},{26,0,15},{26,0,12},{68,5,32},{0,0,0},{111,0,111},{111,0,108},{34,0,15},{34,0,12},{76,13,32},{0,0,0},{123,3,111},{122,5,108},{42,3,15},{42,6,12},{125,1,96},{6,0,3},{135,8,111},{131,14,108},{50,0,11},{51,15,12},{134,10,96},{15,0,3},{95,0,27}, +{139,22,108},{59,2,11},{59,5,8},{142,18,96},{23,0,3},{105,0,27},{147,30,108},{99,0,27},{67,13,8},{150,26,96},{31,0,3},{115,0,27},{155,38,108},{113,1,27},{110,4,24},{158,34,96},{39,0,3},{125,7,27},{164,47,108},{125,7,27},{119,13,24},{167,43,96},{48,6,3},{133,15,27},{172,55,108},{133,15,27},{127,21,24},{134,5,16},{56,14,3},{141,23,27},{180,63,108},{141,23,27}, +{135,29,24},{142,13,16},{64,1,2},{149,31,27},{188,71,108},{149,31,27},{143,37,24},{150,21,16},{72,9,2},{158,40,27},{197,80,108},{118,1,6},{117,6,4},{159,30,16},{120,0,6},{166,48,27},{205,88,108},{126,9,6},{125,14,4},{167,38,16},{130,6,6},{174,56,27},{213,96,108},{134,17,6},{133,22,4},{175,46,16},{138,14,6},{182,64,27},{221,104,108},{142,25,6},{141,30,4},{183,54,16}, +{146,22,6},{191,73,27},{230,113,108},{151,34,6},{150,39,4},{192,63,16},{155,31,6},{199,81,27},{238,121,108},{159,42,6},{158,47,4},{200,71,16},{163,39,6},{207,89,27},{246,129,108},{167,50,6},{166,55,4},{208,79,16},{130,1,1},{215,97,27},{254,137,108},{175,58,6},{174,63,4},{216,87,16},{138,9,1},{224,106,27},{224,106,24},{184,67,6},{183,72,4},{225,96,16},{147,18,1},{232,114,27}, +{232,114,24},{192,75,6},{191,80,4},{233,104,16},{155,26,1},{240,122,27},{240,122,24},{200,83,6},{199,88,4},{241,112,16},{163,34,1},{248,130,27},{248,130,24},{208,91,6},{207,96,4},{249,120,16},{171,42,1},{255,140,27},{254,142,24},{217,100,6},{216,105,4},{255,135,16},{180,51,1},{255,149,27},{255,156,24},{225,108,6},{224,113,4},{255,159,16},{188,59,1},{255,159,27},{253,196,28},{233,116,6}, +{232,121,4},{255,184,16},{196,67,1},{247,120,6},{255,205,28},{241,124,6},{240,129,4},{255,208,16},{204,75,1},{252,132,6},{252,132,4},{250,133,6},{249,138,4},{255,236,16},{213,84,1},{255,144,6},{255,150,4},{255,144,6},{255,150,4},{255,0,0},{221,92,1},{254,185,7},{255,175,4},{253,187,7},{255,175,4},{255,0,0},{229,100,1},{255,196,7},{255,199,4},{255,196,7},{255,199,4},{255,0,0}, +{237,108,1},{80,0,47},{80,0,44},{24,0,15},{24,0,12},{80,24,48},{0,0,0},{88,1,47},{88,1,44},{32,0,15},{32,0,12},{88,4,32},{0,0,0},{138,0,111},{138,0,108},{40,0,15},{40,0,12},{96,12,32},{0,0,0},{153,0,111},{153,0,108},{48,0,15},{48,0,12},{104,20,32},{0,0,0},{166,4,111},{164,8,108},{57,4,15},{57,9,12},{167,3,96},{9,0,3},{176,9,111}, +{172,16,108},{65,0,11},{65,17,12},{175,11,96},{17,0,3},{189,13,111},{180,24,108},{73,0,11},{73,1,8},{183,19,96},{25,0,3},{129,0,27},{188,32,108},{83,2,11},{81,9,8},{191,27,96},{33,0,3},{141,0,27},{197,41,108},{132,0,27},{90,18,8},{200,36,96},{42,0,3},{151,0,27},{205,49,108},{148,0,27},{145,3,24},{208,44,96},{50,0,3},{160,3,27},{213,57,108},{160,3,27}, +{153,11,24},{216,52,96},{58,2,3},{168,11,27},{221,65,108},{168,11,27},{161,19,24},{170,0,16},{66,10,3},{177,20,27},{230,74,108},{177,20,27},{170,28,24},{179,7,16},{75,19,3},{185,28,27},{238,82,108},{185,28,27},{178,36,24},{187,15,16},{83,0,2},{193,36,27},{246,90,108},{193,36,27},{186,44,24},{195,23,16},{91,7,2},{201,44,27},{254,98,108},{201,44,27},{147,0,4},{203,31,16}, +{99,15,2},{210,53,27},{211,54,24},{157,1,6},{156,9,4},{212,40,16},{108,24,2},{218,61,27},{219,62,24},{165,9,6},{164,17,4},{220,48,16},{170,6,6},{226,69,27},{227,70,24},{173,17,6},{172,25,4},{228,56,16},{178,14,6},{234,77,27},{235,78,24},{181,25,6},{180,33,4},{236,64,16},{186,22,6},{243,86,27},{244,87,24},{190,34,6},{189,42,4},{245,73,16},{195,31,6},{251,94,27}, +{252,95,24},{198,42,6},{197,50,4},{253,81,16},{203,39,6},{255,104,27},{255,107,24},{206,50,6},{205,58,4},{255,102,16},{211,47,6},{255,113,27},{255,123,24},{214,58,6},{213,66,4},{255,126,16},{219,55,6},{255,126,27},{253,172,28},{223,67,6},{222,75,4},{255,153,16},{174,2,1},{242,66,6},{254,182,28},{231,75,6},{230,83,4},{255,178,16},{182,10,1},{246,79,6},{255,190,28},{239,83,6}, +{238,91,4},{255,202,16},{190,18,1},{251,89,6},{251,88,4},{247,91,6},{246,99,4},{255,227,16},{198,26,1},{255,102,6},{255,108,4},{255,102,6},{255,108,4},{255,0,0},{207,35,1},{255,117,6},{255,132,4},{255,117,6},{255,132,4},{255,0,0},{215,43,1},{254,167,7},{255,156,4},{254,167,7},{255,156,4},{255,0,0},{223,51,1},{255,175,7},{255,181,4},{255,175,7},{255,181,4},{255,0,0}, +{231,59,1},{105,0,47},{105,0,44},{33,0,15},{33,0,12},{106,33,48},{0,0,0},{115,0,47},{114,2,44},{41,0,15},{41,0,12},{114,5,32},{0,0,0},{123,2,47},{124,3,44},{49,0,15},{49,0,12},{122,13,32},{0,0,0},{190,0,111},{190,0,108},{57,0,15},{57,0,12},{130,21,32},{0,0,0},{205,0,111},{205,0,108},{66,0,15},{66,0,12},{139,30,32},{0,0,0},{217,4,111}, +{215,7,108},{74,4,15},{74,8,12},{218,3,96},{8,0,3},{229,8,111},{223,15,108},{80,0,11},{82,16,12},{226,11,96},{16,0,3},{237,13,111},{231,23,108},{89,0,11},{90,24,12},{234,19,96},{24,0,3},{251,17,111},{240,32,108},{99,0,11},{99,1,8},{243,28,96},{33,0,3},{169,0,27},{248,40,108},{108,2,11},{107,9,8},{251,36,96},{41,0,3},{181,0,27},{254,49,108},{166,0,27}, +{115,17,8},{188,79,32},{49,0,3},{190,0,27},{255,59,108},{181,0,27},{123,25,8},{196,87,32},{57,0,3},{203,0,27},{203,0,24},{197,0,27},{196,2,24},{205,96,32},{66,0,3},{213,1,27},{212,3,24},{211,2,27},{204,10,24},{213,104,32},{74,1,3},{221,9,27},{220,11,24},{219,10,27},{212,18,24},{221,0,16},{82,9,3},{229,17,27},{228,19,24},{227,18,27},{220,26,24},{229,5,16}, +{90,17,3},{238,26,27},{237,28,24},{236,27,27},{229,35,24},{238,14,16},{99,26,3},{246,34,27},{245,36,24},{244,35,27},{237,43,24},{246,22,16},{107,34,3},{254,42,27},{253,44,24},{252,43,27},{245,51,24},{254,30,16},{115,6,2},{255,52,27},{255,58,24},{255,52,27},{253,59,24},{255,53,16},{123,14,2},{255,64,27},{255,74,24},{196,0,6},{198,100,8},{255,80,16},{132,23,2},{255,74,27}, +{255,89,24},{206,1,6},{206,4,4},{255,105,16},{140,31,2},{255,86,27},{253,147,28},{215,7,6},{214,12,4},{255,129,16},{219,4,6},{255,95,27},{255,155,28},{223,15,6},{222,20,4},{255,153,16},{227,12,6},{242,17,6},{255,166,28},{232,24,6},{231,29,4},{255,181,16},{236,21,6},{247,26,6},{255,175,28},{240,32,6},{239,37,4},{255,205,16},{244,29,6},{251,38,6},{251,37,4},{248,40,6}, +{247,45,4},{255,230,16},{252,37,6},{255,50,6},{255,53,4},{255,50,6},{255,53,4},{255,0,0},{189,80,2},{255,65,6},{255,80,4},{255,65,6},{255,80,4},{255,0,0},{198,89,2},{252,131,7},{255,105,4},{252,131,7},{255,105,4},{255,0,0},{206,97,2},{254,139,7},{255,129,4},{253,141,7},{255,129,4},{255,0,0},{214,105,2},{255,150,7},{255,153,4},{255,150,7},{255,153,4},{255,0,0}, +{222,0,1},{181,0,47},{178,0,44},{47,0,15},{47,0,12},{183,47,48},{0,0,0},{190,0,47},{190,0,44},{55,0,15},{55,0,12},{191,55,48},{0,0,0},{199,0,47},{199,0,44},{63,0,15},{63,0,12},{199,63,48},{0,0,0},{207,0,47},{207,1,44},{71,0,15},{71,0,12},{207,4,32},{0,0,0},{216,1,47},{218,3,44},{80,0,15},{80,0,12},{216,13,32},{0,0,0},{225,1,47}, +{227,6,44},{88,0,15},{88,0,12},{224,21,32},{0,0,0},{233,2,47},{235,11,44},{96,1,15},{96,2,12},{232,29,32},{2,0,3},{241,4,47},{243,19,44},{104,5,15},{104,10,12},{240,37,32},{10,0,3},{251,5,47},{252,28,44},{113,9,15},{113,19,12},{249,46,32},{19,0,3},{255,9,47},{255,37,44},{117,0,11},{121,27,12},{255,55,32},{27,0,3},{255,9,47},{255,46,44},{126,0,11}, +{129,35,12},{255,67,32},{35,0,3},{248,0,27},{255,55,44},{137,0,11},{137,43,12},{255,79,32},{43,0,3},{250,0,27},{255,64,44},{147,2,11},{146,6,8},{255,93,32},{52,0,3},{251,0,27},{255,73,44},{155,4,11},{154,14,8},{255,104,32},{60,0,3},{253,0,27},{248,0,24},{233,0,27},{162,22,8},{255,116,32},{68,0,3},{254,0,27},{254,0,24},{248,0,27},{170,30,8},{255,128,32}, +{76,0,3},{255,1,27},{255,7,24},{255,1,27},{179,39,8},{255,22,16},{85,0,3},{255,2,27},{255,22,24},{255,7,27},{187,47,8},{255,47,16},{93,0,3},{255,4,27},{251,100,28},{182,0,7},{195,55,8},{255,71,16},{101,0,3},{255,4,27},{253,108,28},{191,0,7},{203,63,8},{255,95,16},{109,0,3},{255,7,27},{255,118,28},{200,0,7},{212,72,8},{255,123,16},{118,0,3},{246,0,7}, +{255,129,28},{209,0,7},{220,80,8},{255,147,16},{126,0,3},{246,0,7},{255,138,28},{218,0,7},{228,88,8},{255,172,16},{134,0,3},{249,3,7},{245,91,8},{228,3,7},{236,96,8},{255,196,16},{142,6,3},{251,14,7},{250,102,8},{237,12,7},{245,105,8},{255,223,16},{151,15,3},{253,22,7},{254,112,8},{245,20,7},{253,113,8},{255,248,16},{159,23,3},{253,31,7},{255,124,8},{249,28,7}, +{255,124,8},{255,0,0},{167,31,3},{254,39,7},{255,10,4},{252,37,7},{255,10,4},{255,0,0},{175,39,3},{255,48,7},{255,38,4},{254,48,7},{255,38,4},{255,0,0},{184,48,3},{255,56,7},{255,62,4},{255,56,7},{255,62,4},{255,0,0},{192,56,3},{255,65,7},{255,86,4},{255,65,7},{255,86,4},{255,0,0},{200,64,3},{255,74,7},{255,111,4},{255,77,7},{255,111,4},{255,0,0}, +{208,5,2}, diff --git a/ext/basis_universal/basisu_transcoder_tables_bc7_m5_color.inc b/ext/basis_universal/basisu_transcoder_tables_bc7_m5_color.inc new file mode 100644 index 0000000000..c0780988d8 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_bc7_m5_color.inc @@ -0,0 +1,481 @@ +{0,7,18},{0,5,2},{0,4,1},{0,3,8},{0,4,35},{0,3,24},{0,3,12},{0,2,29},{0,2,36},{0,2,30},{0,7,18},{0,5,2},{0,4,1},{0,3,8},{2,0,35},{0,3,24},{0,3,12},{0,2,29},{4,0,35},{0,2,29},{0,3,0},{0,3,0},{0,3,0},{0,1,1},{0,1,2},{0,1,2},{0,1,2},{0,1,1},{1,0,3},{0,1,2},{0,3,0}, +{0,3,0},{0,3,0},{0,1,1},{1,0,2},{1,0,2},{1,0,2},{0,1,1},{1,0,2},{0,1,1},{4,0,18},{0,5,2},{0,4,1},{0,3,8},{4,0,18},{7,0,18},{0,3,8},{0,2,20},{7,0,18},{0,2,20},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,15,38},{2,11,20},{2,8,24}, +{1,8,21},{0,16,51},{0,10,19},{0,8,2},{0,6,24},{0,8,76},{0,6,40},{3,13,18},{3,10,2},{3,8,1},{3,7,5},{8,0,51},{1,9,19},{0,8,2},{0,6,24},{16,0,51},{0,6,24},{2,11,20},{2,11,20},{2,11,20},{1,7,20},{0,12,8},{0,7,2},{0,7,2},{0,5,1},{0,5,19},{0,5,10},{3,9,0},{3,9,0},{3,9,0},{3,6,0},{6,0,8}, +{1,7,0},{1,7,0},{0,5,1},{12,0,8},{0,5,1},{10,0,18},{2,11,0},{3,8,1},{0,8,1},{10,0,18},{20,0,18},{0,8,1},{0,6,20},{20,0,18},{0,6,20},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,9,0},{0,9,0},{0,9,0},{0,4,1},{0,3,8},{0,3,8},{6,19,38},{6,15,20},{6,12,24},{5,12,21},{4,20,51},{4,14,19},{4,12,2}, +{4,10,24},{0,14,52},{1,10,20},{7,17,18},{7,14,2},{7,12,1},{7,11,5},{14,0,51},{5,13,19},{4,12,2},{1,10,20},{29,0,51},{1,10,20},{6,15,20},{6,15,20},{6,15,20},{5,11,20},{4,16,8},{4,11,2},{4,11,2},{4,9,1},{0,12,8},{1,9,2},{7,13,0},{7,13,0},{7,13,0},{7,10,0},{12,0,8},{5,11,0},{5,11,0},{3,9,0},{24,0,8}, +{3,9,0},{15,1,18},{6,15,0},{7,12,1},{3,12,0},{15,1,18},{32,0,18},{3,12,0},{0,10,20},{32,0,18},{0,10,20},{5,0,20},{5,0,20},{5,0,20},{5,0,20},{4,13,0},{4,13,0},{4,13,0},{4,8,1},{1,10,0},{1,10,0},{10,23,38},{10,19,20},{10,16,24},{9,16,21},{8,24,51},{8,18,19},{8,16,2},{8,14,24},{3,18,52},{5,14,20},{11,21,18}, +{11,18,2},{11,16,1},{11,15,5},{20,0,51},{9,17,19},{8,16,2},{5,14,20},{41,0,51},{5,14,20},{10,19,20},{10,19,20},{10,19,20},{9,15,20},{8,20,8},{8,15,2},{8,15,2},{8,13,1},{4,16,8},{5,13,2},{11,17,0},{11,17,0},{11,17,0},{11,14,0},{18,0,8},{9,15,0},{9,15,0},{7,13,0},{36,0,8},{7,13,0},{21,1,18},{10,19,0},{11,16,1}, +{7,16,0},{21,1,18},{44,0,18},{7,16,0},{0,14,20},{44,0,18},{0,14,20},{9,0,20},{9,0,20},{9,0,20},{9,0,20},{8,17,0},{8,17,0},{8,17,0},{8,12,1},{5,14,0},{5,14,0},{14,29,36},{14,24,18},{14,21,23},{14,20,20},{13,28,52},{13,22,20},{13,20,2},{12,19,23},{7,23,51},{9,19,18},{16,25,19},{15,23,1},{16,20,2},{15,20,6},{27,0,51}, +{13,22,19},{13,20,1},{8,19,18},{55,0,51},{8,19,18},{14,24,18},{14,24,18},{14,24,18},{14,19,18},{13,23,9},{13,20,1},{13,20,1},{12,17,2},{9,20,8},{10,18,1},{16,20,1},{16,20,1},{16,20,1},{16,18,1},{24,1,8},{14,19,0},{14,19,0},{12,17,1},{50,0,8},{12,17,1},{28,0,18},{15,23,0},{16,20,1},{12,20,1},{28,0,18},{58,0,18},{12,20,1}, +{0,19,18},{58,0,18},{0,19,18},{14,0,18},{14,0,18},{14,0,18},{14,0,18},{13,20,1},{13,20,1},{13,20,1},{12,17,1},{10,18,0},{10,18,0},{18,33,36},{18,28,18},{18,25,23},{18,24,20},{17,32,52},{17,26,20},{17,24,2},{16,23,23},{11,27,51},{13,23,18},{20,29,19},{19,27,1},{20,24,2},{19,24,6},{33,0,51},{17,26,19},{17,24,1},{12,23,18},{66,0,51}, +{12,23,18},{18,28,18},{18,28,18},{18,28,18},{18,23,18},{17,27,9},{17,24,1},{17,24,1},{16,21,2},{13,24,8},{14,22,1},{20,24,1},{20,24,1},{20,24,1},{20,22,1},{30,1,8},{18,23,0},{18,23,0},{16,21,1},{62,0,8},{16,21,1},{34,0,18},{19,27,0},{20,24,1},{16,24,1},{34,0,18},{69,0,18},{16,24,1},{0,23,18},{69,0,18},{0,23,18},{18,0,18}, +{18,0,18},{18,0,18},{18,0,18},{17,24,1},{17,24,1},{17,24,1},{16,21,1},{14,22,0},{14,22,0},{22,37,36},{22,32,18},{22,29,23},{22,28,20},{21,36,52},{21,30,20},{21,28,2},{20,27,23},{15,31,51},{17,27,18},{24,33,19},{23,31,1},{24,28,2},{23,28,6},{39,0,51},{21,30,19},{21,28,1},{16,27,18},{78,0,51},{16,27,18},{22,32,18},{22,32,18},{22,32,18}, +{22,27,18},{21,31,9},{21,28,1},{21,28,1},{20,25,2},{17,28,8},{18,26,1},{24,28,1},{24,28,1},{24,28,1},{24,26,1},{36,1,8},{22,27,0},{22,27,0},{20,25,1},{74,0,8},{20,25,1},{40,0,18},{23,31,0},{24,28,1},{20,28,1},{40,0,18},{82,0,18},{20,28,1},{0,27,18},{82,0,18},{0,27,18},{22,0,18},{22,0,18},{22,0,18},{22,0,18},{21,28,1}, +{21,28,1},{21,28,1},{20,25,1},{18,26,0},{18,26,0},{26,41,36},{26,36,18},{26,33,23},{26,32,20},{25,40,52},{25,34,20},{25,32,2},{24,31,23},{19,35,51},{21,31,18},{28,37,19},{27,35,1},{28,32,2},{27,32,6},{45,0,51},{25,34,19},{25,32,1},{20,31,18},{91,0,51},{20,31,18},{26,36,18},{26,36,18},{26,36,18},{26,31,18},{25,35,9},{25,32,1},{25,32,1}, +{24,29,2},{21,32,8},{22,30,1},{28,32,1},{28,32,1},{28,32,1},{28,30,1},{42,1,8},{26,31,0},{26,31,0},{24,29,1},{86,0,8},{24,29,1},{46,0,18},{27,35,0},{28,32,1},{24,32,1},{46,0,18},{94,0,18},{24,32,1},{0,31,18},{94,0,18},{0,31,18},{26,0,18},{26,0,18},{26,0,18},{26,0,18},{25,32,1},{25,32,1},{25,32,1},{24,29,1},{22,30,0}, +{22,30,0},{31,44,38},{31,40,20},{31,37,24},{30,37,21},{29,45,51},{29,39,19},{29,37,2},{29,35,24},{24,39,52},{26,35,20},{32,42,18},{32,39,2},{32,37,1},{32,36,5},{51,0,51},{30,38,19},{29,37,2},{26,35,20},{104,0,51},{26,35,20},{31,40,20},{31,40,20},{31,40,20},{30,36,20},{29,41,8},{29,36,2},{29,36,2},{29,34,1},{25,37,8},{26,34,2},{32,38,0}, +{32,38,0},{32,38,0},{32,35,0},{49,0,8},{30,36,0},{30,36,0},{28,34,0},{100,0,8},{28,34,0},{53,0,18},{31,40,0},{32,37,1},{28,37,0},{53,0,18},{107,0,18},{28,37,0},{0,35,20},{107,0,18},{0,35,20},{30,0,20},{30,0,20},{30,0,20},{30,0,20},{29,38,0},{29,38,0},{29,38,0},{29,33,1},{26,35,0},{26,35,0},{35,48,38},{35,44,20},{35,41,24}, +{34,41,21},{33,49,51},{33,43,19},{33,41,2},{33,39,24},{28,43,52},{30,39,20},{36,46,18},{36,43,2},{36,41,1},{36,40,5},{57,0,51},{34,42,19},{33,41,2},{30,39,20},{117,0,51},{30,39,20},{35,44,20},{35,44,20},{35,44,20},{34,40,20},{33,45,8},{33,40,2},{33,40,2},{33,38,1},{29,41,8},{30,38,2},{36,42,0},{36,42,0},{36,42,0},{36,39,0},{55,0,8}, +{34,40,0},{34,40,0},{32,38,0},{112,0,8},{32,38,0},{59,0,18},{35,44,0},{36,41,1},{32,41,0},{59,0,18},{120,0,18},{32,41,0},{0,39,20},{120,0,18},{0,39,20},{34,0,20},{34,0,20},{34,0,20},{34,0,20},{33,42,0},{33,42,0},{33,42,0},{33,37,1},{30,39,0},{30,39,0},{39,52,38},{39,48,20},{39,45,24},{38,45,21},{37,53,51},{37,47,19},{37,45,2}, +{37,43,24},{32,47,52},{34,43,20},{40,50,18},{40,47,2},{40,45,1},{40,44,5},{63,0,51},{38,46,19},{37,45,2},{34,43,20},{127,1,51},{34,43,20},{39,48,20},{39,48,20},{39,48,20},{38,44,20},{37,49,8},{37,44,2},{37,44,2},{37,42,1},{33,45,8},{34,42,2},{40,46,0},{40,46,0},{40,46,0},{40,43,0},{61,0,8},{38,44,0},{38,44,0},{36,42,0},{124,0,8}, +{36,42,0},{64,0,18},{39,48,0},{40,45,1},{36,45,0},{64,0,18},{126,3,18},{36,45,0},{0,43,20},{126,3,18},{0,43,20},{38,0,20},{38,0,20},{38,0,20},{38,0,20},{37,46,0},{37,46,0},{37,46,0},{37,41,1},{34,43,0},{34,43,0},{43,56,38},{43,52,20},{43,49,24},{42,49,21},{41,57,51},{41,51,19},{41,49,2},{41,47,24},{36,51,52},{38,47,20},{44,54,18}, +{44,51,2},{44,49,1},{44,48,5},{69,0,51},{42,50,19},{41,49,2},{38,47,20},{127,7,51},{38,47,20},{43,52,20},{43,52,20},{43,52,20},{42,48,20},{41,53,8},{41,48,2},{41,48,2},{41,46,1},{37,49,8},{38,46,2},{44,50,0},{44,50,0},{44,50,0},{44,47,0},{66,1,8},{42,48,0},{42,48,0},{40,46,0},{126,5,8},{40,46,0},{70,0,18},{43,52,0},{44,49,1}, +{40,49,0},{70,0,18},{126,9,18},{40,49,0},{0,47,20},{126,9,18},{0,47,20},{42,0,20},{42,0,20},{42,0,20},{42,0,20},{41,50,0},{41,50,0},{41,50,0},{41,45,1},{38,47,0},{38,47,0},{47,62,36},{47,57,18},{47,54,23},{47,53,20},{46,61,52},{46,55,20},{46,53,2},{45,52,23},{40,56,51},{42,52,18},{49,58,19},{48,56,1},{49,53,2},{48,53,6},{75,1,51}, +{46,55,19},{46,53,1},{41,52,18},{126,14,51},{41,52,18},{47,57,18},{47,57,18},{47,57,18},{47,52,18},{46,56,9},{46,53,1},{46,53,1},{45,50,2},{42,53,8},{43,51,1},{49,53,1},{49,53,1},{49,53,1},{49,51,1},{73,0,8},{47,52,0},{47,52,0},{45,50,1},{126,12,8},{45,50,1},{77,0,18},{48,56,0},{49,53,1},{45,53,1},{77,0,18},{127,15,18},{45,53,1}, +{0,52,18},{127,15,18},{0,52,18},{47,0,18},{47,0,18},{47,0,18},{47,0,18},{46,53,1},{46,53,1},{46,53,1},{45,50,1},{43,51,0},{43,51,0},{51,65,36},{51,61,18},{51,58,23},{51,57,20},{50,64,52},{50,59,20},{50,57,2},{49,56,23},{44,60,51},{46,56,18},{53,62,19},{52,60,1},{53,57,2},{52,57,6},{81,0,51},{50,59,19},{50,57,1},{45,56,18},{126,20,51}, +{45,56,18},{51,61,18},{51,61,18},{51,61,18},{51,56,18},{50,60,9},{50,57,1},{50,57,1},{49,54,2},{46,57,8},{47,55,1},{53,57,1},{53,57,1},{53,57,1},{53,55,1},{79,0,8},{51,56,0},{51,56,0},{49,54,1},{127,17,8},{49,54,1},{83,0,18},{52,60,0},{53,57,1},{49,57,1},{83,0,18},{127,21,18},{49,57,1},{0,56,18},{127,21,18},{0,56,18},{51,0,18}, +{51,0,18},{51,0,18},{51,0,18},{50,57,1},{50,57,1},{50,57,1},{49,54,1},{47,55,0},{47,55,0},{55,69,36},{55,64,19},{55,62,23},{55,61,20},{54,68,52},{54,63,20},{54,61,2},{53,60,23},{48,64,51},{50,60,18},{57,65,19},{56,64,2},{57,61,2},{56,61,6},{87,0,51},{54,63,19},{54,61,1},{49,60,18},{126,26,51},{49,60,18},{55,65,18},{55,65,18},{55,65,18}, +{55,60,18},{54,64,9},{54,61,1},{54,61,1},{53,58,2},{50,61,8},{51,59,1},{57,61,1},{57,61,1},{57,61,1},{57,59,1},{85,0,8},{55,60,0},{55,60,0},{53,58,1},{127,23,8},{53,58,1},{89,0,18},{55,64,1},{57,61,1},{53,61,1},{89,0,18},{127,27,18},{53,61,1},{0,60,18},{127,27,18},{0,60,18},{55,0,18},{55,0,18},{55,0,18},{55,0,18},{54,61,1}, +{54,61,1},{54,61,1},{53,58,1},{51,59,0},{51,59,0},{59,73,36},{59,68,19},{59,66,26},{59,64,22},{58,72,52},{57,67,19},{57,65,2},{57,63,28},{52,68,51},{53,64,21},{61,69,19},{60,67,2},{61,65,1},{60,65,5},{93,0,51},{57,67,18},{57,65,1},{52,64,20},{126,32,51},{52,64,20},{59,69,18},{59,69,18},{59,69,18},{59,64,18},{58,68,9},{58,64,2},{58,64,2}, +{57,62,2},{55,64,9},{55,63,1},{61,65,1},{61,65,1},{61,65,1},{61,63,1},{91,0,8},{58,64,1},{58,64,1},{57,62,1},{127,29,8},{57,62,1},{95,0,18},{60,67,1},{61,65,0},{56,65,0},{95,0,18},{127,33,18},{56,65,0},{0,64,20},{127,33,18},{0,64,20},{59,0,18},{59,0,18},{59,0,18},{59,0,18},{58,65,1},{58,65,1},{58,65,1},{57,62,1},{55,63,0}, +{55,63,0},{63,79,38},{63,73,21},{64,70,28},{63,69,22},{62,78,51},{62,71,18},{62,69,2},{61,68,26},{57,72,51},{58,68,19},{65,74,19},{64,72,1},{65,69,2},{64,69,6},{100,0,51},{62,71,18},{62,69,2},{58,68,18},{127,38,51},{58,68,18},{63,74,20},{63,74,20},{63,74,20},{63,68,21},{62,73,8},{62,69,1},{62,69,1},{62,66,1},{59,69,9},{60,66,2},{65,69,1}, +{65,69,1},{65,69,1},{65,67,1},{98,0,8},{63,68,1},{63,68,1},{62,66,1},{127,36,8},{62,66,1},{101,1,18},{64,72,0},{65,69,1},{62,69,1},{101,1,18},{126,40,18},{62,69,1},{0,68,18},{126,40,18},{0,68,18},{63,0,20},{63,0,20},{63,0,20},{63,0,20},{62,70,0},{62,70,0},{62,70,0},{62,66,0},{60,66,1},{60,66,1},{67,82,36},{67,77,18},{67,74,23}, +{67,73,20},{66,81,52},{66,75,20},{66,73,2},{65,72,23},{61,76,51},{62,72,19},{69,78,19},{68,76,1},{69,73,2},{68,73,6},{106,0,51},{66,75,19},{66,73,1},{62,72,18},{127,44,51},{62,72,18},{67,77,18},{67,77,18},{67,77,18},{67,72,18},{66,76,9},{66,73,1},{66,73,1},{65,70,2},{63,73,9},{63,71,2},{69,73,1},{69,73,1},{69,73,1},{69,71,1},{104,0,8}, +{67,72,0},{67,72,0},{65,70,1},{127,42,8},{65,70,1},{107,1,18},{68,76,0},{69,73,1},{65,73,1},{107,1,18},{126,46,18},{65,73,1},{0,72,18},{126,46,18},{0,72,18},{67,0,18},{67,0,18},{67,0,18},{67,0,18},{66,73,1},{66,73,1},{66,73,1},{65,70,1},{63,71,1},{63,71,1},{71,86,36},{71,81,18},{71,78,23},{71,77,20},{70,85,52},{70,79,20},{70,77,2}, +{69,76,23},{64,80,51},{66,76,18},{73,82,19},{72,80,1},{73,77,2},{72,77,6},{112,0,51},{70,79,19},{70,77,1},{65,76,18},{127,50,51},{65,76,18},{71,81,18},{71,81,18},{71,81,18},{71,76,18},{70,80,9},{70,77,1},{70,77,1},{69,74,2},{66,77,8},{67,75,1},{73,77,1},{73,77,1},{73,77,1},{73,75,1},{110,0,8},{71,76,0},{71,76,0},{69,74,1},{126,48,8}, +{69,74,1},{113,0,18},{72,80,0},{73,77,1},{69,77,1},{113,0,18},{126,52,18},{69,77,1},{0,76,18},{126,52,18},{0,76,18},{71,0,18},{71,0,18},{71,0,18},{71,0,18},{70,77,1},{70,77,1},{70,77,1},{69,74,1},{67,75,0},{67,75,0},{75,90,36},{75,85,18},{75,82,23},{75,81,20},{74,89,52},{74,83,20},{74,81,2},{73,80,23},{68,84,51},{70,80,18},{77,86,19}, +{76,84,1},{77,81,2},{76,81,6},{118,0,51},{74,83,19},{74,81,1},{69,80,18},{127,56,51},{69,80,18},{75,85,18},{75,85,18},{75,85,18},{75,80,18},{74,84,9},{74,81,1},{74,81,1},{73,78,2},{70,81,8},{71,79,1},{77,81,1},{77,81,1},{77,81,1},{77,79,1},{115,1,8},{75,80,0},{75,80,0},{73,78,1},{126,54,8},{73,78,1},{119,0,18},{76,84,0},{77,81,1}, +{73,81,1},{119,0,18},{126,58,18},{73,81,1},{0,80,18},{126,58,18},{0,80,18},{75,0,18},{75,0,18},{75,0,18},{75,0,18},{74,81,1},{74,81,1},{74,81,1},{73,78,1},{71,79,0},{71,79,0},{80,93,38},{80,89,20},{80,86,24},{79,86,21},{78,94,51},{78,88,19},{78,86,2},{78,84,24},{73,88,52},{75,84,20},{81,91,18},{81,88,2},{81,86,1},{81,85,5},{124,1,51}, +{79,87,19},{78,86,2},{75,84,20},{126,63,51},{75,84,20},{80,89,20},{80,89,20},{80,89,20},{79,85,20},{78,90,8},{78,85,2},{78,85,2},{78,83,1},{74,86,8},{75,83,2},{81,87,0},{81,87,0},{81,87,0},{81,84,0},{122,0,8},{79,85,0},{79,85,0},{77,83,0},{126,61,8},{77,83,0},{126,0,18},{80,89,0},{81,86,1},{77,86,0},{126,0,18},{126,64,18},{77,86,0}, +{0,84,20},{126,64,18},{0,84,20},{79,0,20},{79,0,20},{79,0,20},{79,0,20},{78,87,0},{78,87,0},{78,87,0},{78,82,1},{75,84,0},{75,84,0},{84,97,38},{84,93,20},{84,90,24},{83,90,21},{82,98,51},{82,92,19},{82,90,2},{82,88,24},{77,92,52},{79,88,20},{85,95,18},{85,92,2},{85,90,1},{85,89,5},{127,7,51},{83,91,19},{82,90,2},{79,88,20},{127,68,51}, +{79,88,20},{84,93,20},{84,93,20},{84,93,20},{83,89,20},{82,94,8},{82,89,2},{82,89,2},{82,87,1},{78,90,8},{79,87,2},{85,91,0},{85,91,0},{85,91,0},{85,88,0},{127,2,8},{83,89,0},{83,89,0},{81,87,0},{127,66,8},{81,87,0},{127,10,18},{84,93,0},{85,90,1},{81,90,0},{127,10,18},{126,70,18},{81,90,0},{0,88,20},{126,70,18},{0,88,20},{83,0,20}, +{83,0,20},{83,0,20},{83,0,20},{82,91,0},{82,91,0},{82,91,0},{82,86,1},{79,88,0},{79,88,0},{88,101,38},{88,97,20},{88,94,24},{87,94,21},{86,102,51},{86,96,19},{86,94,2},{86,92,24},{81,96,52},{83,92,20},{89,99,18},{89,96,2},{89,94,1},{89,93,5},{127,19,51},{87,95,19},{86,94,2},{83,92,20},{127,74,51},{83,92,20},{88,97,20},{88,97,20},{88,97,20}, +{87,93,20},{86,98,8},{86,93,2},{86,93,2},{86,91,1},{82,94,8},{83,91,2},{89,95,0},{89,95,0},{89,95,0},{89,92,0},{127,14,8},{87,93,0},{87,93,0},{85,91,0},{127,72,8},{85,91,0},{127,22,18},{88,97,0},{89,94,1},{85,94,0},{127,22,18},{126,76,18},{85,94,0},{0,92,20},{126,76,18},{0,92,20},{87,0,20},{87,0,20},{87,0,20},{87,0,20},{86,95,0}, +{86,95,0},{86,95,0},{86,90,1},{83,92,0},{83,92,0},{92,105,38},{92,101,20},{92,98,24},{91,98,21},{90,106,51},{90,100,19},{90,98,2},{90,96,24},{85,100,52},{87,96,20},{93,103,18},{93,100,2},{93,98,1},{93,97,5},{127,31,51},{91,99,19},{90,98,2},{87,96,20},{127,80,51},{87,96,20},{92,101,20},{92,101,20},{92,101,20},{91,97,20},{90,102,8},{90,97,2},{90,97,2}, +{90,95,1},{86,98,8},{87,95,2},{93,99,0},{93,99,0},{93,99,0},{93,96,0},{127,27,8},{91,97,0},{91,97,0},{89,95,0},{126,78,8},{89,95,0},{127,34,18},{92,101,0},{93,98,1},{89,98,0},{127,34,18},{126,82,18},{89,98,0},{0,96,20},{126,82,18},{0,96,20},{91,0,20},{91,0,20},{91,0,20},{91,0,20},{90,99,0},{90,99,0},{90,99,0},{90,94,1},{87,96,0}, +{87,96,0},{96,111,36},{96,106,18},{96,103,23},{96,102,20},{95,110,52},{95,104,20},{95,102,2},{94,101,23},{89,105,51},{91,101,18},{98,107,19},{97,105,1},{98,102,2},{97,102,6},{127,45,51},{95,104,19},{95,102,1},{90,101,18},{126,87,51},{90,101,18},{96,106,18},{96,106,18},{96,106,18},{96,101,18},{95,105,9},{95,102,1},{95,102,1},{94,99,2},{91,102,8},{92,100,1},{98,102,1}, +{98,102,1},{98,102,1},{98,100,1},{127,40,8},{96,101,0},{96,101,0},{94,99,1},{126,85,8},{94,99,1},{127,48,18},{97,105,0},{98,102,1},{94,102,1},{127,48,18},{127,88,18},{94,102,1},{0,101,18},{127,88,18},{0,101,18},{96,0,18},{96,0,18},{96,0,18},{96,0,18},{95,102,1},{95,102,1},{95,102,1},{94,99,1},{92,100,0},{92,100,0},{100,115,36},{100,110,18},{100,107,23}, +{100,106,20},{99,114,52},{99,108,20},{99,106,2},{98,105,23},{93,109,51},{95,105,18},{102,111,19},{101,109,1},{102,106,2},{101,106,6},{127,57,51},{99,108,19},{99,106,1},{94,105,18},{126,93,51},{94,105,18},{100,110,18},{100,110,18},{100,110,18},{100,105,18},{99,109,9},{99,106,1},{99,106,1},{98,103,2},{95,106,8},{96,104,1},{102,106,1},{102,106,1},{102,106,1},{102,104,1},{127,53,8}, +{100,105,0},{100,105,0},{98,103,1},{126,91,8},{98,103,1},{127,60,18},{101,109,0},{102,106,1},{98,106,1},{127,60,18},{127,94,18},{98,106,1},{0,105,18},{127,94,18},{0,105,18},{100,0,18},{100,0,18},{100,0,18},{100,0,18},{99,106,1},{99,106,1},{99,106,1},{98,103,1},{96,104,0},{96,104,0},{104,119,36},{104,114,18},{104,111,23},{104,110,20},{103,118,52},{103,112,20},{103,110,2}, +{102,109,23},{97,113,51},{99,109,18},{106,115,19},{105,113,1},{106,110,2},{105,110,6},{127,69,51},{103,112,19},{103,110,1},{98,109,18},{126,99,51},{98,109,18},{104,114,18},{104,114,18},{104,114,18},{104,109,18},{103,113,9},{103,110,1},{103,110,1},{102,107,2},{99,110,8},{100,108,1},{106,110,1},{106,110,1},{106,110,1},{106,108,1},{127,64,8},{104,109,0},{104,109,0},{102,107,1},{126,97,8}, +{102,107,1},{127,72,18},{105,113,0},{106,110,1},{102,110,1},{127,72,18},{127,100,18},{102,110,1},{0,109,18},{127,100,18},{0,109,18},{104,0,18},{104,0,18},{104,0,18},{104,0,18},{103,110,1},{103,110,1},{103,110,1},{102,107,1},{100,108,0},{100,108,0},{108,123,36},{108,118,18},{108,115,23},{108,114,20},{107,122,52},{107,116,20},{107,114,2},{106,113,23},{101,117,51},{103,113,18},{110,119,19}, +{109,117,1},{110,114,2},{109,114,6},{127,81,51},{107,116,19},{107,114,1},{102,113,18},{126,105,51},{102,113,18},{108,118,18},{108,118,18},{108,118,18},{108,113,18},{107,117,9},{107,114,1},{107,114,1},{106,111,2},{103,114,8},{104,112,1},{110,114,1},{110,114,1},{110,114,1},{110,112,1},{127,76,8},{108,113,0},{108,113,0},{106,111,1},{126,103,8},{106,111,1},{127,84,18},{109,117,0},{110,114,1}, +{106,114,1},{127,84,18},{127,106,18},{106,114,1},{0,113,18},{127,106,18},{0,113,18},{108,0,18},{108,0,18},{108,0,18},{108,0,18},{107,114,1},{107,114,1},{107,114,1},{106,111,1},{104,112,0},{104,112,0},{113,126,38},{113,122,20},{113,119,24},{112,119,21},{111,127,51},{111,121,19},{111,119,2},{111,117,24},{106,121,52},{108,117,20},{114,124,18},{114,121,2},{114,119,1},{114,118,5},{127,95,51}, +{112,120,19},{111,119,2},{108,117,20},{127,111,51},{108,117,20},{113,122,20},{113,122,20},{113,122,20},{112,118,20},{111,123,8},{111,118,2},{111,118,2},{111,116,1},{107,119,8},{108,116,2},{114,120,0},{114,120,0},{114,120,0},{114,117,0},{127,90,8},{112,118,0},{112,118,0},{110,116,0},{127,109,8},{110,116,0},{127,98,18},{113,122,0},{114,119,1},{110,119,0},{127,98,18},{126,113,18},{110,119,0}, +{0,117,20},{126,113,18},{0,117,20},{112,0,20},{112,0,20},{112,0,20},{112,0,20},{111,120,0},{111,120,0},{111,120,0},{111,115,1},{108,117,0},{108,117,0},{117,127,46},{117,126,20},{117,123,24},{116,123,21},{116,126,63},{115,125,19},{115,123,2},{115,121,24},{110,125,52},{112,121,20},{118,127,20},{118,125,2},{118,123,1},{118,122,5},{127,107,51},{116,124,19},{115,123,2},{112,121,20},{127,117,51}, +{112,121,20},{117,126,20},{117,126,20},{117,126,20},{116,122,20},{115,127,8},{115,122,2},{115,122,2},{115,120,1},{111,123,8},{112,120,2},{118,124,0},{118,124,0},{118,124,0},{118,121,0},{127,102,8},{116,122,0},{116,122,0},{114,120,0},{127,115,8},{114,120,0},{127,110,18},{117,126,0},{118,123,1},{114,123,0},{127,110,18},{126,119,18},{114,123,0},{0,121,20},{126,119,18},{0,121,20},{116,0,20}, +{116,0,20},{116,0,20},{116,0,20},{115,124,0},{115,124,0},{115,124,0},{115,119,1},{112,121,0},{112,121,0},{122,126,86},{121,127,40},{121,127,24},{120,127,21},{121,127,88},{119,127,27},{119,127,2},{119,125,24},{116,127,60},{116,125,20},{123,127,30},{122,127,10},{122,127,1},{122,126,5},{127,119,51},{121,127,24},{119,127,2},{116,125,20},{127,123,51},{116,125,20},{121,127,24},{121,127,24},{121,127,24}, +{120,126,20},{120,127,14},{119,126,2},{119,126,2},{119,124,1},{115,127,8},{116,124,2},{122,126,1},{122,126,1},{122,126,1},{122,125,0},{127,115,8},{120,126,0},{120,126,0},{118,124,0},{127,121,8},{118,124,0},{127,122,18},{124,127,8},{122,127,1},{118,127,0},{127,122,18},{126,125,18},{118,127,0},{0,125,20},{126,125,18},{0,125,20},{120,0,20},{120,0,20},{120,0,20},{120,0,20},{119,126,1}, +{119,126,1},{119,126,1},{119,123,1},{116,125,0},{116,125,0},{125,126,38},{125,127,30},{125,127,29},{125,127,21},{125,126,35},{124,127,16},{124,127,12},{123,127,1},{122,127,20},{122,127,2},{126,127,2},{126,127,2},{126,127,1},{126,127,1},{127,125,3},{127,126,3},{125,127,2},{124,127,0},{127,126,3},{124,127,0},{125,126,29},{125,126,29},{125,126,29},{125,127,21},{124,127,24},{124,127,12},{124,127,12}, +{123,127,1},{122,127,11},{122,127,2},{126,127,1},{126,127,1},{126,127,1},{126,127,1},{127,125,2},{127,126,2},{127,126,2},{124,127,0},{127,126,2},{124,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{124,0,20},{124,0,20},{124,0,20},{124,0,20},{124,127,8},{124,127,8},{124,127,8},{123,127,1},{122,127,2}, +{122,127,2},{0,16,72},{0,11,8},{0,8,1},{0,7,25},{0,10,153},{0,8,97},{0,6,50},{0,4,115},{0,5,162},{0,4,124},{0,16,72},{0,11,8},{0,8,1},{0,7,25},{5,0,153},{0,8,97},{0,6,50},{0,4,115},{10,0,153},{0,4,115},{0,7,0},{0,7,0},{0,7,0},{0,4,0},{0,3,13},{0,2,5},{0,2,5},{0,1,10},{0,2,14},{0,1,11},{0,7,0}, +{0,7,0},{0,7,0},{0,4,0},{2,0,13},{0,2,5},{0,2,5},{0,1,10},{3,0,13},{0,1,10},{8,0,72},{0,11,8},{0,8,1},{0,7,25},{8,0,72},{16,0,72},{0,7,25},{0,5,74},{16,0,72},{0,5,74},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,27,77},{1,18,5},{1,13,15}, +{1,11,18},{0,21,243},{0,14,108},{0,11,29},{0,8,154},{0,9,287},{0,8,179},{2,25,73},{1,18,1},{2,12,6},{1,11,14},{10,1,243},{0,14,108},{0,11,29},{0,8,154},{21,0,243},{0,8,154},{1,17,5},{1,17,5},{1,17,5},{1,9,5},{0,12,50},{0,8,8},{0,8,8},{0,5,25},{0,5,61},{0,5,34},{2,15,1},{2,15,1},{2,15,1},{1,9,1},{6,0,50}, +{0,8,8},{0,8,8},{0,5,25},{12,0,50},{0,5,25},{14,0,72},{1,18,0},{4,12,1},{0,12,10},{14,0,72},{29,0,72},{0,12,10},{0,9,74},{29,0,72},{0,9,74},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,2,1},{0,2,1},{3,35,133},{3,24,63},{4,17,90},{3,16,66},{0,33,243},{0,19,75},{0,16,2}, +{0,13,110},{0,14,345},{0,12,179},{6,29,73},{5,22,1},{6,16,6},{5,15,14},{16,0,243},{0,19,75},{0,16,2},{0,13,110},{33,0,243},{0,13,110},{3,26,61},{3,26,61},{3,26,61},{3,14,61},{0,24,50},{0,16,1},{0,16,1},{0,10,5},{0,11,101},{0,9,46},{6,19,1},{6,19,1},{6,19,1},{5,13,1},{12,0,50},{1,15,0},{1,15,0},{0,10,5},{24,0,50}, +{0,10,5},{20,0,72},{5,22,0},{8,16,1},{0,16,2},{20,0,72},{41,0,72},{0,16,2},{0,13,74},{41,0,72},{0,13,74},{3,0,61},{3,0,61},{3,0,61},{3,0,61},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,5,25},{0,5,25},{7,39,146},{7,28,76},{8,21,107},{6,20,79},{4,37,244},{4,23,76},{4,20,3},{3,16,107},{0,22,292},{0,17,106},{10,33,73}, +{9,26,1},{10,20,6},{9,19,14},{22,0,243},{2,25,72},{4,20,2},{0,17,90},{45,0,243},{0,17,90},{7,30,74},{7,30,74},{7,30,74},{7,18,74},{4,28,51},{4,20,2},{4,20,2},{3,14,6},{0,17,68},{0,14,5},{10,23,1},{10,23,1},{10,23,1},{9,17,1},{18,0,50},{5,19,0},{5,19,0},{0,14,1},{36,0,50},{0,14,1},{26,0,72},{9,26,0},{12,20,1}, +{3,20,1},{26,0,72},{53,0,72},{3,20,1},{0,17,74},{53,0,72},{0,17,74},{6,0,74},{6,0,74},{6,0,74},{6,0,74},{4,20,1},{4,20,1},{4,20,1},{4,12,1},{0,14,4},{0,14,4},{11,44,144},{11,32,76},{12,25,105},{11,24,77},{8,43,243},{8,28,75},{8,25,2},{8,21,105},{0,28,248},{1,22,76},{14,38,72},{14,30,1},{15,25,5},{14,24,13},{29,0,243}, +{7,29,72},{8,25,2},{0,22,76},{59,0,243},{0,22,76},{11,35,72},{11,35,72},{11,35,72},{11,23,72},{8,34,50},{8,24,1},{8,24,1},{8,18,5},{1,24,51},{3,19,1},{14,29,0},{14,29,0},{14,29,0},{14,21,1},{24,1,50},{9,24,0},{9,24,0},{3,19,0},{50,0,50},{3,19,0},{33,0,72},{13,31,0},{16,25,0},{6,25,0},{33,0,72},{66,0,72},{6,25,0}, +{0,22,72},{66,0,72},{0,22,72},{11,0,72},{11,0,72},{11,0,72},{11,0,72},{8,26,0},{8,26,0},{8,26,0},{8,17,0},{2,20,0},{2,20,0},{15,48,144},{15,36,76},{16,29,105},{15,28,77},{12,47,243},{12,32,75},{12,29,2},{12,25,105},{2,33,244},{5,26,76},{18,42,72},{18,34,1},{19,29,5},{18,28,13},{35,0,243},{11,33,72},{12,29,2},{1,26,72},{71,0,243}, +{1,26,72},{15,39,72},{15,39,72},{15,39,72},{15,27,72},{12,38,50},{12,28,1},{12,28,1},{12,22,5},{5,28,51},{7,23,1},{18,33,0},{18,33,0},{18,33,0},{18,25,1},{30,1,50},{13,28,0},{13,28,0},{7,23,0},{62,0,50},{7,23,0},{39,0,72},{17,35,0},{20,29,0},{10,29,0},{39,0,72},{78,0,72},{10,29,0},{0,26,72},{78,0,72},{0,26,72},{15,0,72}, +{15,0,72},{15,0,72},{15,0,72},{12,30,0},{12,30,0},{12,30,0},{12,21,0},{6,24,0},{6,24,0},{19,52,144},{19,40,76},{20,33,105},{19,32,77},{16,51,243},{16,36,75},{16,33,2},{16,29,105},{6,37,244},{9,30,76},{22,46,72},{22,38,1},{23,33,5},{22,32,13},{41,0,243},{15,37,72},{16,33,2},{5,30,72},{83,0,243},{5,30,72},{19,43,72},{19,43,72},{19,43,72}, +{19,31,72},{16,42,50},{16,32,1},{16,32,1},{16,26,5},{9,32,51},{11,27,1},{22,37,0},{22,37,0},{22,37,0},{22,29,1},{36,1,50},{17,32,0},{17,32,0},{11,27,0},{74,0,50},{11,27,0},{45,0,72},{21,39,0},{24,33,0},{14,33,0},{45,0,72},{91,0,72},{14,33,0},{0,30,72},{91,0,72},{0,30,72},{19,0,72},{19,0,72},{19,0,72},{19,0,72},{16,34,0}, +{16,34,0},{16,34,0},{16,25,0},{10,28,0},{10,28,0},{23,56,144},{23,44,76},{24,37,105},{23,36,77},{20,55,243},{20,40,75},{20,37,2},{20,33,105},{10,41,244},{13,34,76},{26,50,72},{26,42,1},{27,37,5},{26,36,13},{47,0,243},{19,41,72},{20,37,2},{9,34,72},{95,0,243},{9,34,72},{23,47,72},{23,47,72},{23,47,72},{23,35,72},{20,46,50},{20,36,1},{20,36,1}, +{20,30,5},{13,36,51},{15,31,1},{26,41,0},{26,41,0},{26,41,0},{26,33,1},{42,1,50},{21,36,0},{21,36,0},{15,31,0},{86,0,50},{15,31,0},{50,1,72},{25,43,0},{28,37,0},{18,37,0},{50,1,72},{103,0,72},{18,37,0},{0,34,72},{103,0,72},{0,34,72},{23,0,72},{23,0,72},{23,0,72},{23,0,72},{20,38,0},{20,38,0},{20,38,0},{20,29,0},{14,32,0}, +{14,32,0},{28,60,146},{28,49,76},{29,42,107},{27,41,79},{25,58,244},{25,44,76},{25,41,3},{24,37,107},{14,46,244},{17,38,76},{31,54,73},{30,47,1},{31,41,6},{30,40,14},{53,1,243},{23,46,72},{25,41,2},{15,38,74},{109,0,243},{15,38,74},{28,51,74},{28,51,74},{28,51,74},{28,39,74},{25,49,51},{25,41,2},{25,41,2},{24,35,6},{18,40,51},{19,36,1},{31,44,1}, +{31,44,1},{31,44,1},{30,38,1},{49,0,50},{26,40,0},{26,40,0},{21,35,1},{100,0,50},{21,35,1},{57,0,72},{30,47,0},{33,41,1},{24,41,1},{57,0,72},{117,0,72},{24,41,1},{0,38,74},{117,0,72},{0,38,74},{27,0,74},{27,0,74},{27,0,74},{27,0,74},{25,41,1},{25,41,1},{25,41,1},{25,33,1},{19,36,0},{19,36,0},{32,64,146},{32,53,76},{33,46,107}, +{31,45,79},{29,62,244},{29,48,76},{29,45,3},{28,41,107},{18,50,244},{21,42,76},{35,58,73},{34,51,1},{35,45,6},{34,44,14},{59,1,243},{27,50,72},{29,45,2},{19,42,74},{121,0,243},{19,42,74},{32,55,74},{32,55,74},{32,55,74},{32,43,74},{29,53,51},{29,45,2},{29,45,2},{28,39,6},{22,44,51},{23,40,1},{35,48,1},{35,48,1},{35,48,1},{34,42,1},{55,0,50}, +{30,44,0},{30,44,0},{25,39,1},{112,0,50},{25,39,1},{63,0,72},{34,51,0},{37,45,1},{28,45,1},{63,0,72},{127,1,72},{28,45,1},{0,42,74},{127,1,72},{0,42,74},{31,0,74},{31,0,74},{31,0,74},{31,0,74},{29,45,1},{29,45,1},{29,45,1},{29,37,1},{23,40,0},{23,40,0},{36,67,146},{36,57,76},{37,50,107},{35,49,79},{33,66,244},{33,52,76},{33,49,3}, +{32,45,107},{22,54,244},{25,46,76},{39,62,73},{38,55,1},{39,49,6},{38,48,14},{65,0,243},{31,54,72},{33,49,2},{23,46,74},{127,3,243},{23,46,74},{36,59,74},{36,59,74},{36,59,74},{36,47,74},{33,57,51},{33,49,2},{33,49,2},{32,43,6},{26,48,51},{27,44,1},{39,52,1},{39,52,1},{39,52,1},{38,46,1},{61,0,50},{34,48,0},{34,48,0},{29,43,1},{124,0,50}, +{29,43,1},{69,0,72},{38,55,0},{41,49,1},{32,49,1},{69,0,72},{127,7,72},{32,49,1},{0,46,74},{127,7,72},{0,46,74},{35,0,74},{35,0,74},{35,0,74},{35,0,74},{33,49,1},{33,49,1},{33,49,1},{33,41,1},{27,44,0},{27,44,0},{40,71,146},{40,61,76},{41,54,107},{39,53,79},{37,70,244},{37,56,76},{37,53,3},{36,49,107},{26,58,244},{29,50,76},{43,65,73}, +{42,59,1},{43,53,6},{42,52,14},{71,0,243},{35,58,72},{37,53,2},{27,50,74},{127,9,243},{27,50,74},{40,63,74},{40,63,74},{40,63,74},{40,51,74},{37,61,51},{37,53,2},{37,53,2},{36,47,6},{30,52,51},{31,48,1},{43,56,1},{43,56,1},{43,56,1},{42,50,1},{66,1,50},{38,52,0},{38,52,0},{33,47,1},{126,5,50},{33,47,1},{75,0,72},{42,59,0},{45,53,1}, +{36,53,1},{75,0,72},{127,13,72},{36,53,1},{0,50,74},{127,13,72},{0,50,74},{39,0,74},{39,0,74},{39,0,74},{39,0,74},{37,53,1},{37,53,1},{37,53,1},{37,45,1},{31,48,0},{31,48,0},{44,77,144},{44,65,77},{45,58,105},{44,57,77},{41,75,243},{41,61,75},{41,58,2},{41,54,105},{31,62,244},{34,55,76},{47,71,72},{47,63,1},{48,58,5},{47,57,13},{78,0,243}, +{40,62,72},{41,58,2},{30,55,72},{126,16,243},{30,55,72},{44,68,72},{44,68,72},{44,68,72},{44,56,72},{41,66,50},{41,57,1},{41,57,1},{41,51,5},{34,57,51},{36,52,1},{47,62,0},{47,62,0},{47,62,0},{47,54,1},{73,0,50},{42,57,0},{42,57,0},{36,52,0},{126,12,50},{36,52,0},{81,0,72},{47,63,1},{49,58,0},{39,58,0},{81,0,72},{126,20,72},{39,58,0}, +{0,55,72},{126,20,72},{0,55,72},{44,0,72},{44,0,72},{44,0,72},{44,0,72},{41,59,0},{41,59,0},{41,59,0},{41,50,0},{35,53,0},{35,53,0},{48,81,144},{48,69,77},{49,62,105},{48,61,77},{45,79,243},{45,65,73},{45,62,2},{45,58,105},{34,67,243},{38,59,76},{51,75,72},{51,66,1},{52,62,5},{51,61,13},{83,1,243},{45,65,73},{45,62,2},{34,59,72},{126,22,243}, +{34,59,72},{48,72,72},{48,72,72},{48,72,72},{48,60,72},{45,70,50},{45,61,1},{45,61,1},{45,55,5},{38,61,51},{40,56,1},{51,65,0},{51,65,0},{51,65,0},{51,58,1},{79,0,50},{46,61,0},{46,61,0},{40,56,0},{127,17,50},{40,56,0},{87,0,72},{51,66,1},{53,62,0},{43,62,0},{87,0,72},{126,26,72},{43,62,0},{0,59,72},{126,26,72},{0,59,72},{48,0,72}, +{48,0,72},{48,0,72},{48,0,72},{45,63,0},{45,63,0},{45,63,0},{45,54,0},{39,57,0},{39,57,0},{52,85,144},{52,73,77},{53,67,105},{52,65,77},{49,83,243},{49,69,73},{49,65,2},{49,62,105},{38,71,243},{42,63,76},{55,79,72},{55,70,1},{55,66,5},{54,65,14},{89,1,243},{49,69,73},{49,65,2},{38,63,72},{126,28,243},{38,63,72},{52,76,72},{52,76,72},{52,76,72}, +{52,63,73},{49,74,50},{49,65,1},{49,65,1},{49,59,5},{41,65,50},{44,60,1},{55,69,0},{55,69,0},{55,69,0},{55,62,1},{85,0,50},{50,64,1},{50,64,1},{44,60,0},{127,23,50},{44,60,0},{93,0,72},{55,70,1},{57,65,1},{48,65,1},{93,0,72},{126,32,72},{48,65,1},{0,63,72},{126,32,72},{0,63,72},{52,0,72},{52,0,72},{52,0,72},{52,0,72},{49,67,0}, +{49,67,0},{49,67,0},{49,58,0},{43,61,0},{43,61,0},{56,89,144},{56,77,77},{57,71,105},{56,69,77},{53,87,243},{53,73,73},{53,69,2},{52,66,103},{42,75,243},{45,66,79},{59,83,72},{59,74,1},{59,70,5},{58,69,14},{95,1,243},{53,73,73},{53,69,2},{43,66,74},{126,34,243},{43,66,74},{56,80,72},{56,80,72},{56,80,72},{56,67,73},{53,78,50},{53,69,1},{53,69,1}, +{53,63,5},{45,69,50},{47,64,2},{59,73,0},{59,73,0},{59,73,0},{59,66,0},{91,0,50},{55,67,1},{55,67,1},{47,64,1},{127,29,50},{47,64,1},{99,0,72},{59,74,1},{61,69,1},{52,69,1},{99,0,72},{126,38,72},{52,69,1},{0,66,74},{126,38,72},{0,66,74},{56,0,72},{56,0,72},{56,0,72},{56,0,72},{53,71,0},{53,71,0},{53,71,0},{53,62,0},{47,64,1}, +{47,64,1},{61,92,146},{61,80,79},{61,75,103},{60,74,78},{58,91,244},{57,78,74},{58,74,2},{56,70,105},{47,79,243},{49,71,77},{63,88,73},{63,79,2},{64,74,5},{63,73,14},{102,0,243},{57,78,73},{58,74,1},{47,71,72},{126,41,243},{47,71,72},{61,83,74},{61,83,74},{61,83,74},{60,72,74},{58,82,51},{58,73,2},{58,73,2},{57,68,5},{50,73,50},{52,68,1},{63,79,1}, +{63,79,1},{63,79,1},{63,71,1},{98,0,50},{59,72,1},{59,72,1},{53,68,0},{127,36,50},{53,68,0},{106,0,72},{63,79,1},{65,74,0},{56,74,0},{106,0,72},{127,44,72},{56,74,0},{0,71,72},{127,44,72},{0,71,72},{60,0,74},{60,0,74},{60,0,74},{60,0,74},{58,74,1},{58,74,1},{58,74,1},{57,66,1},{52,68,1},{52,68,1},{64,97,144},{64,85,76},{65,78,105}, +{64,77,77},{62,95,244},{61,82,74},{62,78,2},{60,74,105},{51,83,243},{53,75,77},{67,91,72},{67,83,1},{68,78,5},{67,77,13},{108,0,243},{61,82,73},{62,78,1},{51,75,72},{125,47,243},{51,75,72},{64,88,72},{64,88,72},{64,88,72},{64,76,72},{62,86,51},{62,77,2},{62,77,2},{61,72,5},{54,77,50},{56,72,1},{67,82,0},{67,82,0},{67,82,0},{67,74,1},{104,0,50}, +{63,76,1},{63,76,1},{57,72,0},{127,42,50},{57,72,0},{112,0,72},{66,84,0},{69,78,0},{60,78,0},{112,0,72},{127,50,72},{60,78,0},{0,75,72},{127,50,72},{0,75,72},{64,0,72},{64,0,72},{64,0,72},{64,0,72},{62,78,1},{62,78,1},{62,78,1},{61,70,1},{56,72,1},{56,72,1},{68,101,144},{68,89,76},{69,82,105},{68,81,77},{65,100,243},{65,85,75},{65,82,2}, +{65,78,105},{55,87,243},{57,79,77},{71,95,72},{71,87,1},{72,82,5},{71,81,13},{114,0,243},{64,86,72},{65,82,2},{55,79,72},{127,52,243},{55,79,72},{68,92,72},{68,92,72},{68,92,72},{68,80,72},{65,91,50},{65,81,1},{65,81,1},{65,75,5},{58,81,50},{60,76,1},{71,86,0},{71,86,0},{71,86,0},{71,78,1},{110,0,50},{66,81,0},{66,81,0},{61,76,0},{126,48,50}, +{61,76,0},{118,0,72},{70,88,0},{73,82,0},{64,82,0},{118,0,72},{127,56,72},{64,82,0},{0,79,72},{127,56,72},{0,79,72},{68,0,72},{68,0,72},{68,0,72},{68,0,72},{65,83,0},{65,83,0},{65,83,0},{65,74,0},{60,76,1},{60,76,1},{72,105,144},{72,93,76},{73,86,105},{72,85,77},{69,104,243},{69,89,75},{69,86,2},{69,82,105},{59,91,243},{61,83,77},{75,99,72}, +{75,91,1},{76,86,5},{75,85,13},{120,0,243},{68,90,72},{69,86,2},{59,83,72},{127,58,243},{59,83,72},{72,96,72},{72,96,72},{72,96,72},{72,84,72},{69,95,50},{69,85,1},{69,85,1},{69,79,5},{62,85,50},{64,80,1},{75,90,0},{75,90,0},{75,90,0},{75,82,1},{115,1,50},{70,85,0},{70,85,0},{64,80,0},{126,54,50},{64,80,0},{124,0,72},{74,92,0},{77,86,0}, +{67,86,0},{124,0,72},{127,62,72},{67,86,0},{0,83,72},{127,62,72},{0,83,72},{72,0,72},{72,0,72},{72,0,72},{72,0,72},{69,87,0},{69,87,0},{69,87,0},{69,78,0},{64,80,1},{64,80,1},{77,109,146},{77,98,76},{78,91,107},{76,90,79},{74,107,244},{74,93,76},{74,90,3},{73,86,107},{63,96,243},{66,87,76},{80,103,73},{79,96,1},{80,90,6},{79,89,14},{127,0,243}, +{72,95,72},{74,90,2},{64,87,74},{126,65,243},{64,87,74},{77,100,74},{77,100,74},{77,100,74},{77,88,74},{74,98,51},{74,90,2},{74,90,2},{73,84,6},{67,89,51},{68,85,1},{80,93,1},{80,93,1},{80,93,1},{79,87,1},{122,0,50},{75,89,0},{75,89,0},{70,84,1},{126,61,50},{70,84,1},{127,7,72},{79,96,0},{82,90,1},{73,90,1},{127,7,72},{127,68,72},{73,90,1}, +{0,87,74},{127,68,72},{0,87,74},{76,0,74},{76,0,74},{76,0,74},{76,0,74},{74,90,1},{74,90,1},{74,90,1},{74,82,1},{68,85,0},{68,85,0},{81,113,146},{81,102,76},{82,95,107},{80,94,79},{78,111,244},{78,97,76},{78,94,3},{77,90,107},{67,99,244},{70,91,76},{84,107,73},{83,100,1},{84,94,6},{83,93,14},{127,11,243},{76,99,72},{78,94,2},{68,91,74},{126,71,243}, +{68,91,74},{81,104,74},{81,104,74},{81,104,74},{81,92,74},{78,102,51},{78,94,2},{78,94,2},{77,88,6},{71,93,51},{72,89,1},{84,97,1},{84,97,1},{84,97,1},{83,91,1},{127,2,50},{79,93,0},{79,93,0},{74,88,1},{127,66,50},{74,88,1},{127,19,72},{83,100,0},{86,94,1},{77,94,1},{127,19,72},{127,74,72},{77,94,1},{0,91,74},{127,74,72},{0,91,74},{80,0,74}, +{80,0,74},{80,0,74},{80,0,74},{78,94,1},{78,94,1},{78,94,1},{78,86,1},{72,89,0},{72,89,0},{85,117,146},{85,106,76},{86,99,107},{84,98,79},{82,115,244},{82,101,76},{82,98,3},{81,94,107},{71,103,244},{74,95,76},{88,111,73},{87,104,1},{88,98,6},{87,97,14},{127,24,243},{80,103,72},{82,98,2},{72,95,74},{125,77,243},{72,95,74},{85,108,74},{85,108,74},{85,108,74}, +{85,96,74},{82,106,51},{82,98,2},{82,98,2},{81,92,6},{75,97,51},{76,93,1},{88,101,1},{88,101,1},{88,101,1},{87,95,1},{127,14,50},{83,97,0},{83,97,0},{78,92,1},{127,72,50},{78,92,1},{127,31,72},{87,104,0},{90,98,1},{81,98,1},{127,31,72},{127,80,72},{81,98,1},{0,95,74},{127,80,72},{0,95,74},{84,0,74},{84,0,74},{84,0,74},{84,0,74},{82,98,1}, +{82,98,1},{82,98,1},{82,90,1},{76,93,0},{76,93,0},{89,121,146},{89,110,76},{90,103,107},{88,102,79},{86,119,244},{86,105,76},{86,102,3},{85,98,107},{75,107,244},{78,99,76},{92,115,73},{91,108,1},{92,102,6},{91,101,14},{127,36,243},{84,107,72},{86,102,2},{76,99,74},{127,82,243},{76,99,74},{89,112,74},{89,112,74},{89,112,74},{89,100,74},{86,110,51},{86,102,2},{86,102,2}, +{85,96,6},{79,101,51},{80,97,1},{92,105,1},{92,105,1},{92,105,1},{91,99,1},{127,27,50},{87,101,0},{87,101,0},{82,96,1},{126,78,50},{82,96,1},{127,43,72},{91,108,0},{94,102,1},{85,102,1},{127,43,72},{127,86,72},{85,102,1},{0,99,74},{127,86,72},{0,99,74},{88,0,74},{88,0,74},{88,0,74},{88,0,74},{86,102,1},{86,102,1},{86,102,1},{86,94,1},{80,97,0}, +{80,97,0},{93,126,144},{93,114,76},{94,107,105},{93,106,77},{90,125,243},{90,110,75},{90,107,2},{90,103,105},{80,111,244},{83,104,76},{96,120,72},{96,112,1},{97,107,5},{96,106,13},{127,50,243},{89,111,72},{90,107,2},{79,104,72},{127,89,243},{79,104,72},{93,117,72},{93,117,72},{93,117,72},{93,105,72},{90,116,50},{90,106,1},{90,106,1},{90,100,5},{83,106,51},{85,101,1},{96,111,0}, +{96,111,0},{96,111,0},{96,103,1},{127,40,50},{91,106,0},{91,106,0},{85,101,0},{126,85,50},{85,101,0},{127,57,72},{95,113,0},{98,107,0},{88,107,0},{127,57,72},{126,93,72},{88,107,0},{0,104,72},{126,93,72},{0,104,72},{93,0,72},{93,0,72},{93,0,72},{93,0,72},{90,108,0},{90,108,0},{90,108,0},{90,99,0},{84,102,0},{84,102,0},{97,127,152},{97,118,76},{98,111,105}, +{97,110,77},{94,127,244},{94,114,75},{94,111,2},{94,107,105},{84,115,244},{87,108,76},{100,124,72},{100,116,1},{101,111,5},{100,110,13},{127,62,243},{93,115,72},{94,111,2},{83,108,72},{127,95,243},{83,108,72},{97,121,72},{97,121,72},{97,121,72},{97,109,72},{94,120,50},{94,110,1},{94,110,1},{94,104,5},{87,110,51},{89,105,1},{100,115,0},{100,115,0},{100,115,0},{100,107,1},{127,53,50}, +{95,110,0},{95,110,0},{89,105,0},{126,91,50},{89,105,0},{127,69,72},{99,117,0},{102,111,0},{92,111,0},{127,69,72},{126,99,72},{92,111,0},{0,108,72},{126,99,72},{0,108,72},{97,0,72},{97,0,72},{97,0,72},{97,0,72},{94,112,0},{94,112,0},{94,112,0},{94,103,0},{88,106,0},{88,106,0},{102,126,184},{101,122,76},{102,115,105},{101,114,77},{100,127,260},{98,118,75},{98,115,2}, +{98,111,105},{88,119,244},{91,112,76},{104,127,74},{104,120,1},{105,115,5},{104,114,13},{127,73,243},{97,119,72},{98,115,2},{87,112,72},{127,101,243},{87,112,72},{101,125,72},{101,125,72},{101,125,72},{101,113,72},{98,124,50},{98,114,1},{98,114,1},{98,108,5},{91,114,51},{93,109,1},{104,119,0},{104,119,0},{104,119,0},{104,111,1},{127,64,50},{99,114,0},{99,114,0},{93,109,0},{126,97,50}, +{93,109,0},{127,81,72},{103,121,0},{106,115,0},{96,115,0},{127,81,72},{126,105,72},{96,115,0},{0,112,72},{126,105,72},{0,112,72},{101,0,72},{101,0,72},{101,0,72},{101,0,72},{98,116,0},{98,116,0},{98,116,0},{98,107,0},{92,110,0},{92,110,0},{106,127,224},{105,126,76},{106,119,105},{105,118,77},{104,127,299},{102,122,75},{102,119,2},{102,115,105},{92,123,244},{95,116,76},{109,127,84}, +{108,124,1},{109,119,5},{108,118,13},{127,86,243},{101,123,72},{102,119,2},{91,116,72},{127,107,243},{91,116,72},{105,126,76},{105,126,76},{105,126,76},{105,117,72},{102,126,52},{102,118,1},{102,118,1},{102,112,5},{95,118,51},{97,113,1},{108,123,0},{108,123,0},{108,123,0},{108,115,1},{127,76,50},{103,118,0},{103,118,0},{97,113,0},{126,103,50},{97,113,0},{127,93,72},{107,125,0},{110,119,0}, +{100,119,0},{127,93,72},{126,111,72},{100,119,0},{0,116,72},{126,111,72},{0,116,72},{105,0,72},{105,0,72},{105,0,72},{105,0,72},{102,120,0},{102,120,0},{102,120,0},{102,111,0},{96,114,0},{96,114,0},{111,127,290},{111,127,103},{111,124,107},{109,123,79},{111,127,345},{107,126,76},{107,123,3},{106,119,107},{98,127,248},{99,120,76},{114,127,113},{113,127,5},{113,123,6},{112,122,14},{127,99,243}, +{107,126,75},{107,123,2},{97,120,74},{126,114,243},{97,120,74},{110,126,90},{110,126,90},{110,126,90},{110,121,74},{108,126,67},{107,123,2},{107,123,2},{106,117,6},{100,122,51},{101,118,1},{113,126,1},{113,126,1},{113,126,1},{112,120,1},{127,90,50},{108,122,0},{108,122,0},{103,117,1},{127,109,50},{103,117,1},{127,107,72},{113,127,4},{115,123,1},{106,123,1},{127,107,72},{127,117,72},{106,123,1}, +{0,120,74},{127,117,72},{0,120,74},{109,0,74},{109,0,74},{109,0,74},{109,0,74},{107,123,1},{107,123,1},{107,123,1},{107,115,1},{101,118,0},{101,118,0},{117,127,343},{115,127,179},{114,127,110},{113,126,78},{115,127,387},{111,127,102},{111,127,2},{110,123,90},{105,127,263},{103,124,63},{120,127,134},{118,127,46},{117,127,5},{116,126,9},{127,110,221},{113,127,89},{111,127,1},{101,124,61},{126,119,221}, +{101,124,61},{114,127,110},{114,127,110},{114,127,110},{114,125,74},{112,127,91},{111,127,2},{111,127,2},{110,121,6},{104,126,51},{105,122,1},{117,127,5},{117,127,5},{117,127,5},{116,124,1},{127,102,50},{112,126,0},{112,126,0},{107,121,1},{127,115,50},{107,121,1},{127,118,61},{119,127,25},{119,127,0},{110,127,0},{127,118,61},{126,123,61},{110,127,0},{0,124,61},{126,123,61},{0,124,61},{113,0,74}, +{113,0,74},{113,0,74},{113,0,74},{111,127,1},{111,127,1},{111,127,1},{111,119,1},{105,122,0},{105,122,0},{120,127,239},{119,127,179},{119,127,154},{118,127,83},{120,127,254},{116,127,78},{116,127,29},{114,126,15},{113,127,169},{109,126,5},{123,127,54},{122,127,34},{122,127,25},{121,127,2},{127,119,93},{119,127,33},{119,127,8},{109,126,5},{127,123,93},{109,126,5},{119,126,154},{119,126,154},{119,126,154}, +{118,127,83},{117,127,125},{116,127,29},{116,127,29},{114,125,6},{110,127,72},{109,126,1},{122,126,25},{122,126,25},{122,126,25},{121,127,2},{127,115,50},{119,127,8},{119,127,8},{111,125,1},{127,121,50},{111,125,1},{127,124,5},{125,127,1},{125,127,0},{122,127,0},{127,124,5},{126,126,5},{122,127,0},{0,126,5},{126,126,5},{0,126,5},{117,0,74},{117,0,74},{117,0,74},{117,0,74},{115,127,10}, +{115,127,10},{115,127,10},{115,123,1},{109,126,0},{109,126,0},{123,127,140},{123,127,124},{123,127,115},{122,127,83},{123,127,131},{121,127,66},{120,127,50},{119,127,1},{119,127,86},{116,127,8},{126,127,11},{125,127,11},{125,127,10},{125,127,2},{127,124,17},{125,127,6},{124,127,5},{119,127,0},{126,126,17},{119,127,0},{123,127,115},{123,127,115},{123,127,115},{122,127,83},{121,127,98},{120,127,50},{120,127,50}, +{119,127,1},{116,127,57},{116,127,8},{125,126,10},{125,126,10},{125,126,10},{125,127,2},{127,122,13},{124,127,5},{124,127,5},{119,127,0},{126,125,13},{119,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{121,0,74},{121,0,74},{121,0,74},{121,0,74},{120,127,25},{120,127,25},{120,127,25},{119,127,1},{116,127,8}, +{116,127,8},{0,29,200},{0,19,18},{0,14,1},{0,13,73},{0,20,441},{0,11,281},{0,11,134},{0,7,331},{0,8,474},{0,7,356},{0,29,200},{0,19,18},{0,14,1},{0,13,73},{10,0,441},{0,11,281},{0,11,134},{0,7,331},{20,0,441},{0,7,331},{0,13,0},{0,13,0},{0,13,0},{0,7,0},{0,6,41},{0,5,13},{0,5,13},{0,3,25},{0,3,45},{0,3,29},{0,13,0}, +{0,13,0},{0,13,0},{0,7,0},{3,0,41},{0,5,13},{0,5,13},{0,3,25},{6,0,41},{0,3,25},{14,0,200},{0,19,18},{0,14,1},{0,13,73},{14,0,200},{29,0,200},{0,13,73},{0,9,202},{29,0,200},{0,9,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,41,200},{0,27,2},{1,19,18}, +{0,17,45},{0,27,686},{0,19,346},{0,15,158},{0,10,467},{0,11,762},{0,10,516},{0,41,200},{0,27,2},{1,19,14},{0,17,45},{13,1,686},{0,19,346},{0,15,158},{0,10,467},{27,0,686},{0,10,467},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{0,12,145},{0,11,53},{0,11,53},{0,6,89},{0,5,158},{0,6,105},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{6,0,145}, +{0,11,53},{0,11,53},{0,6,89},{12,0,145},{0,6,89},{20,0,200},{1,26,2},{4,18,1},{0,17,45},{20,0,200},{41,0,200},{0,17,45},{0,13,202},{41,0,200},{0,13,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,49,225},{2,32,27},{3,24,71},{1,21,54},{0,39,723},{0,25,283},{0,20,65}, +{0,15,419},{0,17,865},{0,15,519},{4,45,201},{3,32,1},{5,23,19},{3,21,35},{19,0,723},{0,25,283},{0,20,65},{0,15,419},{39,0,723},{0,15,419},{2,34,25},{2,34,25},{2,34,25},{2,17,26},{0,24,162},{0,17,20},{0,17,20},{0,10,61},{0,11,213},{0,9,110},{4,30,1},{4,30,1},{4,30,1},{3,17,1},{12,0,162},{0,17,20},{0,17,20},{0,10,61},{24,0,162}, +{0,10,61},{26,0,200},{3,32,0},{8,22,1},{0,21,18},{26,0,200},{53,0,200},{0,21,18},{0,17,202},{53,0,200},{0,17,202},{2,0,25},{2,0,25},{2,0,25},{2,0,25},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,5,9},{0,5,9},{4,57,313},{4,39,121},{5,28,198},{4,25,131},{0,52,723},{0,31,227},{0,26,9},{0,20,362},{0,22,959},{0,19,515},{8,49,201}, +{7,36,1},{9,27,19},{7,25,35},{25,0,723},{0,31,227},{0,26,9},{0,20,362},{52,0,723},{0,20,362},{4,42,113},{4,42,113},{4,42,113},{4,22,114},{0,36,162},{0,24,2},{0,24,2},{0,15,34},{0,17,285},{0,14,122},{8,34,1},{8,34,1},{8,34,1},{7,21,1},{18,0,162},{1,23,2},{1,23,2},{0,15,34},{36,0,162},{0,15,34},{32,0,200},{7,36,0},{12,26,1}, +{0,26,5},{32,0,200},{65,0,200},{0,26,5},{0,21,202},{65,0,200},{0,21,202},{4,0,113},{4,0,113},{4,0,113},{4,0,113},{0,23,0},{0,23,0},{0,23,0},{0,11,0},{0,8,41},{0,8,41},{7,64,400},{7,43,216},{8,32,312},{7,30,213},{2,61,723},{1,38,208},{2,31,2},{0,24,312},{0,31,980},{0,24,440},{12,54,200},{12,40,0},{13,31,20},{11,29,36},{32,0,723}, +{0,38,203},{2,31,2},{0,24,296},{65,0,723},{0,24,296},{7,49,200},{7,49,200},{7,49,200},{7,28,200},{2,46,162},{2,31,2},{2,31,2},{2,20,20},{0,22,280},{0,19,84},{12,39,0},{12,39,0},{12,39,0},{12,25,1},{24,1,162},{4,29,0},{4,29,0},{0,20,13},{50,0,162},{0,20,13},{39,0,200},{12,40,0},{16,31,0},{0,31,0},{39,0,200},{78,0,200},{0,31,0}, +{0,26,200},{78,0,200},{0,26,200},{7,0,200},{7,0,200},{7,0,200},{7,0,200},{2,32,0},{2,32,0},{2,32,0},{2,17,0},{0,14,50},{0,14,50},{11,68,400},{11,47,216},{12,36,312},{11,34,213},{6,65,723},{5,42,208},{6,35,2},{4,28,312},{0,37,868},{0,28,304},{16,58,200},{16,44,0},{17,35,20},{15,33,36},{38,0,723},{3,43,200},{6,35,2},{0,29,257},{77,0,723}, +{0,29,257},{11,53,200},{11,53,200},{11,53,200},{11,32,200},{6,50,162},{6,35,2},{6,35,2},{6,24,20},{0,28,216},{0,24,20},{16,43,0},{16,43,0},{16,43,0},{16,29,1},{30,1,162},{8,33,0},{8,33,0},{0,24,4},{62,0,162},{0,24,4},{45,0,200},{16,44,0},{20,35,0},{4,35,0},{45,0,200},{91,0,200},{4,35,0},{0,30,200},{91,0,200},{0,30,200},{11,0,200}, +{11,0,200},{11,0,200},{11,0,200},{6,36,0},{6,36,0},{6,36,0},{6,21,0},{0,22,8},{0,22,8},{15,72,400},{15,51,216},{16,40,312},{15,38,213},{10,69,723},{9,46,208},{10,39,2},{8,32,312},{0,43,788},{0,33,228},{20,62,200},{20,48,0},{21,39,20},{19,37,36},{44,0,723},{7,47,200},{10,39,2},{0,33,224},{89,0,723},{0,33,224},{15,57,200},{15,57,200},{15,57,200}, +{15,36,200},{10,54,162},{10,39,2},{10,39,2},{10,28,20},{0,35,179},{1,29,0},{20,47,0},{20,47,0},{20,47,0},{20,33,1},{36,1,162},{12,37,0},{12,37,0},{1,29,0},{74,0,162},{1,29,0},{50,1,200},{20,48,0},{24,39,0},{8,39,0},{50,1,200},{103,0,200},{8,39,0},{0,34,200},{103,0,200},{0,34,200},{15,0,200},{15,0,200},{15,0,200},{15,0,200},{10,40,0}, +{10,40,0},{10,40,0},{10,25,0},{1,29,0},{1,29,0},{19,76,400},{19,55,216},{20,44,312},{19,42,213},{14,73,723},{13,50,208},{14,43,2},{12,36,312},{0,49,740},{1,37,216},{24,66,200},{24,52,0},{25,43,20},{23,41,36},{50,0,723},{11,51,200},{14,43,2},{0,38,209},{101,0,723},{0,38,209},{19,61,200},{19,61,200},{19,61,200},{19,40,200},{14,58,162},{14,43,2},{14,43,2}, +{14,32,20},{1,42,163},{5,33,0},{24,51,0},{24,51,0},{24,51,0},{24,37,1},{42,1,162},{16,41,0},{16,41,0},{5,33,0},{86,0,162},{5,33,0},{56,1,200},{24,52,0},{28,43,0},{12,43,0},{56,1,200},{115,0,200},{12,43,0},{0,38,200},{115,0,200},{0,38,200},{19,0,200},{19,0,200},{19,0,200},{19,0,200},{14,44,0},{14,44,0},{14,44,0},{14,29,0},{5,33,0}, +{5,33,0},{24,80,402},{24,60,212},{25,49,308},{23,47,212},{19,76,724},{19,53,212},{19,47,4},{17,41,308},{1,55,724},{6,42,212},{29,69,201},{28,57,1},{30,48,19},{28,46,35},{56,1,723},{15,56,200},{19,47,3},{1,42,202},{115,0,723},{1,42,202},{24,64,202},{24,64,202},{24,64,202},{24,44,202},{19,61,163},{19,46,3},{19,46,3},{18,36,19},{6,46,163},{9,38,1},{29,55,1}, +{29,55,1},{29,55,1},{28,42,1},{49,0,162},{20,46,0},{20,46,0},{11,37,1},{100,0,162},{11,37,1},{63,0,200},{28,57,0},{33,47,1},{18,47,1},{63,0,200},{127,1,200},{18,47,1},{0,42,202},{127,1,200},{0,42,202},{23,0,202},{23,0,202},{23,0,202},{23,0,202},{19,48,1},{19,48,1},{19,48,1},{19,33,1},{9,38,0},{9,38,0},{28,84,402},{28,64,215},{29,53,308}, +{27,51,212},{23,80,724},{23,57,212},{23,51,4},{21,45,308},{5,59,724},{10,46,212},{33,73,201},{32,61,1},{34,52,19},{32,50,35},{62,1,723},{19,60,200},{23,51,3},{5,46,202},{127,0,723},{5,46,202},{28,68,202},{28,68,202},{28,68,202},{28,48,202},{23,65,163},{23,50,3},{23,50,3},{22,40,19},{10,50,163},{13,42,1},{33,59,1},{33,59,1},{33,59,1},{32,46,1},{55,0,162}, +{24,50,0},{24,50,0},{15,41,1},{112,0,162},{15,41,1},{69,0,200},{32,61,0},{37,51,1},{22,51,1},{69,0,200},{127,7,200},{22,51,1},{0,46,202},{127,7,200},{0,46,202},{27,0,202},{27,0,202},{27,0,202},{27,0,202},{23,52,1},{23,52,1},{23,52,1},{23,37,1},{13,42,0},{13,42,0},{32,88,402},{32,68,215},{33,57,308},{31,55,212},{27,84,724},{27,61,212},{27,55,4}, +{25,49,308},{8,64,723},{14,50,212},{37,77,201},{36,64,2},{38,56,19},{36,54,35},{68,0,723},{22,64,201},{27,55,3},{9,50,202},{127,6,723},{9,50,202},{32,72,202},{32,72,202},{32,72,202},{32,52,202},{27,69,163},{27,54,3},{27,54,3},{26,44,19},{14,54,163},{17,46,1},{37,63,1},{37,63,1},{37,63,1},{36,50,1},{61,0,162},{28,54,0},{28,54,0},{19,45,1},{124,0,162}, +{19,45,1},{75,0,200},{36,64,1},{41,55,1},{26,55,1},{75,0,200},{127,13,200},{26,55,1},{0,50,202},{127,13,200},{0,50,202},{31,0,202},{31,0,202},{31,0,202},{31,0,202},{27,56,1},{27,56,1},{27,56,1},{27,41,1},{17,46,0},{17,46,0},{36,92,402},{36,72,215},{37,61,308},{35,59,212},{31,88,724},{30,65,207},{31,59,4},{29,53,308},{12,68,723},{18,54,212},{41,81,201}, +{41,67,2},{42,60,19},{40,58,35},{74,0,723},{28,67,201},{31,59,3},{13,54,202},{127,12,723},{13,54,202},{36,76,202},{36,76,202},{36,76,202},{36,56,202},{31,73,163},{31,58,3},{31,58,3},{30,48,19},{18,58,163},{21,50,1},{41,66,1},{41,66,1},{41,66,1},{40,54,1},{66,1,162},{32,58,0},{32,58,0},{23,49,1},{126,5,162},{23,49,1},{80,1,200},{41,67,1},{45,59,1}, +{30,59,1},{80,1,200},{126,19,200},{30,59,1},{0,54,202},{126,19,200},{0,54,202},{35,0,202},{35,0,202},{35,0,202},{35,0,202},{31,60,1},{31,60,1},{31,60,1},{31,45,1},{21,50,0},{21,50,0},{40,97,400},{40,77,213},{42,64,314},{40,63,213},{35,94,723},{35,70,209},{35,64,6},{33,57,312},{17,72,723},{22,58,216},{45,87,200},{45,72,1},{46,64,21},{44,62,36},{80,1,723}, +{33,71,201},{36,63,4},{16,59,200},{126,19,723},{16,59,200},{40,82,200},{40,82,200},{40,82,200},{40,61,200},{35,78,162},{35,63,4},{35,63,4},{35,53,20},{22,63,163},{26,54,0},{45,72,0},{45,72,0},{45,72,0},{45,58,1},{73,0,162},{37,62,0},{37,62,0},{26,54,0},{126,12,162},{26,54,0},{87,0,200},{45,72,1},{49,64,1},{32,64,1},{87,0,200},{126,26,200},{32,64,1}, +{0,59,200},{126,26,200},{0,59,200},{40,0,200},{40,0,200},{40,0,200},{40,0,200},{35,65,0},{35,65,0},{35,65,0},{35,50,0},{26,54,0},{26,54,0},{44,101,400},{44,81,213},{46,68,314},{44,66,213},{39,98,723},{39,74,209},{39,67,2},{37,61,312},{21,76,723},{26,62,216},{49,91,200},{49,76,1},{50,68,21},{48,66,38},{86,1,723},{37,75,201},{39,67,2},{20,63,200},{126,25,723}, +{20,63,200},{44,86,200},{44,86,200},{44,86,200},{44,64,200},{39,82,162},{39,67,1},{39,67,1},{39,57,20},{25,67,162},{30,58,0},{49,76,0},{49,76,0},{49,76,0},{49,62,1},{79,0,162},{41,65,1},{41,65,1},{30,58,0},{127,17,162},{30,58,0},{93,0,200},{49,76,1},{53,67,1},{38,67,1},{93,0,200},{126,32,200},{38,67,1},{0,63,200},{126,32,200},{0,63,200},{44,0,200}, +{44,0,200},{44,0,200},{44,0,200},{39,69,0},{39,69,0},{39,69,0},{39,54,0},{30,58,0},{30,58,0},{48,105,400},{48,85,213},{50,72,314},{48,70,213},{43,102,723},{43,78,209},{43,71,2},{41,65,315},{25,80,723},{29,66,215},{53,95,200},{53,80,1},{54,72,21},{52,70,38},{92,1,723},{41,79,201},{43,71,2},{25,66,202},{126,31,723},{25,66,202},{48,90,200},{48,90,200},{48,90,200}, +{48,68,200},{43,86,162},{43,71,1},{43,71,1},{43,61,20},{29,71,162},{34,62,0},{53,80,0},{53,80,0},{53,80,0},{53,66,0},{85,0,162},{45,69,1},{45,69,1},{34,62,0},{127,23,162},{34,62,0},{99,0,200},{53,80,1},{57,71,1},{42,71,1},{99,0,200},{126,38,200},{42,71,1},{0,66,202},{126,38,200},{0,66,202},{48,0,200},{48,0,200},{48,0,200},{48,0,200},{43,73,0}, +{43,73,0},{43,73,0},{43,58,0},{34,62,0},{34,62,0},{52,109,400},{52,89,213},{54,76,314},{52,74,213},{47,106,723},{47,82,209},{47,75,2},{45,69,315},{29,84,723},{33,70,215},{57,99,200},{57,84,1},{58,76,21},{56,74,38},{98,1,723},{45,83,201},{47,75,2},{29,70,202},{126,37,723},{29,70,202},{52,94,200},{52,94,200},{52,94,200},{52,72,200},{47,90,162},{47,75,1},{47,75,1}, +{46,65,21},{33,75,162},{38,65,2},{57,84,0},{57,84,0},{57,84,0},{57,70,0},{91,0,162},{49,73,1},{49,73,1},{39,65,1},{127,29,162},{39,65,1},{105,0,200},{57,84,1},{61,75,1},{46,75,1},{105,0,200},{126,44,200},{46,75,1},{0,70,202},{126,44,200},{0,70,202},{52,0,200},{52,0,200},{52,0,200},{52,0,200},{47,77,0},{47,77,0},{47,77,0},{47,62,0},{38,65,1}, +{38,65,1},{57,113,402},{57,93,215},{58,82,315},{56,79,215},{52,109,724},{51,86,207},{52,80,2},{51,73,314},{33,89,723},{38,75,213},{62,102,201},{62,88,2},{62,81,21},{60,79,38},{105,0,723},{49,88,201},{52,80,1},{33,75,200},{126,44,723},{33,75,200},{57,97,202},{57,97,202},{57,97,202},{56,77,202},{52,94,163},{52,79,2},{52,79,2},{51,69,21},{38,79,162},{42,70,1},{62,87,1}, +{62,87,1},{62,87,1},{62,74,1},{98,0,162},{54,77,1},{54,77,1},{43,70,0},{127,36,162},{43,70,0},{112,0,200},{62,88,1},{65,80,0},{50,80,0},{112,0,200},{127,50,200},{50,80,0},{0,75,200},{127,50,200},{0,75,200},{56,0,202},{56,0,202},{56,0,202},{56,0,202},{52,80,1},{52,80,1},{52,80,1},{51,66,1},{43,69,1},{43,69,1},{61,117,402},{61,97,215},{62,86,315}, +{60,83,215},{56,113,724},{55,90,207},{56,84,2},{55,77,314},{37,93,723},{42,79,213},{65,107,200},{65,93,0},{66,84,20},{64,82,36},{111,0,723},{53,92,201},{56,84,1},{37,79,200},{127,49,723},{37,79,200},{61,101,202},{61,101,202},{61,101,202},{60,81,202},{56,98,163},{56,83,2},{56,83,2},{55,73,21},{42,83,162},{46,74,1},{65,92,0},{65,92,0},{65,92,0},{65,78,1},{104,0,162}, +{58,81,1},{58,81,1},{47,74,0},{127,42,162},{47,74,0},{118,0,200},{65,93,0},{69,84,0},{54,84,0},{118,0,200},{127,56,200},{54,84,0},{0,79,200},{127,56,200},{0,79,200},{60,0,202},{60,0,202},{60,0,202},{60,0,202},{56,84,1},{56,84,1},{56,84,1},{55,70,1},{47,73,1},{47,73,1},{64,122,400},{64,100,216},{65,89,312},{64,87,213},{60,117,724},{59,94,207},{60,88,2}, +{59,81,314},{41,97,723},{46,83,213},{69,111,200},{69,97,0},{70,88,20},{68,86,36},{117,0,723},{57,96,201},{60,88,1},{41,83,200},{127,55,723},{41,83,200},{64,106,200},{64,106,200},{64,106,200},{64,85,200},{60,102,163},{60,87,2},{60,87,2},{59,77,21},{46,87,162},{50,78,1},{69,96,0},{69,96,0},{69,96,0},{69,82,1},{110,0,162},{62,85,1},{62,85,1},{51,78,0},{126,48,162}, +{51,78,0},{124,0,200},{69,97,0},{73,88,0},{58,88,0},{124,0,200},{127,62,200},{58,88,0},{0,83,200},{127,62,200},{0,83,200},{64,0,200},{64,0,200},{64,0,200},{64,0,200},{60,88,1},{60,88,1},{60,88,1},{59,74,1},{51,77,1},{51,77,1},{68,126,400},{68,104,216},{69,93,312},{68,91,213},{63,123,724},{63,98,207},{63,92,6},{63,85,314},{45,101,723},{50,87,213},{73,115,200}, +{73,101,0},{74,92,20},{72,90,36},{123,0,723},{61,100,201},{64,91,4},{45,87,200},{127,61,723},{45,87,200},{68,110,200},{68,110,200},{68,110,200},{68,89,200},{63,108,163},{64,91,4},{64,91,4},{63,81,21},{50,91,162},{54,82,1},{73,100,0},{73,100,0},{73,100,0},{73,86,1},{115,1,162},{65,90,0},{65,90,0},{55,82,0},{126,54,162},{55,82,0},{127,5,200},{73,101,0},{77,92,0}, +{62,92,0},{127,5,200},{126,68,200},{62,92,0},{0,87,200},{126,68,200},{0,87,200},{68,0,200},{68,0,200},{68,0,200},{68,0,200},{63,94,1},{63,94,1},{63,94,1},{63,78,1},{55,81,1},{55,81,1},{73,126,410},{73,109,212},{74,98,308},{72,96,212},{68,126,724},{68,102,212},{68,96,4},{66,90,308},{50,105,723},{54,91,215},{78,119,201},{77,106,1},{79,97,19},{77,95,35},{127,5,723}, +{64,105,200},{68,96,3},{50,91,202},{126,68,723},{50,91,202},{73,114,202},{73,114,202},{73,114,202},{73,93,202},{68,110,163},{68,95,3},{68,95,3},{67,85,19},{54,96,162},{59,86,2},{78,104,1},{78,104,1},{78,104,1},{77,91,1},{122,0,162},{69,95,0},{69,95,0},{60,86,1},{126,61,162},{60,86,1},{127,19,200},{77,106,0},{82,96,1},{67,96,1},{127,19,200},{127,74,200},{67,96,1}, +{0,91,202},{127,74,200},{0,91,202},{72,0,202},{72,0,202},{72,0,202},{72,0,202},{68,97,1},{68,97,1},{68,97,1},{68,82,1},{59,86,1},{59,86,1},{77,127,434},{77,113,212},{78,102,308},{76,100,212},{72,127,732},{72,106,212},{72,100,4},{70,94,308},{54,109,723},{58,95,215},{82,123,201},{81,110,1},{83,101,19},{81,99,35},{127,18,723},{68,109,200},{72,100,3},{54,95,202},{126,74,723}, +{54,95,202},{77,118,202},{77,118,202},{77,118,202},{77,97,202},{72,114,163},{72,99,3},{72,99,3},{71,89,19},{58,100,162},{63,90,2},{82,108,1},{82,108,1},{82,108,1},{81,95,1},{127,2,162},{73,99,0},{73,99,0},{64,90,1},{127,66,162},{64,90,1},{127,31,200},{81,110,0},{86,100,1},{71,100,1},{127,31,200},{127,80,200},{71,100,1},{0,95,202},{127,80,200},{0,95,202},{76,0,202}, +{76,0,202},{76,0,202},{76,0,202},{72,101,1},{72,101,1},{72,101,1},{72,86,1},{63,90,1},{63,90,1},{82,127,468},{81,117,212},{82,106,308},{80,104,212},{77,127,753},{76,110,212},{76,104,4},{74,98,308},{58,113,723},{62,99,215},{86,127,201},{85,114,1},{87,105,19},{85,103,35},{127,30,723},{72,113,200},{76,104,3},{58,99,202},{127,79,723},{58,99,202},{81,122,202},{81,122,202},{81,122,202}, +{81,101,202},{76,118,163},{76,103,3},{76,103,3},{75,93,19},{62,104,162},{66,95,1},{86,112,1},{86,112,1},{86,112,1},{85,99,1},{127,14,162},{77,103,0},{77,103,0},{68,94,1},{127,72,162},{68,94,1},{127,43,200},{85,114,0},{90,104,1},{75,104,1},{127,43,200},{127,86,200},{75,104,1},{0,99,202},{127,86,200},{0,99,202},{80,0,202},{80,0,202},{80,0,202},{80,0,202},{76,105,1}, +{76,105,1},{76,105,1},{76,90,1},{66,95,0},{66,95,0},{86,127,546},{85,121,212},{86,110,308},{84,108,212},{82,127,788},{80,114,212},{80,108,4},{78,102,308},{62,117,723},{67,103,212},{91,127,211},{89,118,1},{91,109,19},{89,107,35},{127,42,723},{76,117,200},{80,108,3},{62,103,202},{127,85,723},{62,103,202},{85,126,202},{85,126,202},{85,126,202},{85,105,202},{80,122,163},{80,107,3},{80,107,3}, +{79,97,19},{67,107,163},{70,99,1},{90,116,1},{90,116,1},{90,116,1},{89,103,1},{127,27,162},{81,107,0},{81,107,0},{72,98,1},{126,78,162},{72,98,1},{127,56,200},{89,118,0},{94,108,1},{79,108,1},{127,56,200},{127,92,200},{79,108,1},{0,103,202},{127,92,200},{0,103,202},{84,0,202},{84,0,202},{84,0,202},{84,0,202},{80,109,1},{80,109,1},{80,109,1},{80,94,1},{70,99,0}, +{70,99,0},{91,127,632},{89,125,216},{90,114,312},{89,112,213},{88,127,852},{83,120,208},{84,113,2},{82,106,312},{66,121,724},{71,107,216},{97,127,244},{94,122,0},{95,113,20},{93,111,36},{127,56,723},{81,121,200},{84,113,2},{65,108,200},{127,92,723},{65,108,200},{89,127,209},{89,127,209},{89,127,209},{89,110,200},{84,126,164},{84,113,2},{84,113,2},{84,102,20},{71,112,163},{75,103,0},{94,121,0}, +{94,121,0},{94,121,0},{94,107,1},{127,40,162},{86,111,0},{86,111,0},{75,103,0},{126,85,162},{75,103,0},{127,69,200},{94,122,0},{98,113,0},{82,113,0},{127,69,200},{126,99,200},{82,113,0},{0,108,200},{126,99,200},{0,108,200},{89,0,200},{89,0,200},{89,0,200},{89,0,200},{84,114,0},{84,114,0},{84,114,0},{84,99,0},{75,103,0},{75,103,0},{97,127,728},{94,127,228},{94,118,312}, +{93,116,213},{94,127,932},{87,124,208},{88,117,2},{86,110,312},{70,125,724},{75,111,216},{101,127,286},{98,126,0},{99,117,20},{97,115,36},{127,67,723},{85,125,200},{88,117,2},{69,112,200},{127,98,723},{69,112,200},{94,127,224},{94,127,224},{94,127,224},{93,114,200},{89,127,174},{88,117,2},{88,117,2},{88,106,20},{75,116,163},{79,107,0},{98,125,0},{98,125,0},{98,125,0},{98,111,1},{127,53,162}, +{90,115,0},{90,115,0},{79,107,0},{126,91,162},{79,107,0},{127,81,200},{98,126,0},{102,117,0},{86,117,0},{127,81,200},{126,105,200},{86,117,0},{0,112,200},{126,105,200},{0,112,200},{93,0,200},{93,0,200},{93,0,200},{93,0,200},{88,118,0},{88,118,0},{88,118,0},{88,103,0},{79,107,0},{79,107,0},{100,127,864},{99,127,304},{98,122,312},{97,120,213},{98,127,1043},{92,127,211},{92,121,2}, +{90,114,312},{76,127,732},{79,115,216},{106,127,336},{102,127,20},{103,121,20},{101,119,36},{127,79,723},{90,127,208},{92,121,2},{73,116,200},{127,104,723},{73,116,200},{98,127,257},{98,127,257},{98,127,257},{97,118,200},{94,127,196},{92,121,2},{92,121,2},{92,110,20},{79,120,163},{83,111,0},{102,126,4},{102,126,4},{102,126,4},{102,115,1},{127,64,162},{94,119,0},{94,119,0},{83,111,0},{126,97,162}, +{83,111,0},{127,93,200},{105,127,8},{106,121,0},{90,121,0},{127,93,200},{126,111,200},{90,121,0},{0,116,200},{126,111,200},{0,116,200},{97,0,200},{97,0,200},{97,0,200},{97,0,200},{92,122,0},{92,122,0},{92,122,0},{92,107,0},{83,111,0},{83,111,0},{106,127,992},{103,127,440},{102,126,312},{101,124,213},{103,127,1144},{96,127,272},{96,125,2},{94,118,312},{84,127,804},{83,119,216},{111,127,398}, +{108,127,84},{107,125,20},{105,123,36},{127,92,723},{99,127,248},{96,125,2},{77,120,200},{126,110,723},{77,120,200},{103,127,296},{103,127,296},{103,127,296},{101,122,200},{100,127,244},{96,125,2},{96,125,2},{96,114,20},{83,124,163},{87,115,0},{107,127,13},{107,127,13},{107,127,13},{106,119,1},{127,76,162},{98,123,0},{98,123,0},{87,115,0},{126,103,162},{87,115,0},{127,105,200},{111,127,45},{110,125,0}, +{94,125,0},{127,105,200},{126,117,200},{94,125,0},{0,120,200},{126,117,200},{0,120,200},{101,0,200},{101,0,200},{101,0,200},{101,0,200},{96,126,0},{96,126,0},{96,126,0},{96,111,0},{87,115,0},{87,115,0},{111,127,919},{108,127,515},{107,127,362},{105,127,203},{109,127,1027},{102,127,267},{101,127,9},{99,122,198},{93,127,703},{88,123,121},{115,127,338},{113,127,122},{112,127,34},{110,126,14},{127,102,546}, +{108,127,202},{102,127,2},{85,123,113},{127,115,546},{85,123,113},{107,127,362},{107,127,362},{107,127,362},{106,126,202},{104,127,309},{101,127,9},{101,127,9},{100,118,19},{89,127,168},{91,120,1},{112,127,34},{112,127,34},{112,127,34},{110,124,1},{127,90,162},{104,126,2},{104,126,2},{93,119,1},{127,109,162},{93,119,1},{127,115,113},{119,127,41},{116,127,0},{104,127,0},{127,115,113},{127,121,113},{104,127,0}, +{0,123,113},{127,121,113},{0,123,113},{105,0,202},{105,0,202},{105,0,202},{105,0,202},{101,127,5},{101,127,5},{101,127,5},{101,115,1},{91,120,0},{91,120,0},{114,127,751},{111,127,514},{111,127,414},{110,127,218},{114,127,814},{108,127,219},{107,127,65},{103,124,71},{102,127,539},{94,125,27},{120,127,206},{117,127,110},{117,127,61},{115,127,2},{127,110,333},{113,127,121},{110,127,20},{93,125,25},{126,119,333}, +{93,125,25},{111,127,414},{111,127,414},{111,127,414},{110,127,218},{109,127,371},{107,127,65},{107,127,65},{104,122,19},{96,127,203},{95,124,1},{117,127,61},{117,127,61},{117,127,61},{115,127,2},{127,102,162},{110,127,20},{110,127,20},{97,123,1},{127,115,162},{97,123,1},{127,121,25},{122,127,9},{122,127,0},{116,127,0},{127,121,25},{127,124,25},{116,127,0},{0,125,25},{127,124,25},{0,125,25},{109,0,202}, +{109,0,202},{109,0,202},{109,0,202},{106,127,18},{106,127,18},{106,127,18},{105,119,1},{95,124,0},{95,124,0},{117,127,636},{117,127,516},{117,127,467},{115,127,282},{117,127,643},{111,127,241},{111,127,141},{108,126,18},{108,127,434},{99,127,2},{123,127,131},{121,127,105},{121,127,89},{119,127,26},{127,118,193},{119,127,86},{116,127,53},{101,127,0},{126,123,193},{101,127,0},{117,127,467},{117,127,467},{117,127,467}, +{115,127,282},{114,127,410},{111,127,141},{111,127,141},{108,126,14},{105,127,254},{99,127,2},{121,127,89},{121,127,89},{121,127,89},{119,127,26},{127,113,145},{116,127,53},{116,127,53},{101,127,0},{127,120,145},{101,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{113,0,202},{113,0,202},{113,0,202},{113,0,202},{111,127,41}, +{111,127,41},{111,127,41},{109,123,1},{101,126,2},{101,126,2},{120,127,412},{120,127,356},{120,127,331},{118,127,238},{120,127,387},{116,127,183},{116,127,134},{113,127,1},{113,127,262},{108,127,18},{124,127,41},{124,127,29},{124,127,25},{122,127,10},{127,122,54},{122,127,22},{122,127,13},{113,127,0},{126,125,54},{113,127,0},{120,127,331},{120,127,331},{120,127,331},{118,127,238},{117,127,266},{116,127,134},{116,127,134}, +{113,127,1},{110,127,161},{108,127,18},{124,127,25},{124,127,25},{124,127,25},{122,127,10},{127,119,41},{122,127,13},{122,127,13},{113,127,0},{127,123,41},{113,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{117,0,202},{117,0,202},{117,0,202},{117,0,202},{114,127,73},{114,127,73},{114,127,73},{113,127,1},{108,127,18}, +{108,127,18},{0,41,421},{0,28,41},{0,21,1},{0,18,157},{0,27,925},{0,19,569},{0,17,285},{0,12,701},{0,12,1005},{0,10,751},{0,41,421},{0,28,41},{0,21,1},{0,18,157},{13,1,925},{0,19,569},{0,17,285},{0,12,701},{27,0,925},{0,12,701},{0,20,0},{0,20,0},{0,20,0},{0,10,0},{0,9,85},{0,8,29},{0,8,29},{0,4,50},{0,5,94},{0,4,59},{0,20,0}, +{0,20,0},{0,20,0},{0,10,0},{5,0,85},{0,8,29},{0,8,29},{0,4,50},{9,0,85},{0,4,50},{20,0,421},{0,28,41},{0,21,1},{0,18,157},{20,0,421},{41,0,421},{0,18,157},{0,14,421},{41,0,421},{0,14,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,53,421},{0,37,9},{1,25,17}, +{0,21,113},{0,36,1261},{0,22,677},{0,20,305},{0,15,881},{0,17,1383},{0,13,971},{0,53,421},{0,37,9},{1,25,13},{0,21,113},{18,0,1261},{0,22,677},{0,20,305},{0,15,881},{36,0,1261},{0,15,881},{0,32,0},{0,32,0},{0,32,0},{0,15,1},{0,15,221},{0,11,85},{0,11,85},{0,7,130},{0,8,246},{0,7,155},{0,32,0},{0,32,0},{0,32,0},{0,15,1},{8,0,221}, +{0,11,85},{0,11,85},{0,7,130},{15,0,221},{0,7,130},{26,0,421},{0,37,9},{3,25,1},{0,21,113},{26,0,421},{53,0,421},{0,21,113},{0,18,421},{53,0,421},{0,18,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,63,426},{1,42,6},{2,29,66},{0,27,74},{0,45,1514},{0,28,706},{0,25,258}, +{0,18,974},{0,19,1706},{0,18,1118},{2,61,422},{1,42,2},{3,30,38},{0,27,74},{22,0,1514},{0,28,706},{0,25,258},{0,18,974},{45,0,1514},{0,18,974},{1,42,5},{1,42,5},{1,42,5},{1,21,5},{0,24,338},{0,19,90},{0,19,90},{0,10,181},{0,11,389},{0,10,230},{2,40,1},{2,40,1},{2,40,1},{1,21,1},{12,0,338},{0,19,90},{0,19,90},{0,10,181},{24,0,338}, +{0,10,181},{32,0,421},{1,42,1},{7,29,1},{0,27,65},{32,0,421},{65,0,421},{0,27,65},{0,22,421},{65,0,421},{0,22,421},{1,0,5},{1,0,5},{1,0,5},{1,0,5},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,2,1},{0,2,1},{3,71,482},{3,48,62},{4,34,158},{2,31,117},{0,58,1514},{0,37,594},{0,31,122},{0,23,881},{0,25,1818},{0,21,1086},{6,65,422}, +{5,46,2},{7,34,38},{4,31,74},{28,0,1514},{0,37,594},{0,31,122},{0,23,881},{58,0,1514},{0,23,881},{3,50,61},{3,50,61},{3,50,61},{3,26,61},{0,36,338},{0,25,34},{0,25,34},{0,15,130},{0,17,461},{0,14,226},{6,44,1},{6,44,1},{6,44,1},{5,25,1},{18,0,338},{0,25,34},{0,25,34},{0,15,130},{36,0,338},{0,15,130},{38,0,421},{5,46,1},{11,33,1}, +{0,32,40},{38,0,421},{77,0,421},{0,32,40},{0,26,421},{77,0,421},{0,26,421},{3,0,61},{3,0,61},{3,0,61},{3,0,61},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,5,25},{0,5,25},{5,80,621},{5,55,213},{7,40,357},{5,35,241},{0,71,1514},{0,43,497},{0,36,29},{0,27,761},{0,31,1989},{0,26,1079},{10,70,421},{10,50,1},{11,38,41},{8,35,77},{35,0,1514}, +{0,43,497},{0,36,29},{0,27,761},{71,0,1514},{0,27,761},{5,60,200},{5,60,200},{5,60,200},{5,32,200},{0,50,338},{0,34,4},{0,34,4},{0,21,80},{0,22,552},{0,19,244},{10,49,0},{10,49,0},{10,49,0},{10,29,0},{24,1,338},{0,34,4},{0,34,4},{0,21,80},{50,0,338},{0,21,80},{45,0,421},{10,50,1},{16,37,1},{0,36,13},{45,0,421},{91,0,421},{0,36,13}, +{0,30,421},{91,0,421},{0,30,421},{5,0,200},{5,0,200},{5,0,200},{5,0,200},{0,30,0},{0,30,0},{0,30,0},{0,15,0},{0,11,74},{0,11,74},{7,89,813},{7,60,421},{10,43,617},{7,40,417},{0,83,1514},{0,51,446},{0,41,3},{0,32,686},{0,37,2165},{0,31,1101},{14,74,421},{14,54,1},{15,42,41},{12,39,77},{41,0,1514},{0,51,446},{0,41,3},{0,32,686},{83,0,1514}, +{0,32,686},{7,67,392},{7,67,392},{7,67,392},{7,37,392},{0,62,338},{0,41,2},{0,41,2},{0,24,52},{0,28,680},{0,23,298},{14,53,0},{14,53,0},{14,53,0},{14,33,0},{30,1,338},{2,39,0},{2,39,0},{0,24,52},{62,0,338},{0,24,52},{51,0,421},{14,54,1},{20,41,1},{0,41,2},{51,0,421},{103,0,421},{0,41,2},{0,34,421},{103,0,421},{0,34,421},{7,0,392}, +{7,0,392},{7,0,392},{7,0,392},{0,42,0},{0,42,0},{0,42,0},{0,21,0},{0,17,146},{0,17,146},{11,93,842},{11,65,453},{12,48,654},{11,44,446},{4,87,1515},{3,54,435},{4,45,4},{0,36,654},{0,43,2030},{0,35,882},{18,78,421},{18,58,1},{19,46,41},{16,43,77},{47,0,1514},{0,57,422},{4,45,3},{0,36,605},{95,0,1514},{0,36,605},{11,71,421},{11,71,421},{11,71,421}, +{11,41,421},{4,66,339},{4,45,3},{4,45,3},{2,29,41},{0,34,581},{0,28,161},{18,57,0},{18,57,0},{18,57,0},{18,37,0},{36,1,338},{6,43,0},{6,43,0},{0,30,20},{74,0,338},{0,30,20},{57,0,421},{18,58,1},{24,45,1},{2,45,1},{57,0,421},{115,0,421},{2,45,1},{0,38,421},{115,0,421},{0,38,421},{11,0,421},{11,0,421},{11,0,421},{11,0,421},{4,46,1}, +{4,46,1},{4,46,1},{3,25,1},{0,22,85},{0,22,85},{15,97,842},{16,67,453},{16,52,654},{15,48,446},{8,91,1515},{7,58,435},{8,49,4},{4,40,654},{0,51,1850},{0,40,682},{22,82,421},{22,62,1},{23,50,41},{20,47,77},{53,0,1514},{3,61,421},{8,49,3},{0,41,554},{107,0,1514},{0,41,554},{15,75,421},{15,75,421},{15,75,421},{15,45,421},{8,70,339},{8,49,3},{8,49,3}, +{6,33,41},{0,40,477},{0,34,57},{22,61,0},{22,61,0},{22,61,0},{22,41,0},{42,1,338},{10,47,0},{10,47,0},{0,34,8},{86,0,338},{0,34,8},{63,0,421},{22,62,1},{28,49,1},{6,49,1},{63,0,421},{127,0,421},{6,49,1},{0,42,421},{127,0,421},{0,42,421},{15,0,421},{15,0,421},{15,0,421},{15,0,421},{8,50,1},{8,50,1},{8,50,1},{7,29,1},{0,31,29}, +{0,31,29},{19,102,842},{20,71,451},{21,57,650},{19,52,446},{12,97,1514},{12,63,437},{12,54,2},{9,45,650},{0,57,1710},{0,45,530},{27,86,422},{26,67,1},{28,55,38},{25,52,74},{59,1,1514},{7,66,421},{12,54,2},{0,45,494},{121,0,1514},{0,45,494},{19,81,421},{19,81,421},{19,81,421},{19,49,422},{12,75,338},{12,54,2},{12,54,2},{11,38,38},{0,49,402},{0,39,6},{27,64,1}, +{27,64,1},{27,64,1},{26,46,1},{49,0,338},{14,52,0},{14,52,0},{1,39,1},{100,0,338},{1,39,1},{69,0,421},{26,67,0},{32,54,1},{10,54,0},{69,0,421},{127,7,421},{10,54,0},{0,47,421},{127,7,421},{0,47,421},{19,0,421},{19,0,421},{19,0,421},{19,0,421},{12,56,0},{12,56,0},{12,56,0},{12,33,1},{0,38,5},{0,38,5},{23,106,842},{24,75,451},{25,61,650}, +{23,56,446},{16,101,1514},{15,67,434},{16,58,2},{13,49,650},{0,64,1617},{0,50,462},{31,90,422},{30,71,1},{32,59,38},{29,56,74},{65,0,1514},{11,70,421},{16,58,2},{0,50,461},{127,3,1514},{0,50,461},{23,85,421},{23,85,421},{23,85,421},{23,53,422},{16,79,338},{16,58,2},{16,58,2},{15,42,38},{0,54,349},{3,43,2},{31,68,1},{31,68,1},{31,68,1},{30,50,1},{55,0,338}, +{18,56,0},{18,56,0},{5,43,1},{112,0,338},{5,43,1},{75,0,421},{30,71,0},{36,58,1},{14,58,0},{75,0,421},{127,13,421},{14,58,0},{0,51,421},{127,13,421},{0,51,421},{23,0,421},{23,0,421},{23,0,421},{23,0,421},{16,60,0},{16,60,0},{16,60,0},{16,37,1},{3,43,1},{3,43,1},{27,110,842},{28,79,451},{30,64,650},{27,60,446},{20,105,1514},{19,71,434},{20,62,2}, +{17,53,650},{0,70,1553},{1,54,450},{35,94,422},{34,75,1},{36,63,38},{33,60,74},{71,0,1514},{15,74,421},{20,62,2},{0,54,441},{127,9,1514},{0,54,441},{27,89,421},{27,89,421},{27,89,421},{27,57,422},{20,83,338},{20,62,2},{20,62,2},{19,46,38},{0,61,338},{7,47,2},{35,72,1},{35,72,1},{35,72,1},{34,54,1},{61,0,338},{22,60,0},{22,60,0},{9,47,1},{124,0,338}, +{9,47,1},{81,0,421},{34,75,0},{40,62,1},{18,62,0},{81,0,421},{126,19,421},{18,62,0},{0,55,421},{126,19,421},{0,55,421},{27,0,421},{27,0,421},{27,0,421},{27,0,421},{20,64,0},{20,64,0},{20,64,0},{20,41,1},{7,47,1},{7,47,1},{31,114,842},{32,83,451},{33,67,650},{31,64,446},{24,109,1514},{23,75,434},{24,65,6},{21,57,650},{0,76,1521},{5,58,450},{39,98,422}, +{38,79,1},{41,66,42},{37,63,81},{77,0,1514},{19,78,421},{25,65,2},{0,59,425},{127,15,1514},{0,59,425},{31,93,421},{31,93,421},{31,93,421},{31,61,422},{24,87,338},{24,64,5},{24,64,5},{23,50,38},{5,64,339},{11,51,2},{39,76,1},{39,76,1},{39,76,1},{38,58,1},{66,1,338},{25,64,1},{25,64,1},{13,51,1},{126,5,338},{13,51,1},{87,0,421},{38,79,0},{45,65,1}, +{23,65,1},{87,0,421},{126,25,421},{23,65,1},{0,59,421},{126,25,421},{0,59,421},{31,0,421},{31,0,421},{31,0,421},{31,0,421},{24,67,0},{24,67,0},{24,67,0},{24,45,1},{11,51,1},{11,51,1},{36,118,842},{37,88,453},{38,72,646},{35,69,445},{29,112,1515},{27,79,438},{29,69,6},{25,61,654},{3,82,1515},{10,63,450},{43,103,421},{43,83,2},{45,70,41},{42,67,76},{83,1,1514}, +{24,82,421},{29,69,5},{2,63,421},{126,22,1514},{2,63,421},{36,96,421},{36,96,421},{36,96,421},{36,65,421},{29,91,339},{29,69,2},{29,69,2},{27,54,41},{10,68,339},{15,56,1},{43,82,0},{43,82,0},{43,82,0},{43,62,0},{73,0,338},{31,67,1},{31,67,1},{16,56,0},{126,12,338},{16,56,0},{93,0,421},{42,84,0},{49,70,0},{26,70,0},{93,0,421},{126,32,421},{26,70,0}, +{0,63,421},{126,32,421},{0,63,421},{36,0,421},{36,0,421},{36,0,421},{36,0,421},{29,71,1},{29,71,1},{29,71,1},{28,50,1},{15,56,1},{15,56,1},{40,122,842},{41,92,453},{42,76,646},{39,73,445},{33,116,1515},{31,83,438},{33,73,6},{30,64,650},{7,86,1515},{15,66,451},{47,107,421},{47,87,2},{49,74,41},{46,71,76},{89,1,1514},{28,86,421},{33,73,5},{5,67,421},{126,28,1514}, +{5,67,421},{40,100,421},{40,100,421},{40,100,421},{40,69,421},{33,95,339},{33,73,2},{33,73,2},{31,58,41},{14,72,339},{19,60,1},{47,86,0},{47,86,0},{47,86,0},{47,66,0},{79,0,338},{35,71,1},{35,71,1},{20,60,0},{127,17,338},{20,60,0},{99,0,421},{46,88,0},{53,74,0},{30,74,0},{99,0,421},{126,38,421},{30,74,0},{0,67,421},{126,38,421},{0,67,421},{40,0,421}, +{40,0,421},{40,0,421},{40,0,421},{33,75,1},{33,75,1},{33,75,1},{32,54,1},{19,60,1},{19,60,1},{44,126,842},{45,96,453},{46,80,646},{43,77,445},{37,120,1515},{35,87,438},{37,77,6},{34,68,650},{11,90,1515},{19,70,451},{51,111,421},{51,91,2},{53,78,41},{50,75,76},{95,1,1514},{32,90,421},{37,77,5},{9,71,421},{126,34,1514},{9,71,421},{44,104,421},{44,104,421},{44,104,421}, +{44,73,421},{37,99,339},{37,77,2},{37,77,2},{35,62,41},{18,76,339},{23,64,1},{51,90,0},{51,90,0},{51,90,0},{51,70,0},{85,0,338},{39,75,1},{39,75,1},{23,64,1},{127,23,338},{23,64,1},{105,0,421},{50,92,0},{57,78,0},{34,78,0},{105,0,421},{126,44,421},{34,78,0},{0,71,421},{126,44,421},{0,71,421},{44,0,421},{44,0,421},{44,0,421},{44,0,421},{37,79,1}, +{37,79,1},{37,79,1},{36,58,1},{23,64,0},{23,64,0},{48,126,854},{49,100,453},{50,84,646},{47,81,445},{41,124,1515},{39,91,438},{41,81,6},{38,72,650},{15,94,1515},{23,74,451},{55,115,421},{55,95,2},{57,82,41},{54,79,76},{101,1,1514},{36,94,421},{41,81,5},{13,75,421},{126,40,1514},{13,75,421},{48,108,421},{48,108,421},{48,108,421},{48,77,421},{41,103,339},{41,81,2},{41,81,2}, +{40,65,42},{22,80,339},{27,68,1},{55,94,0},{55,94,0},{55,94,0},{55,74,0},{91,0,338},{43,79,1},{43,79,1},{29,67,1},{127,29,338},{29,67,1},{111,0,421},{54,96,0},{61,82,0},{38,82,0},{111,0,421},{127,49,421},{38,82,0},{0,75,421},{127,49,421},{0,75,421},{48,0,421},{48,0,421},{48,0,421},{48,0,421},{41,83,1},{41,83,1},{41,83,1},{40,62,1},{27,68,0}, +{27,68,0},{53,127,886},{53,104,451},{54,88,650},{52,85,446},{46,126,1521},{44,96,434},{45,86,6},{43,77,646},{18,99,1515},{27,78,453},{60,119,422},{59,100,1},{62,87,42},{59,84,75},{108,0,1514},{40,99,421},{46,86,2},{18,79,421},{125,47,1514},{18,79,421},{52,114,421},{52,114,421},{52,114,421},{52,82,421},{45,108,338},{45,85,5},{45,85,5},{45,70,41},{26,85,339},{31,72,2},{60,97,1}, +{60,97,1},{60,97,1},{60,78,1},{98,0,338},{48,83,1},{48,83,1},{33,72,0},{127,36,338},{33,72,0},{118,0,421},{59,100,0},{65,86,1},{44,86,1},{118,0,421},{127,56,421},{44,86,1},{0,79,421},{127,56,421},{0,79,421},{52,0,421},{52,0,421},{52,0,421},{52,0,421},{45,88,0},{45,88,0},{45,88,0},{45,66,0},{31,73,0},{31,73,0},{58,127,926},{57,108,451},{58,92,650}, +{56,89,446},{51,126,1542},{48,100,434},{49,90,6},{47,81,646},{22,103,1515},{31,82,453},{63,125,422},{63,104,1},{64,91,41},{63,88,75},{114,0,1514},{44,103,421},{50,90,2},{22,83,421},{127,52,1514},{22,83,421},{56,118,421},{56,118,421},{56,118,421},{56,86,421},{49,112,338},{49,89,5},{49,89,5},{49,74,41},{30,89,339},{35,76,2},{63,103,1},{63,103,1},{63,103,1},{63,82,2},{104,0,338}, +{52,87,1},{52,87,1},{37,76,0},{127,42,338},{37,76,0},{124,0,421},{63,104,0},{69,90,1},{48,90,1},{124,0,421},{127,62,421},{48,90,1},{0,83,421},{127,62,421},{0,83,421},{56,0,421},{56,0,421},{56,0,421},{56,0,421},{49,92,0},{49,92,0},{49,92,0},{49,70,0},{35,77,0},{35,77,0},{62,127,1010},{61,112,451},{62,96,650},{60,93,446},{56,127,1577},{52,104,434},{53,94,6}, +{51,85,646},{26,107,1515},{35,86,453},{67,126,425},{67,107,1},{68,95,41},{65,92,77},{120,0,1514},{48,107,421},{54,94,2},{26,87,421},{127,58,1514},{26,87,421},{60,122,421},{60,122,421},{60,122,421},{60,90,421},{53,116,338},{53,93,5},{53,93,5},{53,78,41},{34,93,339},{39,80,2},{67,106,0},{67,106,0},{67,106,0},{67,86,0},{110,0,338},{56,91,1},{56,91,1},{41,80,0},{126,48,338}, +{41,80,0},{127,5,421},{67,107,1},{73,94,1},{52,94,1},{127,5,421},{126,68,421},{52,94,1},{0,87,421},{126,68,421},{0,87,421},{60,0,421},{60,0,421},{60,0,421},{60,0,421},{53,96,0},{53,96,0},{53,96,0},{53,74,0},{39,81,0},{39,81,0},{68,127,1098},{64,117,450},{65,101,654},{64,97,446},{61,127,1626},{56,108,434},{57,98,6},{55,89,646},{30,111,1515},{39,90,453},{72,127,437}, +{71,111,1},{72,99,41},{69,96,77},{126,0,1514},{52,111,421},{58,98,2},{30,91,421},{126,64,1514},{30,91,421},{64,125,421},{64,125,421},{64,125,421},{64,94,421},{57,120,338},{57,97,5},{57,97,5},{57,82,41},{38,97,339},{43,84,2},{71,110,0},{71,110,0},{71,110,0},{71,90,0},{115,1,338},{60,95,1},{60,95,1},{45,84,0},{126,54,338},{45,84,0},{127,18,421},{71,111,1},{77,98,1}, +{56,98,1},{127,18,421},{126,74,421},{56,98,1},{0,91,421},{126,74,421},{0,91,421},{64,0,421},{64,0,421},{64,0,421},{64,0,421},{57,100,0},{57,100,0},{57,100,0},{57,78,0},{43,85,0},{43,85,0},{71,127,1214},{69,122,450},{70,106,650},{68,101,446},{66,127,1722},{60,112,438},{62,102,6},{59,93,650},{36,115,1515},{44,95,451},{78,126,470},{75,116,2},{77,104,38},{74,101,74},{127,11,1514}, +{57,115,421},{62,102,5},{34,96,421},{126,71,1514},{34,96,421},{68,127,425},{68,127,425},{68,127,425},{68,98,422},{62,124,339},{62,102,2},{62,102,2},{61,86,42},{43,101,339},{48,89,1},{76,114,1},{76,114,1},{76,114,1},{75,95,1},{122,0,338},{63,101,1},{63,101,1},{50,88,1},{126,61,338},{50,88,1},{127,31,421},{75,116,1},{81,103,1},{59,103,0},{127,31,421},{127,80,421},{59,103,0}, +{0,96,421},{127,80,421},{0,96,421},{68,0,421},{68,0,421},{68,0,421},{68,0,421},{62,104,1},{62,104,1},{62,104,1},{62,82,1},{48,89,0},{48,89,0},{77,127,1334},{73,126,450},{74,110,650},{72,105,446},{71,127,1805},{65,116,437},{65,107,2},{63,97,650},{40,119,1515},{48,99,451},{82,127,506},{79,120,2},{81,108,38},{78,105,74},{127,24,1514},{61,119,421},{65,107,2},{38,100,421},{125,77,1514}, +{38,100,421},{73,126,441},{73,126,441},{73,126,441},{72,102,422},{65,127,340},{65,107,2},{65,107,2},{64,91,38},{47,105,339},{52,93,1},{80,118,1},{80,118,1},{80,118,1},{79,99,1},{127,2,338},{67,105,0},{67,105,0},{54,92,1},{127,66,338},{54,92,1},{127,43,421},{79,120,1},{85,107,1},{63,107,0},{127,43,421},{127,86,421},{63,107,0},{0,100,421},{127,86,421},{0,100,421},{72,0,421}, +{72,0,421},{72,0,421},{72,0,421},{65,109,0},{65,109,0},{65,109,0},{65,86,1},{52,93,0},{52,93,0},{82,127,1470},{77,127,462},{78,114,650},{76,109,446},{77,127,1917},{69,120,437},{69,111,2},{66,102,650},{44,123,1515},{52,103,451},{88,127,562},{83,124,2},{85,112,38},{82,109,74},{127,36,1514},{65,122,421},{69,111,2},{42,104,421},{127,82,1514},{42,104,421},{77,127,461},{77,127,461},{77,127,461}, +{76,106,422},{71,127,356},{69,111,2},{69,111,2},{68,95,38},{51,109,339},{56,97,1},{84,122,1},{84,122,1},{84,122,1},{83,103,1},{127,14,338},{71,109,0},{71,109,0},{58,96,1},{127,72,338},{58,96,1},{127,56,421},{83,124,1},{89,111,1},{67,111,0},{127,56,421},{127,92,421},{67,111,0},{0,104,421},{127,92,421},{0,104,421},{76,0,421},{76,0,421},{76,0,421},{76,0,421},{69,113,0}, +{69,113,0},{69,113,0},{69,90,1},{56,97,0},{56,97,0},{85,127,1634},{82,127,530},{82,118,650},{80,113,446},{82,127,2030},{73,124,437},{73,115,2},{70,106,650},{48,127,1515},{56,107,451},{92,127,646},{87,127,6},{89,116,38},{86,113,74},{127,48,1514},{69,126,421},{73,115,2},{46,108,421},{127,88,1514},{46,108,421},{82,127,494},{82,127,494},{82,127,494},{80,110,422},{75,127,386},{73,115,2},{73,115,2}, +{72,99,38},{55,113,339},{60,101,1},{88,126,1},{88,126,1},{88,126,1},{87,107,1},{127,27,338},{75,113,0},{75,113,0},{62,100,1},{126,78,338},{62,100,1},{127,67,421},{89,126,5},{93,115,1},{71,115,0},{127,67,421},{127,98,421},{71,115,0},{0,108,421},{127,98,421},{0,108,421},{80,0,421},{80,0,421},{80,0,421},{80,0,421},{73,117,0},{73,117,0},{73,117,0},{73,94,1},{60,101,0}, +{60,101,0},{91,127,1838},{87,127,682},{86,122,654},{85,118,446},{88,127,2198},{78,127,450},{78,119,4},{74,110,654},{57,127,1557},{60,111,453},{97,127,741},{93,127,57},{93,120,41},{90,117,77},{127,62,1514},{76,127,446},{78,119,3},{51,112,421},{127,95,1514},{51,112,421},{86,127,554},{86,127,554},{86,127,554},{85,115,421},{80,127,435},{78,119,3},{78,119,3},{76,103,41},{59,118,339},{64,105,1},{93,126,8}, +{93,126,8},{93,126,8},{92,111,0},{127,40,338},{80,117,0},{80,117,0},{65,105,0},{126,85,338},{65,105,0},{127,81,421},{96,127,29},{98,119,1},{76,119,1},{127,81,421},{126,105,421},{76,119,1},{0,112,421},{126,105,421},{0,112,421},{85,0,421},{85,0,421},{85,0,421},{85,0,421},{78,120,1},{78,120,1},{78,120,1},{77,99,1},{64,105,1},{64,105,1},{97,127,2070},{92,127,882},{90,126,654}, +{89,122,446},{91,127,2382},{84,127,546},{82,123,4},{78,114,654},{64,127,1658},{62,116,453},{103,127,837},{99,127,161},{97,124,41},{94,121,77},{127,73,1514},{84,127,521},{82,123,3},{55,116,421},{127,101,1514},{55,116,421},{91,127,605},{91,127,605},{91,127,605},{89,119,421},{85,127,485},{82,123,3},{82,123,3},{80,107,41},{63,122,339},{68,109,1},{97,127,20},{97,127,20},{97,127,20},{96,115,0},{127,53,338}, +{84,121,0},{84,121,0},{69,109,0},{126,91,338},{69,109,0},{127,93,421},{102,127,85},{102,123,1},{80,123,1},{127,93,421},{126,111,421},{80,123,1},{0,116,421},{126,111,421},{0,116,421},{89,0,421},{89,0,421},{89,0,421},{89,0,421},{82,124,1},{82,124,1},{82,124,1},{81,103,1},{68,109,1},{68,109,1},{100,127,2201},{96,127,1101},{95,127,686},{93,126,441},{97,127,2469},{87,127,689},{86,127,3}, +{84,117,617},{73,127,1735},{67,120,421},{109,127,916},{104,127,298},{102,127,52},{98,125,68},{127,86,1459},{93,127,584},{86,127,2},{59,120,392},{127,107,1459},{59,120,392},{95,127,686},{95,127,686},{95,127,686},{93,123,421},{91,127,557},{86,127,3},{86,127,3},{84,111,41},{66,126,338},{72,113,1},{102,126,52},{102,126,52},{102,126,52},{100,119,0},{127,64,338},{88,125,0},{88,125,0},{73,113,0},{126,97,338}, +{73,113,0},{127,105,392},{110,127,146},{106,127,0},{84,127,0},{127,105,392},{126,117,392},{84,127,0},{0,120,392},{126,117,392},{0,120,392},{93,0,421},{93,0,421},{93,0,421},{93,0,421},{86,127,2},{86,127,2},{86,127,2},{85,107,1},{72,113,1},{72,113,1},{103,127,1901},{101,127,1079},{100,127,761},{97,127,421},{100,127,2093},{93,127,537},{91,127,29},{87,120,357},{81,127,1425},{72,122,213},{111,127,638}, +{108,127,244},{106,127,80},{103,126,17},{127,93,1064},{99,127,392},{93,127,4},{67,122,200},{126,111,1064},{67,122,200},{100,127,761},{100,127,761},{100,127,761},{97,127,421},{95,127,659},{91,127,29},{91,127,29},{88,115,41},{73,127,350},{76,117,1},{106,127,80},{106,127,80},{106,127,80},{104,123,0},{127,76,338},{93,127,4},{93,127,4},{77,117,0},{126,103,338},{77,117,0},{127,111,200},{116,127,74},{112,127,0}, +{96,127,0},{127,111,200},{126,120,200},{96,127,0},{0,122,200},{126,120,200},{0,122,200},{97,0,421},{97,0,421},{97,0,421},{97,0,421},{91,127,13},{91,127,13},{91,127,13},{89,111,1},{76,117,1},{76,117,1},{109,127,1646},{106,127,1086},{104,127,881},{102,127,450},{106,127,1730},{99,127,474},{96,127,122},{93,123,158},{87,127,1166},{79,124,62},{114,127,446},{111,127,225},{111,127,125},{108,127,2},{127,102,722}, +{105,127,254},{102,127,34},{76,124,61},{127,115,722},{76,124,61},{104,127,881},{104,127,881},{104,127,881},{102,127,450},{100,127,770},{96,127,122},{96,127,122},{93,120,38},{81,127,426},{81,121,2},{111,127,125},{111,127,125},{111,127,125},{108,127,2},{127,90,338},{102,127,34},{102,127,34},{83,121,1},{127,109,338},{83,121,1},{127,118,61},{119,127,25},{119,127,0},{110,127,0},{127,118,61},{126,123,61},{110,127,0}, +{0,124,61},{126,123,61},{0,124,61},{101,0,421},{101,0,421},{101,0,421},{101,0,421},{95,127,40},{95,127,40},{95,127,40},{94,115,1},{81,121,1},{81,121,1},{111,127,1450},{111,127,1109},{109,127,974},{105,127,542},{111,127,1505},{102,127,514},{102,127,258},{98,125,66},{96,127,1026},{84,126,6},{120,127,342},{117,127,230},{117,127,181},{113,127,37},{127,110,509},{111,127,213},{108,127,90},{85,126,5},{126,119,509}, +{85,126,5},{109,127,974},{109,127,974},{109,127,974},{105,127,542},{106,127,882},{102,127,258},{102,127,258},{97,124,38},{90,127,530},{85,125,2},{117,127,181},{117,127,181},{117,127,181},{113,127,37},{127,102,338},{108,127,90},{108,127,90},{87,125,1},{127,115,338},{87,125,1},{127,124,5},{125,127,1},{125,127,0},{122,127,0},{127,124,5},{126,126,5},{122,127,0},{0,126,5},{126,126,5},{0,126,5},{105,0,421}, +{105,0,421},{105,0,421},{105,0,421},{100,127,65},{100,127,65},{100,127,65},{98,119,1},{85,125,1},{85,125,1},{114,127,1179},{114,127,971},{112,127,881},{111,127,545},{114,127,1170},{108,127,457},{107,127,305},{102,126,17},{102,127,793},{90,127,9},{121,127,209},{120,127,155},{120,127,130},{118,127,45},{127,116,294},{116,127,134},{113,127,85},{95,127,0},{126,122,294},{95,127,0},{112,127,881},{112,127,881},{112,127,881}, +{111,127,545},{111,127,765},{107,127,305},{107,127,305},{102,126,13},{96,127,465},{90,127,9},{120,127,130},{120,127,130},{120,127,130},{118,127,45},{127,110,221},{113,127,85},{113,127,85},{95,127,0},{126,119,221},{95,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{109,0,421},{109,0,421},{109,0,421},{109,0,421},{106,127,113}, +{106,127,113},{106,127,113},{102,123,1},{90,127,9},{90,127,9},{117,127,871},{117,127,751},{115,127,701},{113,127,502},{117,127,822},{111,127,364},{111,127,264},{106,127,1},{105,127,537},{99,127,41},{123,127,75},{123,127,59},{123,127,50},{121,127,17},{127,121,113},{119,127,54},{119,127,29},{107,127,0},{127,124,113},{107,127,0},{115,127,701},{115,127,701},{115,127,701},{113,127,502},{114,127,561},{111,127,264},{111,127,264}, +{106,127,1},{102,127,329},{99,127,41},{123,127,50},{123,127,50},{123,127,50},{121,127,17},{127,116,85},{119,127,29},{119,127,29},{107,127,0},{126,122,85},{107,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{113,0,421},{113,0,421},{113,0,421},{113,0,421},{109,127,157},{109,127,157},{109,127,157},{106,127,1},{99,127,41}, +{99,127,41},{0,59,882},{0,40,100},{0,30,4},{0,24,340},{0,39,1896},{0,25,1188},{0,23,590},{0,15,1444},{0,19,2040},{0,15,1544},{0,59,882},{0,40,100},{0,30,4},{0,24,340},{19,0,1896},{0,25,1188},{0,23,590},{0,15,1444},{39,0,1896},{0,15,1444},{0,27,0},{0,27,0},{0,27,0},{0,13,1},{0,13,162},{0,11,58},{0,11,58},{0,7,97},{0,5,179},{0,6,116},{0,27,0}, +{0,27,0},{0,27,0},{0,13,1},{7,0,162},{0,11,58},{0,11,58},{0,7,97},{13,0,162},{0,7,97},{29,0,882},{0,40,100},{0,30,4},{0,24,340},{29,0,882},{59,0,882},{0,24,340},{0,19,884},{59,0,882},{0,19,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,71,882},{0,49,40},{1,34,12}, +{0,30,260},{0,47,2355},{0,31,1332},{0,28,612},{0,18,1700},{0,22,2556},{0,18,1844},{0,71,882},{0,49,40},{1,34,8},{0,30,260},{23,0,2355},{0,31,1332},{0,28,612},{0,18,1700},{47,0,2355},{0,18,1700},{0,39,0},{0,39,0},{0,39,0},{0,19,0},{0,20,338},{0,14,130},{0,14,130},{0,10,205},{0,8,371},{0,9,244},{0,39,0},{0,39,0},{0,39,0},{0,19,0},{10,0,338}, +{0,14,130},{0,14,130},{0,10,205},{20,0,338},{0,10,205},{35,0,882},{0,49,40},{3,34,0},{0,30,260},{35,0,882},{71,0,882},{0,30,260},{0,23,884},{71,0,882},{0,23,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,83,882},{0,55,8},{1,40,60},{0,33,200},{0,56,2899},{0,37,1508},{0,31,660}, +{0,21,2004},{0,25,3176},{0,21,2200},{0,83,882},{0,55,8},{2,38,52},{0,33,200},{27,1,2899},{0,37,1508},{0,31,660},{0,21,2004},{56,0,2899},{0,21,2004},{0,52,0},{0,52,0},{0,52,0},{0,25,0},{0,26,578},{0,19,208},{0,19,208},{0,13,353},{0,11,635},{0,10,414},{0,52,0},{0,52,0},{0,52,0},{0,25,0},{13,0,578},{0,19,208},{0,19,208},{0,13,353},{26,0,578}, +{0,13,353},{41,0,882},{0,55,8},{7,38,0},{0,33,200},{41,0,882},{83,0,882},{0,33,200},{0,27,884},{83,0,882},{0,27,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,91,902},{1,62,20},{3,44,133},{0,39,172},{0,66,3048},{0,43,1416},{0,37,488},{0,27,1944},{0,31,3460},{0,26,2254},{3,89,882}, +{3,60,2},{5,44,68},{2,38,168},{33,0,3048},{0,43,1416},{0,37,488},{0,27,1944},{66,0,3048},{0,27,1944},{2,60,20},{2,60,20},{2,60,20},{2,30,20},{0,36,648},{0,28,160},{0,28,160},{0,15,340},{0,17,771},{0,15,440},{3,58,0},{3,58,0},{3,58,0},{3,30,0},{18,0,648},{0,28,160},{0,28,160},{0,15,340},{36,0,648},{0,15,340},{47,0,882},{1,62,0},{11,42,0}, +{0,39,136},{47,0,882},{95,0,882},{0,39,136},{0,31,884},{95,0,882},{0,31,884},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,9,0},{0,9,0},{0,9,0},{0,4,1},{0,3,8},{0,3,8},{4,101,995},{4,67,114},{6,48,283},{3,44,242},{0,80,3048},{0,51,1224},{0,43,267},{0,32,1794},{0,37,3651},{0,30,2195},{8,93,883},{7,65,2},{9,48,67},{6,42,171},{39,1,3048}, +{0,51,1224},{0,43,267},{0,32,1794},{80,0,3048},{0,32,1794},{4,69,113},{4,69,113},{4,69,113},{4,36,113},{0,50,648},{0,34,74},{0,34,74},{0,21,250},{0,22,862},{0,19,434},{8,61,1},{8,61,1},{8,61,1},{8,34,1},{24,1,648},{0,34,74},{0,34,74},{0,21,250},{50,0,648},{0,21,250},{53,1,882},{6,65,1},{15,47,1},{0,44,89},{53,1,882},{109,0,882},{0,44,89}, +{0,36,882},{109,0,882},{0,36,882},{4,0,113},{4,0,113},{4,0,113},{4,0,113},{0,23,0},{0,23,0},{0,23,0},{0,11,0},{0,8,41},{0,8,41},{6,109,1147},{6,72,274},{8,53,499},{5,47,367},{0,92,3048},{0,57,1096},{0,47,129},{0,36,1635},{0,43,3859},{0,34,2183},{12,97,883},{11,69,2},{13,52,67},{10,46,171},{45,1,3048},{0,57,1096},{0,47,129},{0,36,1635},{92,0,3048}, +{0,36,1635},{6,77,265},{6,77,265},{6,77,265},{6,41,265},{0,62,648},{0,43,26},{0,43,26},{0,26,193},{0,28,990},{0,23,458},{12,65,1},{12,65,1},{12,65,1},{12,38,1},{30,1,648},{0,43,26},{0,43,26},{0,26,193},{62,0,648},{0,26,193},{59,1,882},{10,69,1},{19,51,1},{0,49,58},{59,1,882},{121,0,882},{0,49,58},{0,40,882},{121,0,882},{0,40,882},{6,0,265}, +{6,0,265},{6,0,265},{6,0,265},{0,35,0},{0,35,0},{0,35,0},{0,17,0},{0,14,97},{0,14,97},{8,117,1363},{8,77,506},{10,58,795},{7,52,559},{0,104,3048},{0,63,1000},{0,53,41},{0,39,1523},{0,46,4095},{0,38,2195},{16,101,883},{15,73,2},{17,56,67},{14,50,171},{51,0,3048},{0,63,1000},{0,53,41},{0,39,1523},{104,0,3048},{0,39,1523},{8,85,481},{8,85,481},{8,85,481}, +{8,46,481},{0,74,648},{0,49,2},{0,49,2},{0,30,130},{0,31,1146},{0,28,494},{16,69,1},{16,69,1},{16,69,1},{16,42,1},{36,1,648},{0,49,2},{0,49,2},{0,30,130},{74,0,648},{0,30,130},{65,0,882},{14,73,1},{23,55,1},{0,53,25},{65,0,882},{127,3,882},{0,53,25},{0,44,882},{127,3,882},{0,44,882},{8,0,481},{8,0,481},{8,0,481},{8,0,481},{0,47,0}, +{0,47,0},{0,47,0},{0,23,0},{0,19,169},{0,19,169},{10,125,1643},{11,83,802},{13,61,1159},{9,56,826},{0,117,3048},{0,70,933},{0,58,11},{0,45,1395},{0,54,4321},{0,43,2227},{20,105,883},{19,77,2},{21,60,67},{18,54,171},{57,0,3048},{0,70,933},{0,58,11},{0,45,1395},{117,0,3048},{0,45,1395},{10,93,761},{10,93,761},{10,93,761},{10,51,761},{0,86,648},{0,56,4},{0,56,4}, +{0,35,89},{0,37,1322},{0,31,578},{20,73,1},{20,73,1},{20,73,1},{20,46,1},{42,1,648},{3,54,0},{3,54,0},{0,35,89},{86,0,648},{0,35,89},{71,0,882},{18,77,1},{27,59,1},{0,58,10},{71,0,882},{127,9,882},{0,58,10},{0,48,882},{127,9,882},{0,48,882},{10,0,761},{10,0,761},{10,0,761},{10,0,761},{0,59,0},{0,59,0},{0,59,0},{0,29,0},{0,22,277}, +{0,22,277},{14,126,1784},{14,89,929},{17,65,1329},{13,60,945},{3,124,3048},{2,75,910},{3,62,14},{0,50,1329},{0,60,4212},{0,47,1974},{24,110,882},{24,80,5},{27,64,70},{23,59,168},{63,2,3048},{0,77,893},{4,63,10},{0,50,1293},{126,2,3048},{0,50,1293},{14,99,884},{14,99,884},{14,99,884},{13,56,884},{3,94,648},{3,62,10},{3,62,10},{1,40,68},{0,46,1256},{0,37,428},{24,78,0}, +{24,78,0},{24,78,0},{24,51,0},{49,0,648},{7,59,0},{7,59,0},{0,39,52},{100,0,648},{0,39,52},{78,0,882},{23,81,1},{32,63,0},{0,63,1},{78,0,882},{126,16,882},{0,63,1},{0,52,884},{126,16,882},{0,52,884},{13,0,884},{13,0,884},{13,0,884},{13,0,884},{3,66,0},{3,66,0},{3,66,0},{3,34,0},{0,31,232},{0,31,232},{19,126,1814},{18,93,929},{21,69,1329}, +{17,65,942},{7,127,3051},{6,79,910},{7,66,14},{4,54,1329},{0,67,3975},{0,52,1640},{28,114,882},{28,84,5},{30,67,66},{27,63,168},{69,1,3048},{1,83,882},{9,66,10},{0,53,1205},{126,8,3048},{0,53,1205},{18,103,884},{18,103,884},{18,103,884},{17,60,884},{7,98,648},{8,65,9},{8,65,9},{5,44,68},{0,51,1059},{0,43,236},{28,82,0},{28,82,0},{28,82,0},{28,55,0},{55,0,648}, +{11,63,0},{11,63,0},{0,45,20},{112,0,648},{0,45,20},{83,1,882},{27,85,1},{36,66,1},{4,66,1},{83,1,882},{126,22,882},{4,66,1},{0,56,884},{126,22,882},{0,56,884},{17,0,884},{17,0,884},{17,0,884},{17,0,884},{7,70,0},{7,70,0},{7,70,0},{7,38,0},{0,37,136},{0,37,136},{23,127,1854},{22,97,929},{25,73,1329},{21,69,942},{12,127,3064},{10,83,910},{11,70,14}, +{8,58,1329},{0,73,3751},{0,57,1374},{32,118,882},{32,88,5},{34,71,66},{30,67,165},{75,1,3048},{5,87,882},{13,70,10},{0,59,1125},{126,14,3048},{0,59,1125},{22,107,884},{22,107,884},{22,107,884},{21,64,884},{11,102,648},{12,69,9},{12,69,9},{9,48,68},{0,57,923},{0,49,108},{32,86,0},{32,86,0},{32,86,0},{32,59,0},{61,0,648},{16,65,1},{16,65,1},{0,49,8},{124,0,648}, +{0,49,8},{89,1,882},{31,89,1},{40,70,1},{8,70,1},{89,1,882},{126,28,882},{8,70,1},{0,60,884},{126,28,882},{0,60,884},{21,0,884},{21,0,884},{21,0,884},{21,0,884},{11,74,0},{11,74,0},{11,74,0},{11,42,0},{0,46,68},{0,46,68},{29,127,1934},{26,101,929},{29,77,1329},{25,73,942},{17,127,3091},{14,87,910},{15,74,14},{12,62,1329},{0,79,3559},{0,62,1174},{36,122,882}, +{36,92,5},{38,75,66},{34,71,165},{81,0,3048},{9,91,882},{17,74,10},{0,62,1053},{126,20,3048},{0,62,1053},{26,111,884},{26,111,884},{26,111,884},{26,67,884},{15,106,648},{16,73,9},{16,73,9},{13,52,68},{0,64,810},{0,54,26},{36,90,0},{36,90,0},{36,90,0},{36,63,0},{66,1,648},{20,69,1},{20,69,1},{0,54,1},{126,5,648},{0,54,1},{95,1,882},{35,93,1},{44,74,1}, +{12,74,1},{95,1,882},{126,34,882},{12,74,1},{0,64,882},{126,34,882},{0,64,882},{25,0,884},{25,0,884},{25,0,884},{25,0,884},{15,78,0},{15,78,0},{15,78,0},{15,46,0},{0,51,18},{0,51,18},{33,127,2036},{31,106,931},{33,81,1331},{29,77,942},{23,127,3145},{19,92,910},{19,79,14},{17,65,1329},{0,87,3375},{0,66,1021},{41,126,883},{40,98,2},{43,80,65},{39,76,166},{88,0,3048}, +{14,95,882},{21,78,9},{0,66,996},{127,26,3048},{0,66,996},{30,116,882},{30,116,882},{30,116,882},{30,72,882},{20,109,649},{20,77,10},{20,77,10},{18,57,67},{0,70,729},{1,59,3},{41,94,1},{41,94,1},{41,94,1},{40,67,1},{73,0,648},{24,74,1},{24,74,1},{4,58,1},{126,12,648},{4,58,1},{102,0,882},{39,98,1},{48,79,0},{15,79,0},{102,0,882},{126,41,882},{15,79,0}, +{0,68,884},{126,41,882},{0,68,884},{30,0,882},{30,0,882},{30,0,882},{30,0,882},{20,82,1},{20,82,1},{20,82,1},{19,51,1},{0,60,0},{0,60,0},{38,127,2134},{35,110,931},{37,85,1331},{33,81,942},{29,127,3217},{23,96,910},{23,83,14},{21,69,1329},{0,93,3247},{0,71,949},{45,127,891},{44,102,2},{47,84,65},{43,80,166},{94,0,3048},{18,99,882},{25,82,9},{0,72,948},{127,32,3048}, +{0,72,948},{34,120,882},{34,120,882},{34,120,882},{34,76,882},{24,113,649},{24,81,10},{24,81,10},{22,61,67},{0,79,673},{5,63,3},{45,98,1},{45,98,1},{45,98,1},{44,71,1},{79,0,648},{28,78,1},{28,78,1},{8,62,1},{127,17,648},{8,62,1},{108,0,882},{43,102,1},{52,83,0},{19,83,0},{108,0,882},{125,47,882},{19,83,0},{0,72,884},{125,47,882},{0,72,884},{34,0,882}, +{34,0,882},{34,0,882},{34,0,882},{24,86,1},{24,86,1},{24,86,1},{23,55,1},{3,64,1},{3,64,1},{42,127,2284},{39,114,931},{41,89,1331},{37,85,942},{33,127,3316},{27,100,910},{27,87,14},{25,73,1329},{0,99,3151},{1,76,929},{50,127,909},{48,106,2},{51,88,65},{47,84,166},{100,0,3048},{22,103,882},{29,86,9},{0,75,916},{127,38,3048},{0,75,916},{38,124,882},{38,124,882},{38,124,882}, +{38,80,882},{28,117,649},{28,85,10},{28,85,10},{27,64,66},{0,85,649},{8,66,5},{49,102,1},{49,102,1},{49,102,1},{48,75,1},{85,0,648},{32,82,1},{32,82,1},{11,66,0},{127,23,648},{11,66,0},{114,0,882},{47,106,1},{56,87,0},{23,87,0},{114,0,882},{127,52,882},{23,87,0},{0,76,884},{127,52,882},{0,76,884},{38,0,882},{38,0,882},{38,0,882},{38,0,882},{28,90,1}, +{28,90,1},{28,90,1},{27,59,1},{8,67,1},{8,67,1},{47,127,2414},{43,118,931},{45,93,1331},{41,89,942},{38,127,3409},{31,104,910},{31,91,14},{29,77,1329},{0,105,3087},{5,80,929},{55,127,939},{52,110,2},{55,92,65},{51,88,166},{106,0,3048},{26,107,882},{33,90,9},{0,80,893},{127,44,3048},{0,80,893},{42,127,883},{42,127,883},{42,127,883},{42,84,882},{32,121,649},{32,89,10},{32,89,10}, +{31,68,66},{4,89,649},{12,70,5},{53,106,1},{53,106,1},{53,106,1},{52,79,1},{91,0,648},{36,86,1},{36,86,1},{15,70,0},{127,29,648},{15,70,0},{120,0,882},{51,110,1},{60,91,0},{27,91,0},{120,0,882},{127,58,882},{27,91,0},{0,80,884},{127,58,882},{0,80,884},{42,0,882},{42,0,882},{42,0,882},{42,0,882},{32,94,1},{32,94,1},{32,94,1},{31,63,1},{12,71,1}, +{12,71,1},{52,127,2584},{47,122,929},{50,98,1329},{46,94,942},{44,127,3547},{35,108,910},{36,95,14},{34,82,1331},{0,112,3055},{9,84,931},{61,127,996},{57,113,5},{59,96,66},{55,92,165},{112,1,3048},{30,112,882},{38,95,10},{0,85,883},{126,51,3048},{0,85,883},{47,127,893},{47,127,893},{47,127,893},{47,88,884},{36,127,648},{37,94,9},{37,94,9},{35,72,65},{9,93,649},{17,75,2},{57,111,0}, +{57,111,0},{57,111,0},{57,83,0},{98,0,648},{41,90,1},{41,90,1},{21,74,1},{127,36,648},{21,74,1},{127,0,882},{56,114,1},{64,96,1},{33,95,1},{127,0,882},{126,65,882},{33,95,1},{0,85,882},{126,65,882},{0,85,882},{46,0,884},{46,0,884},{46,0,884},{46,0,884},{36,99,0},{36,99,0},{36,99,0},{36,67,0},{17,75,1},{17,75,1},{58,127,2792},{51,126,929},{54,102,1329}, +{50,98,942},{49,127,3672},{39,112,910},{40,99,14},{38,86,1331},{3,117,3049},{13,88,931},{65,127,1061},{61,117,5},{63,100,66},{59,96,165},{118,1,3048},{34,116,882},{42,99,10},{2,89,882},{126,57,3048},{2,89,882},{52,127,916},{52,127,916},{52,127,916},{51,92,884},{41,127,654},{41,98,9},{41,98,9},{39,76,65},{13,97,649},{21,79,2},{61,115,0},{61,115,0},{61,115,0},{61,87,0},{104,0,648}, +{45,94,1},{45,94,1},{25,78,1},{127,42,648},{25,78,1},{127,11,882},{60,118,1},{68,100,1},{37,99,1},{127,11,882},{126,71,882},{37,99,1},{0,89,882},{126,71,882},{0,89,882},{50,0,884},{50,0,884},{50,0,884},{50,0,884},{40,103,0},{40,103,0},{40,103,0},{40,71,0},{21,79,1},{21,79,1},{61,127,2984},{55,127,949},{58,106,1329},{54,102,942},{55,127,3832},{43,116,910},{44,103,14}, +{42,90,1331},{7,121,3049},{17,92,931},{71,127,1149},{64,122,3},{66,105,67},{63,100,165},{124,1,3048},{38,120,882},{46,103,10},{6,93,882},{126,63,3048},{6,93,882},{55,127,948},{55,127,948},{55,127,948},{55,96,884},{46,126,682},{45,102,9},{45,102,9},{43,80,65},{17,101,649},{25,83,2},{65,118,1},{65,118,1},{65,118,1},{65,91,1},{110,0,648},{49,98,1},{49,98,1},{29,82,1},{126,48,648}, +{29,82,1},{127,24,882},{63,123,1},{72,104,1},{41,103,1},{127,24,882},{125,77,882},{41,103,1},{0,93,882},{125,77,882},{0,93,882},{54,0,884},{54,0,884},{54,0,884},{54,0,884},{44,107,0},{44,107,0},{44,107,0},{44,75,0},{25,83,1},{25,83,1},{65,127,3214},{61,127,1021},{62,110,1329},{58,106,942},{61,127,4024},{47,120,910},{48,107,14},{46,94,1331},{11,125,3049},{21,96,931},{74,127,1245}, +{68,126,3},{70,109,67},{67,103,171},{127,7,3048},{42,124,882},{50,107,10},{10,97,882},{127,68,3048},{10,97,882},{61,127,996},{61,127,996},{61,127,996},{59,100,884},{50,127,714},{49,106,9},{49,106,9},{47,84,65},{21,105,649},{29,87,2},{69,122,1},{69,122,1},{69,122,1},{69,95,1},{115,1,648},{53,102,1},{53,102,1},{33,86,1},{126,54,648},{33,86,1},{127,36,882},{67,127,0},{76,108,1}, +{45,107,1},{127,36,882},{127,82,882},{45,107,1},{0,97,882},{127,82,882},{0,97,882},{58,0,884},{58,0,884},{58,0,884},{58,0,884},{48,111,0},{48,111,0},{48,111,0},{48,79,0},{29,87,1},{29,87,1},{71,127,3494},{65,127,1174},{66,114,1320},{62,110,942},{65,127,4231},{52,125,910},{52,112,14},{50,98,1329},{19,127,3067},{26,101,929},{79,127,1364},{73,127,26},{75,114,68},{72,108,168},{127,21,3048}, +{48,127,885},{54,111,9},{16,101,884},{127,75,3048},{16,101,884},{65,127,1053},{65,127,1053},{65,127,1053},{63,105,882},{56,127,769},{53,110,10},{53,110,10},{52,89,66},{25,110,649},{33,91,5},{73,126,1},{73,126,1},{73,126,1},{73,100,0},{122,0,648},{57,107,1},{57,107,1},{36,91,0},{126,61,648},{36,91,0},{127,50,882},{76,127,18},{81,112,0},{48,112,0},{127,50,882},{127,89,882},{48,112,0}, +{0,101,884},{127,89,882},{0,101,884},{63,0,882},{63,0,882},{63,0,882},{63,0,882},{53,115,1},{53,115,1},{53,115,1},{53,83,1},{33,92,1},{33,92,1},{74,127,3782},{70,127,1374},{70,118,1320},{66,113,945},{71,127,4455},{57,127,926},{56,116,14},{54,102,1329},{25,127,3139},{30,105,929},{85,127,1476},{79,127,97},{79,118,68},{76,112,168},{127,33,3048},{57,127,925},{58,115,9},{20,105,884},{126,81,3048}, +{20,105,884},{68,127,1125},{68,127,1125},{68,127,1125},{66,109,884},{61,127,827},{57,114,10},{57,114,10},{56,93,66},{29,114,649},{37,95,5},{78,126,8},{78,126,8},{78,126,8},{77,104,0},{127,2,648},{61,111,1},{61,111,1},{40,95,0},{127,66,648},{40,95,0},{127,62,882},{81,127,68},{85,116,0},{52,116,0},{127,62,882},{127,95,882},{52,116,0},{0,105,884},{127,95,882},{0,105,884},{66,0,884}, +{66,0,884},{66,0,884},{66,0,884},{57,119,1},{57,119,1},{57,119,1},{57,87,1},{37,96,1},{37,96,1},{79,127,4024},{75,127,1640},{74,122,1320},{70,117,945},{74,127,4699},{63,127,1030},{60,120,14},{58,106,1329},{34,127,3259},{34,109,929},{91,127,1620},{84,127,236},{83,122,68},{80,116,168},{127,45,3048},{64,127,1003},{62,119,9},{24,109,884},{126,87,3048},{24,109,884},{74,127,1205},{74,127,1205},{74,127,1205}, +{70,113,884},{65,127,910},{61,118,10},{61,118,10},{60,97,66},{33,118,649},{41,99,5},{82,127,20},{82,127,20},{82,127,20},{81,108,0},{127,14,648},{64,116,0},{64,116,0},{44,99,0},{127,72,648},{44,99,0},{127,73,882},{90,127,136},{89,120,0},{56,120,0},{127,73,882},{127,101,882},{56,120,0},{0,109,884},{127,101,882},{0,109,884},{70,0,884},{70,0,884},{70,0,884},{70,0,884},{61,123,1}, +{61,123,1},{61,123,1},{61,91,1},{41,100,1},{41,100,1},{85,127,4328},{79,127,1925},{78,126,1320},{74,121,945},{79,127,4920},{67,127,1215},{64,123,14},{62,110,1329},{43,127,3435},{38,113,929},{94,127,1784},{90,127,428},{87,126,68},{84,120,168},{127,57,3048},{70,127,1131},{65,124,10},{28,113,884},{126,93,3048},{28,113,884},{77,127,1293},{77,127,1293},{77,127,1293},{74,117,884},{71,127,1006},{64,123,10},{64,123,10}, +{63,100,70},{37,122,649},{45,103,5},{87,126,52},{87,126,52},{87,126,52},{85,112,0},{127,27,648},{68,120,0},{68,120,0},{48,103,0},{126,78,648},{48,103,0},{127,86,882},{96,127,232},{93,124,0},{60,124,0},{127,86,882},{127,107,882},{60,124,0},{0,113,884},{127,107,882},{0,113,884},{74,0,884},{74,0,884},{74,0,884},{74,0,884},{64,126,1},{64,126,1},{64,126,1},{64,95,0},{45,104,1}, +{45,104,1},{88,127,4403},{84,127,2227},{82,127,1395},{78,125,922},{85,127,4875},{73,127,1326},{69,127,11},{65,115,1174},{54,127,3438},{44,116,802},{100,127,1746},{95,127,578},{92,127,89},{88,124,126},{127,69,2814},{79,127,1146},{71,127,4},{33,117,761},{126,99,2814},{33,117,761},{82,127,1395},{82,127,1395},{82,127,1395},{79,121,883},{77,127,1137},{69,127,11},{69,127,11},{67,106,67},{42,126,649},{50,108,2},{92,127,89}, +{92,127,89},{92,127,89},{90,116,1},{127,40,648},{73,124,0},{73,124,0},{54,107,1},{126,85,648},{54,107,1},{127,96,761},{105,127,277},{98,127,0},{67,127,0},{127,96,761},{127,112,761},{67,127,0},{0,117,761},{127,112,761},{0,117,761},{79,0,882},{79,0,882},{79,0,882},{79,0,882},{69,127,10},{69,127,10},{69,127,10},{68,100,1},{50,108,1},{50,108,1},{94,127,3955},{89,127,2195},{88,127,1523}, +{83,127,886},{91,127,4323},{79,127,1139},{74,127,41},{71,116,799},{60,127,2958},{49,118,506},{103,127,1386},{99,127,494},{97,127,130},{92,125,50},{127,76,2249},{87,127,870},{78,127,2},{42,119,481},{126,103,2249},{42,119,481},{88,127,1523},{88,127,1523},{88,127,1523},{83,125,883},{82,127,1251},{74,127,41},{74,127,41},{71,110,67},{48,127,670},{54,112,2},{97,127,130},{97,127,130},{97,127,130},{94,120,1},{127,53,648}, +{78,127,2},{78,127,2},{58,111,1},{126,91,648},{58,111,1},{127,102,481},{108,127,169},{104,127,0},{79,127,0},{127,102,481},{127,115,481},{79,127,0},{0,119,481},{127,115,481},{0,119,481},{83,0,882},{83,0,882},{83,0,882},{83,0,882},{74,127,25},{74,127,25},{74,127,25},{72,104,1},{54,112,1},{54,112,1},{97,127,3571},{93,127,2183},{91,127,1635},{87,127,891},{94,127,3827},{84,127,1035},{79,127,114}, +{74,119,499},{67,127,2577},{55,121,274},{106,127,1098},{102,127,458},{101,127,193},{97,126,9},{127,86,1769},{93,127,654},{84,127,26},{50,121,265},{127,107,1769},{50,121,265},{91,127,1635},{91,127,1635},{91,127,1635},{87,127,891},{85,127,1387},{79,127,114},{79,127,114},{75,114,67},{57,127,734},{58,116,2},{101,127,193},{101,127,193},{101,127,193},{98,124,1},{127,64,648},{84,127,26},{84,127,26},{62,115,1},{126,97,648}, +{62,115,1},{127,108,265},{113,127,97},{110,127,0},{92,127,0},{127,108,265},{127,118,265},{92,127,0},{0,121,265},{127,118,265},{0,121,265},{87,0,882},{87,0,882},{87,0,882},{87,0,882},{79,127,50},{79,127,50},{79,127,50},{76,108,1},{58,116,1},{58,116,1},{100,127,3267},{97,127,2195},{95,127,1794},{92,127,954},{97,127,3435},{87,127,975},{84,127,267},{79,121,283},{73,127,2281},{60,123,114},{111,127,838}, +{107,127,434},{106,127,250},{102,127,2},{127,93,1374},{99,127,502},{93,127,74},{58,123,113},{126,111,1374},{58,123,113},{95,127,1794},{95,127,1794},{95,127,1794},{92,127,954},{91,127,1539},{84,127,267},{84,127,267},{79,118,67},{64,127,840},{62,120,2},{106,127,250},{106,127,250},{106,127,250},{102,127,2},{127,76,648},{93,127,74},{93,127,74},{65,119,1},{126,103,648},{65,119,1},{127,115,113},{119,127,41},{116,127,0}, +{104,127,0},{127,115,113},{127,121,113},{104,127,0},{0,123,113},{127,121,113},{0,123,113},{91,0,882},{91,0,882},{91,0,882},{91,0,882},{83,127,89},{83,127,89},{83,127,89},{80,112,1},{62,120,1},{62,120,1},{103,127,3032},{101,127,2254},{100,127,1944},{96,127,1080},{103,127,3096},{93,127,1012},{90,127,488},{83,124,133},{81,127,2104},{65,126,20},{114,127,666},{111,127,425},{111,127,325},{108,127,52},{127,102,1032}, +{105,127,404},{99,127,160},{67,125,20},{127,115,1032},{67,125,20},{100,127,1944},{100,127,1944},{100,127,1944},{96,127,1080},{97,127,1736},{90,127,488},{90,127,488},{83,122,68},{73,127,1011},{67,124,2},{111,127,325},{111,127,325},{111,127,325},{108,127,52},{127,90,648},{99,127,160},{99,127,160},{69,124,0},{127,109,648},{69,124,0},{127,122,18},{124,127,8},{122,127,1},{118,127,0},{127,122,18},{126,125,18},{118,127,0}, +{0,125,20},{126,125,18},{0,125,20},{95,0,884},{95,0,884},{95,0,884},{95,0,884},{88,127,136},{88,127,136},{88,127,136},{85,116,0},{65,126,0},{65,126,0},{109,127,2756},{106,127,2200},{103,127,2004},{102,127,1188},{106,127,2760},{96,127,1060},{96,127,660},{87,126,60},{87,127,1900},{72,127,8},{117,127,534},{117,127,414},{114,127,353},{111,127,104},{127,110,771},{108,127,352},{108,127,208},{75,127,0},{126,119,771}, +{75,127,0},{103,127,2004},{103,127,2004},{103,127,2004},{102,127,1188},{100,127,1784},{96,127,660},{96,127,660},{89,125,52},{81,127,1112},{72,127,8},{114,127,353},{114,127,353},{114,127,353},{111,127,104},{127,101,578},{108,127,208},{108,127,208},{75,127,0},{127,114,578},{75,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{99,0,884}, +{99,0,884},{99,0,884},{99,0,884},{94,127,200},{94,127,200},{94,127,200},{89,120,0},{72,127,8},{72,127,8},{111,127,2214},{109,127,1844},{109,127,1700},{105,127,1096},{109,127,2180},{102,127,900},{99,127,612},{93,126,12},{93,127,1468},{78,127,40},{120,127,306},{118,127,244},{117,127,205},{116,127,65},{127,113,451},{113,127,211},{111,127,125},{87,127,0},{127,120,451},{87,127,0},{109,127,1700},{109,127,1700},{109,127,1700}, +{105,127,1096},{103,127,1460},{99,127,612},{99,127,612},{93,126,8},{87,127,872},{78,127,40},{117,127,205},{117,127,205},{117,127,205},{116,127,65},{127,107,338},{111,127,125},{111,127,125},{87,127,0},{127,117,338},{87,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{103,0,884},{103,0,884},{103,0,884},{103,0,884},{97,127,260}, +{97,127,260},{97,127,260},{93,124,0},{78,127,40},{78,127,40},{114,127,1798},{111,127,1521},{111,127,1421},{108,127,1028},{111,127,1675},{105,127,792},{104,127,590},{97,127,4},{96,127,1128},{87,127,100},{123,127,150},{121,127,116},{120,127,97},{119,127,29},{127,118,216},{119,127,99},{116,127,58},{99,127,0},{126,123,216},{99,127,0},{111,127,1421},{111,127,1421},{111,127,1421},{108,127,1028},{109,127,1188},{104,127,590},{104,127,590}, +{97,127,4},{93,127,696},{87,127,100},{120,127,97},{120,127,97},{120,127,97},{119,127,29},{127,113,162},{116,127,58},{116,127,58},{99,127,0},{127,120,162},{99,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{107,0,884},{107,0,884},{107,0,884},{107,0,884},{103,127,340},{103,127,340},{103,127,340},{97,127,4},{87,127,100}, +{87,127,100},{0,78,1568},{0,54,170},{0,40,4},{0,33,596},{0,53,3371},{0,34,2124},{0,31,1048},{0,21,2552},{0,25,3628},{0,21,2748},{0,78,1568},{0,54,170},{0,40,4},{0,33,596},{26,0,3371},{0,34,2124},{0,31,1048},{0,21,2552},{53,0,3371},{0,21,2552},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{0,18,288},{0,14,106},{0,14,106},{0,9,180},{0,8,315},{0,7,206},{0,36,0}, +{0,36,0},{0,36,0},{0,18,0},{9,0,288},{0,14,106},{0,14,106},{0,9,180},{18,0,288},{0,9,180},{39,0,1568},{0,54,170},{0,40,4},{0,33,596},{39,0,1568},{78,0,1568},{0,33,596},{0,26,1568},{78,0,1568},{0,26,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,91,1568},{0,63,90},{0,45,8}, +{0,39,500},{0,61,3968},{0,40,2316},{0,35,1078},{0,24,2880},{0,28,4304},{0,24,3136},{0,91,1568},{0,63,90},{1,44,8},{0,39,500},{30,0,3968},{0,40,2316},{0,35,1078},{0,24,2880},{61,0,3968},{0,24,2880},{0,48,0},{0,48,0},{0,48,0},{0,24,0},{0,24,512},{0,19,180},{0,19,180},{0,10,313},{0,11,563},{0,10,362},{0,48,0},{0,48,0},{0,48,0},{0,24,0},{12,0,512}, +{0,19,180},{0,19,180},{0,10,313},{24,0,512},{0,10,313},{45,0,1568},{0,63,90},{2,44,0},{0,39,500},{45,0,1568},{91,0,1568},{0,39,500},{0,30,1568},{91,0,1568},{0,30,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,103,1568},{0,70,37},{1,49,48},{0,42,400},{0,68,4651},{0,46,2540},{0,40,1128}, +{0,27,3256},{0,31,5084},{0,27,3580},{0,103,1568},{0,70,37},{1,49,44},{0,42,400},{33,1,4651},{0,46,2540},{0,40,1128},{0,27,3256},{68,0,4651},{0,27,3256},{0,61,0},{0,61,0},{0,61,0},{0,30,0},{0,30,800},{0,25,292},{0,25,292},{0,13,485},{0,14,883},{0,13,566},{0,61,0},{0,61,0},{0,61,0},{0,30,0},{15,0,800},{0,25,292},{0,25,292},{0,13,485},{30,0,800}, +{0,13,485},{50,1,1568},{0,70,37},{6,48,0},{0,42,400},{50,1,1568},{103,0,1568},{0,42,400},{0,34,1568},{103,0,1568},{0,34,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,115,1568},{0,76,5},{1,54,145},{0,47,325},{0,77,5419},{0,51,2755},{0,43,1208},{0,30,3680},{0,34,5968},{0,30,4080},{0,115,1568}, +{0,76,5},{3,53,121},{0,47,325},{38,0,5419},{0,51,2755},{0,43,1208},{0,30,3680},{77,0,5419},{0,30,3680},{0,72,0},{0,72,0},{0,72,0},{0,36,0},{0,36,1152},{0,28,424},{0,28,424},{0,18,720},{0,17,1275},{0,15,824},{0,72,0},{0,72,0},{0,72,0},{0,36,0},{18,0,1152},{0,28,424},{0,28,424},{0,18,720},{36,0,1152},{0,18,720},{56,1,1568},{0,76,5},{10,52,0}, +{0,47,325},{56,1,1568},{115,0,1568},{0,47,325},{0,38,1568},{115,0,1568},{0,38,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,125,1609},{2,82,42},{5,58,254},{1,51,318},{0,91,5419},{0,57,2480},{0,49,835},{0,36,3427},{0,40,6191},{0,35,3991},{5,119,1569},{4,80,6},{8,58,122},{2,52,302},{45,0,5419}, +{0,57,2480},{0,49,835},{0,36,3427},{91,0,5419},{0,36,3427},{2,82,41},{2,82,41},{2,82,41},{2,41,42},{0,50,1152},{0,37,274},{0,37,274},{0,21,586},{0,22,1366},{0,20,782},{5,76,1},{5,76,1},{5,76,1},{5,40,1},{24,1,1152},{0,37,274},{0,37,274},{0,21,586},{50,0,1152},{0,21,586},{63,0,1568},{2,82,1},{15,56,1},{0,53,245},{63,0,1568},{127,1,1568},{0,53,245}, +{0,42,1570},{127,1,1568},{0,42,1570},{2,0,41},{2,0,41},{2,0,41},{2,0,41},{0,13,0},{0,13,0},{0,13,0},{0,7,0},{0,5,13},{0,5,13},{5,126,1735},{4,87,150},{7,63,426},{3,56,382},{0,103,5419},{0,64,2265},{0,54,557},{0,39,3243},{0,46,6415},{0,39,3919},{9,123,1569},{8,84,6},{12,62,122},{6,56,302},{50,1,5419},{0,64,2265},{0,54,557},{0,39,3243},{103,0,5419}, +{0,39,3243},{4,90,145},{4,90,145},{4,90,145},{4,46,146},{0,62,1152},{0,43,170},{0,43,170},{0,27,482},{0,28,1494},{0,24,770},{9,80,1},{9,80,1},{9,80,1},{9,44,1},{30,1,1152},{0,43,170},{0,43,170},{0,27,482},{62,0,1152},{0,27,482},{69,0,1568},{6,86,1},{19,60,1},{0,56,181},{69,0,1568},{127,7,1568},{0,56,181},{0,46,1570},{127,7,1568},{0,46,1570},{4,0,145}, +{4,0,145},{4,0,145},{4,0,145},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{0,11,53},{0,11,53},{9,127,1991},{7,93,322},{9,66,678},{5,61,518},{0,115,5419},{0,70,2081},{0,60,341},{0,45,3035},{0,51,6641},{0,42,3891},{13,127,1569},{12,88,6},{15,66,122},{10,60,302},{56,1,5419},{0,70,2081},{0,60,341},{0,45,3035},{115,0,5419},{0,45,3035},{6,98,313},{6,98,313},{6,98,313}, +{6,51,314},{0,74,1152},{0,51,80},{0,51,80},{0,30,394},{0,31,1650},{0,28,782},{13,84,1},{13,84,1},{13,84,1},{13,48,1},{36,1,1152},{0,51,80},{0,51,80},{0,30,394},{74,0,1152},{0,30,394},{75,0,1568},{10,90,1},{23,64,0},{0,62,125},{75,0,1568},{127,13,1568},{0,62,125},{0,50,1570},{127,13,1568},{0,50,1570},{6,0,313},{6,0,313},{6,0,313},{6,0,313},{0,38,0}, +{0,38,0},{0,38,0},{0,18,1},{0,14,117},{0,14,117},{12,127,2387},{9,98,566},{11,71,1002},{7,64,721},{0,127,5419},{0,76,1929},{0,64,181},{0,50,2886},{0,57,6921},{0,47,3879},{17,127,1577},{16,92,6},{19,70,122},{13,64,309},{62,1,5419},{0,76,1929},{0,64,181},{0,50,2886},{127,0,5419},{0,50,2886},{8,106,545},{8,106,545},{8,106,545},{8,56,545},{0,86,1152},{0,57,32},{0,57,32}, +{0,36,306},{0,37,1826},{0,34,822},{17,88,1},{17,88,1},{17,88,1},{17,52,1},{42,1,1152},{0,57,32},{0,57,32},{0,36,306},{86,0,1152},{0,36,306},{80,1,1568},{14,94,1},{27,68,0},{0,66,80},{80,1,1568},{126,19,1568},{0,66,80},{0,54,1570},{126,19,1568},{0,54,1570},{8,0,545},{8,0,545},{8,0,545},{8,0,545},{0,50,0},{0,50,0},{0,50,0},{0,24,1},{0,19,193}, +{0,19,193},{15,127,3004},{11,106,925},{14,77,1461},{9,69,1030},{3,127,5520},{0,84,1769},{0,70,66},{0,53,2697},{0,63,7276},{0,51,3898},{23,127,1602},{21,97,5},{23,74,125},{19,67,306},{69,0,5419},{0,84,1769},{0,70,66},{0,53,2697},{127,7,5419},{0,53,2697},{11,114,884},{11,114,884},{11,114,884},{10,62,884},{0,100,1152},{0,65,5},{0,65,5},{0,42,232},{0,43,2064},{0,37,896},{21,93,0}, +{21,93,0},{21,93,0},{21,57,0},{49,0,1152},{0,65,5},{0,65,5},{0,42,232},{100,0,1152},{0,42,232},{87,0,1568},{19,98,1},{31,73,1},{0,71,45},{87,0,1568},{126,26,1568},{0,71,45},{0,59,1568},{126,26,1568},{0,59,1568},{10,0,884},{10,0,884},{10,0,884},{10,0,884},{0,64,0},{0,64,0},{0,64,0},{0,31,0},{0,25,320},{0,25,320},{17,127,3702},{13,111,1317},{17,80,1945}, +{11,74,1374},{6,127,5788},{0,90,1681},{0,75,18},{0,59,2537},{0,70,7631},{0,55,3952},{29,127,1650},{25,101,5},{27,78,125},{23,71,306},{75,0,5419},{0,90,1681},{0,75,18},{0,59,2537},{127,13,5419},{0,59,2537},{13,122,1252},{13,122,1252},{13,122,1252},{13,66,1252},{0,112,1152},{0,72,5},{0,72,5},{0,45,164},{0,51,2291},{0,43,992},{25,97,0},{25,97,0},{25,97,0},{25,61,0},{55,0,1152}, +{3,70,1},{3,70,1},{0,45,164},{112,0,1152},{0,45,164},{93,0,1568},{23,102,1},{35,77,1},{0,75,18},{93,0,1568},{126,32,1568},{0,75,18},{0,63,1568},{126,32,1568},{0,63,1568},{12,0,1252},{12,0,1252},{12,0,1252},{12,0,1252},{0,75,0},{0,75,0},{0,75,0},{0,37,0},{0,31,464},{0,31,464},{23,127,4370},{16,114,1661},{19,85,2353},{14,77,1674},{12,127,6128},{0,99,1621},{2,80,18}, +{0,62,2397},{0,73,7815},{0,60,3858},{32,127,1702},{29,105,5},{31,82,125},{27,75,306},{80,1,5419},{0,99,1617},{2,80,14},{0,62,2393},{126,19,5419},{0,62,2393},{15,127,1572},{15,127,1572},{15,127,1572},{15,71,1568},{1,122,1152},{1,79,17},{1,79,17},{0,50,121},{0,54,2403},{0,46,996},{29,101,0},{29,101,0},{29,101,0},{29,64,0},{61,0,1152},{7,74,1},{7,74,1},{0,50,117},{124,0,1152}, +{0,50,117},{99,0,1568},{27,106,1},{39,81,1},{0,80,5},{99,0,1568},{126,38,1568},{0,80,5},{0,66,1570},{126,38,1568},{0,66,1570},{15,0,1568},{15,0,1568},{15,0,1568},{15,0,1568},{1,86,0},{1,86,0},{1,86,0},{1,43,0},{0,34,544},{0,34,544},{26,127,4586},{20,118,1661},{23,89,2353},{18,81,1674},{17,127,6275},{3,102,1617},{6,84,18},{1,67,2355},{0,81,7401},{0,64,3371},{38,127,1766}, +{33,109,5},{35,86,125},{31,79,306},{86,1,5419},{0,105,1577},{6,84,14},{0,66,2259},{126,25,5419},{0,66,2259},{20,127,1585},{20,127,1585},{20,127,1585},{19,75,1568},{5,126,1152},{5,83,17},{5,83,17},{4,54,121},{0,60,2155},{0,51,682},{33,105,0},{33,105,0},{33,105,0},{33,68,0},{66,1,1152},{11,78,1},{11,78,1},{0,55,80},{126,5,1152},{0,55,80},{105,0,1568},{31,110,1},{43,85,1}, +{0,84,1},{105,0,1568},{126,44,1568},{0,84,1},{0,70,1570},{126,44,1568},{0,70,1570},{19,0,1568},{19,0,1568},{19,0,1568},{19,0,1568},{5,90,0},{5,90,0},{5,90,0},{5,47,0},{0,43,388},{0,43,388},{32,127,4866},{25,123,1659},{27,93,2355},{23,86,1670},{23,127,6489},{8,107,1615},{10,88,18},{5,71,2353},{0,87,7039},{0,70,2897},{44,127,1865},{37,113,6},{40,91,122},{36,84,305},{93,0,5419}, +{2,111,1569},{10,88,17},{0,72,2124},{126,32,5419},{0,72,2124},{24,127,1619},{24,127,1619},{24,127,1619},{24,79,1570},{10,127,1161},{10,88,14},{10,88,14},{8,58,122},{0,67,1905},{0,57,409},{38,109,1},{38,109,1},{38,109,1},{37,73,1},{73,0,1152},{15,83,1},{15,83,1},{0,59,41},{126,12,1152},{0,59,41},{112,0,1568},{35,115,1},{48,89,0},{4,89,0},{112,0,1568},{127,50,1568},{4,89,0}, +{0,75,1568},{127,50,1568},{0,75,1568},{23,0,1570},{23,0,1570},{23,0,1570},{23,0,1570},{10,93,1},{10,93,1},{10,93,1},{10,51,1},{0,51,232},{0,51,232},{35,127,5154},{29,127,1659},{31,97,2355},{27,90,1670},{26,127,6689},{12,111,1615},{14,92,18},{9,75,2353},{0,93,6751},{0,74,2541},{49,127,1955},{41,117,6},{44,95,122},{40,88,305},{99,0,5419},{6,115,1569},{14,92,17},{0,75,2020},{126,38,5419}, +{0,75,2020},{29,127,1650},{29,127,1650},{29,127,1650},{28,83,1570},{15,127,1179},{14,92,14},{14,92,14},{12,62,122},{0,76,1713},{0,63,225},{42,113,1},{42,113,1},{42,113,1},{41,77,1},{79,0,1152},{19,87,1},{19,87,1},{0,64,20},{127,17,1152},{0,64,20},{118,0,1568},{39,119,1},{52,93,0},{8,93,0},{118,0,1568},{127,56,1568},{8,93,0},{0,79,1568},{127,56,1568},{0,79,1568},{27,0,1570}, +{27,0,1570},{27,0,1570},{27,0,1570},{14,97,1},{14,97,1},{14,97,1},{14,55,1},{0,57,136},{0,57,136},{41,127,5426},{33,127,1711},{35,101,2355},{31,94,1670},{32,127,6905},{16,115,1615},{18,96,18},{13,79,2353},{0,102,6483},{0,79,2241},{52,127,2075},{45,121,6},{48,99,122},{44,92,305},{105,0,5419},{10,119,1569},{18,96,17},{0,80,1929},{126,44,5419},{0,80,1929},{33,127,1707},{33,127,1707},{33,127,1707}, +{32,87,1570},{20,127,1209},{18,96,14},{18,96,14},{15,66,125},{0,81,1526},{0,67,97},{46,117,1},{46,117,1},{46,117,1},{45,81,1},{85,0,1152},{23,91,1},{23,91,1},{0,69,4},{127,23,1152},{0,69,4},{124,0,1568},{43,123,1},{56,97,0},{12,97,0},{124,0,1568},{127,62,1568},{12,97,0},{0,83,1568},{127,62,1568},{0,83,1568},{31,0,1570},{31,0,1570},{31,0,1570},{31,0,1570},{18,101,1}, +{18,101,1},{18,101,1},{18,59,1},{0,64,65},{0,64,65},{44,127,5762},{38,127,1811},{39,105,2355},{35,98,1670},{38,127,7153},{20,119,1615},{22,100,18},{17,83,2353},{0,108,6243},{0,83,2009},{58,127,2195},{49,125,6},{52,103,122},{48,96,305},{111,0,5419},{14,123,1569},{22,100,17},{0,85,1856},{127,49,5419},{0,85,1856},{38,127,1762},{38,127,1762},{38,127,1762},{36,91,1570},{26,127,1265},{22,100,14},{22,100,14}, +{19,70,125},{0,87,1398},{0,73,25},{50,121,1},{50,121,1},{50,121,1},{49,85,1},{91,0,1152},{27,95,1},{27,95,1},{0,73,0},{127,29,1152},{0,73,0},{127,5,1568},{47,127,1},{60,101,0},{16,101,0},{127,5,1568},{126,68,1568},{16,101,0},{0,87,1568},{126,68,1568},{0,87,1568},{35,0,1570},{35,0,1570},{35,0,1570},{35,0,1570},{22,105,1},{22,105,1},{22,105,1},{22,63,1},{0,70,25}, +{0,70,25},{52,127,6088},{43,127,2009},{44,110,2353},{39,102,1674},{44,127,7451},{24,123,1617},{27,105,18},{22,88,2355},{0,113,5999},{0,89,1811},{65,127,2385},{54,127,25},{56,107,125},{52,100,306},{118,0,5419},{19,127,1569},{27,105,14},{0,89,1762},{127,56,5419},{0,89,1762},{42,127,1856},{42,127,1856},{42,127,1856},{40,96,1568},{30,127,1344},{26,104,17},{26,104,17},{24,75,122},{0,96,1281},{1,78,6},{54,126,0}, +{54,126,0},{54,126,0},{54,89,0},{98,0,1152},{32,99,1},{32,99,1},{6,77,1},{127,36,1152},{6,77,1},{127,19,1568},{54,127,25},{64,105,1},{21,105,1},{127,19,1568},{127,74,1568},{21,105,1},{0,91,1570},{127,74,1568},{0,91,1570},{40,0,1568},{40,0,1568},{40,0,1568},{40,0,1568},{26,111,0},{26,111,0},{26,111,0},{26,67,0},{0,79,1},{0,79,1},{55,127,6416},{48,127,2241},{48,114,2353}, +{43,106,1674},{49,127,7696},{28,127,1617},{31,109,18},{26,92,2355},{0,122,5827},{0,94,1711},{68,127,2521},{60,127,97},{60,111,125},{56,104,306},{124,0,5419},{25,127,1601},{31,109,14},{0,94,1707},{127,62,5419},{0,94,1707},{47,127,1929},{47,127,1929},{47,127,1929},{44,100,1568},{35,127,1414},{30,108,17},{30,108,17},{28,79,122},{0,102,1209},{5,82,6},{58,127,4},{58,127,4},{58,127,4},{58,93,0},{104,0,1152}, +{36,103,1},{36,103,1},{10,81,1},{127,42,1152},{10,81,1},{127,31,1568},{63,127,65},{68,109,1},{25,109,1},{127,31,1568},{127,80,1568},{25,109,1},{0,95,1570},{127,80,1568},{0,95,1570},{44,0,1568},{44,0,1568},{44,0,1568},{44,0,1568},{30,115,0},{30,115,0},{30,115,0},{30,71,0},{4,83,1},{4,83,1},{61,127,6800},{53,127,2541},{52,118,2353},{47,110,1674},{52,127,7996},{34,127,1665},{35,113,18}, +{30,96,2355},{0,126,5709},{0,98,1659},{74,127,2705},{64,127,225},{65,115,122},{60,108,306},{127,5,5419},{34,127,1665},{35,113,14},{0,98,1650},{126,68,5419},{0,98,1650},{52,127,2020},{52,127,2020},{52,127,2020},{48,104,1568},{41,127,1510},{34,112,17},{34,112,17},{32,83,122},{0,108,1169},{9,86,6},{63,126,20},{63,126,20},{63,126,20},{62,97,0},{110,0,1152},{40,107,1},{40,107,1},{14,85,1},{126,48,1152}, +{14,85,1},{127,43,1568},{70,127,136},{72,113,1},{29,113,1},{127,43,1568},{127,86,1568},{29,113,1},{0,99,1570},{127,86,1568},{0,99,1570},{48,0,1568},{48,0,1568},{48,0,1568},{48,0,1568},{34,119,0},{34,119,0},{34,119,0},{34,75,0},{8,87,1},{8,87,1},{65,127,7186},{57,127,2897},{56,122,2353},{51,114,1674},{58,127,8300},{40,127,1809},{39,117,18},{34,100,2355},{5,127,5791},{4,102,1659},{79,127,2875}, +{70,127,409},{69,119,122},{63,114,310},{127,18,5419},{43,127,1777},{39,117,14},{0,103,1619},{126,74,5419},{0,103,1619},{55,127,2124},{55,127,2124},{55,127,2124},{52,108,1568},{44,127,1634},{38,116,17},{38,116,17},{36,87,122},{1,115,1153},{13,90,6},{68,127,41},{68,127,41},{68,127,41},{66,101,1},{115,1,1152},{44,111,1},{44,111,1},{18,89,1},{126,54,1152},{18,89,1},{127,56,1568},{76,127,232},{76,117,1}, +{33,117,1},{127,56,1568},{127,92,1568},{33,117,1},{0,103,1570},{127,92,1568},{0,103,1570},{52,0,1568},{52,0,1568},{52,0,1568},{52,0,1568},{38,123,0},{38,123,0},{38,123,0},{38,79,0},{12,91,1},{12,91,1},{68,127,7650},{63,127,3371},{60,126,2355},{56,119,1670},{65,127,8695},{46,127,2083},{43,121,18},{38,104,2353},{14,127,6049},{6,107,1661},{82,127,3112},{76,127,682},{73,123,121},{67,117,305},{127,31,5419}, +{51,127,1977},{43,121,17},{0,107,1585},{127,80,5419},{0,107,1585},{61,127,2259},{61,127,2259},{61,127,2259},{57,112,1570},{52,127,1755},{43,121,14},{43,121,14},{40,91,125},{6,119,1153},{18,94,5},{72,127,80},{72,127,80},{72,127,80},{70,106,0},{122,0,1152},{48,116,1},{48,116,1},{21,94,0},{126,61,1152},{21,94,0},{127,69,1568},{84,127,388},{80,122,0},{37,122,0},{127,69,1568},{126,99,1568},{37,122,0}, +{0,108,1568},{126,99,1568},{0,108,1568},{56,0,1570},{56,0,1570},{56,0,1570},{56,0,1570},{43,126,1},{43,126,1},{43,126,1},{42,84,1},{16,96,1},{16,96,1},{74,127,8066},{67,127,3858},{65,127,2397},{60,123,1670},{68,127,9035},{51,127,2458},{47,125,18},{42,108,2353},{22,127,6379},{10,111,1661},{88,127,3320},{79,127,977},{77,127,121},{71,121,305},{127,43,5419},{60,127,2185},{47,125,17},{0,112,1572},{127,86,5419}, +{0,112,1572},{65,127,2393},{65,127,2393},{65,127,2393},{61,116,1570},{55,127,1891},{47,125,14},{47,125,14},{44,95,125},{10,123,1153},{22,98,5},{77,127,117},{77,127,117},{77,127,117},{74,110,0},{127,2,1152},{52,120,1},{52,120,1},{25,98,0},{127,66,1152},{25,98,0},{127,81,1568},{93,127,544},{84,126,0},{41,126,0},{127,81,1568},{126,105,1568},{41,126,0},{0,112,1568},{126,105,1568},{0,112,1568},{60,0,1570}, +{60,0,1570},{60,0,1570},{60,0,1570},{47,127,5},{47,127,5},{47,127,5},{46,88,1},{20,100,1},{20,100,1},{79,127,7660},{72,127,3952},{68,127,2537},{64,125,1620},{74,127,8515},{57,127,2310},{52,127,18},{47,110,1945},{28,127,5939},{16,114,1317},{91,127,2984},{84,127,992},{82,127,164},{76,123,201},{127,53,4803},{64,127,1931},{54,126,5},{5,114,1252},{126,91,4803},{5,114,1252},{68,127,2537},{68,127,2537},{68,127,2537}, +{64,120,1569},{61,127,2043},{52,127,18},{52,127,18},{48,99,125},{14,127,1153},{26,102,5},{82,127,164},{82,127,164},{82,127,164},{78,114,0},{127,14,1152},{56,124,1},{56,124,1},{29,102,0},{127,72,1152},{29,102,0},{127,89,1250},{96,127,464},{90,127,0},{51,127,0},{127,89,1250},{125,109,1250},{51,127,0},{0,114,1252},{125,109,1250},{0,114,1252},{64,0,1568},{64,0,1568},{64,0,1568},{64,0,1568},{52,127,18}, +{52,127,18},{52,127,18},{50,92,1},{24,104,1},{24,104,1},{82,127,7060},{76,127,3898},{74,127,2697},{68,126,1576},{79,127,7756},{60,127,2062},{57,127,66},{50,113,1461},{37,127,5307},{21,116,925},{97,127,2504},{90,127,896},{85,127,232},{80,125,96},{127,60,4056},{70,127,1563},{60,127,5},{13,116,884},{127,94,4056},{13,116,884},{74,127,2697},{74,127,2697},{74,127,2697},{68,124,1569},{65,127,2214},{57,127,66},{57,127,66}, +{52,103,125},{22,127,1186},{30,106,5},{85,127,232},{85,127,232},{85,127,232},{82,118,0},{127,27,1152},{62,126,5},{62,126,5},{33,106,0},{126,78,1152},{33,106,0},{127,95,882},{102,127,320},{96,127,0},{63,127,0},{127,95,882},{127,111,882},{63,127,0},{0,116,884},{127,111,882},{0,116,884},{68,0,1568},{68,0,1568},{68,0,1568},{68,0,1568},{56,127,45},{56,127,45},{56,127,45},{54,96,1},{28,108,1}, +{28,108,1},{85,127,6483},{79,127,3828},{79,127,2867},{73,127,1574},{82,127,6979},{67,127,1846},{63,127,181},{56,116,1002},{43,127,4714},{29,118,566},{100,127,2034},{93,127,822},{91,127,306},{86,125,26},{127,69,3318},{76,127,1233},{70,127,32},{20,119,545},{126,99,3318},{20,119,545},{79,127,2867},{79,127,2867},{79,127,2867},{73,127,1574},{71,127,2425},{63,127,181},{63,127,181},{57,108,122},{31,127,1273},{34,111,6},{91,127,306}, +{91,127,306},{91,127,306},{87,122,1},{127,40,1152},{70,127,32},{70,127,32},{39,110,1},{126,85,1152},{39,110,1},{127,101,545},{108,127,193},{102,127,1},{76,127,0},{127,101,545},{127,114,545},{76,127,0},{0,119,545},{127,114,545},{0,119,545},{72,0,1570},{72,0,1570},{72,0,1570},{72,0,1570},{61,127,80},{61,127,80},{61,127,80},{59,100,0},{33,112,1},{33,112,1},{88,127,6059},{84,127,3891},{82,127,3035}, +{76,127,1634},{85,127,6411},{70,127,1754},{67,127,341},{61,118,678},{51,127,4330},{34,120,322},{103,127,1698},{98,127,782},{97,127,394},{90,127,2},{127,76,2753},{84,127,1018},{76,127,80},{28,121,313},{126,103,2753},{28,121,313},{82,127,3035},{82,127,3035},{82,127,3035},{76,127,1634},{77,127,2641},{67,127,341},{67,127,341},{61,112,122},{37,127,1401},{38,115,6},{97,127,394},{97,127,394},{97,127,394},{91,126,1},{127,53,1152}, +{76,127,80},{76,127,80},{43,114,1},{126,91,1152},{43,114,1},{127,107,313},{111,127,116},{108,127,1},{89,127,0},{127,107,313},{127,117,313},{89,127,0},{0,121,313},{127,117,313},{0,121,313},{76,0,1570},{76,0,1570},{76,0,1570},{76,0,1570},{65,127,125},{65,127,125},{65,127,125},{63,104,0},{37,116,1},{37,116,1},{94,127,5691},{88,127,3919},{88,127,3243},{81,127,1739},{88,127,5947},{76,127,1722},{73,127,557}, +{64,120,426},{57,127,3994},{39,122,150},{106,127,1434},{102,127,770},{100,127,482},{95,127,17},{127,86,2273},{90,127,850},{84,127,170},{36,123,145},{127,107,2273},{36,123,145},{88,127,3243},{88,127,3243},{88,127,3243},{81,127,1739},{79,127,2835},{73,127,557},{73,127,557},{65,115,122},{46,127,1561},{42,119,6},{100,127,482},{100,127,482},{100,127,482},{95,127,17},{127,64,1152},{84,127,170},{84,127,170},{47,118,1},{126,97,1152}, +{47,118,1},{127,113,145},{116,127,53},{114,127,0},{101,127,0},{127,113,145},{127,120,145},{101,127,0},{0,123,145},{127,120,145},{0,123,145},{80,0,1570},{80,0,1570},{80,0,1570},{80,0,1570},{71,127,181},{71,127,181},{71,127,181},{67,108,1},{41,120,1},{41,120,1},{97,127,5379},{92,127,3991},{91,127,3427},{87,127,1907},{94,127,5539},{79,127,1783},{79,127,822},{69,122,254},{64,127,3745},{44,125,42},{111,127,1210}, +{106,127,782},{106,127,586},{99,127,82},{127,93,1878},{96,127,746},{90,127,274},{44,125,41},{126,111,1878},{44,125,41},{91,127,3427},{91,127,3427},{91,127,3427},{87,127,1907},{85,127,3051},{79,127,822},{79,127,822},{69,119,122},{54,127,1798},{46,123,6},{106,127,586},{106,127,586},{106,127,586},{99,127,82},{127,76,1152},{90,127,274},{90,127,274},{51,122,1},{126,103,1152},{51,122,1},{127,119,41},{122,127,13},{120,127,0}, +{113,127,0},{127,119,41},{127,123,41},{113,127,0},{0,125,41},{127,123,41},{0,125,41},{84,0,1570},{84,0,1570},{84,0,1570},{84,0,1570},{74,127,245},{74,127,245},{74,127,245},{71,112,1},{45,124,1},{45,124,1},{100,127,5128},{97,127,4080},{97,127,3680},{90,127,2152},{97,127,5200},{87,127,1964},{84,127,1208},{73,126,145},{73,127,3580},{51,127,5},{114,127,1062},{111,127,797},{111,127,697},{105,127,212},{127,102,1536}, +{102,127,708},{99,127,424},{54,127,0},{127,115,1536},{54,127,0},{97,127,3680},{97,127,3680},{97,127,3680},{90,127,2152},{91,127,3328},{84,127,1208},{84,127,1208},{74,124,121},{63,127,2089},{51,127,5},{111,127,697},{111,127,697},{111,127,697},{105,127,212},{127,90,1152},{99,127,424},{99,127,424},{54,127,0},{127,109,1152},{54,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0}, +{0,127,0},{127,127,0},{0,127,0},{89,0,1568},{89,0,1568},{89,0,1568},{89,0,1568},{79,127,320},{79,127,320},{79,127,320},{75,117,0},{51,127,5},{51,127,5},{103,127,4416},{100,127,3580},{100,127,3256},{96,127,2040},{100,127,4372},{90,127,1736},{87,127,1128},{79,126,57},{76,127,2956},{57,127,37},{117,127,738},{114,127,566},{114,127,485},{108,127,148},{127,107,1067},{108,127,484},{102,127,292},{66,127,0},{127,117,1067}, +{66,127,0},{100,127,3256},{100,127,3256},{100,127,3256},{96,127,2040},{94,127,2852},{87,127,1128},{87,127,1128},{78,125,45},{70,127,1739},{57,127,37},{114,127,485},{114,127,485},{114,127,485},{108,127,148},{127,96,800},{102,127,292},{102,127,292},{66,127,0},{127,112,800},{66,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{93,0,1568}, +{93,0,1568},{93,0,1568},{93,0,1568},{85,127,400},{85,127,400},{85,127,400},{79,121,0},{57,127,37},{57,127,37},{106,127,3784},{103,127,3136},{103,127,2880},{99,127,1924},{103,127,3648},{93,127,1564},{92,127,1078},{82,127,8},{81,127,2480},{64,127,90},{117,127,482},{117,127,362},{117,127,313},{113,127,97},{127,110,683},{111,127,321},{108,127,180},{78,127,0},{126,119,683},{78,127,0},{103,127,2880},{103,127,2880},{103,127,2880}, +{99,127,1924},{97,127,2448},{92,127,1078},{92,127,1078},{83,126,8},{76,127,1451},{64,127,90},{117,127,313},{117,127,313},{117,127,313},{113,127,97},{127,102,512},{108,127,180},{108,127,180},{78,127,0},{127,115,512},{78,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{97,0,1568},{97,0,1568},{97,0,1568},{97,0,1568},{88,127,500}, +{88,127,500},{88,127,500},{83,125,0},{64,127,90},{64,127,90},{109,127,3232},{106,127,2748},{106,127,2552},{102,127,1832},{106,127,3028},{99,127,1420},{96,127,1048},{87,127,4},{87,127,2032},{73,127,170},{120,127,262},{120,127,206},{118,127,180},{116,127,53},{127,115,384},{116,127,179},{113,127,106},{90,127,0},{127,121,384},{90,127,0},{106,127,2552},{106,127,2552},{106,127,2552},{102,127,1832},{103,127,2112},{96,127,1048},{96,127,1048}, +{87,127,4},{81,127,1260},{73,127,170},{118,127,180},{118,127,180},{118,127,180},{116,127,53},{127,108,288},{113,127,106},{113,127,106},{90,127,0},{127,118,288},{90,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{101,0,1568},{101,0,1568},{101,0,1568},{101,0,1568},{94,127,596},{94,127,596},{94,127,596},{87,127,4},{73,127,170}, +{73,127,170},{0,104,2665},{0,73,274},{0,53,4},{0,45,985},{0,69,5885},{0,46,3677},{0,41,1789},{0,27,4441},{0,31,6341},{0,27,4765},{0,104,2665},{0,73,274},{0,53,4},{0,45,985},{34,0,5885},{0,46,3677},{0,41,1789},{0,27,4441},{69,0,5885},{0,27,4441},{0,50,0},{0,50,0},{0,50,0},{0,24,1},{0,24,545},{0,19,193},{0,19,193},{0,12,337},{0,11,598},{0,10,387},{0,50,0}, +{0,50,0},{0,50,0},{0,24,1},{12,0,545},{0,19,193},{0,19,193},{0,12,337},{24,0,545},{0,12,337},{51,0,2665},{0,73,274},{0,53,4},{0,45,985},{51,0,2665},{104,0,2665},{0,45,985},{0,35,2665},{104,0,2665},{0,35,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,117,2665},{0,81,160},{1,57,12}, +{0,50,872},{0,78,6669},{0,51,3898},{0,46,1825},{0,33,4865},{0,34,7249},{0,30,5277},{0,117,2665},{0,81,160},{1,57,8},{0,50,872},{39,0,6669},{0,51,3898},{0,46,1825},{0,33,4865},{78,0,6669},{0,33,4865},{0,62,0},{0,62,0},{0,62,0},{0,30,1},{0,30,841},{0,25,305},{0,25,305},{0,13,514},{0,14,926},{0,13,595},{0,62,0},{0,62,0},{0,62,0},{0,30,1},{15,0,841}, +{0,25,305},{0,25,305},{0,13,514},{30,0,841},{0,13,514},{57,0,2665},{0,81,160},{3,57,0},{0,50,872},{57,0,2665},{117,0,2665},{0,50,872},{0,39,2665},{117,0,2665},{0,39,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,127,2669},{0,87,80},{1,63,60},{0,53,740},{0,86,7538},{0,57,4178},{0,49,1889}, +{0,36,5333},{0,40,8241},{0,33,5845},{0,127,2669},{0,87,80},{2,61,52},{0,53,740},{42,1,7538},{0,57,4178},{0,49,1889},{0,36,5333},{86,0,7538},{0,36,5333},{0,74,0},{0,74,0},{0,74,0},{0,36,1},{0,36,1201},{0,28,445},{0,28,445},{0,18,745},{0,17,1326},{0,15,861},{0,74,0},{0,74,0},{0,74,0},{0,36,1},{18,0,1201},{0,28,445},{0,28,445},{0,18,745},{36,0,1201}, +{0,18,745},{63,0,2665},{0,87,80},{7,61,0},{0,53,740},{63,0,2665},{127,1,2665},{0,53,740},{0,43,2665},{127,1,2665},{0,43,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,127,2797},{0,93,32},{2,65,154},{0,59,628},{0,94,8493},{0,63,4490},{0,54,1965},{0,39,5849},{0,43,9333},{0,36,6469},{3,127,2761}, +{0,93,32},{3,66,126},{0,59,628},{46,0,8493},{0,63,4490},{0,54,1965},{0,39,5849},{94,0,8493},{0,39,5849},{0,86,0},{0,86,0},{0,86,0},{0,42,1},{0,42,1625},{0,34,605},{0,34,605},{0,21,1009},{0,19,1781},{0,18,1161},{0,86,0},{0,86,0},{0,86,0},{0,42,1},{21,0,1625},{0,34,605},{0,34,605},{0,21,1009},{42,0,1625},{0,21,1009},{69,0,2665},{0,93,32},{11,64,1}, +{0,59,628},{69,0,2665},{127,7,2665},{0,59,628},{0,47,2665},{127,7,2665},{0,47,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,127,3157},{0,102,2},{2,71,304},{0,62,514},{0,103,9669},{0,67,4865},{0,60,2107},{0,42,6485},{0,46,10689},{0,39,7245},{6,127,3029},{0,102,2},{5,71,260},{0,62,514},{50,1,9669}, +{0,67,4865},{0,60,2107},{0,42,6485},{103,0,9669},{0,42,6485},{0,100,0},{0,100,0},{0,100,0},{0,49,0},{0,50,2178},{0,40,820},{0,40,820},{0,24,1348},{0,22,2392},{0,21,1556},{0,100,0},{0,100,0},{0,100,0},{0,49,0},{24,1,2178},{0,40,820},{0,40,820},{0,24,1348},{50,0,2178},{0,24,1348},{76,0,2665},{0,102,2},{15,69,0},{0,62,514},{76,0,2665},{126,14,2665},{0,62,514}, +{0,51,2665},{126,14,2665},{0,51,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,127,3509},{2,108,32},{4,76,424},{1,67,473},{0,115,9669},{0,73,4529},{0,64,1649},{0,45,6209},{0,51,10919},{0,45,7109},{12,127,3141},{4,106,2},{9,75,260},{1,67,469},{56,1,9669},{0,73,4529},{0,64,1649},{0,45,6209},{115,0,9669}, +{0,45,6209},{2,108,32},{2,108,32},{2,108,32},{2,54,32},{0,62,2178},{0,46,628},{0,46,628},{0,27,1184},{0,28,2520},{0,26,1502},{4,104,0},{4,104,0},{4,104,0},{4,53,0},{30,1,2178},{0,46,628},{0,46,628},{0,27,1184},{62,0,2178},{0,27,1184},{81,0,2665},{2,108,0},{19,73,0},{0,66,421},{81,0,2665},{126,20,2665},{0,66,421},{0,55,2665},{126,20,2665},{0,55,2665},{2,0,32}, +{2,0,32},{2,0,32},{2,0,32},{0,12,0},{0,12,0},{0,12,0},{0,6,0},{0,5,10},{0,5,10},{12,127,3989},{4,114,130},{7,79,616},{3,72,525},{0,127,9669},{0,81,4178},{0,67,1265},{0,50,5950},{0,57,11199},{0,49,7029},{17,127,3253},{8,110,2},{13,79,260},{5,71,469},{62,1,9669},{0,81,4178},{0,67,1265},{0,50,5950},{127,0,9669},{0,50,5950},{4,116,128},{4,116,128},{4,116,128}, +{4,59,128},{0,74,2178},{0,54,442},{0,54,442},{0,33,1040},{0,31,2676},{0,30,1460},{8,108,0},{8,108,0},{8,108,0},{8,57,0},{36,1,2178},{0,54,442},{0,54,442},{0,33,1040},{74,0,2178},{0,33,1040},{87,0,2665},{6,112,0},{23,77,0},{0,72,325},{87,0,2665},{126,26,2665},{0,72,325},{0,59,2665},{126,26,2665},{0,59,2665},{4,0,128},{4,0,128},{4,0,128},{4,0,128},{0,24,0}, +{0,24,0},{0,24,0},{0,12,0},{0,8,50},{0,8,50},{15,127,4613},{6,118,304},{9,84,880},{4,76,645},{3,127,9761},{0,87,3898},{0,73,913},{0,56,5686},{0,63,11511},{0,53,6939},{20,127,3401},{12,114,2},{17,83,260},{9,75,469},{68,0,9669},{0,87,3898},{0,73,913},{0,56,5686},{127,6,9669},{0,56,5686},{6,124,288},{6,124,288},{6,124,288},{6,63,289},{0,86,2178},{0,60,306},{0,60,306}, +{0,36,900},{0,37,2852},{0,34,1452},{12,112,0},{12,112,0},{12,112,0},{12,61,0},{42,1,2178},{0,60,306},{0,60,306},{0,36,900},{86,0,2178},{0,36,900},{93,0,2665},{10,116,0},{27,81,0},{0,77,260},{93,0,2665},{126,32,2665},{0,77,260},{0,63,2665},{126,32,2665},{0,63,2665},{6,0,288},{6,0,288},{6,0,288},{6,0,288},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{0,14,106}, +{0,14,106},{17,127,5446},{9,124,575},{12,90,1267},{8,80,862},{7,127,10073},{0,96,3625},{0,79,594},{0,59,5393},{0,70,11905},{0,57,6894},{26,127,3570},{16,119,3},{21,87,259},{14,80,470},{75,0,9669},{0,96,3625},{0,79,594},{0,59,5393},{127,13,9669},{0,59,5393},{9,127,558},{9,127,558},{9,127,558},{8,69,545},{0,100,2178},{0,67,185},{0,67,185},{0,42,754},{0,43,3090},{0,38,1478},{17,115,1}, +{17,115,1},{17,115,1},{16,65,1},{49,0,2178},{0,67,185},{0,67,185},{0,42,754},{100,0,2178},{0,42,754},{100,0,2665},{15,120,0},{32,85,1},{0,82,193},{100,0,2665},{127,38,2665},{0,82,193},{0,67,2665},{127,38,2665},{0,67,2665},{8,0,545},{8,0,545},{8,0,545},{8,0,545},{0,50,0},{0,50,0},{0,50,0},{0,24,1},{0,19,193},{0,19,193},{20,127,6378},{12,127,915},{15,93,1695}, +{9,84,1118},{12,127,10506},{0,102,3401},{0,84,366},{0,65,5186},{0,76,12289},{0,61,6870},{32,127,3738},{20,123,3},{25,91,259},{18,84,470},{80,1,9669},{0,102,3401},{0,84,366},{0,65,5186},{126,19,9669},{0,65,5186},{12,127,914},{12,127,914},{12,127,914},{10,74,841},{0,112,2178},{0,76,97},{0,76,97},{0,45,650},{0,51,3317},{0,43,1514},{21,119,1},{21,119,1},{21,119,1},{20,69,1},{55,0,2178}, +{0,76,97},{0,76,97},{0,45,650},{112,0,2178},{0,45,650},{106,0,2665},{19,124,0},{36,89,1},{0,86,130},{106,0,2665},{127,44,2665},{0,86,130},{0,71,2665},{127,44,2665},{0,71,2665},{10,0,841},{10,0,841},{10,0,841},{10,0,841},{0,62,0},{0,62,0},{0,62,0},{0,30,1},{0,25,305},{0,25,305},{23,127,7454},{15,127,1431},{17,97,2214},{11,89,1438},{15,127,11102},{0,108,3209},{0,90,198}, +{0,69,4913},{0,81,12639},{0,65,6875},{38,127,3938},{24,127,3},{29,95,259},{22,88,470},{86,1,9669},{0,108,3209},{0,90,198},{0,69,4913},{126,25,9669},{0,69,4913},{15,127,1382},{15,127,1382},{15,127,1382},{12,79,1201},{0,124,2178},{0,84,37},{0,84,37},{0,50,549},{0,54,3565},{0,46,1598},{25,123,1},{25,123,1},{25,123,1},{24,73,1},{61,0,2178},{0,84,37},{0,84,37},{0,50,549},{124,0,2178}, +{0,50,549},{112,0,2665},{24,127,2},{40,93,1},{0,91,89},{112,0,2665},{127,50,2665},{0,91,89},{0,75,2665},{127,50,2665},{0,75,2665},{12,0,1201},{12,0,1201},{12,0,1201},{12,0,1201},{0,74,0},{0,74,0},{0,74,0},{0,36,1},{0,28,445},{0,28,445},{26,127,8674},{18,127,2131},{19,102,2786},{13,93,1839},{17,127,11833},{0,113,3038},{0,95,86},{0,72,4685},{0,84,13079},{0,70,6909},{41,127,4130}, +{30,127,35},{33,99,259},{26,92,470},{92,1,9669},{0,113,3038},{0,95,86},{0,72,4685},{126,31,9669},{0,72,4685},{17,127,1941},{17,127,1941},{17,127,1941},{14,84,1625},{3,127,2222},{0,90,5},{0,90,5},{0,56,445},{0,60,3861},{0,51,1674},{29,127,1},{29,127,1},{29,127,1},{28,77,1},{66,1,2178},{0,90,5},{0,90,5},{0,56,445},{126,5,2178},{0,56,445},{118,0,2665},{31,127,20},{44,97,1}, +{0,95,50},{118,0,2665},{127,56,2665},{0,95,50},{0,79,2665},{127,56,2665},{0,79,2665},{14,0,1625},{14,0,1625},{14,0,1625},{14,0,1625},{0,86,0},{0,86,0},{0,86,0},{0,42,1},{0,34,605},{0,34,605},{32,127,10209},{21,127,3140},{22,108,3525},{15,98,2360},{20,127,12902},{0,122,2885},{0,101,21},{0,78,4450},{0,93,13598},{0,73,6982},{47,127,4373},{34,127,134},{38,104,260},{30,96,469},{99,0,9669}, +{0,122,2885},{0,101,21},{0,78,4450},{126,38,9669},{0,78,4450},{20,127,2717},{20,127,2717},{20,127,2717},{16,90,2180},{6,127,2420},{0,98,1},{0,98,1},{0,62,353},{0,64,4230},{0,57,1814},{34,126,13},{34,126,13},{34,126,13},{33,81,1},{73,0,2178},{2,96,1},{2,96,1},{0,62,353},{126,12,2178},{0,62,353},{125,0,2665},{40,127,74},{48,102,0},{0,101,20},{125,0,2665},{126,63,2665},{0,101,20}, +{0,84,2665},{126,63,2665},{0,84,2665},{16,0,2180},{16,0,2180},{16,0,2180},{16,0,2180},{0,100,0},{0,100,0},{0,100,0},{0,49,0},{0,40,820},{0,40,820},{35,127,11582},{25,127,4131},{25,111,4166},{17,103,2825},{26,127,13903},{1,126,2826},{1,105,18},{0,83,4290},{0,96,13969},{0,79,6967},{52,127,4577},{40,127,270},{42,108,260},{34,100,469},{105,0,9669},{1,126,2825},{1,105,17},{0,83,4289},{126,44,9669}, +{0,83,4289},{23,127,3434},{23,127,3434},{23,127,3434},{19,94,2666},{9,127,2709},{1,105,14},{1,105,14},{0,66,275},{0,70,4491},{0,60,1893},{38,127,29},{38,127,29},{38,127,29},{37,85,1},{79,0,2178},{6,100,1},{6,100,1},{0,66,274},{127,17,2178},{0,66,274},{127,7,2665},{46,127,146},{52,106,0},{0,105,8},{127,7,2665},{127,68,2665},{0,105,8},{0,88,2665},{127,68,2665},{0,88,2665},{19,0,2665}, +{19,0,2665},{19,0,2665},{19,0,2665},{1,110,1},{1,110,1},{1,110,1},{0,55,1},{0,43,985},{0,43,985},{38,127,12090},{30,127,4561},{29,115,4166},{21,107,2825},{29,127,14311},{5,127,2910},{5,109,18},{0,86,4166},{0,105,13477},{0,84,6285},{58,127,4833},{46,127,470},{46,112,260},{38,104,469},{111,0,9669},{5,127,2909},{5,109,17},{0,86,4085},{127,49,9669},{0,86,4085},{26,127,3590},{26,127,3590},{26,127,3590}, +{23,98,2666},{12,127,2853},{5,109,14},{5,109,14},{3,69,259},{0,76,4147},{0,64,1475},{44,127,61},{44,127,61},{44,127,61},{41,89,1},{85,0,2178},{10,104,1},{10,104,1},{0,69,202},{127,23,2178},{0,69,202},{127,19,2665},{54,127,260},{56,110,0},{0,110,0},{127,19,2665},{127,74,2665},{0,110,0},{0,92,2665},{127,74,2665},{0,92,2665},{23,0,2665},{23,0,2665},{23,0,2665},{23,0,2665},{5,114,1}, +{5,114,1},{5,114,1},{4,59,1},{0,51,745},{0,51,745},{44,127,12610},{34,127,5039},{33,119,4166},{25,111,2825},{35,127,14719},{11,127,3118},{9,113,18},{4,90,4166},{0,113,13003},{0,87,5661},{61,127,5093},{51,127,736},{50,116,260},{42,108,469},{117,0,9669},{14,127,3073},{9,113,17},{0,89,3929},{127,55,9669},{0,89,3929},{32,127,3726},{32,127,3726},{32,127,3726},{27,102,2666},{17,127,2979},{9,113,14},{9,113,14}, +{7,73,259},{0,84,3784},{0,70,1091},{47,127,97},{47,127,97},{47,127,97},{45,93,1},{91,0,2178},{14,108,1},{14,108,1},{0,75,146},{127,29,2178},{0,75,146},{127,31,2665},{60,127,388},{60,114,0},{3,114,0},{127,31,2665},{127,80,2665},{3,114,0},{0,96,2665},{127,80,2665},{0,96,2665},{27,0,2665},{27,0,2665},{27,0,2665},{27,0,2665},{9,118,1},{9,118,1},{9,118,1},{8,63,1},{0,60,565}, +{0,60,565},{49,127,13154},{40,127,5661},{37,123,4166},{30,116,2823},{41,127,15213},{16,127,3497},{14,118,18},{8,94,4166},{0,116,12489},{0,93,5039},{68,127,5409},{57,127,1091},{54,120,259},{47,113,470},{124,0,9669},{22,127,3341},{14,118,14},{0,95,3726},{127,62,9669},{0,95,3726},{38,127,3929},{38,127,3929},{38,127,3929},{31,107,2665},{23,127,3156},{13,117,17},{13,117,17},{11,77,260},{0,90,3467},{0,76,736},{52,127,146}, +{52,127,146},{52,127,146},{49,98,1},{98,0,2178},{19,112,1},{19,112,1},{0,80,97},{127,36,2178},{0,80,97},{127,45,2665},{67,127,565},{64,119,1},{9,118,1},{127,45,2665},{126,87,2665},{9,118,1},{0,100,2665},{126,87,2665},{0,100,2665},{31,0,2665},{31,0,2665},{31,0,2665},{31,0,2665},{13,123,0},{13,123,0},{13,123,0},{13,67,0},{0,67,388},{0,67,388},{52,127,13734},{43,127,6285},{41,127,4166}, +{34,120,2823},{47,127,15677},{22,127,3905},{18,122,18},{12,98,4166},{0,125,12093},{0,97,4561},{71,127,5701},{60,127,1475},{58,124,259},{51,117,470},{127,5,9669},{31,127,3601},{18,122,14},{0,101,3590},{126,68,9669},{0,101,3590},{41,127,4085},{41,127,4085},{41,127,4085},{35,111,2665},{29,127,3332},{17,121,17},{17,121,17},{15,81,260},{0,99,3211},{0,81,470},{58,127,202},{58,127,202},{58,127,202},{53,102,1},{104,0,2178}, +{23,116,1},{23,116,1},{0,83,61},{127,42,2178},{0,83,61},{127,57,2665},{76,127,745},{68,123,1},{13,122,1},{127,57,2665},{126,93,2665},{13,122,1},{0,104,2665},{126,93,2665},{0,104,2665},{35,0,2665},{35,0,2665},{35,0,2665},{35,0,2665},{17,127,0},{17,127,0},{17,127,0},{17,71,0},{0,73,260},{0,73,260},{58,127,14302},{48,127,6967},{44,127,4290},{38,124,2823},{52,127,16094},{28,127,4409},{22,126,18}, +{16,102,4166},{0,126,11883},{0,102,4131},{77,127,6005},{67,127,1893},{61,127,275},{55,121,470},{127,18,9669},{40,127,3909},{22,126,14},{0,104,3434},{126,74,9669},{0,104,3434},{44,127,4289},{44,127,4289},{44,127,4289},{39,115,2665},{35,127,3540},{21,125,17},{21,125,17},{19,85,260},{0,105,2979},{0,87,270},{61,127,274},{61,127,274},{61,127,274},{57,106,1},{110,0,2178},{27,120,1},{27,120,1},{0,89,29},{126,48,2178}, +{0,89,29},{127,69,2665},{81,127,985},{72,127,1},{17,126,1},{127,69,2665},{126,99,2665},{17,126,1},{0,108,2665},{126,99,2665},{0,108,2665},{39,0,2665},{39,0,2665},{39,0,2665},{39,0,2665},{22,126,8},{22,126,8},{22,126,8},{21,75,0},{0,81,146},{0,81,146},{61,127,13635},{53,127,6982},{49,127,4450},{42,125,2742},{55,127,15195},{34,127,4106},{26,127,21},{19,105,3525},{2,127,10776},{0,106,3140},{79,127,5396}, +{70,127,1814},{65,127,353},{59,122,321},{127,27,8712},{46,127,3462},{29,127,1},{0,107,2717},{126,78,8712},{0,107,2717},{49,127,4450},{49,127,4450},{49,127,4450},{43,119,2665},{38,127,3736},{26,127,21},{26,127,21},{23,89,260},{0,113,2772},{0,93,134},{65,127,353},{65,127,353},{65,127,353},{61,110,1},{115,1,2178},{31,124,1},{31,124,1},{0,93,13},{126,54,2178},{0,93,13},{127,76,2178},{87,127,820},{78,127,0}, +{27,127,0},{127,76,2178},{126,103,2178},{27,127,0},{0,110,2180},{126,103,2178},{0,110,2180},{43,0,2665},{43,0,2665},{43,0,2665},{43,0,2665},{26,127,20},{26,127,20},{26,127,20},{25,79,0},{0,87,74},{0,87,74},{65,127,12750},{57,127,6909},{55,127,4685},{48,126,2678},{61,127,14070},{37,127,3711},{32,127,86},{25,108,2786},{5,127,9739},{0,109,2131},{85,127,4658},{76,127,1674},{71,127,445},{64,123,173},{127,36,7578}, +{51,127,2949},{37,127,5},{0,110,1941},{127,82,7578},{0,110,1941},{55,127,4685},{55,127,4685},{55,127,4685},{48,123,2666},{44,127,3987},{32,127,86},{32,127,86},{28,94,259},{0,119,2571},{0,97,35},{71,127,445},{71,127,445},{71,127,445},{66,114,1},{122,0,2178},{37,127,5},{37,127,5},{0,98,1},{126,61,2178},{0,98,1},{127,83,1625},{93,127,605},{84,127,1},{40,127,0},{127,83,1625},{126,106,1625},{40,127,0}, +{0,113,1625},{126,106,1625},{0,113,1625},{48,0,2665},{48,0,2665},{48,0,2665},{48,0,2665},{32,127,50},{32,127,50},{32,127,50},{30,83,1},{0,96,20},{0,96,20},{68,127,12050},{62,127,6875},{58,127,4913},{52,127,2666},{65,127,13165},{43,127,3423},{37,127,198},{30,110,2214},{11,127,8987},{0,112,1431},{88,127,4082},{79,127,1547},{77,127,549},{68,124,81},{127,43,6661},{57,127,2525},{43,127,37},{0,112,1382},{127,86,6661}, +{0,112,1382},{58,127,4913},{58,127,4913},{58,127,4913},{52,127,2666},{49,127,4197},{37,127,198},{37,127,198},{32,98,259},{0,125,2435},{0,103,3},{77,127,549},{77,127,549},{77,127,549},{70,118,1},{127,2,2178},{43,127,37},{43,127,37},{3,102,1},{127,66,2178},{3,102,1},{127,89,1201},{99,127,445},{90,127,1},{53,127,0},{127,89,1201},{125,109,1201},{53,127,0},{0,115,1201},{125,109,1201},{0,115,1201},{52,0,2665}, +{52,0,2665},{52,0,2665},{52,0,2665},{36,127,89},{36,127,89},{36,127,89},{34,87,1},{0,103,2},{0,103,2},{74,127,11418},{65,127,6870},{62,127,5186},{56,127,2701},{68,127,12313},{46,127,3251},{43,127,366},{34,112,1695},{14,127,8383},{0,115,915},{91,127,3578},{84,127,1514},{79,127,650},{73,126,21},{127,53,5829},{63,127,2165},{51,127,97},{0,115,914},{126,91,5829},{0,115,914},{62,127,5186},{62,127,5186},{62,127,5186}, +{56,127,2701},{55,127,4461},{43,127,366},{43,127,366},{36,102,259},{2,127,2427},{4,107,3},{79,127,650},{79,127,650},{79,127,650},{74,122,1},{127,14,2178},{51,127,97},{51,127,97},{7,106,1},{127,72,2178},{7,106,1},{127,95,841},{102,127,305},{96,127,1},{64,127,0},{127,95,841},{127,111,841},{64,127,0},{0,117,841},{127,111,841},{0,117,841},{56,0,2665},{56,0,2665},{56,0,2665},{56,0,2665},{41,127,130}, +{41,127,130},{41,127,130},{38,91,1},{3,108,0},{3,108,0},{77,127,10830},{69,127,6894},{68,127,5393},{60,127,2786},{71,127,11565},{54,127,3154},{48,127,594},{37,115,1267},{25,127,7825},{3,118,575},{94,127,3146},{87,127,1478},{85,127,754},{77,127,1},{127,60,5082},{70,127,1869},{57,127,185},{0,118,558},{127,94,5082},{0,118,558},{68,127,5393},{68,127,5393},{68,127,5393},{60,127,2786},{58,127,4725},{48,127,594},{48,127,594}, +{40,106,259},{8,127,2587},{8,111,3},{85,127,754},{85,127,754},{85,127,754},{78,126,1},{127,27,2178},{57,127,185},{57,127,185},{11,110,1},{126,78,2178},{11,110,1},{127,101,545},{108,127,193},{102,127,1},{76,127,0},{127,101,545},{127,114,545},{76,127,0},{0,119,545},{127,114,545},{0,119,545},{60,0,2665},{60,0,2665},{60,0,2665},{60,0,2665},{45,127,193},{45,127,193},{45,127,193},{42,95,1},{7,112,0}, +{7,112,0},{79,127,10221},{74,127,6939},{71,127,5686},{64,127,2954},{77,127,10836},{57,127,3109},{54,127,913},{42,117,880},{34,127,7300},{8,120,304},{100,127,2736},{93,127,1452},{91,127,900},{83,127,29},{127,69,4344},{76,127,1611},{67,127,306},{2,121,288},{126,99,4344},{2,121,288},{71,127,5686},{71,127,5686},{71,127,5686},{64,127,2954},{65,127,5051},{54,127,913},{54,127,913},{44,110,260},{14,127,2856},{13,115,2},{91,127,900}, +{91,127,900},{91,127,900},{83,127,29},{127,40,2178},{67,127,306},{67,127,306},{15,115,0},{126,85,2178},{15,115,0},{127,108,288},{113,127,106},{109,127,0},{90,127,0},{127,108,288},{127,118,288},{90,127,0},{0,121,288},{127,118,288},{0,121,288},{64,0,2665},{64,0,2665},{64,0,2665},{64,0,2665},{50,127,260},{50,127,260},{50,127,260},{46,100,0},{11,117,0},{11,117,0},{85,127,9781},{79,127,6942},{77,127,5950}, +{70,127,3146},{79,127,10205},{63,127,3141},{57,127,1265},{47,119,616},{40,127,6924},{13,123,130},{103,127,2436},{97,127,1460},{94,127,1040},{87,127,104},{127,76,3779},{81,127,1496},{73,127,442},{10,123,128},{126,103,3779},{10,123,128},{77,127,5950},{77,127,5950},{77,127,5950},{70,127,3146},{68,127,5347},{57,127,1265},{57,127,1265},{48,114,260},{25,127,3115},{17,119,2},{94,127,1040},{94,127,1040},{94,127,1040},{87,127,104},{127,53,2178}, +{73,127,442},{73,127,442},{19,119,0},{126,91,2178},{19,119,0},{127,115,128},{116,127,50},{115,127,0},{102,127,0},{127,115,128},{127,121,128},{102,127,0},{0,123,128},{127,121,128},{0,123,128},{68,0,2665},{68,0,2665},{68,0,2665},{68,0,2665},{55,127,325},{55,127,325},{55,127,325},{50,104,0},{15,121,0},{15,121,0},{88,127,9417},{82,127,7109},{82,127,6209},{73,127,3406},{85,127,9733},{67,127,3260},{63,127,1649}, +{50,122,424},{46,127,6644},{19,125,32},{106,127,2208},{101,127,1502},{100,127,1184},{93,127,232},{127,86,3299},{87,127,1400},{81,127,628},{19,125,32},{127,107,3299},{19,125,32},{82,127,6209},{82,127,6209},{82,127,6209},{73,127,3406},{74,127,5659},{63,127,1649},{63,127,1649},{52,118,260},{34,127,3419},{21,123,2},{100,127,1184},{100,127,1184},{100,127,1184},{93,127,232},{127,64,2178},{81,127,628},{81,127,628},{23,123,0},{126,97,2178}, +{23,123,0},{127,121,32},{122,127,10},{121,127,0},{115,127,0},{127,121,32},{127,124,32},{115,127,0},{0,125,32},{127,124,32},{0,125,32},{72,0,2665},{72,0,2665},{72,0,2665},{72,0,2665},{61,127,421},{61,127,421},{61,127,421},{54,108,0},{19,125,0},{19,125,0},{91,127,9133},{88,127,7245},{85,127,6485},{79,127,3710},{88,127,9325},{73,127,3460},{67,127,2107},{55,124,304},{54,127,6532},{25,127,2},{111,127,2038}, +{106,127,1556},{103,127,1348},{96,127,416},{127,93,2904},{93,127,1368},{87,127,820},{27,127,0},{126,111,2904},{27,127,0},{85,127,6485},{85,127,6485},{85,127,6485},{79,127,3710},{79,127,5949},{67,127,2107},{67,127,2107},{56,122,260},{40,127,3771},{25,127,2},{103,127,1348},{103,127,1348},{103,127,1348},{96,127,416},{127,76,2178},{87,127,820},{87,127,820},{27,127,0},{126,103,2178},{27,127,0},{127,127,0},{127,127,0},{127,127,0}, +{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{76,0,2665},{76,0,2665},{76,0,2665},{76,0,2665},{65,127,514},{65,127,514},{65,127,514},{58,112,0},{25,127,2},{25,127,2},{94,127,8049},{91,127,6469},{88,127,5849},{84,127,3561},{91,127,8053},{76,127,3106},{73,127,1965},{62,125,154},{60,127,5562},{34,127,32},{111,127,1507},{109,127,1161},{106,127,1009},{102,127,305},{127,98,2166}, +{99,127,1009},{93,127,605},{40,127,0},{126,113,2166},{40,127,0},{88,127,5849},{88,127,5849},{88,127,5849},{84,127,3561},{82,127,5209},{73,127,1965},{73,127,1965},{61,124,126},{46,127,3225},{34,127,32},{106,127,1009},{106,127,1009},{106,127,1009},{102,127,305},{127,83,1625},{93,127,605},{93,127,605},{40,127,0},{126,106,1625},{40,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0}, +{0,127,0},{127,127,0},{0,127,0},{80,0,2665},{80,0,2665},{80,0,2665},{80,0,2665},{68,127,628},{68,127,628},{68,127,628},{63,116,1},{34,127,32},{34,127,32},{97,127,7165},{94,127,5845},{91,127,5333},{87,127,3401},{94,127,7033},{79,127,2823},{79,127,1862},{64,126,60},{64,127,4795},{40,127,80},{114,127,1107},{111,127,830},{111,127,730},{105,127,221},{127,102,1601},{102,127,737},{99,127,445},{53,127,0},{127,115,1601}, +{53,127,0},{91,127,5333},{91,127,5333},{91,127,5333},{87,127,3401},{85,127,4629},{79,127,1862},{79,127,1862},{66,125,52},{54,127,2834},{40,127,80},{111,127,730},{111,127,730},{111,127,730},{105,127,221},{127,89,1201},{99,127,445},{99,127,445},{53,127,0},{125,109,1201},{53,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{84,0,2665}, +{84,0,2665},{84,0,2665},{84,0,2665},{74,127,740},{74,127,740},{74,127,740},{66,120,0},{40,127,80},{40,127,80},{100,127,6361},{97,127,5277},{94,127,4865},{90,127,3265},{97,127,6117},{84,127,2641},{79,127,1814},{70,126,12},{70,127,4123},{46,127,160},{117,127,779},{114,127,595},{114,127,514},{108,127,153},{127,105,1121},{105,127,513},{102,127,305},{64,127,0},{126,117,1121},{64,127,0},{94,127,4865},{94,127,4865},{94,127,4865}, +{90,127,3265},{91,127,4117},{79,127,1814},{79,127,1814},{70,126,8},{60,127,2474},{46,127,160},{114,127,514},{114,127,514},{114,127,514},{108,127,153},{127,95,841},{102,127,305},{102,127,305},{64,127,0},{127,111,841},{64,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{88,0,2665},{88,0,2665},{88,0,2665},{88,0,2665},{79,127,853}, +{79,127,853},{79,127,853},{70,124,0},{46,127,160},{46,127,160},{103,127,5637},{100,127,4765},{100,127,4441},{93,127,3153},{100,127,5305},{90,127,2465},{86,127,1789},{74,127,4},{73,127,3543},{54,127,274},{117,127,507},{117,127,387},{115,127,337},{111,127,101},{127,110,726},{108,127,337},{108,127,193},{76,127,0},{126,119,726},{76,127,0},{100,127,4441},{100,127,4441},{100,127,4441},{93,127,3153},{94,127,3657},{86,127,1789},{86,127,1789}, +{74,127,4},{67,127,2182},{54,127,274},{115,127,337},{115,127,337},{115,127,337},{111,127,101},{127,101,545},{108,127,193},{108,127,193},{76,127,0},{127,114,545},{76,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{92,0,2665},{92,0,2665},{92,0,2665},{92,0,2665},{82,127,985},{82,127,985},{82,127,985},{74,127,4},{54,127,274}, +{54,127,274},{17,127,39416},{1,127,2073},{0,90,164},{0,86,5261},{17,127,49709},{0,113,21212},{0,85,8480},{0,75,26137},{0,87,56335},{0,67,37225},{12,127,10274},{0,122,1413},{0,90,148},{0,75,3940},{57,0,18065},{0,76,12036},{0,68,6166},{0,45,14098},{117,0,18065},{0,45,14098},{0,71,0},{0,71,0},{0,71,0},{0,35,0},{0,35,1105},{0,28,405},{0,28,405},{0,15,689},{0,14,1226},{0,15,789},{0,71,0}, +{0,71,0},{0,71,0},{0,35,0},{17,0,1105},{0,28,405},{0,28,405},{0,15,689},{35,0,1105},{0,15,689},{85,0,9248},{0,122,1413},{0,90,148},{0,75,3940},{85,0,9248},{127,23,9248},{0,75,3940},{0,57,9250},{127,23,9248},{0,57,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{20,127,44736},{2,127,2677},{0,95,64}, +{0,92,4941},{17,127,55213},{0,119,21820},{0,89,8426},{0,78,27209},{0,90,60583},{0,73,39465},{15,127,10870},{0,125,1213},{0,93,52},{0,78,3656},{61,0,19334},{0,81,12395},{0,73,6176},{0,50,14795},{124,0,19334},{0,50,14795},{0,83,0},{0,83,0},{0,83,0},{0,41,0},{0,41,1513},{0,34,565},{0,34,565},{0,18,937},{0,19,1661},{0,18,1081},{0,83,0},{0,83,0},{0,83,0},{0,41,0},{20,0,1513}, +{0,34,565},{0,34,565},{0,18,937},{41,0,1513},{0,18,937},{91,0,9248},{0,125,1213},{0,93,52},{0,78,3656},{91,0,9248},{127,29,9248},{0,78,3656},{0,61,9250},{127,29,9248},{0,61,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{20,127,50624},{2,127,4005},{0,99,4},{0,95,4545},{20,127,61345},{0,125,22460},{0,93,8410}, +{0,83,28480},{0,96,65039},{0,76,41789},{17,127,11556},{1,127,1217},{0,99,4},{0,83,3425},{64,0,20689},{0,87,12835},{0,76,6216},{0,53,15539},{126,3,20689},{0,53,15539},{0,95,0},{0,95,0},{0,95,0},{0,47,0},{0,47,1985},{0,37,745},{0,37,745},{0,21,1225},{0,22,2185},{0,21,1421},{0,95,0},{0,95,0},{0,95,0},{0,47,0},{23,0,1985},{0,37,745},{0,37,745},{0,21,1225},{47,0,1985}, +{0,21,1225},{97,0,9248},{2,127,1205},{0,99,4},{0,83,3425},{97,0,9248},{127,35,9248},{0,83,3425},{0,65,9248},{127,35,9248},{0,65,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{23,127,56952},{5,127,6081},{0,103,9},{0,98,4221},{20,127,65535},{0,126,23535},{0,97,8416},{0,86,29640},{0,99,65535},{0,79,44233},{20,127,12416}, +{2,127,1397},{1,103,8},{0,86,3181},{69,0,22129},{0,90,13307},{0,81,6266},{0,56,16331},{127,7,22129},{0,56,16331},{0,107,0},{0,107,0},{0,107,0},{0,53,0},{0,53,2521},{0,43,953},{0,43,953},{0,24,1553},{0,22,2777},{0,24,1809},{0,107,0},{0,107,0},{0,107,0},{0,53,0},{26,0,2521},{0,43,953},{0,43,953},{0,24,1553},{53,0,2521},{0,24,1553},{103,0,9248},{2,127,1381},{2,103,0}, +{0,86,3181},{103,0,9248},{127,41,9248},{0,86,3181},{0,69,9248},{127,41,9248},{0,69,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{26,127,64790},{5,127,9105},{1,108,78},{0,104,3845},{23,127,65535},{2,127,25370},{0,102,8458},{0,89,31046},{0,105,65535},{0,81,47079},{23,127,13542},{5,127,1881},{2,109,50},{0,92,2897},{73,0,23851}, +{0,96,13865},{0,87,6374},{0,59,17289},{126,12,23851},{0,59,17289},{0,121,0},{0,121,0},{0,121,0},{0,59,1},{0,61,3200},{0,51,1210},{0,51,1210},{0,27,1972},{0,25,3528},{0,27,2296},{0,121,0},{0,121,0},{0,121,0},{0,59,1},{30,0,3200},{0,51,1210},{0,51,1210},{0,27,1972},{61,0,3200},{0,27,1972},{110,0,9248},{11,127,1693},{7,107,1},{0,92,2897},{110,0,9248},{126,48,9248},{0,92,2897}, +{0,73,9250},{126,48,9248},{0,73,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{26,127,65535},{5,127,12609},{1,111,198},{0,107,3541},{26,127,65535},{2,127,27706},{0,105,8522},{0,92,32390},{0,113,65535},{0,87,49743},{26,127,14690},{8,127,2501},{3,113,126},{0,98,2665},{77,0,25472},{0,102,14385},{0,90,6486},{0,62,18185},{127,15,25472}, +{0,62,18185},{0,127,16},{0,127,16},{0,127,16},{0,65,0},{0,66,3872},{0,51,1450},{0,51,1450},{0,30,2384},{0,28,4268},{0,27,2776},{1,127,13},{1,127,13},{1,127,13},{0,65,0},{33,0,3872},{0,51,1450},{0,51,1450},{0,30,2384},{66,0,3872},{0,30,2384},{115,1,9248},{19,127,2041},{11,111,1},{0,98,2665},{115,1,9248},{126,54,9248},{0,98,2665},{0,77,9250},{126,54,9248},{0,77,9250},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{29,127,65535},{8,127,16605},{1,116,349},{0,112,3274},{26,127,65535},{2,127,30470},{0,109,8346},{0,98,33226},{0,113,65535},{0,90,52035},{29,127,15746},{11,127,3213},{5,117,217},{0,101,2445},{81,0,26744},{0,108,14657},{0,96,6398},{0,66,18739},{126,20,26744},{0,66,18739},{3,127,116},{3,127,116},{3,127,116}, +{0,71,4},{0,74,4418},{0,57,1586},{0,57,1586},{0,33,2664},{0,31,4916},{0,30,3140},{3,127,80},{3,127,80},{3,127,80},{1,70,1},{36,1,4418},{0,57,1586},{0,57,1586},{0,33,2664},{74,0,4418},{0,33,2664},{121,1,9248},{25,127,2377},{15,115,1},{0,101,2441},{121,1,9248},{126,60,9248},{0,101,2441},{0,81,9250},{126,60,9248},{0,81,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,3,0}, +{0,3,0},{0,3,0},{0,1,1},{1,0,2},{1,0,2},{32,127,65535},{11,127,21205},{2,120,605},{0,115,3106},{29,127,65535},{2,127,33062},{0,114,7330},{0,101,32522},{0,119,65535},{0,93,52995},{35,127,16210},{14,127,3809},{9,121,217},{0,107,2325},{87,0,26744},{0,116,14054},{0,99,5606},{0,72,18275},{126,26,26744},{0,72,18275},{6,127,292},{6,127,292},{6,127,292},{2,76,52},{0,86,4418},{0,64,1313},{0,64,1313}, +{0,39,2440},{0,37,5092},{0,36,3044},{9,127,128},{9,127,128},{9,127,128},{5,74,1},{42,1,4418},{0,64,1313},{0,64,1313},{0,39,2440},{86,0,4418},{0,39,2440},{127,1,9248},{34,127,2741},{19,119,1},{0,107,2225},{127,1,9248},{127,65,9248},{0,107,2225},{0,85,9250},{127,65,9248},{0,85,9250},{2,0,52},{2,0,52},{2,0,52},{2,0,52},{0,15,0},{0,15,0},{0,15,0},{0,7,1},{0,5,18}, +{0,5,18},{35,127,65535},{11,127,27154},{3,124,1078},{0,121,3041},{32,127,65535},{5,127,36765},{0,119,6285},{0,107,31809},{0,125,65535},{0,96,54246},{38,127,16729},{22,127,4594},{14,126,218},{4,111,2318},{94,0,26744},{0,122,13481},{0,105,4785},{0,75,17772},{127,32,26744},{0,75,17772},{9,127,614},{9,127,614},{9,127,614},{5,81,181},{0,100,4418},{0,73,1037},{0,73,1037},{0,42,2210},{0,43,5330},{0,41,2986},{13,127,193}, +{13,127,193},{13,127,193},{9,79,1},{49,0,4418},{0,73,1037},{0,73,1037},{0,42,2210},{100,0,4418},{0,42,2210},{127,14,9248},{40,127,3177},{23,124,0},{0,110,2009},{127,14,9248},{127,72,9248},{0,110,2009},{0,90,9248},{127,72,9248},{0,90,9248},{5,0,181},{5,0,181},{5,0,181},{5,0,181},{0,29,0},{0,29,0},{0,29,0},{0,14,0},{0,11,65},{0,11,65},{35,127,65535},{14,127,31662},{4,127,1705}, +{0,124,3025},{35,127,65535},{8,127,39325},{0,122,5245},{0,110,30421},{0,125,65535},{0,102,54322},{44,127,16749},{25,127,5034},{17,127,245},{7,114,2214},{99,0,26259},{0,125,12725},{0,111,3981},{0,78,16984},{126,38,26259},{0,78,16984},{10,127,1025},{10,127,1025},{10,127,1025},{7,86,365},{0,112,4418},{0,81,797},{0,81,797},{0,47,2025},{0,51,5557},{0,45,2950},{17,127,245},{17,127,245},{17,127,245},{13,83,1},{55,0,4418}, +{0,81,797},{0,81,797},{0,47,2025},{112,0,4418},{0,47,2025},{127,25,8978},{46,127,3385},{28,127,0},{0,115,1732},{127,25,8978},{127,77,8978},{0,115,1732},{0,93,8980},{127,77,8978},{0,93,8980},{7,0,365},{7,0,365},{7,0,365},{7,0,365},{0,41,0},{0,41,0},{0,41,0},{0,20,0},{0,17,137},{0,17,137},{38,127,65535},{14,127,32078},{6,127,2618},{1,125,2789},{35,127,65535},{8,127,37485},{0,123,3805}, +{0,110,27013},{0,125,65535},{0,102,51330},{49,127,15435},{31,127,4714},{23,127,317},{12,116,1830},{104,0,24371},{0,125,11205},{0,113,2881},{0,83,15117},{127,42,24371},{0,83,15117},{12,127,1538},{12,127,1538},{12,127,1538},{9,91,613},{0,124,4418},{0,87,605},{0,87,605},{0,53,1825},{0,54,5805},{0,49,2946},{23,127,317},{23,127,317},{23,127,317},{17,87,1},{61,0,4418},{0,87,605},{0,87,605},{0,53,1825},{124,0,4418}, +{0,53,1825},{127,31,7938},{51,127,3029},{34,127,0},{0,118,1224},{127,31,7938},{127,80,7938},{0,118,1224},{0,95,7940},{127,80,7938},{0,95,7940},{9,0,613},{9,0,613},{9,0,613},{9,0,613},{0,53,0},{0,53,0},{0,53,0},{0,26,0},{0,22,221},{0,22,221},{38,127,65535},{14,127,32750},{6,127,3706},{3,124,2753},{35,127,65535},{8,127,35901},{0,124,2601},{0,110,23861},{0,125,65535},{0,102,48594},{52,127,14211}, +{34,127,4410},{26,127,405},{16,117,1482},{107,1,22568},{2,127,9869},{0,116,1973},{0,86,13349},{126,46,22568},{0,86,13349},{17,127,2137},{17,127,2137},{17,127,2137},{11,96,925},{3,127,4462},{0,93,445},{0,93,445},{0,56,1649},{0,60,6101},{0,54,2966},{26,127,405},{26,127,405},{26,127,405},{21,91,1},{66,1,4418},{0,93,445},{0,93,445},{0,56,1649},{126,5,4418},{0,56,1649},{127,37,6962},{57,127,2645},{40,127,0}, +{0,118,808},{127,37,6962},{127,83,6962},{0,118,808},{0,97,6964},{127,83,6962},{0,97,6964},{11,0,925},{11,0,925},{11,0,925},{11,0,925},{0,65,0},{0,65,0},{0,65,0},{0,32,0},{0,25,337},{0,25,337},{38,127,65535},{14,127,33812},{7,127,5233},{4,125,2961},{35,127,65535},{8,127,34425},{0,125,1509},{0,112,20542},{0,125,65535},{0,105,45810},{55,127,12917},{40,127,4114},{32,127,505},{22,117,1140},{112,0,20642}, +{2,127,8609},{0,119,1157},{0,89,11489},{127,50,20642},{0,89,11489},{20,127,2969},{20,127,2969},{20,127,2969},{13,102,1352},{6,127,4660},{0,102,289},{0,102,289},{0,62,1445},{0,64,6470},{0,57,3018},{32,127,505},{32,127,505},{32,127,505},{26,95,1},{73,0,4418},{0,102,289},{0,102,289},{0,62,1445},{126,12,4418},{0,62,1445},{127,43,5941},{63,127,2248},{46,127,1},{0,121,433},{127,43,5941},{127,86,5941},{0,121,433}, +{0,100,5941},{127,86,5941},{0,100,5941},{13,0,1352},{13,0,1352},{13,0,1352},{13,0,1352},{0,78,0},{0,78,0},{0,78,0},{0,39,0},{0,31,500},{0,31,500},{38,127,65535},{19,127,34934},{9,127,6748},{5,126,3381},{38,127,65535},{11,127,33369},{0,125,789},{0,112,17822},{0,125,65535},{0,105,43458},{58,127,11849},{43,127,3870},{38,127,617},{27,119,868},{115,1,19021},{5,127,7741},{0,120,621},{0,92,9957},{126,54,19021}, +{0,92,9957},{23,127,3833},{23,127,3833},{23,127,3833},{15,107,1800},{9,127,4984},{0,108,185},{0,108,185},{0,66,1282},{0,70,6822},{0,63,3090},{38,127,617},{38,127,617},{38,127,617},{30,99,1},{79,0,4418},{0,108,185},{0,108,185},{0,66,1282},{127,17,4418},{0,66,1282},{127,50,5101},{67,127,1921},{52,127,0},{0,124,205},{127,50,5101},{127,89,5101},{0,124,205},{0,102,5101},{127,89,5101},{0,102,5101},{15,0,1800}, +{15,0,1800},{15,0,1800},{15,0,1800},{0,91,0},{0,91,0},{0,91,0},{0,45,0},{0,37,676},{0,37,676},{41,127,65535},{19,127,36134},{9,127,8476},{5,126,4005},{38,127,65535},{11,127,32489},{0,126,309},{0,115,15210},{0,125,65535},{0,105,41362},{61,127,10853},{46,127,3674},{41,127,725},{31,120,632},{120,0,17485},{11,127,6965},{0,123,249},{0,95,8537},{127,58,17485},{0,95,8537},{23,127,4809},{23,127,4809},{23,127,4809}, +{17,112,2312},{12,127,5444},{0,116,89},{0,116,89},{0,72,1130},{0,76,7206},{0,67,3194},{41,127,725},{41,127,725},{41,127,725},{34,103,1},{85,0,4418},{0,116,89},{0,116,89},{0,72,1130},{127,23,4418},{0,72,1130},{127,56,4325},{70,127,1625},{58,127,0},{0,124,61},{127,56,4325},{127,92,4325},{0,124,61},{0,104,4325},{127,92,4325},{0,104,4325},{17,0,2312},{17,0,2312},{17,0,2312},{17,0,2312},{0,103,0}, +{0,103,0},{0,103,0},{0,50,1},{0,40,872},{0,40,872},{41,127,65535},{19,127,37590},{9,127,10460},{6,127,4841},{38,127,65535},{11,127,31865},{0,127,65},{0,115,12842},{0,125,65535},{0,105,39522},{65,127,9918},{51,127,3500},{47,127,853},{35,121,436},{124,0,16034},{14,127,6273},{0,125,53},{0,98,7229},{127,62,16034},{0,98,7229},{26,127,5881},{26,127,5881},{26,127,5881},{19,117,2888},{15,127,6040},{0,125,37},{0,125,37}, +{0,75,986},{0,81,7565},{0,70,3318},{47,127,853},{47,127,853},{47,127,853},{38,107,1},{91,0,4418},{0,125,37},{0,125,37},{0,75,986},{127,29,4418},{0,75,986},{127,62,3613},{76,127,1345},{64,127,0},{0,127,1},{127,62,3613},{127,95,3613},{0,127,1},{0,106,3613},{127,95,3613},{0,106,3613},{19,0,2888},{19,0,2888},{19,0,2888},{19,0,2888},{0,115,0},{0,115,0},{0,115,0},{0,56,1},{0,46,1096}, +{0,46,1096},{41,127,65535},{22,127,39522},{12,127,12842},{7,127,6030},{38,127,65535},{11,127,31469},{0,127,65},{0,118,10460},{0,125,65535},{0,108,37590},{68,127,8954},{57,127,3318},{52,127,986},{40,123,258},{127,2,14504},{22,127,5594},{2,127,37},{0,101,5881},{127,66,14504},{0,101,5881},{29,127,7229},{29,127,7229},{29,127,7229},{21,122,3614},{17,127,6824},{1,127,53},{1,127,53},{0,80,853},{0,87,8059},{0,76,3500},{52,127,986}, +{52,127,986},{52,127,986},{42,112,1},{98,0,4418},{2,127,37},{2,127,37},{0,80,853},{127,36,4418},{0,80,853},{127,69,2888},{81,127,1096},{70,127,1},{11,127,0},{127,69,2888},{126,99,2888},{11,127,0},{0,108,2888},{126,99,2888},{0,108,2888},{21,0,3613},{21,0,3613},{21,0,3613},{21,0,3613},{0,127,1},{0,127,1},{0,127,1},{0,63,0},{0,51,1345},{0,51,1345},{41,127,65535},{22,127,41362},{12,127,15210}, +{8,127,7309},{41,127,65535},{11,127,31389},{1,127,309},{0,118,8476},{0,125,65535},{0,108,36134},{71,127,8174},{60,127,3194},{55,127,1130},{45,123,137},{127,10,13235},{28,127,5018},{11,127,89},{0,101,4809},{126,70,13235},{0,101,4809},{32,127,8537},{32,127,8537},{32,127,8537},{23,127,4326},{20,127,7700},{4,127,249},{4,127,249},{0,86,725},{0,93,8531},{0,81,3674},{55,127,1130},{55,127,1130},{55,127,1130},{46,116,1},{104,0,4418}, +{11,127,89},{11,127,89},{0,86,725},{127,42,4418},{0,86,725},{127,75,2312},{87,127,872},{76,127,1},{24,127,0},{127,75,2312},{126,102,2312},{24,127,0},{0,110,2312},{126,102,2312},{0,110,2312},{23,0,4325},{23,0,4325},{23,0,4325},{23,0,4325},{3,127,61},{3,127,61},{3,127,61},{0,69,0},{0,54,1625},{0,54,1625},{44,127,65535},{22,127,43458},{15,127,17822},{8,127,8829},{41,127,65535},{14,127,31497},{2,127,789}, +{0,118,6748},{0,125,65535},{0,108,34934},{77,127,7454},{64,127,3090},{61,127,1282},{50,125,53},{127,19,12051},{34,127,4506},{16,127,185},{0,104,3833},{127,74,12051},{0,104,3833},{35,127,9957},{35,127,9957},{35,127,9957},{25,127,5150},{23,127,8712},{5,127,621},{5,127,621},{0,89,617},{0,96,9035},{0,84,3870},{61,127,1282},{61,127,1282},{61,127,1282},{50,120,1},{110,0,4418},{16,127,185},{16,127,185},{0,89,617},{126,48,4418}, +{0,89,617},{127,81,1800},{90,127,676},{82,127,0},{36,127,0},{127,81,1800},{126,105,1800},{36,127,0},{0,112,1800},{126,105,1800},{0,112,1800},{25,0,5101},{25,0,5101},{25,0,5101},{25,0,5101},{3,127,205},{3,127,205},{3,127,205},{0,75,0},{0,60,1921},{0,60,1921},{44,127,65535},{22,127,45810},{15,127,20542},{10,127,10546},{41,127,65535},{14,127,31833},{2,127,1509},{0,120,5233},{0,125,65535},{0,113,33812},{79,127,6740}, +{70,127,3018},{65,127,1445},{54,126,9},{127,27,10952},{40,127,4058},{25,127,289},{0,107,2969},{126,78,10952},{0,107,2969},{38,127,11489},{38,127,11489},{38,127,11489},{28,127,6114},{26,127,9860},{8,127,1157},{8,127,1157},{0,95,505},{0,102,9555},{0,87,4114},{65,127,1445},{65,127,1445},{65,127,1445},{54,124,1},{115,1,4418},{25,127,289},{25,127,289},{0,95,505},{126,54,4418},{0,95,505},{127,87,1352},{96,127,500},{88,127,0}, +{48,127,0},{127,87,1352},{126,108,1352},{48,127,0},{0,114,1352},{126,108,1352},{0,114,1352},{27,0,5941},{27,0,5941},{27,0,5941},{27,0,5941},{6,127,433},{6,127,433},{6,127,433},{0,80,1},{0,64,2248},{0,64,2248},{44,127,65535},{25,127,48594},{17,127,23861},{11,127,12725},{41,127,65535},{14,127,32517},{3,127,2601},{0,121,3706},{0,126,65535},{0,113,32750},{82,127,6098},{73,127,2966},{71,127,1649},{59,127,4},{127,36,9818}, +{46,127,3638},{34,127,445},{0,110,2137},{127,82,9818},{0,110,2137},{41,127,13349},{41,127,13349},{41,127,13349},{31,127,7380},{29,127,11310},{11,127,1973},{11,127,1973},{0,101,405},{0,108,10181},{0,93,4410},{71,127,1649},{71,127,1649},{71,127,1649},{59,127,4},{122,0,4418},{34,127,445},{34,127,445},{0,101,405},{126,61,4418},{0,101,405},{127,93,925},{102,127,337},{95,127,0},{62,127,0},{127,93,925},{126,111,925},{62,127,0}, +{0,116,925},{126,111,925},{0,116,925},{29,0,6964},{29,0,6964},{29,0,6964},{29,0,6964},{9,127,808},{9,127,808},{9,127,808},{0,87,0},{0,70,2645},{0,70,2645},{44,127,65535},{25,127,51330},{17,127,27013},{11,127,14917},{41,127,65535},{14,127,33397},{4,127,3805},{0,121,2618},{1,126,65535},{0,113,32078},{88,127,5594},{79,127,2891},{74,127,1825},{64,127,45},{127,43,8901},{54,127,3373},{40,127,605},{0,115,1538},{127,86,8901}, +{0,115,1538},{44,127,15117},{44,127,15117},{44,127,15117},{34,127,8664},{32,127,12746},{14,127,2881},{14,127,2881},{0,104,317},{0,113,10694},{0,96,4714},{74,127,1825},{74,127,1825},{74,127,1825},{64,127,45},{127,2,4418},{40,127,605},{40,127,605},{0,104,317},{127,66,4418},{0,104,317},{127,99,613},{105,127,221},{101,127,0},{73,127,0},{127,99,613},{126,114,613},{73,127,0},{0,118,613},{126,114,613},{0,118,613},{31,0,7940}, +{31,0,7940},{31,0,7940},{31,0,7940},{9,127,1224},{9,127,1224},{9,127,1224},{0,93,0},{0,76,3029},{0,76,3029},{49,127,65535},{25,127,54322},{17,127,30421},{13,127,17348},{44,127,65535},{14,127,34533},{5,127,5245},{0,123,1705},{2,127,65535},{0,113,31662},{91,127,5146},{82,127,2950},{79,127,1994},{67,127,145},{127,53,8069},{60,127,3125},{46,127,797},{0,117,1025},{126,91,8069},{0,117,1025},{49,127,16984},{49,127,16984},{49,127,16984}, +{37,127,10100},{35,127,14318},{16,127,3981},{16,127,3981},{0,110,245},{0,119,11302},{0,102,5034},{79,127,1994},{79,127,1994},{79,127,1994},{67,127,145},{127,14,4418},{46,127,797},{46,127,797},{0,110,245},{127,72,4418},{0,110,245},{127,105,365},{111,127,136},{107,127,0},{86,127,0},{127,105,365},{126,117,365},{86,127,0},{0,120,365},{126,117,365},{0,120,365},{33,0,8980},{33,0,8980},{33,0,8980},{33,0,8980},{12,127,1732}, +{12,127,1732},{12,127,1732},{0,99,0},{0,81,3385},{0,81,3385},{49,127,65535},{28,127,54246},{20,127,31809},{16,127,18396},{49,127,65535},{19,127,34118},{8,127,6285},{3,124,1078},{2,127,65535},{0,116,27154},{94,127,4770},{86,127,2986},{82,127,2210},{73,127,281},{127,60,7322},{67,127,2945},{54,127,1037},{0,118,614},{127,94,7322},{0,118,614},{52,127,17772},{52,127,17772},{52,127,17772},{40,127,10764},{38,127,15150},{22,127,4785},{22,127,4785}, +{1,113,218},{0,125,10994},{0,105,4594},{82,127,2210},{82,127,2210},{82,127,2210},{73,127,281},{127,27,4418},{54,127,1037},{54,127,1037},{0,114,193},{126,78,4418},{0,114,193},{127,111,181},{116,127,65},{113,127,0},{98,127,0},{127,111,181},{126,120,181},{98,127,0},{0,122,181},{126,120,181},{0,122,181},{37,0,9248},{37,0,9248},{37,0,9248},{37,0,9248},{17,127,2009},{17,127,2009},{17,127,2009},{3,104,0},{0,87,3177}, +{0,87,3177},{52,127,65535},{34,127,52995},{26,127,32522},{21,127,19126},{49,127,65535},{22,127,32935},{13,127,7330},{7,125,605},{2,127,64493},{0,116,21205},{97,127,4436},{91,127,3044},{88,127,2440},{79,127,505},{127,69,6584},{73,127,2811},{63,127,1313},{0,121,292},{126,99,6584},{0,121,292},{55,127,18275},{55,127,18275},{55,127,18275},{46,127,11259},{44,127,15797},{28,127,5606},{28,127,5606},{6,118,217},{0,125,10589},{0,113,3809},{88,127,2440}, +{88,127,2440},{88,127,2440},{79,127,505},{127,40,4418},{63,127,1313},{63,127,1313},{0,118,128},{126,85,4418},{0,118,128},{127,119,50},{122,127,18},{119,127,1},{111,127,0},{127,119,50},{127,123,50},{111,127,0},{0,124,52},{127,123,50},{0,124,52},{41,0,9250},{41,0,9250},{41,0,9250},{41,0,9250},{20,127,2225},{20,127,2225},{20,127,2225},{8,108,1},{0,93,2741},{0,93,2741},{55,127,65535},{37,127,52035},{29,127,33226}, +{25,127,19751},{52,127,65535},{28,127,31983},{18,127,8346},{11,126,349},{2,127,60061},{0,119,16605},{100,127,4216},{97,127,3140},{94,127,2664},{84,127,776},{127,76,6019},{76,127,2779},{70,127,1586},{0,124,116},{126,103,6019},{0,124,116},{61,127,18739},{61,127,18739},{61,127,18739},{51,127,11794},{49,127,16315},{31,127,6398},{31,127,6398},{10,122,217},{2,127,10565},{0,116,3213},{94,127,2664},{94,127,2664},{94,127,2664},{84,127,776},{127,53,4418}, +{70,127,1586},{70,127,1586},{0,124,80},{126,91,4418},{0,124,80},{127,125,2},{127,126,2},{125,127,1},{124,127,0},{127,125,2},{127,126,2},{124,127,0},{0,126,4},{127,126,2},{0,126,4},{45,0,9250},{45,0,9250},{45,0,9250},{45,0,9250},{26,127,2441},{26,127,2441},{26,127,2441},{12,112,1},{0,102,2377},{0,102,2377},{58,127,65535},{40,127,49743},{35,127,32390},{28,127,19671},{55,127,65535},{31,127,30383},{22,127,8522}, +{15,126,198},{2,127,55505},{0,122,12609},{103,127,3648},{100,127,2776},{97,127,2384},{87,127,740},{127,83,5163},{84,127,2468},{73,127,1450},{0,127,16},{126,106,5163},{0,127,16},{65,127,18185},{65,127,18185},{65,127,18185},{54,127,11714},{52,127,15699},{37,127,6486},{37,127,6486},{14,124,126},{2,127,9785},{0,119,2501},{97,127,2384},{97,127,2384},{97,127,2384},{87,127,740},{127,60,3872},{73,127,1450},{73,127,1450},{0,126,13},{127,94,3872}, +{0,126,13},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{49,0,9250},{49,0,9250},{49,0,9250},{49,0,9250},{29,127,2665},{29,127,2665},{29,127,2665},{16,116,1},{0,108,2041},{0,108,2041},{61,127,65535},{46,127,47079},{38,127,31046},{33,127,19370},{58,127,65535},{34,127,28647},{25,127,8458},{19,126,78},{2,127,51393},{0,122,9105},{106,127,3012}, +{100,127,2296},{100,127,1972},{90,127,612},{127,86,4267},{87,127,2028},{76,127,1210},{5,127,0},{127,107,4267},{5,127,0},{65,127,17289},{65,127,17289},{65,127,17289},{57,127,11462},{55,127,14739},{40,127,6374},{40,127,6374},{18,125,50},{2,127,8937},{0,122,1881},{100,127,1972},{100,127,1972},{100,127,1972},{90,127,612},{127,66,3200},{76,127,1210},{76,127,1210},{5,127,0},{127,97,3200},{5,127,0},{127,127,0},{127,127,0},{127,127,0}, +{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{53,0,9250},{53,0,9250},{53,0,9250},{53,0,9250},{35,127,2897},{35,127,2897},{35,127,2897},{20,120,1},{0,116,1693},{0,116,1693},{65,127,65535},{48,127,44233},{41,127,29640},{37,127,18961},{61,127,65535},{40,127,26823},{30,127,8416},{24,127,9},{8,127,47133},{0,122,6081},{109,127,2377},{103,127,1809},{103,127,1553},{96,127,481},{127,90,3361}, +{90,127,1593},{84,127,953},{19,127,0},{127,109,3361},{19,127,0},{71,127,16331},{71,127,16331},{71,127,16331},{63,127,11212},{61,127,13721},{46,127,6266},{46,127,6266},{24,126,8},{5,127,8245},{0,125,1397},{103,127,1553},{103,127,1553},{103,127,1553},{96,127,481},{127,72,2521},{84,127,953},{84,127,953},{19,127,0},{127,100,2521},{19,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0}, +{0,127,0},{127,127,0},{0,127,0},{58,0,9248},{58,0,9248},{58,0,9248},{58,0,9248},{41,127,3181},{41,127,3181},{41,127,3181},{24,125,0},{0,125,1381},{0,125,1381},{65,127,65535},{51,127,41789},{44,127,28480},{40,127,18673},{65,127,65535},{43,127,25251},{34,127,8410},{28,127,4},{14,127,43557},{0,125,4005},{111,127,1843},{106,127,1421},{106,127,1225},{99,127,373},{127,95,2646},{96,127,1241},{90,127,745},{31,127,0},{127,111,2646}, +{31,127,0},{74,127,15539},{74,127,15539},{74,127,15539},{64,127,10979},{65,127,12914},{51,127,6216},{51,127,6216},{28,127,4},{11,127,7709},{0,126,1217},{106,127,1225},{106,127,1225},{106,127,1225},{99,127,373},{127,78,1985},{90,127,745},{90,127,745},{31,127,0},{127,103,1985},{31,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{62,0,9248}, +{62,0,9248},{62,0,9248},{62,0,9248},{44,127,3425},{44,127,3425},{44,127,3425},{28,127,4},{0,125,1205},{0,125,1205},{68,127,65535},{54,127,39465},{49,127,27209},{46,127,18393},{65,127,64563},{46,127,23799},{38,127,8426},{32,127,64},{14,127,40437},{0,125,2677},{111,127,1411},{111,127,1070},{109,127,937},{102,127,281},{127,99,2017},{99,127,937},{93,127,565},{43,127,0},{126,114,2017},{43,127,0},{77,127,14795},{77,127,14795},{77,127,14795}, +{70,127,10779},{68,127,12146},{54,127,6176},{54,127,6176},{34,127,52},{14,127,7281},{2,127,1213},{109,127,937},{109,127,937},{109,127,937},{102,127,281},{127,84,1513},{93,127,565},{93,127,565},{43,127,0},{127,106,1513},{43,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{65,0,9250},{65,0,9250},{65,0,9250},{65,0,9250},{49,127,3656}, +{49,127,3656},{49,127,3656},{34,127,52},{2,127,1213},{2,127,1213},{71,127,63180},{60,127,37225},{52,127,26137},{48,127,18128},{68,127,59595},{51,127,22636},{42,127,8480},{37,127,164},{22,127,37455},{0,126,2073},{114,127,1019},{111,127,766},{111,127,666},{105,127,205},{127,102,1473},{102,127,681},{99,127,405},{56,127,0},{127,115,1473},{56,127,0},{79,127,14066},{79,127,14066},{79,127,14066},{73,127,10571},{71,127,11450},{59,127,6166},{59,127,6166}, +{37,127,148},{25,127,6914},{5,127,1413},{111,127,666},{111,127,666},{111,127,666},{105,127,205},{127,90,1105},{99,127,405},{99,127,405},{56,127,0},{127,109,1105},{56,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{127,127,0},{0,127,0},{127,127,0},{0,127,0},{69,0,9250},{69,0,9250},{69,0,9250},{69,0,9250},{52,127,3940},{52,127,3940},{52,127,3940},{37,127,148},{5,127,1413}, +{5,127,1413}, diff --git a/ext/basis_universal/basisu_transcoder_tables_dxt1_5.inc b/ext/basis_universal/basisu_transcoder_tables_dxt1_5.inc new file mode 100644 index 0000000000..8244550959 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_dxt1_5.inc @@ -0,0 +1,494 @@ +// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{0,2,18},{0,1,9},{0,1,0},{0,1,9},{0,1,40},{0,1,22},{0,1,13},{0,1,61},{0,1,47},{0,1,65},{0,2,18},{0,1,9},{0,1,0},{0,1,9},{0,1,40},{0,1,22},{0,1,13},{0,1,61},{1,0,40},{0,1,61},{0,1,0},{0,1,0},{0,1,0},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,0}, +{0,1,0},{0,1,0},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{1,0,18},{0,1,9},{0,1,0},{0,1,9},{1,0,18},{2,0,18},{0,1,9},{0,1,36},{2,0,18},{0,1,36},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,5,54},{0,3,40},{0,2,61}, +{0,2,36},{0,4,51},{0,2,37},{0,2,1},{0,2,52},{0,2,77},{0,1,73},{1,3,22},{1,2,13},{1,2,4},{1,2,13},{0,4,51},{1,2,34},{0,2,1},{0,2,52},{4,0,51},{0,2,52},{0,4,37},{0,4,37},{0,4,37},{0,2,36},{0,3,8},{0,2,1},{0,2,1},{0,1,5},{0,1,30},{0,1,9},{1,2,4},{1,2,4},{1,2,4},{1,1,8},{1,1,8}, +{0,2,1},{0,2,1},{0,1,5},{3,0,8},{0,1,5},{2,1,18},{0,3,4},{1,2,0},{0,2,0},{2,1,18},{5,0,18},{0,2,0},{0,2,36},{5,0,18},{0,2,36},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,5},{0,1,5},{1,6,54},{1,4,40},{1,3,61},{1,3,36},{1,5,51},{1,3,37},{1,3,1}, +{1,3,52},{0,3,72},{0,3,40},{2,4,22},{2,3,13},{2,3,4},{2,3,13},{1,5,51},{0,4,29},{1,3,1},{0,3,40},{7,0,51},{0,3,40},{1,5,37},{1,5,37},{1,5,37},{1,3,36},{1,4,8},{1,3,1},{1,3,1},{1,2,5},{0,3,8},{1,2,9},{2,3,4},{2,3,4},{2,3,4},{2,2,8},{3,0,8},{1,3,1},{1,3,1},{1,2,5},{6,0,8}, +{1,2,5},{3,2,18},{1,4,4},{2,3,0},{1,3,0},{3,2,18},{6,1,18},{1,3,0},{0,3,36},{6,1,18},{0,3,36},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,3,1},{1,3,1},{1,3,1},{1,2,1},{0,3,4},{0,3,4},{2,7,54},{2,5,40},{2,4,62},{2,4,38},{2,6,51},{2,4,27},{2,4,3},{2,3,69},{0,5,60},{1,4,54},{3,5,22}, +{3,4,9},{3,4,6},{3,4,21},{5,0,51},{2,4,27},{2,4,3},{0,4,50},{10,0,51},{0,4,50},{2,6,37},{2,6,37},{2,6,37},{2,4,37},{2,5,8},{2,4,2},{2,4,2},{2,3,5},{1,4,8},{2,3,9},{3,4,5},{3,4,5},{3,4,5},{3,3,8},{4,1,8},{2,4,2},{2,4,2},{2,3,5},{9,0,8},{2,3,5},{3,5,18},{2,5,4},{3,4,2}, +{2,4,2},{3,5,18},{7,2,18},{2,4,2},{0,4,50},{7,2,18},{0,4,50},{2,0,36},{2,0,36},{2,0,36},{2,0,36},{2,4,1},{2,4,1},{2,4,1},{2,3,1},{1,4,4},{1,4,4},{3,8,68},{3,6,60},{4,5,68},{3,5,50},{3,7,53},{3,6,28},{3,5,5},{3,5,53},{3,5,68},{2,5,38},{4,6,22},{4,5,13},{4,5,4},{4,5,13},{6,1,52}, +{3,6,27},{3,5,4},{1,5,37},{13,0,52},{1,5,37},{3,7,50},{3,7,50},{3,7,50},{3,5,50},{3,6,11},{3,5,5},{3,5,5},{3,4,6},{2,5,11},{3,4,9},{4,5,4},{4,5,4},{4,5,4},{4,4,8},{4,4,8},{3,5,4},{3,5,4},{3,4,5},{12,0,8},{3,4,5},{7,0,18},{4,5,9},{4,5,0},{3,5,0},{7,0,18},{14,0,18},{3,5,0}, +{0,5,36},{14,0,18},{0,5,36},{3,0,50},{3,0,50},{3,0,50},{3,0,50},{3,6,2},{3,6,2},{3,6,2},{3,4,2},{2,5,2},{2,5,2},{4,9,54},{4,7,40},{4,6,61},{4,6,36},{4,8,51},{4,6,37},{4,6,1},{4,6,52},{2,7,68},{3,6,38},{5,7,22},{5,6,13},{5,6,4},{5,6,13},{8,0,51},{5,6,34},{4,6,1},{2,6,37},{16,0,51}, +{2,6,37},{4,8,37},{4,8,37},{4,8,37},{4,6,36},{4,7,8},{4,6,1},{4,6,1},{4,5,5},{3,6,11},{4,5,9},{5,6,4},{5,6,4},{5,6,4},{5,5,8},{5,5,8},{4,6,1},{4,6,1},{4,5,5},{15,0,8},{4,5,5},{8,1,18},{4,7,4},{5,6,0},{4,6,0},{8,1,18},{17,0,18},{4,6,0},{0,6,36},{17,0,18},{0,6,36},{4,0,36}, +{4,0,36},{4,0,36},{4,0,36},{4,6,1},{4,6,1},{4,6,1},{4,5,1},{3,6,2},{3,6,2},{5,10,54},{5,8,40},{5,7,61},{5,7,36},{5,9,51},{5,7,37},{5,7,1},{5,7,52},{3,8,60},{4,7,40},{6,8,22},{6,7,13},{6,7,4},{6,7,13},{9,1,51},{4,8,29},{5,7,1},{3,7,37},{19,0,51},{3,7,37},{5,9,37},{5,9,37},{5,9,37}, +{5,7,36},{5,8,8},{5,7,1},{5,7,1},{5,6,5},{4,7,8},{5,6,9},{6,7,4},{6,7,4},{6,7,4},{6,6,8},{9,0,8},{5,7,1},{5,7,1},{5,6,5},{18,0,8},{5,6,5},{10,0,18},{5,8,4},{6,7,0},{5,7,0},{10,0,18},{18,1,18},{5,7,0},{0,7,36},{18,1,18},{0,7,36},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,7,1}, +{5,7,1},{5,7,1},{5,6,1},{4,7,4},{4,7,4},{6,11,54},{6,9,40},{6,8,62},{6,8,38},{6,10,51},{6,8,27},{6,8,3},{6,7,69},{4,9,60},{5,8,54},{7,9,22},{7,8,9},{7,8,6},{7,8,21},{11,0,51},{6,8,27},{6,8,3},{4,8,50},{22,0,51},{4,8,50},{6,10,37},{6,10,37},{6,10,37},{6,8,37},{6,9,8},{6,8,2},{6,8,2}, +{6,7,5},{5,8,8},{6,7,9},{7,8,5},{7,8,5},{7,8,5},{7,7,8},{10,1,8},{6,8,2},{6,8,2},{6,7,5},{21,0,8},{6,7,5},{11,1,18},{6,9,4},{7,8,2},{6,8,2},{11,1,18},{19,2,18},{6,8,2},{0,8,50},{19,2,18},{0,8,50},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,8,1},{6,8,1},{6,8,1},{6,7,1},{5,8,4}, +{5,8,4},{7,12,68},{7,10,60},{8,9,68},{7,9,50},{7,11,53},{7,10,28},{7,9,5},{7,9,53},{7,9,68},{6,9,38},{8,10,22},{8,9,13},{8,9,4},{8,9,13},{12,1,52},{7,10,27},{7,9,4},{5,9,37},{25,0,52},{5,9,37},{7,11,50},{7,11,50},{7,11,50},{7,9,50},{7,10,11},{7,9,5},{7,9,5},{7,8,6},{6,9,11},{7,8,9},{8,9,4}, +{8,9,4},{8,9,4},{8,8,8},{12,0,8},{7,9,4},{7,9,4},{7,8,5},{24,0,8},{7,8,5},{13,0,18},{8,9,9},{8,9,0},{7,9,0},{13,0,18},{26,0,18},{7,9,0},{0,9,36},{26,0,18},{0,9,36},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,10,2},{7,10,2},{7,10,2},{7,8,2},{6,9,2},{6,9,2},{8,13,54},{8,11,40},{8,10,61}, +{8,10,36},{8,12,51},{8,10,37},{8,10,1},{8,10,52},{6,11,68},{7,10,38},{9,11,22},{9,10,13},{9,10,4},{9,10,13},{12,4,51},{9,10,34},{8,10,1},{6,10,37},{28,0,51},{6,10,37},{8,12,37},{8,12,37},{8,12,37},{8,10,36},{8,11,8},{8,10,1},{8,10,1},{8,9,5},{7,10,11},{8,9,9},{9,10,4},{9,10,4},{9,10,4},{9,9,8},{13,1,8}, +{8,10,1},{8,10,1},{8,9,5},{27,0,8},{8,9,5},{14,1,18},{8,11,4},{9,10,0},{8,10,0},{14,1,18},{29,0,18},{8,10,0},{0,10,36},{29,0,18},{0,10,36},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,10,1},{8,10,1},{8,10,1},{8,9,1},{7,10,2},{7,10,2},{9,14,54},{9,12,40},{9,11,61},{9,11,36},{9,13,51},{9,11,37},{9,11,1}, +{9,11,52},{7,12,60},{8,11,40},{10,12,22},{10,11,13},{10,11,4},{10,11,13},{13,5,51},{8,12,29},{9,11,1},{7,11,37},{31,0,51},{7,11,37},{9,13,37},{9,13,37},{9,13,37},{9,11,36},{9,12,8},{9,11,1},{9,11,1},{9,10,5},{8,11,8},{9,10,9},{10,11,4},{10,11,4},{10,11,4},{10,10,8},{15,0,8},{9,11,1},{9,11,1},{9,10,5},{30,0,8}, +{9,10,5},{15,2,18},{9,12,4},{10,11,0},{9,11,0},{15,2,18},{30,1,18},{9,11,0},{0,11,36},{30,1,18},{0,11,36},{9,0,36},{9,0,36},{9,0,36},{9,0,36},{9,11,1},{9,11,1},{9,11,1},{9,10,1},{8,11,4},{8,11,4},{10,15,54},{10,13,40},{10,12,62},{10,12,38},{10,14,51},{10,12,27},{10,12,3},{10,11,69},{8,13,60},{9,12,54},{11,13,22}, +{11,12,9},{11,12,6},{11,12,21},{17,0,51},{10,12,27},{10,12,3},{8,12,50},{30,2,51},{8,12,50},{10,14,37},{10,14,37},{10,14,37},{10,12,37},{10,13,8},{10,12,2},{10,12,2},{10,11,5},{9,12,8},{10,11,9},{11,12,5},{11,12,5},{11,12,5},{11,11,8},{16,1,8},{10,12,2},{10,12,2},{10,11,5},{31,1,8},{10,11,5},{15,5,18},{10,13,4},{11,12,2}, +{10,12,2},{15,5,18},{31,2,18},{10,12,2},{0,12,50},{31,2,18},{0,12,50},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,12,1},{10,12,1},{10,12,1},{10,11,1},{9,12,4},{9,12,4},{11,16,68},{11,14,60},{12,13,68},{11,13,50},{11,15,53},{11,14,28},{11,13,5},{11,13,53},{11,13,68},{10,13,38},{12,14,22},{12,13,13},{12,13,4},{12,13,13},{18,1,52}, +{11,14,27},{11,13,4},{9,13,37},{31,3,52},{9,13,37},{11,15,50},{11,15,50},{11,15,50},{11,13,50},{11,14,11},{11,13,5},{11,13,5},{11,12,6},{10,13,11},{11,12,9},{12,13,4},{12,13,4},{12,13,4},{12,12,8},{16,4,8},{11,13,4},{11,13,4},{11,12,5},{28,4,8},{11,12,5},{19,0,18},{12,13,9},{12,13,0},{11,13,0},{19,0,18},{30,4,18},{11,13,0}, +{0,13,36},{30,4,18},{0,13,36},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,14,2},{11,14,2},{11,14,2},{11,12,2},{10,13,2},{10,13,2},{12,17,54},{12,15,40},{12,14,61},{12,14,36},{12,16,51},{12,14,37},{12,14,1},{12,14,52},{10,15,68},{11,14,38},{13,15,22},{13,14,13},{13,14,4},{13,14,13},{20,0,51},{13,14,34},{12,14,1},{10,14,37},{24,8,51}, +{10,14,37},{12,16,37},{12,16,37},{12,16,37},{12,14,36},{12,15,8},{12,14,1},{12,14,1},{12,13,5},{11,14,11},{12,13,9},{13,14,4},{13,14,4},{13,14,4},{13,13,8},{17,5,8},{12,14,1},{12,14,1},{12,13,5},{31,4,8},{12,13,5},{20,1,18},{12,15,4},{13,14,0},{12,14,0},{20,1,18},{31,5,18},{12,14,0},{0,14,36},{31,5,18},{0,14,36},{12,0,36}, +{12,0,36},{12,0,36},{12,0,36},{12,14,1},{12,14,1},{12,14,1},{12,13,1},{11,14,2},{11,14,2},{13,18,54},{13,16,40},{13,15,61},{13,15,36},{13,17,51},{13,15,37},{13,15,1},{13,15,52},{11,16,60},{12,15,40},{14,16,22},{14,15,13},{14,15,4},{14,15,13},{21,1,51},{12,16,29},{13,15,1},{11,15,37},{27,8,51},{11,15,37},{13,17,37},{13,17,37},{13,17,37}, +{13,15,36},{13,16,8},{13,15,1},{13,15,1},{13,14,5},{12,15,8},{13,14,9},{14,15,4},{14,15,4},{14,15,4},{14,14,8},{21,0,8},{13,15,1},{13,15,1},{13,14,5},{30,6,8},{13,14,5},{22,0,18},{13,16,4},{14,15,0},{13,15,0},{22,0,18},{30,7,18},{13,15,0},{0,15,36},{30,7,18},{0,15,36},{13,0,36},{13,0,36},{13,0,36},{13,0,36},{13,15,1}, +{13,15,1},{13,15,1},{13,14,1},{12,15,4},{12,15,4},{14,19,54},{14,17,40},{14,16,62},{14,16,38},{14,18,51},{14,16,27},{14,16,3},{14,15,69},{12,17,60},{13,16,54},{15,17,22},{15,16,9},{15,16,6},{15,16,21},{23,0,51},{14,16,27},{14,16,3},{12,16,50},{30,8,51},{12,16,50},{14,18,37},{14,18,37},{14,18,37},{14,16,37},{14,17,8},{14,16,2},{14,16,2}, +{14,15,5},{13,16,8},{14,15,9},{15,16,5},{15,16,5},{15,16,5},{15,15,8},{22,1,8},{14,16,2},{14,16,2},{14,15,5},{31,7,8},{14,15,5},{23,1,18},{14,17,4},{15,16,2},{14,16,2},{23,1,18},{27,10,18},{14,16,2},{0,16,50},{27,10,18},{0,16,50},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,16,1},{14,16,1},{14,16,1},{14,15,1},{13,16,4}, +{13,16,4},{15,20,68},{15,18,60},{16,17,68},{15,17,50},{15,19,53},{15,18,28},{15,17,5},{15,17,53},{15,17,68},{14,17,38},{16,18,22},{16,17,13},{16,17,4},{16,17,13},{24,1,52},{15,18,27},{15,17,4},{13,17,37},{31,9,52},{13,17,37},{15,19,50},{15,19,50},{15,19,50},{15,17,50},{15,18,11},{15,17,5},{15,17,5},{15,16,6},{14,17,11},{15,16,9},{16,17,4}, +{16,17,4},{16,17,4},{16,16,8},{24,0,8},{15,17,4},{15,17,4},{15,16,5},{24,12,8},{15,16,5},{25,0,18},{16,17,9},{16,17,0},{15,17,0},{25,0,18},{30,10,18},{15,17,0},{0,17,36},{30,10,18},{0,17,36},{15,0,50},{15,0,50},{15,0,50},{15,0,50},{15,18,2},{15,18,2},{15,18,2},{15,16,2},{14,17,2},{14,17,2},{16,21,54},{16,19,40},{16,18,61}, +{16,18,36},{16,20,51},{16,18,37},{16,18,1},{16,18,52},{14,19,68},{15,18,38},{17,19,22},{17,18,13},{17,18,4},{17,18,13},{24,4,51},{17,18,34},{16,18,1},{14,18,37},{28,12,51},{14,18,37},{16,20,37},{16,20,37},{16,20,37},{16,18,36},{16,19,8},{16,18,1},{16,18,1},{16,17,5},{15,18,11},{16,17,9},{17,18,4},{17,18,4},{17,18,4},{17,17,8},{25,1,8}, +{16,18,1},{16,18,1},{16,17,5},{27,12,8},{16,17,5},{26,1,18},{16,19,4},{17,18,0},{16,18,0},{26,1,18},{31,11,18},{16,18,0},{0,18,36},{31,11,18},{0,18,36},{16,0,36},{16,0,36},{16,0,36},{16,0,36},{16,18,1},{16,18,1},{16,18,1},{16,17,1},{15,18,2},{15,18,2},{17,22,54},{17,20,40},{17,19,61},{17,19,36},{17,21,51},{17,19,37},{17,19,1}, +{17,19,52},{15,20,60},{16,19,40},{18,20,22},{18,19,13},{18,19,4},{18,19,13},{25,5,51},{16,20,29},{17,19,1},{15,19,37},{31,12,51},{15,19,37},{17,21,37},{17,21,37},{17,21,37},{17,19,36},{17,20,8},{17,19,1},{17,19,1},{17,18,5},{16,19,8},{17,18,9},{18,19,4},{18,19,4},{18,19,4},{18,18,8},{27,0,8},{17,19,1},{17,19,1},{17,18,5},{30,12,8}, +{17,18,5},{27,2,18},{17,20,4},{18,19,0},{17,19,0},{27,2,18},{30,13,18},{17,19,0},{0,19,36},{30,13,18},{0,19,36},{17,0,36},{17,0,36},{17,0,36},{17,0,36},{17,19,1},{17,19,1},{17,19,1},{17,18,1},{16,19,4},{16,19,4},{18,23,54},{18,21,40},{18,20,62},{18,20,38},{18,22,51},{18,20,27},{18,20,3},{18,19,69},{16,21,60},{17,20,54},{19,21,22}, +{19,20,9},{19,20,6},{19,20,21},{29,0,51},{18,20,27},{18,20,3},{16,20,50},{30,14,51},{16,20,50},{18,22,37},{18,22,37},{18,22,37},{18,20,37},{18,21,8},{18,20,2},{18,20,2},{18,19,5},{17,20,8},{18,19,9},{19,20,5},{19,20,5},{19,20,5},{19,19,8},{28,1,8},{18,20,2},{18,20,2},{18,19,5},{31,13,8},{18,19,5},{27,5,18},{18,21,4},{19,20,2}, +{18,20,2},{27,5,18},{31,14,18},{18,20,2},{0,20,50},{31,14,18},{0,20,50},{18,0,36},{18,0,36},{18,0,36},{18,0,36},{18,20,1},{18,20,1},{18,20,1},{18,19,1},{17,20,4},{17,20,4},{19,24,68},{19,22,60},{20,21,68},{19,21,50},{19,23,53},{19,22,28},{19,21,5},{19,21,53},{19,21,68},{18,21,38},{20,22,22},{20,21,13},{20,21,4},{20,21,13},{30,1,52}, +{19,22,27},{19,21,4},{17,21,37},{31,15,52},{17,21,37},{19,23,50},{19,23,50},{19,23,50},{19,21,50},{19,22,11},{19,21,5},{19,21,5},{19,20,6},{18,21,11},{19,20,9},{20,21,4},{20,21,4},{20,21,4},{20,20,8},{28,4,8},{19,21,4},{19,21,4},{19,20,5},{28,16,8},{19,20,5},{31,0,18},{20,21,9},{20,21,0},{19,21,0},{31,0,18},{30,16,18},{19,21,0}, +{0,21,36},{30,16,18},{0,21,36},{19,0,50},{19,0,50},{19,0,50},{19,0,50},{19,22,2},{19,22,2},{19,22,2},{19,20,2},{18,21,2},{18,21,2},{20,25,54},{20,23,40},{20,22,61},{20,22,36},{20,24,51},{20,22,37},{20,22,1},{20,22,52},{18,23,68},{19,22,38},{21,23,22},{21,22,13},{21,22,4},{21,22,13},{28,8,51},{21,22,34},{20,22,1},{18,22,37},{24,20,51}, +{18,22,37},{20,24,37},{20,24,37},{20,24,37},{20,22,36},{20,23,8},{20,22,1},{20,22,1},{20,21,5},{19,22,11},{20,21,9},{21,22,4},{21,22,4},{21,22,4},{21,21,8},{29,5,8},{20,22,1},{20,22,1},{20,21,5},{31,16,8},{20,21,5},{31,3,18},{20,23,4},{21,22,0},{20,22,0},{31,3,18},{31,17,18},{20,22,0},{0,22,36},{31,17,18},{0,22,36},{20,0,36}, +{20,0,36},{20,0,36},{20,0,36},{20,22,1},{20,22,1},{20,22,1},{20,21,1},{19,22,2},{19,22,2},{21,26,54},{21,24,40},{21,23,61},{21,23,36},{21,25,51},{21,23,37},{21,23,1},{21,23,52},{19,24,60},{20,23,40},{22,24,22},{22,23,13},{22,23,4},{22,23,13},{29,9,51},{20,24,29},{21,23,1},{19,23,37},{27,20,51},{19,23,37},{21,25,37},{21,25,37},{21,25,37}, +{21,23,36},{21,24,8},{21,23,1},{21,23,1},{21,22,5},{20,23,8},{21,22,9},{22,23,4},{22,23,4},{22,23,4},{22,22,8},{31,4,8},{21,23,1},{21,23,1},{21,22,5},{30,18,8},{21,22,5},{31,6,18},{21,24,4},{22,23,0},{21,23,0},{31,6,18},{30,19,18},{21,23,0},{0,23,36},{30,19,18},{0,23,36},{21,0,36},{21,0,36},{21,0,36},{21,0,36},{21,23,1}, +{21,23,1},{21,23,1},{21,22,1},{20,23,4},{20,23,4},{22,27,54},{22,25,40},{22,24,62},{22,24,38},{22,26,51},{22,24,27},{22,24,3},{22,23,69},{20,25,60},{21,24,54},{23,25,22},{23,24,9},{23,24,6},{23,24,21},{31,8,51},{22,24,27},{22,24,3},{20,24,50},{30,20,51},{20,24,50},{22,26,37},{22,26,37},{22,26,37},{22,24,37},{22,25,8},{22,24,2},{22,24,2}, +{22,23,5},{21,24,8},{22,23,9},{23,24,5},{23,24,5},{23,24,5},{23,23,8},{31,7,8},{22,24,2},{22,24,2},{22,23,5},{31,19,8},{22,23,5},{31,9,18},{22,25,4},{23,24,2},{22,24,2},{31,9,18},{27,22,18},{22,24,2},{0,24,50},{27,22,18},{0,24,50},{22,0,36},{22,0,36},{22,0,36},{22,0,36},{22,24,1},{22,24,1},{22,24,1},{22,23,1},{21,24,4}, +{21,24,4},{23,28,68},{23,26,60},{24,25,68},{23,25,50},{23,27,53},{23,26,28},{23,25,5},{23,25,53},{23,25,68},{22,25,38},{24,26,22},{24,25,13},{24,25,4},{24,25,13},{31,11,52},{23,26,27},{23,25,4},{21,25,37},{31,21,52},{21,25,37},{23,27,50},{23,27,50},{23,27,50},{23,25,50},{23,26,11},{23,25,5},{23,25,5},{23,24,6},{22,25,11},{23,24,9},{24,25,4}, +{24,25,4},{24,25,4},{24,24,8},{28,16,8},{23,25,4},{23,25,4},{23,24,5},{24,24,8},{23,24,5},{31,12,18},{24,25,9},{24,25,0},{23,25,0},{31,12,18},{30,22,18},{23,25,0},{0,25,36},{30,22,18},{0,25,36},{23,0,50},{23,0,50},{23,0,50},{23,0,50},{23,26,2},{23,26,2},{23,26,2},{23,24,2},{22,25,2},{22,25,2},{24,29,54},{24,27,40},{24,26,61}, +{24,26,36},{24,28,51},{24,26,37},{24,26,1},{24,26,52},{22,27,68},{23,26,38},{25,27,22},{25,26,13},{25,26,4},{25,26,13},{28,20,51},{25,26,34},{24,26,1},{22,26,37},{28,24,51},{22,26,37},{24,28,37},{24,28,37},{24,28,37},{24,26,36},{24,27,8},{24,26,1},{24,26,1},{24,25,5},{23,26,11},{24,25,9},{25,26,4},{25,26,4},{25,26,4},{25,25,8},{29,17,8}, +{24,26,1},{24,26,1},{24,25,5},{27,24,8},{24,25,5},{31,15,18},{24,27,4},{25,26,0},{24,26,0},{31,15,18},{31,23,18},{24,26,0},{0,26,36},{31,23,18},{0,26,36},{24,0,36},{24,0,36},{24,0,36},{24,0,36},{24,26,1},{24,26,1},{24,26,1},{24,25,1},{23,26,2},{23,26,2},{25,30,54},{25,28,40},{25,27,61},{25,27,36},{25,29,51},{25,27,37},{25,27,1}, +{25,27,52},{23,28,60},{24,27,40},{26,28,22},{26,27,13},{26,27,4},{26,27,13},{29,21,51},{24,28,29},{25,27,1},{23,27,37},{31,24,51},{23,27,37},{25,29,37},{25,29,37},{25,29,37},{25,27,36},{25,28,8},{25,27,1},{25,27,1},{25,26,5},{24,27,8},{25,26,9},{26,27,4},{26,27,4},{26,27,4},{26,26,8},{31,16,8},{25,27,1},{25,27,1},{25,26,5},{30,24,8}, +{25,26,5},{31,18,18},{25,28,4},{26,27,0},{25,27,0},{31,18,18},{30,25,18},{25,27,0},{0,27,36},{30,25,18},{0,27,36},{25,0,36},{25,0,36},{25,0,36},{25,0,36},{25,27,1},{25,27,1},{25,27,1},{25,26,1},{24,27,4},{24,27,4},{26,31,54},{26,29,40},{26,28,62},{26,28,38},{26,30,51},{26,28,27},{26,28,3},{26,27,69},{24,29,60},{25,28,54},{27,29,22}, +{27,28,9},{27,28,6},{27,28,21},{31,20,51},{26,28,27},{26,28,3},{24,28,50},{30,26,51},{24,28,50},{26,30,37},{26,30,37},{26,30,37},{26,28,37},{26,29,8},{26,28,2},{26,28,2},{26,27,5},{25,28,8},{26,27,9},{27,28,5},{27,28,5},{27,28,5},{27,27,8},{31,19,8},{26,28,2},{26,28,2},{26,27,5},{31,25,8},{26,27,5},{31,21,18},{26,29,4},{27,28,2}, +{26,28,2},{31,21,18},{31,26,18},{26,28,2},{0,28,50},{31,26,18},{0,28,50},{26,0,36},{26,0,36},{26,0,36},{26,0,36},{26,28,1},{26,28,1},{26,28,1},{26,27,1},{25,28,4},{25,28,4},{28,30,86},{27,30,60},{28,29,68},{27,29,50},{27,31,53},{27,30,28},{27,29,5},{27,29,53},{27,29,68},{26,29,38},{28,30,22},{28,29,13},{28,29,4},{28,29,13},{31,23,52}, +{27,30,27},{27,29,4},{25,29,37},{31,27,52},{25,29,37},{27,31,50},{27,31,50},{27,31,50},{27,29,50},{27,30,11},{27,29,5},{27,29,5},{27,28,6},{26,29,11},{27,28,9},{28,29,4},{28,29,4},{28,29,4},{28,28,8},{28,28,8},{27,29,4},{27,29,4},{27,28,5},{28,28,8},{27,28,5},{31,24,18},{28,29,9},{28,29,0},{27,29,0},{31,24,18},{30,28,18},{27,29,0}, +{0,29,36},{30,28,18},{0,29,36},{27,0,50},{27,0,50},{27,0,50},{27,0,50},{27,30,2},{27,30,2},{27,30,2},{27,28,2},{26,29,2},{26,29,2},{29,31,86},{28,31,40},{28,30,61},{28,30,36},{28,31,72},{28,30,37},{28,30,1},{28,30,52},{26,31,68},{27,30,38},{29,31,22},{29,30,13},{29,30,4},{29,30,13},{31,26,52},{29,30,34},{28,30,1},{26,30,37},{30,29,52}, +{26,30,37},{28,31,40},{28,31,40},{28,31,40},{28,30,36},{28,31,8},{28,30,1},{28,30,1},{28,29,5},{27,30,11},{28,29,9},{29,30,4},{29,30,4},{29,30,4},{29,29,8},{29,29,8},{28,30,1},{28,30,1},{28,29,5},{31,28,8},{28,29,5},{31,27,18},{28,31,4},{29,30,0},{28,30,0},{31,27,18},{31,29,18},{28,30,0},{0,30,36},{31,29,18},{0,30,36},{28,0,36}, +{28,0,36},{28,0,36},{28,0,36},{28,30,1},{28,30,1},{28,30,1},{28,29,1},{27,30,2},{27,30,2},{30,31,104},{30,31,77},{29,31,61},{29,31,36},{30,31,116},{29,31,37},{29,31,1},{29,31,52},{28,31,72},{28,31,40},{30,31,40},{30,31,13},{30,31,4},{30,31,13},{31,29,52},{30,31,34},{29,31,1},{27,31,37},{31,30,52},{27,31,37},{29,31,61},{29,31,61},{29,31,61}, +{29,31,36},{29,31,26},{29,31,1},{29,31,1},{29,30,5},{28,31,8},{29,30,9},{30,31,4},{30,31,4},{30,31,4},{30,30,8},{31,28,8},{29,31,1},{29,31,1},{29,30,5},{30,30,8},{29,30,5},{31,30,18},{30,31,9},{30,31,0},{29,31,0},{31,30,18},{30,31,18},{29,31,0},{0,31,36},{30,31,18},{0,31,36},{29,0,36},{29,0,36},{29,0,36},{29,0,36},{29,31,1}, +{29,31,1},{29,31,1},{29,30,1},{28,31,4},{28,31,4},{31,31,68},{31,31,68},{31,31,68},{30,31,45},{31,31,68},{30,31,34},{30,31,25},{30,31,1},{30,31,23},{30,31,5},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{31,31,68},{31,31,68},{31,31,68},{30,31,45},{30,31,52},{30,31,25},{30,31,25}, +{30,31,1},{30,31,14},{30,31,5},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{30,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,36},{30,0,36},{30,0,36},{30,0,36},{30,31,16},{30,31,16},{30,31,16},{30,31,1},{30,31,5}, +{30,31,5},{0,4,72},{0,3,10},{0,2,1},{0,2,26},{0,3,154},{0,2,99},{0,2,51},{0,1,115},{0,1,173},{0,1,119},{0,4,72},{0,3,10},{0,2,1},{0,2,26},{1,1,154},{0,2,99},{0,2,51},{0,1,115},{3,0,154},{0,1,115},{0,2,0},{0,2,0},{0,2,0},{0,1,0},{0,1,13},{0,1,4},{0,1,4},{0,0,25},{0,0,25},{0,0,25},{0,2,0}, +{0,2,0},{0,2,0},{0,1,0},{0,1,13},{0,1,4},{0,1,4},{0,0,25},{1,0,13},{0,0,25},{0,4,72},{0,3,10},{0,2,1},{0,2,26},{0,4,72},{4,0,72},{0,2,26},{0,1,90},{4,0,72},{0,1,90},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,7,81},{0,5,13},{0,3,35}, +{0,3,19},{0,5,244},{0,3,115},{0,3,35},{0,2,139},{0,2,308},{0,2,164},{0,7,81},{0,5,13},{1,3,26},{0,3,19},{2,1,244},{0,3,115},{0,3,35},{0,2,139},{5,0,244},{0,2,139},{0,5,9},{0,5,9},{0,5,9},{0,2,18},{0,3,50},{0,2,13},{0,2,13},{0,1,29},{0,1,72},{0,1,33},{0,5,9},{0,5,9},{0,5,9},{0,2,18},{1,1,50}, +{0,2,13},{0,2,13},{0,1,29},{3,0,50},{0,1,29},{1,5,72},{0,5,4},{1,3,1},{0,3,10},{1,5,72},{7,0,72},{0,3,10},{0,2,90},{7,0,72},{0,2,90},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,1},{0,1,1},{0,1,1},{0,1,4},{0,1,8},{0,1,8},{1,8,145},{1,6,77},{1,4,98},{1,4,82},{0,8,243},{0,5,76},{0,4,1}, +{0,3,115},{0,4,364},{0,3,179},{1,8,81},{1,6,13},{2,4,25},{1,4,18},{4,0,243},{0,5,76},{0,4,1},{0,3,115},{8,0,243},{0,3,115},{1,6,73},{1,6,73},{1,6,73},{1,3,82},{0,6,50},{0,4,1},{0,4,1},{0,2,26},{0,3,114},{0,2,51},{1,6,9},{1,6,9},{1,6,9},{1,3,18},{3,0,50},{0,4,1},{0,4,1},{0,2,26},{6,0,50}, +{0,2,26},{5,0,72},{1,6,4},{2,4,0},{0,4,1},{5,0,72},{10,0,72},{0,4,1},{0,3,90},{10,0,72},{0,3,90},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,26},{0,2,26},{2,9,162},{2,7,94},{2,5,115},{2,5,99},{1,9,244},{1,6,77},{1,5,2},{1,4,106},{0,5,300},{0,4,105},{2,9,81}, +{2,7,13},{3,5,25},{2,5,18},{5,1,243},{1,6,76},{1,5,1},{0,4,89},{11,0,243},{0,4,89},{2,7,90},{2,7,90},{2,7,90},{2,4,94},{1,7,51},{1,5,2},{1,5,2},{1,3,27},{0,4,74},{0,3,35},{2,7,9},{2,7,9},{2,7,9},{2,4,13},{4,1,50},{1,5,1},{1,5,1},{0,4,25},{9,0,50},{0,4,25},{6,1,72},{2,7,4},{3,5,0}, +{1,5,1},{6,1,72},{13,0,72},{1,5,1},{0,4,80},{13,0,72},{0,4,80},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{1,5,1},{1,5,1},{1,5,1},{1,3,2},{0,3,10},{0,3,10},{3,10,154},{3,8,84},{3,6,117},{3,6,85},{2,10,244},{2,7,75},{2,6,2},{2,5,106},{0,7,253},{0,5,100},{3,10,90},{3,8,20},{4,6,26},{3,6,21},{7,0,244}, +{2,7,75},{2,6,2},{0,5,91},{14,0,244},{0,5,91},{3,8,80},{3,8,80},{3,8,80},{3,6,84},{2,8,52},{2,6,1},{2,6,1},{2,5,25},{0,6,52},{0,5,19},{3,8,16},{3,8,16},{3,8,16},{3,6,20},{4,4,50},{2,6,1},{2,6,1},{0,5,10},{12,0,50},{0,5,10},{8,0,72},{3,8,4},{4,6,1},{2,6,1},{8,0,72},{16,0,72},{2,6,1}, +{0,5,90},{16,0,72},{0,5,90},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{2,6,1},{2,6,1},{2,6,1},{2,4,1},{0,5,10},{0,5,10},{4,11,162},{4,9,94},{4,7,116},{4,7,100},{3,11,244},{3,8,76},{3,7,2},{3,6,106},{1,8,253},{1,6,100},{4,11,81},{4,9,13},{5,7,26},{4,7,19},{8,1,244},{3,8,76},{3,7,2},{1,6,91},{17,0,244}, +{1,6,91},{4,9,90},{4,9,90},{4,9,90},{4,6,99},{3,9,52},{3,7,1},{3,7,1},{3,6,25},{1,7,52},{1,6,19},{4,9,9},{4,9,9},{4,9,9},{4,6,18},{5,5,50},{3,7,1},{3,7,1},{1,6,10},{15,0,50},{1,6,10},{9,1,72},{4,9,4},{5,7,1},{3,7,1},{9,1,72},{19,0,72},{3,7,1},{0,6,90},{19,0,72},{0,6,90},{4,0,90}, +{4,0,90},{4,0,90},{4,0,90},{3,7,1},{3,7,1},{3,7,1},{3,5,1},{1,6,10},{1,6,10},{5,12,162},{5,10,94},{5,8,115},{5,8,99},{4,12,244},{4,9,77},{4,8,2},{4,7,116},{2,9,253},{2,7,100},{5,12,81},{5,10,13},{6,8,25},{5,8,18},{8,4,243},{4,9,76},{4,8,1},{2,7,91},{20,0,243},{2,7,91},{5,10,90},{5,10,90},{5,10,90}, +{5,7,99},{4,10,51},{4,8,2},{4,8,2},{4,6,27},{2,8,50},{2,7,19},{5,10,9},{5,10,9},{5,10,9},{5,7,18},{9,0,50},{4,8,1},{4,8,1},{2,7,10},{18,0,50},{2,7,10},{11,0,72},{5,10,4},{6,8,0},{4,8,1},{11,0,72},{22,0,72},{4,8,1},{0,7,90},{22,0,72},{0,7,90},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,8,1}, +{4,8,1},{4,8,1},{4,6,2},{2,7,10},{2,7,10},{6,13,162},{6,11,94},{6,9,115},{6,9,99},{5,13,244},{5,10,77},{5,9,2},{5,8,106},{3,10,253},{3,8,84},{6,13,81},{6,11,13},{7,9,25},{6,9,18},{9,5,243},{5,10,76},{5,9,1},{3,8,80},{23,0,243},{3,8,80},{6,11,90},{6,11,90},{6,11,90},{6,8,94},{5,11,51},{5,9,2},{5,9,2}, +{5,7,27},{3,9,50},{3,8,20},{6,11,9},{6,11,9},{6,11,9},{6,8,13},{10,1,50},{5,9,1},{5,9,1},{3,8,16},{21,0,50},{3,8,16},{12,1,72},{6,11,4},{7,9,0},{5,9,1},{12,1,72},{25,0,72},{5,9,1},{0,8,80},{25,0,72},{0,8,80},{6,0,90},{6,0,90},{6,0,90},{6,0,90},{5,9,1},{5,9,1},{5,9,1},{5,7,2},{3,8,4}, +{3,8,4},{7,14,154},{7,12,84},{7,10,117},{7,10,85},{6,14,244},{6,11,75},{6,10,2},{6,9,106},{4,11,253},{4,9,100},{7,14,90},{7,12,20},{8,10,26},{7,10,21},{13,0,244},{6,11,75},{6,10,2},{4,9,91},{26,0,244},{4,9,91},{7,12,80},{7,12,80},{7,12,80},{7,10,84},{6,12,52},{6,10,1},{6,10,1},{6,9,25},{4,10,52},{4,9,19},{7,12,16}, +{7,12,16},{7,12,16},{7,10,20},{12,0,50},{6,10,1},{6,10,1},{4,9,10},{24,0,50},{4,9,10},{12,4,72},{7,12,4},{8,10,1},{6,10,1},{12,4,72},{28,0,72},{6,10,1},{0,9,90},{28,0,72},{0,9,90},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{6,10,1},{6,10,1},{6,10,1},{6,8,1},{4,9,10},{4,9,10},{8,15,162},{8,13,94},{8,11,116}, +{8,11,100},{7,15,244},{7,12,76},{7,11,2},{7,10,106},{5,12,253},{5,10,100},{8,15,81},{8,13,13},{9,11,26},{8,11,19},{14,1,244},{7,12,76},{7,11,2},{5,10,91},{29,0,244},{5,10,91},{8,13,90},{8,13,90},{8,13,90},{8,10,99},{7,13,52},{7,11,1},{7,11,1},{7,10,25},{5,11,52},{5,10,19},{8,13,9},{8,13,9},{8,13,9},{8,10,18},{13,1,50}, +{7,11,1},{7,11,1},{5,10,10},{27,0,50},{5,10,10},{13,5,72},{8,13,4},{9,11,1},{7,11,1},{13,5,72},{31,0,72},{7,11,1},{0,10,90},{31,0,72},{0,10,90},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{7,11,1},{7,11,1},{7,11,1},{7,9,1},{5,10,10},{5,10,10},{9,16,162},{9,14,94},{9,12,115},{9,12,99},{8,16,244},{8,13,77},{8,12,2}, +{8,11,116},{6,13,253},{6,11,100},{9,16,81},{9,14,13},{10,12,25},{9,12,18},{16,0,243},{8,13,76},{8,12,1},{6,11,91},{24,4,243},{6,11,91},{9,14,90},{9,14,90},{9,14,90},{9,11,99},{8,14,51},{8,12,2},{8,12,2},{8,10,27},{6,12,50},{6,11,19},{9,14,9},{9,14,9},{9,14,9},{9,11,18},{15,0,50},{8,12,1},{8,12,1},{6,11,10},{30,0,50}, +{6,11,10},{17,0,72},{9,14,4},{10,12,0},{8,12,1},{17,0,72},{30,2,72},{8,12,1},{0,11,90},{30,2,72},{0,11,90},{9,0,90},{9,0,90},{9,0,90},{9,0,90},{8,12,1},{8,12,1},{8,12,1},{8,10,2},{6,11,10},{6,11,10},{10,17,162},{10,15,94},{10,13,115},{10,13,99},{9,17,244},{9,14,77},{9,13,2},{9,12,106},{7,14,253},{7,12,84},{10,17,81}, +{10,15,13},{11,13,25},{10,13,18},{17,1,243},{9,14,76},{9,13,1},{7,12,80},{27,4,243},{7,12,80},{10,15,90},{10,15,90},{10,15,90},{10,12,94},{9,15,51},{9,13,2},{9,13,2},{9,11,27},{7,13,50},{7,12,20},{10,15,9},{10,15,9},{10,15,9},{10,12,13},{16,1,50},{9,13,1},{9,13,1},{7,12,16},{31,1,50},{7,12,16},{18,1,72},{10,15,4},{11,13,0}, +{9,13,1},{18,1,72},{31,3,72},{9,13,1},{0,12,80},{31,3,72},{0,12,80},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,13,1},{9,13,1},{9,13,1},{9,11,2},{7,12,4},{7,12,4},{11,18,154},{11,16,84},{11,14,117},{11,14,85},{10,18,244},{10,15,75},{10,14,2},{10,13,106},{8,15,253},{8,13,100},{11,18,90},{11,16,20},{12,14,26},{11,14,21},{19,0,244}, +{10,15,75},{10,14,2},{8,13,91},{30,4,244},{8,13,91},{11,16,80},{11,16,80},{11,16,80},{11,14,84},{10,16,52},{10,14,1},{10,14,1},{10,13,25},{8,14,52},{8,13,19},{11,16,16},{11,16,16},{11,16,16},{11,14,20},{16,4,50},{10,14,1},{10,14,1},{8,13,10},{28,4,50},{8,13,10},{20,0,72},{11,16,4},{12,14,1},{10,14,1},{20,0,72},{24,8,72},{10,14,1}, +{0,13,90},{24,8,72},{0,13,90},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,14,1},{10,14,1},{10,14,1},{10,12,1},{8,13,10},{8,13,10},{12,19,162},{12,17,94},{12,15,116},{12,15,100},{11,19,244},{11,16,76},{11,15,2},{11,14,106},{9,16,253},{9,14,100},{12,19,81},{12,17,13},{13,15,26},{12,15,19},{20,1,244},{11,16,76},{11,15,2},{9,14,91},{31,5,244}, +{9,14,91},{12,17,90},{12,17,90},{12,17,90},{12,14,99},{11,17,52},{11,15,1},{11,15,1},{11,14,25},{9,15,52},{9,14,19},{12,17,9},{12,17,9},{12,17,9},{12,14,18},{17,5,50},{11,15,1},{11,15,1},{9,14,10},{31,4,50},{9,14,10},{21,1,72},{12,17,4},{13,15,1},{11,15,1},{21,1,72},{27,8,72},{11,15,1},{0,14,90},{27,8,72},{0,14,90},{12,0,90}, +{12,0,90},{12,0,90},{12,0,90},{11,15,1},{11,15,1},{11,15,1},{11,13,1},{9,14,10},{9,14,10},{13,20,162},{13,18,94},{13,16,115},{13,16,99},{12,20,244},{12,17,77},{12,16,2},{12,15,116},{10,17,253},{10,15,100},{13,20,81},{13,18,13},{14,16,25},{13,16,18},{20,4,243},{12,17,76},{12,16,1},{10,15,91},{28,8,243},{10,15,91},{13,18,90},{13,18,90},{13,18,90}, +{13,15,99},{12,18,51},{12,16,2},{12,16,2},{12,14,27},{10,16,50},{10,15,19},{13,18,9},{13,18,9},{13,18,9},{13,15,18},{21,0,50},{12,16,1},{12,16,1},{10,15,10},{30,6,50},{10,15,10},{23,0,72},{13,18,4},{14,16,0},{12,16,1},{23,0,72},{30,8,72},{12,16,1},{0,15,90},{30,8,72},{0,15,90},{13,0,90},{13,0,90},{13,0,90},{13,0,90},{12,16,1}, +{12,16,1},{12,16,1},{12,14,2},{10,15,10},{10,15,10},{14,21,162},{14,19,94},{14,17,115},{14,17,99},{13,21,244},{13,18,77},{13,17,2},{13,16,106},{11,18,253},{11,16,84},{14,21,81},{14,19,13},{15,17,25},{14,17,18},{21,5,243},{13,18,76},{13,17,1},{11,16,80},{31,8,243},{11,16,80},{14,19,90},{14,19,90},{14,19,90},{14,16,94},{13,19,51},{13,17,2},{13,17,2}, +{13,15,27},{11,17,50},{11,16,20},{14,19,9},{14,19,9},{14,19,9},{14,16,13},{22,1,50},{13,17,1},{13,17,1},{11,16,16},{31,7,50},{11,16,16},{24,1,72},{14,19,4},{15,17,0},{13,17,1},{24,1,72},{31,9,72},{13,17,1},{0,16,80},{31,9,72},{0,16,80},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{13,17,1},{13,17,1},{13,17,1},{13,15,2},{11,16,4}, +{11,16,4},{15,22,154},{15,20,84},{15,18,117},{15,18,85},{14,22,244},{14,19,75},{14,18,2},{14,17,106},{12,19,253},{12,17,100},{15,22,90},{15,20,20},{16,18,26},{15,18,21},{25,0,244},{14,19,75},{14,18,2},{12,17,91},{30,10,244},{12,17,91},{15,20,80},{15,20,80},{15,20,80},{15,18,84},{14,20,52},{14,18,1},{14,18,1},{14,17,25},{12,18,52},{12,17,19},{15,20,16}, +{15,20,16},{15,20,16},{15,18,20},{24,0,50},{14,18,1},{14,18,1},{12,17,10},{24,12,50},{12,17,10},{24,4,72},{15,20,4},{16,18,1},{14,18,1},{24,4,72},{28,12,72},{14,18,1},{0,17,90},{28,12,72},{0,17,90},{15,0,80},{15,0,80},{15,0,80},{15,0,80},{14,18,1},{14,18,1},{14,18,1},{14,16,1},{12,17,10},{12,17,10},{16,23,162},{16,21,94},{16,19,116}, +{16,19,100},{15,23,244},{15,20,76},{15,19,2},{15,18,106},{13,20,253},{13,18,100},{16,23,81},{16,21,13},{17,19,26},{16,19,19},{26,1,244},{15,20,76},{15,19,2},{13,18,91},{31,11,244},{13,18,91},{16,21,90},{16,21,90},{16,21,90},{16,18,99},{15,21,52},{15,19,1},{15,19,1},{15,18,25},{13,19,52},{13,18,19},{16,21,9},{16,21,9},{16,21,9},{16,18,18},{25,1,50}, +{15,19,1},{15,19,1},{13,18,10},{27,12,50},{13,18,10},{25,5,72},{16,21,4},{17,19,1},{15,19,1},{25,5,72},{31,12,72},{15,19,1},{0,18,90},{31,12,72},{0,18,90},{16,0,90},{16,0,90},{16,0,90},{16,0,90},{15,19,1},{15,19,1},{15,19,1},{15,17,1},{13,18,10},{13,18,10},{17,24,162},{17,22,94},{17,20,115},{17,20,99},{16,24,244},{16,21,77},{16,20,2}, +{16,19,116},{14,21,253},{14,19,100},{17,24,81},{17,22,13},{18,20,25},{17,20,18},{28,0,243},{16,21,76},{16,20,1},{14,19,91},{24,16,243},{14,19,91},{17,22,90},{17,22,90},{17,22,90},{17,19,99},{16,22,51},{16,20,2},{16,20,2},{16,18,27},{14,20,50},{14,19,19},{17,22,9},{17,22,9},{17,22,9},{17,19,18},{27,0,50},{16,20,1},{16,20,1},{14,19,10},{30,12,50}, +{14,19,10},{29,0,72},{17,22,4},{18,20,0},{16,20,1},{29,0,72},{30,14,72},{16,20,1},{0,19,90},{30,14,72},{0,19,90},{17,0,90},{17,0,90},{17,0,90},{17,0,90},{16,20,1},{16,20,1},{16,20,1},{16,18,2},{14,19,10},{14,19,10},{18,25,162},{18,23,94},{18,21,115},{18,21,99},{17,25,244},{17,22,77},{17,21,2},{17,20,106},{15,22,253},{15,20,84},{18,25,81}, +{18,23,13},{19,21,25},{18,21,18},{29,1,243},{17,22,76},{17,21,1},{15,20,80},{27,16,243},{15,20,80},{18,23,90},{18,23,90},{18,23,90},{18,20,94},{17,23,51},{17,21,2},{17,21,2},{17,19,27},{15,21,50},{15,20,20},{18,23,9},{18,23,9},{18,23,9},{18,20,13},{28,1,50},{17,21,1},{17,21,1},{15,20,16},{31,13,50},{15,20,16},{30,1,72},{18,23,4},{19,21,0}, +{17,21,1},{30,1,72},{31,15,72},{17,21,1},{0,20,80},{31,15,72},{0,20,80},{18,0,90},{18,0,90},{18,0,90},{18,0,90},{17,21,1},{17,21,1},{17,21,1},{17,19,2},{15,20,4},{15,20,4},{19,26,154},{19,24,84},{19,22,117},{19,22,85},{18,26,244},{18,23,75},{18,22,2},{18,21,106},{16,23,253},{16,21,100},{19,26,90},{19,24,20},{20,22,26},{19,22,21},{31,0,244}, +{18,23,75},{18,22,2},{16,21,91},{30,16,244},{16,21,91},{19,24,80},{19,24,80},{19,24,80},{19,22,84},{18,24,52},{18,22,1},{18,22,1},{18,21,25},{16,22,52},{16,21,19},{19,24,16},{19,24,16},{19,24,16},{19,22,20},{28,4,50},{18,22,1},{18,22,1},{16,21,10},{28,16,50},{16,21,10},{28,8,72},{19,24,4},{20,22,1},{18,22,1},{28,8,72},{24,20,72},{18,22,1}, +{0,21,90},{24,20,72},{0,21,90},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,22,1},{18,22,1},{18,22,1},{18,20,1},{16,21,10},{16,21,10},{20,27,162},{20,25,94},{20,23,116},{20,23,100},{19,27,244},{19,24,76},{19,23,2},{19,22,106},{17,24,253},{17,22,100},{20,27,81},{20,25,13},{21,23,26},{20,23,19},{31,3,244},{19,24,76},{19,23,2},{17,22,91},{31,17,244}, +{17,22,91},{20,25,90},{20,25,90},{20,25,90},{20,22,99},{19,25,52},{19,23,1},{19,23,1},{19,22,25},{17,23,52},{17,22,19},{20,25,9},{20,25,9},{20,25,9},{20,22,18},{29,5,50},{19,23,1},{19,23,1},{17,22,10},{31,16,50},{17,22,10},{29,9,72},{20,25,4},{21,23,1},{19,23,1},{29,9,72},{27,20,72},{19,23,1},{0,22,90},{27,20,72},{0,22,90},{20,0,90}, +{20,0,90},{20,0,90},{20,0,90},{19,23,1},{19,23,1},{19,23,1},{19,21,1},{17,22,10},{17,22,10},{21,28,162},{21,26,94},{21,24,115},{21,24,99},{20,28,244},{20,25,77},{20,24,2},{20,23,116},{18,25,253},{18,23,100},{21,28,81},{21,26,13},{22,24,25},{21,24,18},{28,12,243},{20,25,76},{20,24,1},{18,23,91},{28,20,243},{18,23,91},{21,26,90},{21,26,90},{21,26,90}, +{21,23,99},{20,26,51},{20,24,2},{20,24,2},{20,22,27},{18,24,50},{18,23,19},{21,26,9},{21,26,9},{21,26,9},{21,23,18},{31,4,50},{20,24,1},{20,24,1},{18,23,10},{30,18,50},{18,23,10},{31,8,72},{21,26,4},{22,24,0},{20,24,1},{31,8,72},{30,20,72},{20,24,1},{0,23,90},{30,20,72},{0,23,90},{21,0,90},{21,0,90},{21,0,90},{21,0,90},{20,24,1}, +{20,24,1},{20,24,1},{20,22,2},{18,23,10},{18,23,10},{22,29,162},{22,27,94},{22,25,115},{22,25,99},{21,29,244},{21,26,77},{21,25,2},{21,24,106},{19,26,253},{19,24,84},{22,29,81},{22,27,13},{23,25,25},{22,25,18},{29,13,243},{21,26,76},{21,25,1},{19,24,80},{31,20,243},{19,24,80},{22,27,90},{22,27,90},{22,27,90},{22,24,94},{21,27,51},{21,25,2},{21,25,2}, +{21,23,27},{19,25,50},{19,24,20},{22,27,9},{22,27,9},{22,27,9},{22,24,13},{31,7,50},{21,25,1},{21,25,1},{19,24,16},{31,19,50},{19,24,16},{31,11,72},{22,27,4},{23,25,0},{21,25,1},{31,11,72},{31,21,72},{21,25,1},{0,24,80},{31,21,72},{0,24,80},{22,0,90},{22,0,90},{22,0,90},{22,0,90},{21,25,1},{21,25,1},{21,25,1},{21,23,2},{19,24,4}, +{19,24,4},{23,30,154},{23,28,84},{23,26,117},{23,26,85},{22,30,244},{22,27,75},{22,26,2},{22,25,106},{20,27,253},{20,25,100},{23,30,90},{23,28,20},{24,26,26},{23,26,21},{31,12,244},{22,27,75},{22,26,2},{20,25,91},{30,22,244},{20,25,91},{23,28,80},{23,28,80},{23,28,80},{23,26,84},{22,28,52},{22,26,1},{22,26,1},{22,25,25},{20,26,52},{20,25,19},{23,28,16}, +{23,28,16},{23,28,16},{23,26,20},{28,16,50},{22,26,1},{22,26,1},{20,25,10},{24,24,50},{20,25,10},{28,20,72},{23,28,4},{24,26,1},{22,26,1},{28,20,72},{28,24,72},{22,26,1},{0,25,90},{28,24,72},{0,25,90},{23,0,80},{23,0,80},{23,0,80},{23,0,80},{22,26,1},{22,26,1},{22,26,1},{22,24,1},{20,25,10},{20,25,10},{24,31,162},{24,29,94},{24,27,116}, +{24,27,100},{23,31,244},{23,28,76},{23,27,2},{23,26,106},{21,28,253},{21,26,100},{24,31,81},{24,29,13},{25,27,26},{24,27,19},{31,15,244},{23,28,76},{23,27,2},{21,26,91},{31,23,244},{21,26,91},{24,29,90},{24,29,90},{24,29,90},{24,26,99},{23,29,52},{23,27,1},{23,27,1},{23,26,25},{21,27,52},{21,26,19},{24,29,9},{24,29,9},{24,29,9},{24,26,18},{29,17,50}, +{23,27,1},{23,27,1},{21,26,10},{27,24,50},{21,26,10},{29,21,72},{24,29,4},{25,27,1},{23,27,1},{29,21,72},{31,24,72},{23,27,1},{0,26,90},{31,24,72},{0,26,90},{24,0,90},{24,0,90},{24,0,90},{24,0,90},{23,27,1},{23,27,1},{23,27,1},{23,25,1},{21,26,10},{21,26,10},{25,31,180},{25,30,94},{25,28,115},{25,28,99},{24,31,265},{24,29,77},{24,28,2}, +{24,27,116},{22,29,253},{22,27,100},{26,30,97},{25,30,13},{26,28,25},{25,28,18},{28,24,243},{24,29,76},{24,28,1},{22,27,91},{24,28,243},{22,27,91},{25,30,90},{25,30,90},{25,30,90},{25,27,99},{24,30,51},{24,28,2},{24,28,2},{24,26,27},{22,28,50},{22,27,19},{25,30,9},{25,30,9},{25,30,9},{25,27,18},{31,16,50},{24,28,1},{24,28,1},{22,27,10},{30,24,50}, +{22,27,10},{31,20,72},{25,30,4},{26,28,0},{24,28,1},{31,20,72},{30,26,72},{24,28,1},{0,27,90},{30,26,72},{0,27,90},{25,0,90},{25,0,90},{25,0,90},{25,0,90},{24,28,1},{24,28,1},{24,28,1},{24,26,2},{22,27,10},{22,27,10},{26,31,234},{26,31,94},{26,29,115},{26,29,99},{26,31,325},{25,30,77},{25,29,2},{25,28,106},{23,30,253},{23,28,84},{27,31,97}, +{26,31,13},{27,29,25},{26,29,18},{29,25,243},{25,30,76},{25,29,1},{23,28,80},{27,28,243},{23,28,80},{26,31,90},{26,31,90},{26,31,90},{26,28,94},{25,31,51},{25,29,2},{25,29,2},{25,27,27},{23,29,50},{23,28,20},{26,31,9},{26,31,9},{26,31,9},{26,28,13},{31,19,50},{25,29,1},{25,29,1},{23,28,16},{31,25,50},{23,28,16},{31,23,72},{26,31,4},{27,29,0}, +{25,29,1},{31,23,72},{31,27,72},{25,29,1},{0,28,80},{31,27,72},{0,28,80},{26,0,90},{26,0,90},{26,0,90},{26,0,90},{25,29,1},{25,29,1},{25,29,1},{25,27,2},{23,28,4},{23,28,4},{27,31,314},{27,31,105},{27,30,117},{27,30,85},{27,31,347},{26,31,75},{26,30,2},{26,29,106},{24,31,253},{24,29,100},{28,31,115},{28,31,35},{28,30,26},{27,30,21},{31,24,244}, +{26,31,75},{26,30,2},{24,29,91},{30,28,244},{24,29,91},{27,31,89},{27,31,89},{27,31,89},{27,30,84},{26,31,82},{26,30,1},{26,30,1},{26,29,25},{24,30,52},{24,29,19},{28,30,25},{28,30,25},{28,30,25},{27,30,20},{28,28,50},{26,30,1},{26,30,1},{24,29,10},{28,28,50},{24,29,10},{31,26,74},{28,31,10},{28,30,1},{26,30,1},{31,26,74},{30,29,74},{26,30,1}, +{0,29,90},{30,29,74},{0,29,90},{27,0,80},{27,0,80},{27,0,80},{27,0,80},{26,30,1},{26,30,1},{26,30,1},{26,28,1},{24,29,10},{24,29,10},{28,31,371},{28,31,179},{28,31,115},{28,31,99},{28,31,387},{27,31,122},{27,31,1},{27,30,89},{26,31,279},{25,30,83},{29,31,146},{29,31,61},{29,31,25},{28,31,18},{31,27,221},{28,31,98},{27,31,1},{25,30,74},{31,29,221}, +{25,30,74},{28,31,115},{28,31,115},{28,31,115},{28,30,99},{27,31,122},{27,31,1},{27,31,1},{27,30,25},{25,31,52},{25,30,19},{29,31,25},{29,31,25},{29,31,25},{28,30,18},{29,29,50},{27,31,1},{27,31,1},{25,30,10},{31,28,50},{25,30,10},{31,29,61},{30,31,34},{29,31,0},{27,31,0},{31,29,61},{31,30,61},{27,31,0},{0,30,73},{31,30,61},{0,30,73},{28,0,90}, +{28,0,90},{28,0,90},{28,0,90},{27,31,1},{27,31,1},{27,31,1},{27,29,1},{25,30,10},{25,30,10},{29,31,275},{29,31,190},{29,31,154},{29,31,99},{29,31,270},{28,31,99},{28,31,35},{28,31,35},{28,31,195},{26,31,19},{30,31,70},{30,31,43},{30,31,34},{29,31,18},{31,29,94},{29,31,49},{29,31,13},{26,31,10},{31,30,94},{26,31,10},{29,31,154},{29,31,154},{29,31,154}, +{29,31,99},{29,31,149},{28,31,35},{28,31,35},{28,30,27},{27,31,77},{26,31,19},{30,31,34},{30,31,34},{30,31,34},{29,31,18},{31,28,50},{29,31,13},{29,31,13},{26,31,10},{30,30,50},{26,31,10},{31,30,9},{31,31,9},{30,31,9},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{29,0,90},{29,0,90},{29,0,90},{29,0,90},{28,31,10}, +{28,31,10},{28,31,10},{28,30,2},{26,31,10},{26,31,10},{30,31,162},{30,31,135},{30,31,126},{30,31,99},{30,31,154},{30,31,100},{29,31,73},{29,31,2},{29,31,109},{28,31,10},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,22},{30,31,19},{30,31,10},{29,31,1},{30,31,22},{29,31,1},{30,31,126},{30,31,126},{30,31,126},{30,31,99},{30,31,118},{29,31,73},{29,31,73}, +{29,31,2},{29,31,73},{28,31,10},{31,31,25},{31,31,25},{31,31,25},{30,31,18},{31,30,13},{30,31,10},{30,31,10},{29,31,1},{30,31,13},{29,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{30,0,90},{30,0,90},{30,0,90},{30,0,90},{29,31,37},{29,31,37},{29,31,37},{29,31,2},{28,31,10}, +{28,31,10},{0,7,200},{0,5,20},{0,4,20},{0,3,74},{0,5,441},{0,3,282},{0,3,138},{0,2,318},{0,2,487},{0,2,343},{0,7,200},{0,5,20},{0,4,20},{0,3,74},{2,1,441},{0,3,282},{0,3,138},{0,2,318},{5,0,441},{0,2,318},{0,3,1},{0,3,1},{0,3,1},{0,2,1},{0,2,41},{0,1,20},{0,1,20},{0,1,26},{0,1,45},{0,1,30},{0,3,1}, +{0,3,1},{0,3,1},{0,2,1},{1,0,41},{0,1,20},{0,1,20},{0,1,26},{2,0,41},{0,1,26},{1,5,200},{0,5,20},{0,4,20},{0,3,74},{1,5,200},{7,0,200},{0,3,74},{0,2,218},{7,0,200},{0,2,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,10,200},{0,7,5},{0,5,32}, +{0,4,41},{0,7,689},{0,5,369},{0,4,162},{0,3,474},{0,3,762},{0,3,538},{0,10,200},{0,7,5},{0,5,32},{0,4,41},{3,1,686},{0,5,369},{0,4,162},{0,3,474},{3,2,686},{0,3,474},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,3,145},{0,3,65},{0,3,65},{0,2,101},{0,1,173},{0,1,110},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{1,1,145}, +{0,3,65},{0,3,65},{0,2,101},{3,0,145},{0,2,101},{5,0,200},{0,7,5},{1,4,17},{0,4,41},{5,0,200},{10,0,200},{0,4,41},{0,3,218},{10,0,200},{0,3,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,13,249},{0,8,59},{1,6,97},{0,5,69},{0,10,728},{0,6,299},{0,5,56}, +{0,4,433},{0,4,884},{0,4,554},{1,11,201},{1,8,6},{1,6,33},{1,5,42},{5,0,728},{0,6,299},{0,5,56},{0,4,433},{10,0,728},{0,4,433},{0,9,50},{0,9,50},{0,9,50},{0,5,53},{0,6,162},{0,4,25},{0,4,25},{0,3,82},{0,3,226},{0,2,115},{1,7,2},{1,7,2},{1,7,2},{1,4,2},{3,0,162},{0,4,25},{0,4,25},{0,3,82},{6,0,162}, +{0,3,82},{6,1,200},{1,8,5},{2,5,17},{0,5,20},{6,1,200},{13,0,200},{0,5,20},{0,4,208},{13,0,200},{0,4,208},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,3,1},{0,3,1},{0,3,1},{0,1,4},{0,1,8},{0,1,8},{1,14,313},{1,9,123},{1,7,210},{1,6,133},{0,12,724},{0,8,251},{0,6,18},{0,5,352},{0,6,987},{0,5,521},{2,12,201}, +{2,9,6},{2,7,33},{2,6,42},{4,4,724},{0,8,251},{0,6,18},{0,5,352},{12,0,724},{0,5,352},{1,10,114},{1,10,114},{1,10,114},{1,6,117},{0,9,162},{0,6,2},{0,6,2},{0,4,49},{0,4,291},{0,3,146},{2,8,2},{2,8,2},{2,8,2},{2,5,2},{4,1,162},{0,6,2},{0,6,2},{0,4,49},{9,0,162},{0,4,49},{7,2,200},{2,9,5},{3,6,17}, +{0,6,17},{7,2,200},{14,1,200},{0,6,17},{0,5,208},{14,1,200},{0,5,208},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,2,50},{0,2,50},{2,15,410},{2,11,221},{2,8,324},{2,7,234},{1,14,739},{0,10,233},{0,8,40},{0,6,298},{0,7,1013},{0,6,426},{3,13,202},{3,10,1},{3,8,32},{3,7,41},{7,2,723}, +{0,10,217},{0,8,24},{0,6,282},{14,1,723},{0,6,282},{2,12,209},{2,12,209},{2,12,209},{2,7,209},{0,12,178},{1,7,20},{1,7,20},{0,5,26},{0,6,308},{0,5,91},{3,10,1},{3,10,1},{3,10,1},{3,6,4},{4,4,162},{1,7,4},{1,7,4},{0,5,10},{12,0,162},{0,5,10},{9,1,200},{3,10,1},{4,8,20},{0,8,20},{9,1,200},{19,0,200},{0,8,20}, +{0,6,218},{19,0,200},{0,6,218},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{1,7,16},{1,7,16},{1,7,16},{1,4,16},{0,4,53},{0,4,53},{3,16,408},{3,12,225},{3,9,324},{3,8,228},{2,15,739},{1,11,233},{2,8,33},{1,7,298},{0,9,875},{0,7,303},{4,14,201},{4,11,6},{4,9,33},{4,8,42},{7,5,723},{0,11,204},{2,8,17},{0,7,254},{15,2,723}, +{0,7,254},{3,12,209},{3,12,209},{3,12,209},{3,8,212},{1,13,178},{2,8,17},{2,8,17},{1,6,26},{0,7,229},{0,6,17},{4,10,2},{4,10,2},{4,10,2},{4,7,2},{5,5,162},{2,8,1},{2,8,1},{0,6,1},{15,0,162},{0,6,1},{11,0,200},{4,11,5},{5,8,17},{2,8,17},{11,0,200},{22,0,200},{2,8,17},{0,7,218},{22,0,200},{0,7,218},{3,0,208}, +{3,0,208},{3,0,208},{3,0,208},{2,8,16},{2,8,16},{2,8,16},{2,5,16},{0,6,16},{0,6,16},{4,17,418},{4,12,228},{4,10,315},{4,9,238},{3,16,744},{2,11,234},{3,9,33},{2,8,305},{0,11,828},{0,8,228},{5,15,201},{5,12,6},{5,10,33},{5,9,42},{11,0,728},{1,12,204},{3,9,17},{0,8,224},{22,0,728},{0,8,224},{4,13,219},{4,13,219},{4,13,219}, +{4,9,222},{3,12,178},{3,9,17},{3,9,17},{2,7,26},{0,9,178},{0,7,6},{5,11,2},{5,11,2},{5,11,2},{5,8,2},{9,0,162},{3,9,1},{3,9,1},{1,7,1},{18,0,162},{1,7,1},{12,1,200},{5,12,5},{6,9,17},{3,9,17},{12,1,200},{25,0,200},{3,9,17},{0,8,208},{25,0,200},{0,8,208},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{3,9,16}, +{3,9,16},{3,9,16},{3,6,16},{0,7,5},{0,7,5},{5,18,418},{5,13,228},{5,11,315},{5,10,238},{3,19,744},{3,12,225},{3,11,40},{3,9,305},{0,12,749},{0,9,225},{6,16,201},{6,13,6},{6,11,33},{6,10,42},{12,0,724},{2,13,204},{4,10,18},{0,9,209},{24,0,724},{0,9,209},{5,14,219},{5,14,219},{5,14,219},{5,10,222},{3,15,178},{3,11,24},{3,11,24}, +{3,8,32},{1,10,178},{1,8,5},{6,12,2},{6,12,2},{6,12,2},{6,9,2},{10,1,162},{4,10,2},{4,10,2},{2,8,1},{21,0,162},{2,8,1},{14,0,200},{6,13,5},{7,10,17},{4,10,17},{14,0,200},{26,1,200},{4,10,17},{0,9,208},{26,1,200},{0,9,208},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{3,12,17},{3,12,17},{3,12,17},{3,7,20},{1,8,5}, +{1,8,5},{6,19,410},{6,15,221},{6,12,324},{6,11,234},{5,18,739},{4,14,233},{4,12,40},{4,10,298},{0,14,724},{2,10,228},{7,17,202},{7,14,1},{7,12,32},{7,11,41},{14,0,723},{3,14,211},{4,12,24},{1,10,218},{26,1,723},{1,10,218},{6,16,209},{6,16,209},{6,16,209},{6,11,209},{4,16,178},{5,11,20},{5,11,20},{4,9,26},{1,12,171},{3,9,10},{7,14,1}, +{7,14,1},{7,14,1},{7,10,4},{12,0,162},{5,11,4},{5,11,4},{3,9,1},{24,0,162},{3,9,1},{13,5,200},{7,14,1},{8,12,20},{3,12,17},{13,5,200},{31,0,200},{3,12,17},{0,10,218},{31,0,200},{0,10,218},{6,0,208},{6,0,208},{6,0,208},{6,0,208},{5,11,16},{5,11,16},{5,11,16},{5,8,16},{3,9,9},{3,9,9},{7,20,408},{7,16,225},{7,13,324}, +{7,12,228},{6,19,739},{5,15,233},{6,12,33},{5,11,298},{1,15,724},{3,11,228},{8,18,201},{8,15,6},{8,13,33},{8,12,42},{15,1,723},{4,15,204},{6,12,17},{2,11,218},{27,2,723},{2,11,218},{7,16,209},{7,16,209},{7,16,209},{7,12,212},{5,17,178},{6,12,17},{6,12,17},{5,10,26},{2,13,171},{3,10,14},{8,14,2},{8,14,2},{8,14,2},{8,11,2},{13,1,162}, +{6,12,1},{6,12,1},{4,10,1},{27,0,162},{4,10,1},{17,0,200},{8,15,5},{9,12,17},{6,12,17},{17,0,200},{30,2,200},{6,12,17},{0,11,218},{30,2,200},{0,11,218},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{6,12,16},{6,12,16},{6,12,16},{6,9,16},{3,11,10},{3,11,10},{8,21,418},{8,16,228},{8,14,315},{8,13,238},{7,20,744},{6,15,234},{7,13,33}, +{6,12,305},{2,16,729},{3,12,225},{9,19,201},{9,16,6},{9,14,33},{9,13,42},{17,0,728},{5,16,204},{7,13,17},{3,12,209},{30,2,728},{3,12,209},{8,17,219},{8,17,219},{8,17,219},{8,13,222},{7,16,178},{7,13,17},{7,13,17},{6,11,26},{3,14,171},{4,11,6},{9,15,2},{9,15,2},{9,15,2},{9,12,2},{15,0,162},{7,13,1},{7,13,1},{5,11,1},{30,0,162}, +{5,11,1},{18,1,200},{9,16,5},{10,13,17},{7,13,17},{18,1,200},{31,3,200},{7,13,17},{0,12,208},{31,3,200},{0,12,208},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{7,13,16},{7,13,16},{7,13,16},{7,10,16},{4,11,5},{4,11,5},{9,22,418},{9,17,228},{9,15,315},{9,14,238},{7,23,744},{7,16,225},{7,15,40},{7,13,305},{3,17,729},{4,13,225},{10,20,201}, +{10,17,6},{10,15,33},{10,14,42},{16,4,724},{6,17,204},{8,14,18},{4,13,209},{28,4,724},{4,13,209},{9,18,219},{9,18,219},{9,18,219},{9,14,222},{7,19,178},{7,15,24},{7,15,24},{7,12,32},{5,14,178},{5,12,5},{10,16,2},{10,16,2},{10,16,2},{10,13,2},{16,1,162},{8,14,2},{8,14,2},{6,12,1},{31,1,162},{6,12,1},{19,2,200},{10,17,5},{11,14,17}, +{8,14,17},{19,2,200},{30,5,200},{8,14,17},{0,13,208},{30,5,200},{0,13,208},{9,0,218},{9,0,218},{9,0,218},{9,0,218},{7,16,17},{7,16,17},{7,16,17},{7,11,20},{5,12,5},{5,12,5},{10,23,410},{10,19,221},{10,16,324},{10,15,234},{9,22,739},{8,18,233},{8,16,40},{8,14,298},{4,18,724},{6,14,228},{11,21,202},{11,18,1},{11,16,32},{11,15,41},{19,2,723}, +{7,18,211},{8,16,24},{5,14,218},{30,5,723},{5,14,218},{10,20,209},{10,20,209},{10,20,209},{10,15,209},{8,20,178},{9,15,20},{9,15,20},{8,13,26},{5,16,171},{7,13,10},{11,18,1},{11,18,1},{11,18,1},{11,14,4},{16,4,162},{9,15,4},{9,15,4},{7,13,1},{28,4,162},{7,13,1},{21,1,200},{11,18,1},{12,16,20},{7,16,17},{21,1,200},{27,8,200},{7,16,17}, +{0,14,218},{27,8,200},{0,14,218},{10,0,208},{10,0,208},{10,0,208},{10,0,208},{9,15,16},{9,15,16},{9,15,16},{9,12,16},{7,13,9},{7,13,9},{11,24,408},{11,20,225},{11,17,324},{11,16,228},{10,23,739},{9,19,233},{10,16,33},{9,15,298},{5,19,724},{7,15,228},{12,22,201},{12,19,6},{12,17,33},{12,16,42},{19,5,723},{8,19,204},{10,16,17},{6,15,218},{31,6,723}, +{6,15,218},{11,20,209},{11,20,209},{11,20,209},{11,16,212},{9,21,178},{10,16,17},{10,16,17},{9,14,26},{6,17,171},{7,14,14},{12,18,2},{12,18,2},{12,18,2},{12,15,2},{17,5,162},{10,16,1},{10,16,1},{8,14,1},{31,4,162},{8,14,1},{23,0,200},{12,19,5},{13,16,17},{10,16,17},{23,0,200},{30,8,200},{10,16,17},{0,15,218},{30,8,200},{0,15,218},{11,0,208}, +{11,0,208},{11,0,208},{11,0,208},{10,16,16},{10,16,16},{10,16,16},{10,13,16},{7,15,10},{7,15,10},{12,25,418},{12,20,228},{12,18,315},{12,17,238},{11,24,744},{10,19,234},{11,17,33},{10,16,305},{6,20,729},{7,16,225},{13,23,201},{13,20,6},{13,18,33},{13,17,42},{23,0,728},{9,20,204},{11,17,17},{7,16,209},{30,8,728},{7,16,209},{12,21,219},{12,21,219},{12,21,219}, +{12,17,222},{11,20,178},{11,17,17},{11,17,17},{10,15,26},{7,18,171},{8,15,6},{13,19,2},{13,19,2},{13,19,2},{13,16,2},{21,0,162},{11,17,1},{11,17,1},{9,15,1},{30,6,162},{9,15,1},{24,1,200},{13,20,5},{14,17,17},{11,17,17},{24,1,200},{31,9,200},{11,17,17},{0,16,208},{31,9,200},{0,16,208},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{11,17,16}, +{11,17,16},{11,17,16},{11,14,16},{8,15,5},{8,15,5},{13,26,418},{13,21,228},{13,19,315},{13,18,238},{11,27,744},{11,20,225},{11,19,40},{11,17,305},{7,21,729},{8,17,225},{14,24,201},{14,21,6},{14,19,33},{14,18,42},{24,0,724},{10,21,204},{12,18,18},{8,17,209},{24,12,724},{8,17,209},{13,22,219},{13,22,219},{13,22,219},{13,18,222},{11,23,178},{11,19,24},{11,19,24}, +{11,16,32},{9,18,178},{9,16,5},{14,20,2},{14,20,2},{14,20,2},{14,17,2},{22,1,162},{12,18,2},{12,18,2},{10,16,1},{31,7,162},{10,16,1},{26,0,200},{14,21,5},{15,18,17},{12,18,17},{26,0,200},{30,11,200},{12,18,17},{0,17,208},{30,11,200},{0,17,208},{13,0,218},{13,0,218},{13,0,218},{13,0,218},{11,20,17},{11,20,17},{11,20,17},{11,15,20},{9,16,5}, +{9,16,5},{14,27,410},{14,23,221},{14,20,324},{14,19,234},{13,26,739},{12,22,233},{12,20,40},{12,18,298},{8,22,724},{10,18,228},{15,25,202},{15,22,1},{15,20,32},{15,19,41},{26,0,723},{11,22,211},{12,20,24},{9,18,218},{30,11,723},{9,18,218},{14,24,209},{14,24,209},{14,24,209},{14,19,209},{12,24,178},{13,19,20},{13,19,20},{12,17,26},{9,20,171},{11,17,10},{15,22,1}, +{15,22,1},{15,22,1},{15,18,4},{24,0,162},{13,19,4},{13,19,4},{11,17,1},{24,12,162},{11,17,1},{25,5,200},{15,22,1},{16,20,20},{11,20,17},{25,5,200},{31,12,200},{11,20,17},{0,18,218},{31,12,200},{0,18,218},{14,0,208},{14,0,208},{14,0,208},{14,0,208},{13,19,16},{13,19,16},{13,19,16},{13,16,16},{11,17,9},{11,17,9},{15,28,408},{15,24,225},{15,21,324}, +{15,20,228},{14,27,739},{13,23,233},{14,20,33},{13,19,298},{9,23,724},{11,19,228},{16,26,201},{16,23,6},{16,21,33},{16,20,42},{27,1,723},{12,23,204},{14,20,17},{10,19,218},{27,14,723},{10,19,218},{15,24,209},{15,24,209},{15,24,209},{15,20,212},{13,25,178},{14,20,17},{14,20,17},{13,18,26},{10,21,171},{11,18,14},{16,22,2},{16,22,2},{16,22,2},{16,19,2},{25,1,162}, +{14,20,1},{14,20,1},{12,18,1},{27,12,162},{12,18,1},{29,0,200},{16,23,5},{17,20,17},{14,20,17},{29,0,200},{30,14,200},{14,20,17},{0,19,218},{30,14,200},{0,19,218},{15,0,208},{15,0,208},{15,0,208},{15,0,208},{14,20,16},{14,20,16},{14,20,16},{14,17,16},{11,19,10},{11,19,10},{16,29,418},{16,24,228},{16,22,315},{16,21,238},{15,28,744},{14,23,234},{15,21,33}, +{14,20,305},{10,24,729},{11,20,225},{17,27,201},{17,24,6},{17,22,33},{17,21,42},{29,0,728},{13,24,204},{15,21,17},{11,20,209},{30,14,728},{11,20,209},{16,25,219},{16,25,219},{16,25,219},{16,21,222},{15,24,178},{15,21,17},{15,21,17},{14,19,26},{11,22,171},{12,19,6},{17,23,2},{17,23,2},{17,23,2},{17,20,2},{27,0,162},{15,21,1},{15,21,1},{13,19,1},{30,12,162}, +{13,19,1},{30,1,200},{17,24,5},{18,21,17},{15,21,17},{30,1,200},{31,15,200},{15,21,17},{0,20,208},{31,15,200},{0,20,208},{16,0,218},{16,0,218},{16,0,218},{16,0,218},{15,21,16},{15,21,16},{15,21,16},{15,18,16},{12,19,5},{12,19,5},{17,30,418},{17,25,228},{17,23,315},{17,22,238},{15,31,744},{15,24,225},{15,23,40},{15,21,305},{11,25,729},{12,21,225},{18,28,201}, +{18,25,6},{18,23,33},{18,22,42},{28,4,724},{14,25,204},{16,22,18},{12,21,209},{28,16,724},{12,21,209},{17,26,219},{17,26,219},{17,26,219},{17,22,222},{15,27,178},{15,23,24},{15,23,24},{15,20,32},{13,22,178},{13,20,5},{18,24,2},{18,24,2},{18,24,2},{18,21,2},{28,1,162},{16,22,2},{16,22,2},{14,20,1},{31,13,162},{14,20,1},{31,2,200},{18,25,5},{19,22,17}, +{16,22,17},{31,2,200},{30,17,200},{16,22,17},{0,21,208},{30,17,200},{0,21,208},{17,0,218},{17,0,218},{17,0,218},{17,0,218},{15,24,17},{15,24,17},{15,24,17},{15,19,20},{13,20,5},{13,20,5},{18,31,410},{18,27,221},{18,24,324},{18,23,234},{17,30,739},{16,26,233},{16,24,40},{16,22,298},{12,26,724},{14,22,228},{19,29,202},{19,26,1},{19,24,32},{19,23,41},{31,2,723}, +{15,26,211},{16,24,24},{13,22,218},{30,17,723},{13,22,218},{18,28,209},{18,28,209},{18,28,209},{18,23,209},{16,28,178},{17,23,20},{17,23,20},{16,21,26},{13,24,171},{15,21,10},{19,26,1},{19,26,1},{19,26,1},{19,22,4},{28,4,162},{17,23,4},{17,23,4},{15,21,1},{28,16,162},{15,21,1},{29,9,200},{19,26,1},{20,24,20},{15,24,17},{29,9,200},{27,20,200},{15,24,17}, +{0,22,218},{27,20,200},{0,22,218},{18,0,208},{18,0,208},{18,0,208},{18,0,208},{17,23,16},{17,23,16},{17,23,16},{17,20,16},{15,21,9},{15,21,9},{19,31,426},{19,28,225},{19,25,324},{19,24,228},{18,31,739},{17,27,233},{18,24,33},{17,23,298},{13,27,724},{15,23,228},{20,30,201},{20,27,6},{20,25,33},{20,24,42},{31,5,723},{16,27,204},{18,24,17},{14,23,218},{31,18,723}, +{14,23,218},{19,28,209},{19,28,209},{19,28,209},{19,24,212},{17,29,178},{18,24,17},{18,24,17},{17,22,26},{14,25,171},{15,22,14},{20,26,2},{20,26,2},{20,26,2},{20,23,2},{29,5,162},{18,24,1},{18,24,1},{16,22,1},{31,16,162},{16,22,1},{31,8,200},{20,27,5},{21,24,17},{18,24,17},{31,8,200},{30,20,200},{18,24,17},{0,23,218},{30,20,200},{0,23,218},{19,0,208}, +{19,0,208},{19,0,208},{19,0,208},{18,24,16},{18,24,16},{18,24,16},{18,21,16},{15,23,10},{15,23,10},{20,31,468},{20,28,228},{20,26,315},{20,25,238},{19,31,747},{18,27,234},{19,25,33},{18,24,305},{14,28,729},{15,24,225},{21,31,201},{21,28,6},{21,26,33},{21,25,42},{31,8,728},{17,28,204},{19,25,17},{15,24,209},{30,20,728},{15,24,209},{20,29,219},{20,29,219},{20,29,219}, +{20,25,222},{19,28,178},{19,25,17},{19,25,17},{18,23,26},{15,26,171},{16,23,6},{21,27,2},{21,27,2},{21,27,2},{21,24,2},{31,4,162},{19,25,1},{19,25,1},{17,23,1},{30,18,162},{17,23,1},{31,11,200},{21,28,5},{22,25,17},{19,25,17},{31,11,200},{31,21,200},{19,25,17},{0,24,208},{31,21,200},{0,24,208},{20,0,218},{20,0,218},{20,0,218},{20,0,218},{19,25,16}, +{19,25,16},{19,25,16},{19,22,16},{16,23,5},{16,23,5},{21,31,546},{21,29,228},{21,27,315},{21,26,238},{20,31,788},{19,28,225},{19,27,40},{19,25,305},{15,29,729},{16,25,225},{22,31,219},{22,29,6},{22,27,33},{22,26,42},{28,16,724},{18,29,204},{20,26,18},{16,25,209},{24,24,724},{16,25,209},{21,30,219},{21,30,219},{21,30,219},{21,26,222},{19,31,178},{19,27,24},{19,27,24}, +{19,24,32},{17,26,178},{17,24,5},{22,28,2},{22,28,2},{22,28,2},{22,25,2},{31,7,162},{20,26,2},{20,26,2},{18,24,1},{31,19,162},{18,24,1},{31,14,200},{22,29,5},{23,26,17},{20,26,17},{31,14,200},{30,23,200},{20,26,17},{0,25,208},{30,23,200},{0,25,208},{21,0,218},{21,0,218},{21,0,218},{21,0,218},{19,28,17},{19,28,17},{19,28,17},{19,23,20},{17,24,5}, +{17,24,5},{23,31,672},{22,31,221},{22,28,324},{22,27,234},{22,31,888},{20,30,233},{20,28,40},{20,26,298},{16,30,724},{18,26,228},{23,31,272},{23,30,1},{23,28,32},{23,27,41},{31,14,723},{19,30,211},{20,28,24},{17,26,218},{30,23,723},{17,26,218},{22,31,212},{22,31,212},{22,31,212},{22,27,209},{21,30,180},{21,27,20},{21,27,20},{20,25,26},{17,28,171},{19,25,10},{23,30,1}, +{23,30,1},{23,30,1},{23,26,4},{28,16,162},{21,27,4},{21,27,4},{19,25,1},{24,24,162},{19,25,1},{29,21,200},{23,30,1},{24,28,20},{19,28,17},{29,21,200},{31,24,200},{19,28,17},{0,26,218},{31,24,200},{0,26,218},{22,0,208},{22,0,208},{22,0,208},{22,0,208},{21,27,16},{21,27,16},{21,27,16},{21,24,16},{19,25,9},{19,25,9},{24,31,770},{23,31,228},{23,29,324}, +{23,28,228},{23,31,932},{21,31,233},{22,28,33},{21,27,298},{17,31,724},{19,27,228},{25,31,299},{24,31,6},{24,29,33},{24,28,42},{31,17,723},{20,31,204},{22,28,17},{18,27,218},{27,26,723},{18,27,218},{23,31,224},{23,31,224},{23,31,224},{23,28,212},{22,31,180},{22,28,17},{22,28,17},{21,26,26},{18,29,171},{19,26,14},{24,30,2},{24,30,2},{24,30,2},{24,27,2},{29,17,162}, +{22,28,1},{22,28,1},{20,26,1},{27,24,162},{20,26,1},{31,20,200},{24,31,5},{25,28,17},{22,28,17},{31,20,200},{30,26,200},{22,28,17},{0,27,218},{30,26,200},{0,27,218},{23,0,208},{23,0,208},{23,0,208},{23,0,208},{22,28,16},{22,28,16},{22,28,16},{22,25,16},{19,27,10},{19,27,10},{25,31,884},{24,31,303},{24,30,315},{24,29,238},{24,31,1025},{22,31,234},{23,29,33}, +{22,28,305},{19,31,747},{19,28,225},{26,31,353},{25,31,27},{25,30,33},{25,29,42},{31,20,728},{22,31,218},{23,29,17},{19,28,209},{30,26,728},{19,28,209},{24,31,254},{24,31,254},{24,31,254},{24,29,222},{23,31,196},{23,29,17},{23,29,17},{22,27,26},{19,30,171},{20,27,6},{25,31,2},{25,31,2},{25,31,2},{25,28,2},{31,16,162},{23,29,1},{23,29,1},{21,27,1},{30,24,162}, +{21,27,1},{31,23,200},{26,31,20},{26,29,17},{23,29,17},{31,23,200},{31,27,200},{23,29,17},{0,28,208},{31,27,200},{0,28,208},{24,0,218},{24,0,218},{24,0,218},{24,0,218},{23,29,16},{23,29,16},{23,29,16},{23,26,16},{20,27,5},{20,27,5},{26,31,1034},{25,31,468},{25,31,315},{25,30,238},{25,31,1172},{24,31,291},{23,31,40},{23,29,305},{21,31,837},{20,29,225},{27,31,409}, +{26,31,117},{26,31,33},{26,30,42},{28,28,724},{24,31,266},{24,30,18},{20,29,209},{28,28,724},{20,29,209},{25,31,299},{25,31,299},{25,31,299},{25,30,222},{24,31,237},{23,31,24},{23,31,24},{23,28,32},{21,30,178},{21,28,5},{26,31,17},{26,31,17},{26,31,17},{26,29,2},{31,19,162},{24,30,2},{24,30,2},{22,28,1},{31,25,162},{22,28,1},{31,26,200},{27,31,53},{27,30,17}, +{24,30,17},{31,26,200},{30,29,200},{24,30,17},{0,29,208},{30,29,200},{0,29,208},{25,0,218},{25,0,218},{25,0,218},{25,0,218},{23,31,20},{23,31,20},{23,31,20},{23,27,20},{21,28,5},{21,28,5},{27,31,933},{27,31,570},{26,31,377},{26,31,209},{27,31,1054},{25,31,309},{25,31,20},{24,30,193},{23,31,735},{22,30,123},{28,31,338},{28,31,146},{27,31,49},{27,31,16},{29,29,546}, +{26,31,222},{25,31,4},{21,30,113},{31,28,546},{21,30,113},{26,31,377},{26,31,377},{26,31,377},{26,31,209},{26,31,338},{25,31,20},{25,31,20},{24,29,26},{22,31,173},{23,29,10},{27,31,49},{27,31,49},{27,31,49},{27,30,4},{28,28,162},{25,31,4},{25,31,4},{23,29,1},{28,28,162},{23,29,1},{31,28,113},{29,31,52},{28,31,1},{26,31,1},{31,28,113},{30,30,113},{26,31,1}, +{0,30,113},{30,30,113},{0,30,113},{26,0,208},{26,0,208},{26,0,208},{26,0,208},{25,31,16},{25,31,16},{25,31,16},{25,28,16},{23,29,9},{23,29,9},{28,31,779},{27,31,554},{27,31,433},{27,31,224},{28,31,859},{26,31,270},{26,31,74},{25,30,90},{24,31,590},{23,31,59},{29,31,218},{29,31,133},{28,31,82},{28,31,2},{31,27,333},{27,31,146},{27,31,25},{22,31,49},{31,29,333}, +{22,31,49},{27,31,433},{27,31,433},{27,31,433},{27,31,224},{27,31,378},{26,31,74},{26,31,74},{25,30,26},{24,31,229},{23,30,14},{28,31,82},{28,31,82},{28,31,82},{28,31,2},{29,29,162},{27,31,25},{27,31,25},{24,30,1},{31,28,162},{24,30,1},{31,30,25},{30,31,10},{30,31,1},{28,31,1},{31,30,25},{30,31,25},{28,31,1},{0,31,49},{30,31,25},{0,31,49},{27,0,208}, +{27,0,208},{27,0,208},{27,0,208},{26,31,25},{26,31,25},{26,31,25},{26,29,16},{23,31,10},{23,31,10},{29,31,684},{28,31,538},{28,31,474},{28,31,282},{28,31,682},{27,31,283},{27,31,162},{26,31,25},{26,31,482},{24,31,5},{30,31,153},{30,31,126},{30,31,117},{29,31,37},{31,29,193},{29,31,108},{28,31,65},{25,31,0},{31,30,193},{25,31,0},{28,31,474},{28,31,474},{28,31,474}, +{28,31,282},{28,31,426},{27,31,162},{27,31,162},{26,31,25},{26,31,286},{24,31,5},{30,31,117},{30,31,117},{30,31,117},{29,31,37},{31,28,145},{28,31,65},{28,31,65},{25,31,0},{30,30,145},{25,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,218},{28,0,218},{28,0,218},{28,0,218},{27,31,41}, +{27,31,41},{27,31,41},{27,30,16},{24,31,5},{24,31,5},{29,31,460},{29,31,375},{29,31,339},{29,31,254},{29,31,415},{28,31,202},{28,31,138},{27,31,20},{27,31,295},{26,31,26},{30,31,73},{30,31,46},{30,31,37},{30,31,10},{31,30,54},{30,31,27},{30,31,18},{28,31,1},{30,31,54},{28,31,1},{29,31,339},{29,31,339},{29,31,339},{29,31,254},{29,31,294},{28,31,138},{28,31,138}, +{27,31,20},{27,31,174},{26,31,26},{30,31,37},{30,31,37},{30,31,37},{30,31,10},{31,29,45},{30,31,18},{30,31,18},{28,31,1},{31,30,45},{28,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{29,0,218},{29,0,218},{29,0,218},{29,0,218},{28,31,74},{28,31,74},{28,31,74},{27,31,20},{26,31,26}, +{26,31,26},{0,10,421},{0,7,52},{0,5,1},{0,4,162},{0,7,926},{0,5,590},{0,4,283},{0,3,701},{0,3,1005},{0,3,765},{0,10,421},{0,7,52},{0,5,1},{0,4,162},{3,1,925},{0,5,590},{0,4,283},{0,3,701},{3,2,925},{0,3,701},{0,5,0},{0,5,0},{0,5,0},{0,2,9},{0,2,89},{0,2,34},{0,2,34},{0,1,50},{0,1,93},{0,1,54},{0,5,0}, +{0,5,0},{0,5,0},{0,2,9},{1,0,89},{0,2,34},{0,2,34},{0,1,50},{2,0,89},{0,1,50},{5,0,421},{0,7,52},{0,5,1},{0,4,162},{5,0,421},{10,0,421},{0,4,162},{0,3,445},{10,0,421},{0,3,445},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,13,421},{0,9,10},{0,6,26}, +{0,5,117},{0,9,1261},{0,6,701},{0,5,286},{0,4,917},{0,4,1390},{0,3,1005},{0,13,421},{0,9,10},{0,6,26},{0,5,117},{4,1,1261},{0,6,701},{0,5,286},{0,4,917},{9,0,1261},{0,4,917},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,4,221},{0,3,89},{0,3,89},{0,2,125},{0,2,246},{0,2,150},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{2,0,221}, +{0,3,89},{0,3,89},{0,2,125},{4,0,221},{0,2,125},{6,1,421},{0,9,10},{1,6,1},{0,5,117},{6,1,421},{13,0,421},{0,5,117},{0,4,433},{13,0,421},{0,4,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,16,430},{0,11,14},{0,7,110},{0,7,91},{0,11,1514},{0,7,737},{0,6,259}, +{0,4,1002},{0,5,1710},{0,4,1123},{0,16,430},{0,11,14},{1,7,51},{0,7,91},{5,1,1514},{0,7,737},{0,6,259},{0,4,1002},{11,0,1514},{0,4,1002},{0,11,10},{0,11,10},{0,11,10},{0,5,13},{0,6,338},{0,5,104},{0,5,104},{0,3,194},{0,3,402},{0,2,243},{0,11,10},{0,11,10},{0,11,10},{0,5,13},{3,0,338},{0,5,104},{0,5,104},{0,3,194},{6,0,338}, +{0,3,194},{8,0,421},{0,11,5},{2,7,1},{0,7,82},{8,0,421},{16,0,421},{0,7,82},{0,5,433},{16,0,421},{0,5,433},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,1},{0,1,1},{0,1,1},{0,1,4},{0,1,8},{0,1,8},{1,17,494},{1,12,78},{1,8,173},{1,8,154},{0,14,1514},{0,9,602},{0,7,146},{0,6,874},{0,7,1875},{0,5,1066},{1,17,430}, +{1,12,14},{2,8,50},{1,8,90},{7,0,1514},{0,9,602},{0,7,146},{0,6,874},{14,0,1514},{0,6,874},{1,12,74},{1,12,74},{1,12,74},{1,6,77},{0,9,338},{0,6,50},{0,6,50},{0,4,137},{0,4,467},{0,3,258},{1,12,10},{1,12,10},{1,12,10},{1,6,13},{4,1,338},{0,6,50},{0,6,50},{0,4,137},{9,0,338},{0,4,137},{9,1,421},{1,12,5},{3,8,1}, +{0,8,49},{9,1,421},{19,0,421},{0,8,49},{0,6,433},{19,0,421},{0,6,433},{1,0,73},{1,0,73},{1,0,73},{1,0,73},{0,4,0},{0,4,0},{0,4,0},{0,2,1},{0,2,26},{0,2,26},{1,20,629},{1,14,233},{2,10,385},{1,9,245},{0,17,1517},{0,11,521},{0,9,26},{0,7,769},{0,8,2025},{0,6,1085},{3,16,437},{2,13,17},{3,9,53},{2,9,81},{8,1,1517}, +{0,11,521},{0,9,26},{0,7,769},{17,0,1517},{0,7,769},{1,15,208},{1,15,208},{1,15,208},{1,8,208},{0,12,338},{0,8,8},{0,8,8},{0,5,74},{0,5,579},{0,5,243},{3,11,16},{3,11,16},{3,11,16},{3,7,16},{4,4,338},{0,8,8},{0,8,8},{0,5,74},{12,0,338},{0,5,74},{11,0,421},{2,13,1},{4,9,1},{0,9,10},{11,0,421},{22,0,421},{0,9,10}, +{0,7,445},{22,0,421},{0,7,445},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,7,1},{0,7,1},{0,7,1},{0,4,4},{0,3,80},{0,3,80},{2,21,821},{2,15,425},{2,11,645},{2,10,437},{0,20,1514},{0,12,458},{0,10,2},{0,8,689},{0,9,2198},{0,7,1146},{3,19,437},{3,14,17},{4,10,51},{3,10,81},{8,4,1514},{0,12,458},{0,10,2},{0,8,689},{20,0,1514}, +{0,8,689},{2,16,400},{2,16,400},{2,16,400},{2,9,400},{0,15,338},{0,10,1},{0,10,1},{0,6,41},{0,7,717},{0,6,297},{3,14,16},{3,14,16},{3,14,16},{3,8,20},{5,5,338},{0,10,1},{0,10,1},{0,6,41},{15,0,338},{0,6,41},{12,1,421},{3,14,1},{5,10,1},{0,10,1},{12,1,421},{25,0,421},{0,10,1},{0,8,433},{25,0,421},{0,8,433},{2,0,400}, +{2,0,400},{2,0,400},{2,0,400},{0,10,1},{0,10,1},{0,10,1},{0,5,1},{0,4,157},{0,4,157},{3,22,854},{3,15,459},{3,12,666},{3,11,470},{1,21,1515},{1,13,459},{1,11,3},{0,9,651},{0,11,2070},{0,9,891},{4,20,430},{4,15,14},{5,11,51},{4,11,91},{9,5,1514},{0,14,425},{1,11,2},{0,9,602},{23,0,1514},{0,9,602},{3,17,433},{3,17,433},{3,17,433}, +{3,10,433},{1,16,339},{1,11,2},{1,11,2},{1,7,42},{0,8,613},{0,7,173},{4,15,10},{4,15,10},{4,15,10},{4,9,13},{9,0,338},{1,11,1},{1,11,1},{0,7,29},{18,0,338},{0,7,29},{14,0,421},{4,15,5},{6,11,1},{1,11,1},{14,0,421},{28,0,421},{1,11,1},{0,9,433},{28,0,421},{0,9,433},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{1,11,2}, +{1,11,2},{1,11,2},{1,6,2},{0,6,97},{0,6,97},{4,23,866},{4,16,461},{4,12,670},{4,12,494},{2,22,1515},{2,14,459},{2,12,3},{1,10,651},{0,12,1913},{0,10,677},{5,21,430},{5,16,14},{6,12,50},{5,12,90},{13,0,1514},{1,15,425},{2,12,2},{0,10,533},{26,0,1514},{0,10,533},{4,18,446},{4,18,446},{4,18,446},{4,11,446},{2,17,339},{2,12,3},{2,12,3}, +{2,8,42},{0,10,500},{0,8,65},{5,16,10},{5,16,10},{5,16,10},{5,10,13},{10,1,338},{2,12,2},{2,12,2},{0,8,16},{21,0,338},{0,8,16},{15,1,421},{5,16,5},{7,12,1},{2,12,1},{15,1,421},{31,0,421},{2,12,1},{0,10,433},{31,0,421},{0,10,433},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{2,12,2},{2,12,2},{2,12,2},{2,7,2},{0,8,49}, +{0,8,49},{5,24,854},{5,18,458},{5,14,678},{5,13,470},{3,23,1517},{3,15,461},{3,13,5},{2,11,653},{0,14,1758},{0,11,530},{7,20,437},{6,17,17},{7,13,53},{6,13,81},{14,1,1517},{2,16,422},{3,13,5},{0,11,494},{29,0,1517},{0,11,494},{5,19,433},{5,19,433},{5,19,433},{5,12,433},{3,18,340},{3,13,4},{3,13,4},{3,9,41},{0,12,419},{0,10,19},{7,15,16}, +{7,15,16},{7,15,16},{7,11,16},{12,0,338},{3,13,4},{3,13,4},{0,10,10},{24,0,338},{0,10,10},{17,0,421},{6,17,1},{8,13,1},{3,13,1},{17,0,421},{30,2,421},{3,13,1},{0,11,445},{30,2,421},{0,11,445},{5,0,433},{5,0,433},{5,0,433},{5,0,433},{3,14,1},{3,14,1},{3,14,1},{3,8,1},{0,10,10},{0,10,10},{6,25,854},{6,19,458},{6,15,678}, +{6,14,470},{4,24,1515},{4,16,459},{4,14,3},{3,12,666},{0,16,1658},{0,12,459},{7,23,437},{7,18,17},{8,14,51},{7,14,81},{16,0,1514},{3,17,422},{4,14,2},{0,12,458},{24,4,1514},{0,12,458},{6,20,433},{6,20,433},{6,20,433},{6,13,433},{4,19,339},{4,14,2},{4,14,2},{4,10,42},{0,13,365},{0,11,14},{7,18,16},{7,18,16},{7,18,16},{7,12,20},{13,1,338}, +{4,14,1},{4,14,1},{0,11,10},{27,0,338},{0,11,10},{18,1,421},{7,18,1},{9,14,1},{4,14,1},{18,1,421},{31,3,421},{4,14,1},{0,12,433},{31,3,421},{0,12,433},{6,0,433},{6,0,433},{6,0,433},{6,0,433},{4,14,2},{4,14,2},{4,14,2},{4,9,2},{0,11,5},{0,11,5},{7,26,854},{7,19,459},{7,16,666},{7,15,470},{5,25,1515},{5,17,459},{5,15,3}, +{4,13,651},{0,17,1577},{1,13,459},{8,24,430},{8,19,14},{9,15,51},{8,15,91},{17,1,1514},{4,18,425},{5,15,2},{0,13,437},{27,4,1514},{0,13,437},{7,21,433},{7,21,433},{7,21,433},{7,14,433},{5,20,339},{5,15,2},{5,15,2},{5,11,42},{0,15,339},{1,12,21},{8,19,10},{8,19,10},{8,19,10},{8,13,13},{15,0,338},{5,15,1},{5,15,1},{1,12,17},{30,0,338}, +{1,12,17},{20,0,421},{8,19,5},{10,15,1},{5,15,1},{20,0,421},{30,5,421},{5,15,1},{0,13,433},{30,5,421},{0,13,433},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{5,15,2},{5,15,2},{5,15,2},{5,10,2},{1,12,5},{1,12,5},{8,27,866},{8,20,461},{8,16,670},{8,16,494},{6,26,1515},{6,18,459},{6,16,3},{5,14,651},{0,19,1530},{2,14,459},{9,25,430}, +{9,20,14},{10,16,50},{9,16,90},{19,0,1514},{5,19,425},{6,16,2},{0,14,434},{30,4,1514},{0,14,434},{8,22,446},{8,22,446},{8,22,446},{8,15,446},{6,21,339},{6,16,3},{6,16,3},{6,12,42},{1,16,339},{2,13,21},{9,20,10},{9,20,10},{9,20,10},{9,14,13},{16,1,338},{6,16,2},{6,16,2},{4,12,16},{31,1,338},{4,12,16},{21,1,421},{9,20,5},{11,16,1}, +{6,16,1},{21,1,421},{31,6,421},{6,16,1},{0,14,433},{31,6,421},{0,14,433},{8,0,445},{8,0,445},{8,0,445},{8,0,445},{6,16,2},{6,16,2},{6,16,2},{6,11,2},{2,13,5},{2,13,5},{9,28,854},{9,22,458},{9,18,678},{9,17,470},{7,27,1517},{7,19,461},{7,17,5},{6,15,653},{1,20,1526},{3,15,461},{11,24,437},{10,21,17},{11,17,53},{10,17,81},{20,1,1517}, +{6,20,422},{7,17,5},{2,15,446},{31,5,1517},{2,15,446},{9,23,433},{9,23,433},{9,23,433},{9,16,433},{7,22,340},{7,17,4},{7,17,4},{7,13,41},{2,17,340},{4,14,19},{11,19,16},{11,19,16},{11,19,16},{11,15,16},{16,4,338},{7,17,4},{7,17,4},{4,14,10},{28,4,338},{4,14,10},{23,0,421},{10,21,1},{12,17,1},{7,17,1},{23,0,421},{30,8,421},{7,17,1}, +{0,15,445},{30,8,421},{0,15,445},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{7,18,1},{7,18,1},{7,18,1},{7,12,1},{4,14,10},{4,14,10},{10,29,854},{10,23,458},{10,19,678},{10,18,470},{8,28,1515},{8,20,459},{8,18,3},{7,16,666},{2,21,1526},{4,16,459},{11,27,437},{11,22,17},{12,18,51},{11,18,81},{20,4,1514},{7,21,422},{8,18,2},{2,16,434},{28,8,1514}, +{2,16,434},{10,24,433},{10,24,433},{10,24,433},{10,17,433},{8,23,339},{8,18,2},{8,18,2},{8,14,42},{3,18,340},{4,15,14},{11,22,16},{11,22,16},{11,22,16},{11,16,20},{17,5,338},{8,18,1},{8,18,1},{4,15,10},{31,4,338},{4,15,10},{24,1,421},{11,22,1},{13,18,1},{8,18,1},{24,1,421},{31,9,421},{8,18,1},{0,16,433},{31,9,421},{0,16,433},{10,0,433}, +{10,0,433},{10,0,433},{10,0,433},{8,18,2},{8,18,2},{8,18,2},{8,13,2},{4,15,5},{4,15,5},{11,30,854},{11,23,459},{11,20,666},{11,19,470},{9,29,1515},{9,21,459},{9,19,3},{8,17,651},{3,22,1526},{5,17,459},{12,28,430},{12,23,14},{13,19,51},{12,19,91},{21,5,1514},{8,22,425},{9,19,2},{3,17,434},{31,8,1514},{3,17,434},{11,25,433},{11,25,433},{11,25,433}, +{11,18,433},{9,24,339},{9,19,2},{9,19,2},{9,15,42},{4,19,339},{5,16,21},{12,23,10},{12,23,10},{12,23,10},{12,17,13},{21,0,338},{9,19,1},{9,19,1},{5,16,17},{30,6,338},{5,16,17},{26,0,421},{12,23,5},{14,19,1},{9,19,1},{26,0,421},{30,11,421},{9,19,1},{0,17,433},{30,11,421},{0,17,433},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{9,19,2}, +{9,19,2},{9,19,2},{9,14,2},{5,16,5},{5,16,5},{12,31,866},{12,24,461},{12,20,670},{12,20,494},{10,30,1515},{10,22,459},{10,20,3},{9,18,651},{4,23,1530},{6,18,459},{13,29,430},{13,24,14},{14,20,50},{13,20,90},{25,0,1514},{9,23,425},{10,20,2},{4,18,434},{30,10,1514},{4,18,434},{12,26,446},{12,26,446},{12,26,446},{12,19,446},{10,25,339},{10,20,3},{10,20,3}, +{10,16,42},{5,20,339},{6,17,21},{13,24,10},{13,24,10},{13,24,10},{13,18,13},{22,1,338},{10,20,2},{10,20,2},{8,16,16},{31,7,338},{8,16,16},{27,1,421},{13,24,5},{15,20,1},{10,20,1},{27,1,421},{31,12,421},{10,20,1},{0,18,433},{31,12,421},{0,18,433},{12,0,445},{12,0,445},{12,0,445},{12,0,445},{10,20,2},{10,20,2},{10,20,2},{10,15,2},{6,17,5}, +{6,17,5},{13,31,878},{13,26,458},{13,22,678},{13,21,470},{11,31,1517},{11,23,461},{11,21,5},{10,19,653},{5,24,1526},{7,19,461},{15,28,437},{14,25,17},{15,21,53},{14,21,81},{26,1,1517},{10,24,422},{11,21,5},{6,19,446},{31,11,1517},{6,19,446},{13,27,433},{13,27,433},{13,27,433},{13,20,433},{11,26,340},{11,21,4},{11,21,4},{11,17,41},{6,21,340},{8,18,19},{15,23,16}, +{15,23,16},{15,23,16},{15,19,16},{24,0,338},{11,21,4},{11,21,4},{8,18,10},{24,12,338},{8,18,10},{29,0,421},{14,25,1},{16,21,1},{11,21,1},{29,0,421},{30,14,421},{11,21,1},{0,19,445},{30,14,421},{0,19,445},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{11,22,1},{11,22,1},{11,22,1},{11,16,1},{8,18,10},{8,18,10},{14,31,938},{14,27,458},{14,23,678}, +{14,22,470},{12,31,1542},{12,24,459},{12,22,3},{11,20,666},{6,25,1526},{8,20,459},{15,31,437},{15,26,17},{16,22,51},{15,22,81},{28,0,1514},{11,25,422},{12,22,2},{6,20,434},{24,16,1514},{6,20,434},{14,28,433},{14,28,433},{14,28,433},{14,21,433},{12,27,339},{12,22,2},{12,22,2},{12,18,42},{7,22,340},{8,19,14},{15,26,16},{15,26,16},{15,26,16},{15,20,20},{25,1,338}, +{12,22,1},{12,22,1},{8,19,10},{27,12,338},{8,19,10},{30,1,421},{15,26,1},{17,22,1},{12,22,1},{30,1,421},{31,15,421},{12,22,1},{0,20,433},{31,15,421},{0,20,433},{14,0,433},{14,0,433},{14,0,433},{14,0,433},{12,22,2},{12,22,2},{12,22,2},{12,17,2},{8,19,5},{8,19,5},{15,31,998},{15,27,459},{15,24,666},{15,23,470},{14,31,1598},{13,25,459},{13,23,3}, +{12,21,651},{7,26,1526},{9,21,459},{16,31,442},{16,27,14},{17,23,51},{16,23,91},{29,1,1514},{12,26,425},{13,23,2},{7,21,434},{27,16,1514},{7,21,434},{15,29,433},{15,29,433},{15,29,433},{15,22,433},{13,28,339},{13,23,2},{13,23,2},{13,19,42},{8,23,339},{9,20,21},{16,27,10},{16,27,10},{16,27,10},{16,21,13},{27,0,338},{13,23,1},{13,23,1},{9,20,17},{30,12,338}, +{9,20,17},{31,2,421},{16,27,5},{18,23,1},{13,23,1},{31,2,421},{30,17,421},{13,23,1},{0,21,433},{30,17,421},{0,21,433},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{13,23,2},{13,23,2},{13,23,2},{13,18,2},{9,20,5},{9,20,5},{16,31,1086},{16,28,461},{16,24,670},{16,24,494},{15,31,1622},{14,26,459},{14,24,3},{13,22,651},{8,27,1530},{10,22,459},{18,31,446}, +{17,28,14},{18,24,50},{17,24,90},{31,0,1514},{13,27,425},{14,24,2},{8,22,434},{30,16,1514},{8,22,434},{16,30,446},{16,30,446},{16,30,446},{16,23,446},{14,29,339},{14,24,3},{14,24,3},{14,20,42},{9,24,339},{10,21,21},{17,28,10},{17,28,10},{17,28,10},{17,22,13},{28,1,338},{14,24,2},{14,24,2},{12,20,16},{31,13,338},{12,20,16},{31,5,421},{17,28,5},{19,24,1}, +{14,24,1},{31,5,421},{31,18,421},{14,24,1},{0,22,433},{31,18,421},{0,22,433},{16,0,445},{16,0,445},{16,0,445},{16,0,445},{14,24,2},{14,24,2},{14,24,2},{14,19,2},{10,21,5},{10,21,5},{18,31,1242},{17,30,458},{17,26,678},{17,25,470},{16,31,1703},{15,27,461},{15,25,5},{14,23,653},{9,28,1526},{11,23,461},{19,31,461},{18,29,17},{19,25,53},{18,25,81},{31,3,1517}, +{14,28,422},{15,25,5},{10,23,446},{31,17,1517},{10,23,446},{17,31,433},{17,31,433},{17,31,433},{17,24,433},{15,30,340},{15,25,4},{15,25,4},{15,21,41},{10,25,340},{12,22,19},{19,27,16},{19,27,16},{19,27,16},{19,23,16},{28,4,338},{15,25,4},{15,25,4},{12,22,10},{28,16,338},{12,22,10},{31,8,421},{18,29,1},{20,25,1},{15,25,1},{31,8,421},{30,20,421},{15,25,1}, +{0,23,445},{30,20,421},{0,23,445},{17,0,433},{17,0,433},{17,0,433},{17,0,433},{15,26,1},{15,26,1},{15,26,1},{15,20,1},{12,22,10},{12,22,10},{19,31,1326},{18,31,458},{18,27,678},{18,26,470},{17,31,1838},{16,28,459},{16,26,3},{15,24,666},{10,29,1526},{12,24,459},{20,31,506},{19,30,17},{20,26,51},{19,26,81},{28,12,1514},{15,29,422},{16,26,2},{10,24,434},{28,20,1514}, +{10,24,434},{18,31,442},{18,31,442},{18,31,442},{18,25,433},{16,31,339},{16,26,2},{16,26,2},{16,22,42},{11,26,340},{12,23,14},{19,30,16},{19,30,16},{19,30,16},{19,24,20},{29,5,338},{16,26,1},{16,26,1},{12,23,10},{31,16,338},{12,23,10},{31,11,421},{19,30,1},{21,26,1},{16,26,1},{31,11,421},{31,21,421},{16,26,1},{0,24,433},{31,21,421},{0,24,433},{18,0,433}, +{18,0,433},{18,0,433},{18,0,433},{16,26,2},{16,26,2},{16,26,2},{16,21,2},{12,23,5},{12,23,5},{20,31,1470},{19,31,459},{19,28,666},{19,27,470},{19,31,1911},{17,29,459},{17,27,3},{16,25,651},{11,30,1526},{13,25,459},{21,31,590},{20,31,14},{21,27,51},{20,27,91},{29,13,1514},{16,30,425},{17,27,2},{11,25,434},{31,20,1514},{11,25,434},{19,31,458},{19,31,458},{19,31,458}, +{19,26,433},{17,31,357},{17,27,2},{17,27,2},{17,23,42},{12,27,339},{13,24,21},{20,31,10},{20,31,10},{20,31,10},{20,25,13},{31,4,338},{17,27,1},{17,27,1},{13,24,17},{30,18,338},{13,24,17},{31,14,421},{20,31,5},{22,27,1},{17,27,1},{31,14,421},{30,23,421},{17,27,1},{0,25,433},{30,23,421},{0,25,433},{19,0,433},{19,0,433},{19,0,433},{19,0,433},{17,27,2}, +{17,27,2},{17,27,2},{17,22,2},{13,24,5},{13,24,5},{21,31,1650},{20,31,530},{20,28,670},{20,28,494},{20,31,2030},{18,30,459},{18,28,3},{17,26,651},{12,31,1530},{14,26,459},{23,31,650},{21,31,29},{22,28,50},{21,28,90},{31,12,1514},{17,31,425},{18,28,2},{12,26,434},{30,22,1514},{12,26,434},{20,31,494},{20,31,494},{20,31,494},{20,27,446},{18,31,411},{18,28,3},{18,28,3}, +{18,24,42},{13,28,339},{14,25,21},{21,31,13},{21,31,13},{21,31,13},{21,26,13},{31,7,338},{18,28,2},{18,28,2},{16,24,16},{31,19,338},{16,24,16},{31,17,421},{22,31,10},{23,28,1},{18,28,1},{31,17,421},{31,24,421},{18,28,1},{0,26,433},{31,24,421},{0,26,433},{20,0,445},{20,0,445},{20,0,445},{20,0,445},{18,28,2},{18,28,2},{18,28,2},{18,23,2},{14,25,5}, +{14,25,5},{22,31,1902},{21,31,723},{21,30,678},{21,29,470},{21,31,2235},{19,31,461},{19,29,5},{18,27,653},{14,31,1587},{15,27,461},{24,31,734},{23,31,65},{23,29,53},{22,29,81},{31,15,1517},{19,31,461},{19,29,5},{14,27,446},{31,23,1517},{14,27,446},{21,31,554},{21,31,554},{21,31,554},{21,28,433},{20,31,437},{19,29,4},{19,29,4},{19,25,41},{14,29,340},{16,26,19},{23,31,16}, +{23,31,16},{23,31,16},{23,27,16},{28,16,338},{19,29,4},{19,29,4},{16,26,10},{24,24,338},{16,26,10},{31,20,421},{23,31,49},{24,29,1},{19,29,1},{31,20,421},{30,26,421},{19,29,1},{0,27,445},{30,26,421},{0,27,445},{21,0,433},{21,0,433},{21,0,433},{21,0,433},{19,30,1},{19,30,1},{19,30,1},{19,24,1},{16,26,10},{16,26,10},{23,31,2074},{23,31,930},{22,31,678}, +{22,30,470},{23,31,2382},{20,31,570},{20,30,3},{19,28,666},{16,31,1703},{16,28,459},{25,31,854},{24,31,173},{24,30,51},{23,30,81},{28,24,1514},{21,31,554},{20,30,2},{14,28,434},{24,28,1514},{14,28,434},{22,31,629},{22,31,629},{22,31,629},{22,29,433},{21,31,491},{20,30,2},{20,30,2},{20,26,42},{15,30,340},{16,27,14},{24,31,29},{24,31,29},{24,31,29},{23,28,20},{29,17,338}, +{20,30,1},{20,30,1},{16,27,10},{27,24,338},{16,27,10},{31,23,421},{25,31,109},{25,30,1},{20,30,1},{31,23,421},{31,27,421},{20,30,1},{0,28,433},{31,27,421},{0,28,433},{22,0,433},{22,0,433},{22,0,433},{22,0,433},{20,30,2},{20,30,2},{20,30,2},{20,25,2},{16,27,5},{16,27,5},{24,31,2229},{24,31,1146},{23,31,689},{23,31,469},{24,31,2476},{22,31,731},{21,31,2}, +{20,29,618},{18,31,1805},{17,29,426},{26,31,953},{25,31,339},{25,31,50},{24,30,82},{29,25,1459},{23,31,620},{21,31,1},{15,29,401},{27,28,1459},{15,29,401},{23,31,689},{23,31,689},{23,31,689},{23,30,433},{22,31,581},{21,31,2},{21,31,2},{21,27,42},{16,31,339},{17,28,21},{25,31,50},{25,31,50},{25,31,50},{24,29,13},{31,16,338},{21,31,1},{21,31,1},{17,28,17},{30,24,338}, +{17,28,17},{31,26,392},{27,31,157},{26,31,0},{21,31,0},{31,26,392},{30,29,392},{21,31,0},{0,29,400},{30,29,392},{0,29,400},{23,0,433},{23,0,433},{23,0,433},{23,0,433},{21,31,2},{21,31,2},{21,31,2},{21,26,2},{17,28,5},{17,28,5},{25,31,1943},{24,31,1130},{24,31,769},{24,31,446},{25,31,2103},{23,31,573},{22,31,42},{22,29,373},{20,31,1481},{18,30,234},{27,31,657}, +{26,31,285},{26,31,89},{25,31,18},{31,23,1064},{24,31,426},{23,31,8},{16,30,209},{31,27,1064},{16,30,209},{24,31,769},{24,31,769},{24,31,769},{24,31,446},{23,31,661},{22,31,42},{22,31,42},{22,28,42},{18,31,365},{18,29,21},{26,31,89},{26,31,89},{26,31,89},{25,30,13},{31,19,338},{23,31,8},{23,31,8},{20,28,16},{31,25,338},{20,28,16},{31,27,202},{28,31,80},{27,31,4}, +{24,31,1},{31,27,202},{31,29,202},{24,31,1},{0,30,208},{31,29,202},{0,30,208},{24,0,445},{24,0,445},{24,0,445},{24,0,445},{22,31,17},{22,31,17},{22,31,17},{22,27,2},{18,29,5},{18,29,5},{27,31,1710},{26,31,1126},{25,31,917},{25,31,469},{26,31,1779},{24,31,507},{24,31,146},{23,30,154},{22,31,1221},{20,30,83},{28,31,450},{27,31,258},{27,31,137},{27,31,16},{29,29,722}, +{26,31,286},{25,31,52},{20,30,74},{31,28,722},{20,30,74},{25,31,917},{25,31,917},{25,31,917},{25,31,469},{25,31,789},{24,31,146},{24,31,146},{23,29,41},{20,31,446},{20,30,19},{27,31,137},{27,31,137},{27,31,137},{27,31,16},{28,28,338},{25,31,52},{25,31,52},{20,30,10},{28,28,338},{20,30,10},{31,29,61},{30,31,34},{29,31,0},{27,31,0},{31,29,61},{31,30,61},{27,31,0}, +{0,30,73},{31,30,61},{0,30,73},{25,0,433},{25,0,433},{25,0,433},{25,0,433},{23,31,49},{23,31,49},{23,31,49},{23,28,1},{20,30,10},{20,30,10},{27,31,1486},{27,31,1123},{27,31,1002},{26,31,554},{27,31,1519},{25,31,582},{25,31,293},{24,30,106},{23,31,1090},{20,31,14},{29,31,354},{28,31,258},{28,31,194},{28,31,50},{31,27,509},{27,31,234},{27,31,113},{20,31,10},{31,29,509}, +{20,31,10},{27,31,1002},{27,31,1002},{27,31,1002},{26,31,554},{26,31,915},{25,31,293},{25,31,293},{24,30,42},{22,31,564},{20,31,14},{28,31,194},{28,31,194},{28,31,194},{28,31,50},{29,29,338},{27,31,113},{27,31,113},{20,31,10},{31,28,338},{20,31,10},{31,30,9},{31,31,9},{30,31,9},{30,31,0},{31,30,9},{30,31,9},{30,31,0},{0,31,9},{30,31,9},{0,31,9},{26,0,433}, +{26,0,433},{26,0,433},{26,0,433},{24,31,82},{24,31,82},{24,31,82},{24,29,2},{20,31,5},{20,31,5},{28,31,1197},{28,31,1005},{27,31,917},{27,31,554},{28,31,1213},{26,31,522},{26,31,326},{25,31,17},{24,31,870},{22,31,16},{30,31,241},{29,31,182},{29,31,146},{29,31,61},{31,28,297},{28,31,153},{28,31,89},{23,31,1},{30,30,297},{23,31,1},{27,31,917},{27,31,917},{27,31,917}, +{27,31,554},{27,31,774},{26,31,326},{26,31,326},{25,31,17},{24,31,509},{22,31,16},{29,31,146},{29,31,146},{29,31,146},{29,31,61},{31,27,221},{28,31,89},{28,31,89},{23,31,1},{31,29,221},{23,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{27,0,433},{27,0,433},{27,0,433},{27,0,433},{26,31,130}, +{26,31,130},{26,31,130},{25,30,2},{22,31,16},{22,31,16},{29,31,927},{28,31,765},{28,31,701},{28,31,509},{28,31,845},{27,31,404},{27,31,283},{26,31,2},{26,31,589},{24,31,52},{30,31,97},{30,31,70},{30,31,61},{30,31,34},{31,30,118},{30,31,67},{29,31,40},{26,31,1},{30,31,118},{26,31,1},{28,31,701},{28,31,701},{28,31,701},{28,31,509},{28,31,589},{27,31,283},{27,31,283}, +{26,31,2},{25,31,386},{24,31,52},{30,31,61},{30,31,61},{30,31,61},{30,31,34},{31,29,85},{29,31,40},{29,31,40},{26,31,1},{31,30,85},{26,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{28,0,445},{28,0,445},{28,0,445},{28,0,445},{27,31,162},{27,31,162},{27,31,162},{26,31,2},{24,31,52}, +{24,31,52},{0,14,884},{0,10,117},{0,7,10},{0,6,317},{0,10,1899},{0,6,1236},{0,6,573},{0,4,1438},{0,4,2065},{0,4,1559},{0,14,884},{0,10,117},{0,7,10},{0,6,317},{5,0,1899},{0,6,1236},{0,6,573},{0,4,1438},{10,0,1899},{0,4,1438},{0,7,1},{0,7,1},{0,7,1},{0,3,4},{0,3,164},{0,3,68},{0,3,68},{0,2,104},{0,2,189},{0,1,129},{0,7,1}, +{0,7,1},{0,7,1},{0,3,4},{2,0,164},{0,3,68},{0,3,68},{0,2,104},{3,0,164},{0,2,104},{7,0,884},{0,10,117},{0,7,10},{0,6,317},{7,0,884},{14,0,884},{0,6,317},{0,5,890},{14,0,884},{0,5,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,17,884},{0,12,53},{0,8,20}, +{0,7,265},{0,11,2360},{0,8,1384},{0,7,626},{0,5,1683},{0,5,2580},{0,5,1852},{0,17,884},{0,12,53},{0,8,20},{0,7,265},{6,0,2356},{0,8,1384},{0,7,626},{0,5,1683},{10,1,2356},{0,5,1683},{0,10,1},{0,10,1},{0,10,1},{0,5,1},{0,5,338},{0,4,137},{0,4,137},{0,2,200},{0,2,381},{0,2,225},{0,10,1},{0,10,1},{0,10,1},{0,5,1},{2,1,338}, +{0,4,137},{0,4,137},{0,2,200},{5,0,338},{0,2,200},{8,1,884},{0,12,53},{1,8,5},{0,7,265},{8,1,884},{17,0,884},{0,7,265},{0,6,890},{17,0,884},{0,6,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,882},{0,14,16},{0,10,85},{0,8,200},{0,14,2904},{0,9,1530},{0,8,684}, +{0,6,1978},{0,6,3220},{0,5,2172},{0,20,882},{0,14,16},{1,9,84},{0,8,200},{7,0,2904},{0,9,1530},{0,8,684},{0,6,1978},{14,0,2904},{0,6,1978},{0,12,1},{0,12,1},{0,12,1},{0,6,4},{0,6,580},{0,5,218},{0,5,218},{0,3,356},{0,3,644},{0,3,420},{0,12,1},{0,12,1},{0,12,1},{0,6,4},{3,0,580},{0,5,218},{0,5,218},{0,3,356},{6,0,580}, +{0,3,356},{8,4,882},{0,14,16},{2,9,5},{0,8,200},{8,4,882},{20,0,882},{0,8,200},{0,7,890},{20,0,882},{0,7,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,23,918},{0,15,41},{1,11,153},{0,10,184},{0,16,3048},{0,11,1476},{0,9,473},{0,6,1950},{0,7,3517},{0,6,2206},{1,21,886}, +{1,15,20},{1,11,89},{0,10,184},{8,0,3048},{0,11,1476},{0,9,473},{0,6,1950},{16,0,3048},{0,6,1950},{0,15,37},{0,15,37},{0,15,37},{0,8,40},{0,9,648},{0,7,185},{0,7,185},{0,4,337},{0,4,777},{0,4,458},{1,13,5},{1,13,5},{1,13,5},{1,7,8},{4,1,648},{0,7,185},{0,7,185},{0,4,337},{9,0,648},{0,4,337},{9,5,882},{0,15,5},{3,10,5}, +{0,10,148},{9,5,882},{23,0,882},{0,10,148},{0,8,900},{23,0,882},{0,8,900},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,5},{0,1,5},{1,24,997},{1,17,123},{1,12,318},{1,11,243},{0,19,3051},{0,12,1278},{0,10,274},{0,8,1795},{0,9,3672},{0,7,2222},{2,22,885},{2,16,10},{2,12,101},{1,11,179},{10,0,3051}, +{0,12,1278},{0,10,274},{0,8,1795},{19,0,3051},{0,8,1795},{1,17,114},{1,17,114},{1,17,114},{1,9,114},{0,12,648},{0,9,85},{0,9,85},{0,5,244},{0,5,889},{0,5,413},{2,15,1},{2,15,1},{2,15,1},{2,8,5},{4,4,648},{0,9,85},{0,9,85},{0,5,244},{12,0,648},{0,5,244},{13,0,884},{2,16,9},{4,11,10},{0,11,90},{13,0,884},{26,0,884},{0,11,90}, +{0,9,890},{26,0,884},{0,9,890},{1,0,113},{1,0,113},{1,0,113},{1,0,113},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,2,50},{0,2,50},{1,27,1173},{1,18,314},{2,13,510},{1,12,374},{0,22,3051},{0,14,1139},{0,12,153},{0,9,1630},{0,10,3924},{0,8,2199},{3,23,885},{3,17,10},{3,13,101},{2,12,197},{11,0,3051},{0,14,1139},{0,12,153},{0,9,1630},{22,0,3051}, +{0,9,1630},{1,20,290},{1,20,290},{1,20,290},{1,10,293},{0,15,648},{0,10,41},{0,10,41},{0,6,181},{0,7,1027},{0,6,437},{3,16,2},{3,16,2},{3,16,2},{3,9,5},{5,5,648},{0,10,41},{0,10,41},{0,6,181},{15,0,648},{0,6,181},{14,1,884},{3,17,9},{5,12,5},{0,12,53},{14,1,884},{29,0,884},{0,12,53},{0,10,890},{29,0,884},{0,10,890},{1,0,289}, +{1,0,289},{1,0,289},{1,0,289},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,3,113},{0,3,113},{2,28,1365},{2,19,506},{3,14,830},{2,13,566},{0,25,3051},{0,16,1051},{0,13,36},{0,10,1483},{0,12,4164},{0,9,2174},{4,24,886},{4,18,20},{4,14,89},{3,13,197},{12,1,3051},{0,16,1051},{0,13,36},{0,10,1483},{25,0,3051},{0,10,1483},{2,21,482},{2,21,482},{2,21,482}, +{2,11,485},{0,18,648},{0,12,5},{0,12,5},{0,7,149},{0,8,1182},{0,7,510},{4,16,5},{4,16,5},{4,16,5},{4,10,8},{9,0,648},{0,12,5},{0,12,5},{0,7,149},{18,0,648},{0,7,149},{16,0,882},{3,19,10},{6,13,5},{0,13,20},{16,0,882},{24,4,882},{0,13,20},{0,11,890},{24,4,882},{0,11,890},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{0,11,1}, +{0,11,1},{0,11,1},{0,6,1},{0,5,185},{0,5,185},{2,31,1669},{3,20,818},{3,15,1161},{2,14,838},{0,28,3048},{0,17,949},{0,14,6},{0,11,1395},{0,13,4381},{0,10,2228},{5,25,886},{5,19,20},{5,15,89},{4,14,184},{12,4,3048},{0,17,949},{0,14,6},{0,11,1395},{28,0,3048},{0,11,1395},{2,24,786},{2,24,786},{2,24,786},{2,13,786},{0,21,648},{0,14,2},{0,14,2}, +{0,9,101},{0,9,1352},{0,8,590},{5,17,5},{5,17,5},{5,17,5},{5,11,8},{10,1,648},{0,14,2},{0,14,2},{0,9,101},{21,0,648},{0,9,101},{17,1,882},{4,19,5},{7,14,5},{0,14,5},{17,1,882},{27,4,882},{0,14,5},{0,12,900},{27,4,882},{0,12,900},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{0,14,1},{0,14,1},{0,14,1},{0,7,1},{0,6,305}, +{0,6,305},{3,31,1814},{3,22,968},{4,16,1314},{3,15,945},{1,29,3055},{0,19,936},{1,15,17},{0,12,1314},{0,15,4321},{0,12,2007},{6,26,885},{6,20,10},{6,16,101},{5,15,179},{15,2,3051},{0,19,900},{1,15,13},{0,12,1278},{31,0,3051},{0,12,1278},{3,25,900},{3,25,900},{3,25,900},{3,14,900},{1,22,654},{1,15,8},{1,15,8},{0,10,76},{0,11,1296},{0,9,425},{6,19,1}, +{6,19,1},{6,19,1},{6,12,5},{12,0,648},{1,15,4},{1,15,4},{0,10,40},{24,0,648},{0,10,40},{19,0,884},{6,20,9},{8,15,10},{1,15,9},{19,0,884},{30,4,884},{1,15,9},{0,13,890},{30,4,884},{0,13,890},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{1,16,5},{1,16,5},{1,16,5},{1,8,8},{0,7,269},{0,7,269},{5,31,1838},{4,23,948},{5,17,1314}, +{4,16,943},{2,30,3055},{1,20,936},{2,16,13},{1,13,1314},{0,16,4056},{0,13,1620},{7,27,885},{7,21,10},{7,17,101},{6,16,197},{17,0,3051},{0,21,891},{2,16,9},{0,13,1179},{30,2,3051},{0,13,1179},{4,26,891},{4,26,891},{4,26,891},{4,15,891},{2,23,654},{2,16,9},{2,16,9},{1,11,76},{0,13,1107},{0,10,273},{7,20,2},{7,20,2},{7,20,2},{7,13,5},{13,1,648}, +{3,15,5},{3,15,5},{0,11,20},{27,0,648},{0,11,20},{20,1,884},{7,21,9},{9,16,5},{2,16,5},{20,1,884},{31,5,884},{2,16,5},{0,14,890},{31,5,884},{0,14,890},{4,0,890},{4,0,890},{4,0,890},{4,0,890},{2,17,5},{2,17,5},{2,17,5},{2,9,8},{0,9,149},{0,9,149},{6,31,1868},{5,24,948},{6,18,1314},{5,17,943},{3,31,3055},{2,21,936},{3,17,13}, +{2,14,1314},{0,18,3825},{0,14,1354},{8,28,886},{8,22,20},{8,18,89},{7,17,197},{18,1,3051},{1,22,891},{3,17,9},{0,14,1098},{31,3,3051},{0,14,1098},{5,27,891},{5,27,891},{5,27,891},{5,16,891},{3,24,652},{3,17,9},{3,17,9},{2,12,86},{0,14,976},{0,12,126},{8,20,5},{8,20,5},{8,20,5},{8,14,8},{15,0,648},{4,16,5},{4,16,5},{0,12,5},{30,0,648}, +{0,12,5},{20,4,882},{7,23,10},{10,17,5},{3,17,5},{20,4,882},{28,8,882},{3,17,5},{0,15,890},{28,8,882},{0,15,890},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{3,18,5},{3,18,5},{3,18,5},{3,10,8},{0,11,80},{0,11,80},{7,31,1908},{6,25,948},{7,19,1314},{6,18,943},{4,31,3084},{3,22,936},{4,18,15},{3,15,1314},{0,19,3640},{0,15,1175},{9,29,886}, +{9,23,20},{9,19,89},{8,18,184},{20,0,3048},{2,23,891},{4,18,6},{0,15,1054},{24,8,3048},{0,15,1054},{6,28,891},{6,28,891},{6,28,891},{6,17,891},{4,25,657},{4,18,11},{4,18,11},{3,13,86},{0,16,852},{0,13,27},{9,21,5},{9,21,5},{9,21,5},{9,15,8},{16,1,648},{4,18,2},{4,18,2},{0,13,2},{31,1,648},{0,13,2},{21,5,882},{8,23,5},{11,18,5}, +{4,18,5},{21,5,882},{31,8,882},{4,18,5},{0,16,900},{31,8,882},{0,16,900},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{4,18,10},{4,18,10},{4,18,10},{4,11,10},{0,13,26},{0,13,26},{8,31,1998},{7,26,968},{8,20,1314},{7,19,945},{6,31,3160},{4,23,936},{5,19,17},{4,16,1314},{0,21,3420},{0,16,1028},{10,30,885},{10,24,10},{10,20,101},{9,19,179},{22,0,3051}, +{3,24,891},{5,19,13},{0,16,1003},{30,7,3051},{0,16,1003},{7,29,900},{7,29,900},{7,29,900},{7,18,900},{5,26,654},{5,19,8},{5,19,8},{4,14,76},{0,18,750},{1,14,24},{10,23,1},{10,23,1},{10,23,1},{10,16,5},{16,4,648},{5,19,4},{5,19,4},{2,14,5},{28,4,648},{2,14,5},{25,0,884},{10,24,9},{12,19,10},{5,19,9},{25,0,884},{30,10,884},{5,19,9}, +{0,17,890},{30,10,884},{0,17,890},{7,0,900},{7,0,900},{7,0,900},{7,0,900},{5,20,5},{5,20,5},{5,20,5},{5,12,8},{0,15,5},{0,15,5},{9,31,2124},{8,27,948},{9,21,1314},{8,20,943},{7,31,3196},{5,24,936},{6,20,13},{5,17,1314},{0,23,3307},{0,17,971},{11,31,885},{11,25,10},{11,21,101},{10,20,197},{23,0,3051},{4,25,891},{6,20,9},{0,17,970},{30,8,3051}, +{0,17,970},{8,30,891},{8,30,891},{8,30,891},{8,19,891},{6,27,654},{6,20,9},{6,20,9},{5,15,76},{0,19,691},{2,15,24},{11,24,2},{11,24,2},{11,24,2},{11,17,5},{17,5,648},{7,19,5},{7,19,5},{3,15,5},{31,4,648},{3,15,5},{26,1,884},{11,25,9},{13,20,5},{6,20,5},{26,1,884},{31,11,884},{6,20,5},{0,18,890},{31,11,884},{0,18,890},{8,0,890}, +{8,0,890},{8,0,890},{8,0,890},{6,21,5},{6,21,5},{6,21,5},{6,13,8},{1,16,5},{1,16,5},{10,31,2286},{9,28,948},{10,22,1314},{9,21,943},{8,31,3277},{6,25,936},{7,21,13},{6,18,1314},{0,24,3196},{0,19,948},{12,31,904},{12,26,20},{12,22,89},{11,21,197},{24,1,3051},{5,26,891},{7,21,9},{0,19,939},{31,9,3051},{0,19,939},{9,31,891},{9,31,891},{9,31,891}, +{9,20,891},{7,28,652},{7,21,9},{7,21,9},{6,16,86},{0,21,652},{2,16,18},{12,24,5},{12,24,5},{12,24,5},{12,18,8},{21,0,648},{8,20,5},{8,20,5},{3,16,2},{30,6,648},{3,16,2},{28,0,882},{11,27,10},{14,21,5},{7,21,5},{28,0,882},{24,16,882},{7,21,5},{0,19,890},{24,16,882},{0,19,890},{9,0,890},{9,0,890},{9,0,890},{9,0,890},{7,22,5}, +{7,22,5},{7,22,5},{7,14,8},{2,17,5},{2,17,5},{11,31,2414},{10,29,948},{11,23,1314},{10,22,943},{9,31,3412},{7,26,936},{8,22,15},{7,19,1314},{0,26,3115},{1,20,958},{13,31,958},{13,27,20},{13,23,89},{12,22,184},{24,4,3048},{6,27,891},{8,22,6},{0,20,925},{28,12,3048},{0,20,925},{10,31,894},{10,31,894},{10,31,894},{10,21,891},{8,29,657},{8,22,11},{8,22,11}, +{7,17,86},{1,22,652},{3,17,18},{13,25,5},{13,25,5},{13,25,5},{13,19,8},{22,1,648},{8,22,2},{8,22,2},{4,17,2},{31,7,648},{4,17,2},{29,1,882},{12,27,5},{15,22,5},{8,22,5},{29,1,882},{27,16,882},{8,22,5},{0,20,900},{27,16,882},{0,20,900},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{8,22,10},{8,22,10},{8,22,10},{8,15,10},{3,18,5}, +{3,18,5},{13,31,2606},{11,30,968},{12,24,1314},{11,23,945},{11,31,3519},{8,27,936},{9,23,17},{8,20,1314},{0,28,3085},{2,21,942},{15,31,995},{14,28,10},{14,24,101},{13,23,179},{27,2,3051},{7,28,891},{9,23,13},{0,21,891},{31,12,3051},{0,21,891},{11,31,925},{11,31,925},{11,31,925},{11,22,900},{9,30,654},{9,23,8},{9,23,8},{8,18,76},{2,23,651},{5,18,24},{14,27,1}, +{14,27,1},{14,27,1},{14,20,5},{24,0,648},{9,23,4},{9,23,4},{6,18,5},{24,12,648},{6,18,5},{31,0,884},{14,28,9},{16,23,10},{9,23,9},{31,0,884},{30,16,884},{9,23,9},{0,21,890},{30,16,884},{0,21,890},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{9,24,5},{9,24,5},{9,24,5},{9,16,8},{4,19,5},{4,19,5},{14,31,2804},{12,31,948},{13,25,1314}, +{12,24,943},{12,31,3652},{9,28,936},{10,24,13},{9,21,1314},{0,29,3052},{3,22,942},{16,31,1054},{15,29,10},{15,25,101},{14,24,197},{29,0,3051},{8,29,891},{10,24,9},{1,22,891},{30,14,3051},{1,22,891},{12,31,939},{12,31,939},{12,31,939},{12,23,891},{10,31,654},{10,24,9},{10,24,9},{9,19,76},{3,24,652},{6,19,24},{15,28,2},{15,28,2},{15,28,2},{15,21,5},{25,1,648}, +{11,23,5},{11,23,5},{7,19,5},{27,12,648},{7,19,5},{31,3,884},{15,29,9},{17,24,5},{10,24,5},{31,3,884},{31,17,884},{10,24,5},{0,22,890},{31,17,884},{0,22,890},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{10,25,5},{10,25,5},{10,25,5},{10,17,8},{5,20,5},{5,20,5},{15,31,2956},{14,31,979},{14,26,1314},{13,25,943},{13,31,3841},{10,29,936},{11,25,13}, +{10,22,1314},{1,30,3052},{4,23,948},{17,31,1144},{16,30,20},{16,26,89},{15,25,197},{30,1,3051},{9,30,891},{11,25,9},{2,23,891},{31,15,3051},{2,23,891},{14,31,979},{14,31,979},{14,31,979},{13,24,891},{11,31,670},{11,25,9},{11,25,9},{10,20,86},{4,25,652},{6,20,18},{16,28,5},{16,28,5},{16,28,5},{16,22,8},{27,0,648},{12,24,5},{12,24,5},{7,20,2},{30,12,648}, +{7,20,2},{28,12,882},{15,31,10},{18,25,5},{11,25,5},{28,12,882},{28,20,882},{11,25,5},{0,23,890},{28,20,882},{0,23,890},{13,0,890},{13,0,890},{13,0,890},{13,0,890},{11,26,5},{11,26,5},{11,26,5},{11,18,8},{6,21,5},{6,21,5},{16,31,3182},{15,31,1028},{15,27,1314},{14,26,943},{15,31,4020},{11,30,936},{12,26,15},{11,23,1314},{2,31,3052},{5,24,958},{18,31,1270}, +{17,31,20},{17,27,89},{16,26,184},{28,8,3048},{10,31,891},{12,26,6},{2,24,901},{24,20,3048},{2,24,901},{15,31,1003},{15,31,1003},{15,31,1003},{14,25,891},{12,31,707},{12,26,11},{12,26,11},{11,21,86},{5,26,652},{7,21,18},{17,29,5},{17,29,5},{17,29,5},{17,23,8},{28,1,648},{12,26,2},{12,26,2},{8,21,2},{31,13,648},{8,21,2},{29,13,882},{16,31,5},{19,26,5}, +{12,26,5},{29,13,882},{31,20,882},{12,26,5},{0,24,900},{31,20,882},{0,24,900},{14,0,890},{14,0,890},{14,0,890},{14,0,890},{12,26,10},{12,26,10},{12,26,10},{12,19,10},{7,22,5},{7,22,5},{17,31,3508},{16,31,1175},{16,28,1314},{15,27,945},{16,31,4209},{12,31,936},{13,27,17},{12,24,1314},{4,31,3100},{6,25,942},{20,31,1368},{18,31,37},{18,28,101},{17,27,179},{31,6,3051}, +{12,31,900},{13,27,13},{4,25,891},{30,19,3051},{4,25,891},{16,31,1054},{16,31,1054},{16,31,1054},{15,26,900},{14,31,780},{13,27,8},{13,27,8},{12,22,76},{6,27,651},{9,22,24},{18,31,1},{18,31,1},{18,31,1},{18,24,5},{28,4,648},{13,27,4},{13,27,4},{10,22,5},{28,16,648},{10,22,5},{31,12,884},{18,31,36},{20,27,10},{13,27,9},{31,12,884},{30,22,884},{13,27,9}, +{0,25,890},{30,22,884},{0,25,890},{15,0,900},{15,0,900},{15,0,900},{15,0,900},{13,28,5},{13,28,5},{13,28,5},{13,20,8},{8,23,5},{8,23,5},{19,31,3790},{17,31,1412},{17,29,1314},{16,28,943},{17,31,4452},{14,31,954},{14,28,13},{13,25,1314},{7,31,3196},{7,26,942},{21,31,1494},{19,31,126},{19,29,101},{18,28,197},{31,8,3051},{14,31,950},{14,28,9},{5,26,891},{30,20,3051}, +{5,26,891},{17,31,1123},{17,31,1123},{17,31,1123},{16,27,891},{15,31,820},{14,28,9},{14,28,9},{13,23,76},{7,28,652},{10,23,24},{19,31,5},{19,31,5},{19,31,5},{19,25,5},{29,5,648},{15,27,5},{15,27,5},{11,23,5},{31,16,648},{11,23,5},{31,15,884},{20,31,80},{21,28,5},{14,28,5},{31,15,884},{31,23,884},{14,28,5},{0,26,890},{31,23,884},{0,26,890},{16,0,890}, +{16,0,890},{16,0,890},{16,0,890},{14,29,5},{14,29,5},{14,29,5},{14,21,8},{9,24,5},{9,24,5},{20,31,4072},{18,31,1694},{18,30,1314},{17,29,943},{19,31,4705},{15,31,1064},{15,29,13},{14,26,1314},{8,31,3355},{8,27,948},{22,31,1656},{20,31,276},{20,30,89},{19,29,197},{31,11,3051},{16,31,1054},{15,29,9},{6,27,891},{31,21,3051},{6,27,891},{18,31,1210},{18,31,1210},{18,31,1210}, +{17,28,891},{16,31,897},{15,29,9},{15,29,9},{14,24,86},{8,29,652},{10,24,18},{20,31,20},{20,31,20},{20,31,20},{20,26,8},{31,4,648},{16,28,5},{16,28,5},{11,24,2},{30,18,648},{11,24,2},{28,24,882},{22,31,157},{22,29,5},{15,29,5},{28,24,882},{24,28,882},{15,29,5},{0,27,890},{24,28,882},{0,27,890},{17,0,890},{17,0,890},{17,0,890},{17,0,890},{15,30,5}, +{15,30,5},{15,30,5},{15,22,8},{10,25,5},{10,25,5},{21,31,4390},{19,31,2007},{19,31,1314},{18,30,943},{20,31,4932},{16,31,1287},{16,30,15},{15,27,1314},{11,31,3547},{9,28,958},{23,31,1784},{22,31,465},{21,31,89},{20,30,184},{28,20,3048},{18,31,1188},{16,30,6},{6,28,901},{28,24,3048},{6,28,901},{19,31,1278},{19,31,1278},{19,31,1278},{18,29,891},{17,31,1011},{16,30,11},{16,30,11}, +{15,25,86},{9,30,652},{11,25,18},{21,31,53},{21,31,53},{21,31,53},{21,27,8},{31,7,648},{16,30,2},{16,30,2},{12,25,2},{31,19,648},{12,25,2},{29,25,882},{24,31,269},{23,30,5},{16,30,5},{29,25,882},{27,28,882},{16,30,5},{0,28,900},{27,28,882},{0,28,900},{18,0,890},{18,0,890},{18,0,890},{18,0,890},{16,30,10},{16,30,10},{16,30,10},{16,23,10},{11,26,5}, +{11,26,5},{22,31,4471},{20,31,2295},{20,31,1395},{19,31,936},{21,31,4906},{18,31,1414},{17,31,8},{16,28,1161},{13,31,3570},{11,28,818},{24,31,1769},{23,31,590},{23,31,106},{22,30,146},{29,21,2814},{19,31,1206},{17,31,4},{8,29,786},{31,24,2814},{8,29,786},{20,31,1395},{20,31,1395},{20,31,1395},{19,30,900},{19,31,1134},{17,31,8},{17,31,8},{16,26,76},{10,31,651},{13,26,24},{23,31,106}, +{23,31,106},{23,31,106},{22,28,5},{28,16,648},{17,31,4},{17,31,4},{14,26,5},{24,24,648},{14,26,5},{31,24,761},{26,31,317},{24,31,1},{17,31,0},{31,24,761},{30,28,761},{17,31,0},{0,29,785},{30,28,761},{0,29,785},{19,0,900},{19,0,900},{19,0,900},{19,0,900},{17,31,8},{17,31,8},{17,31,8},{17,24,8},{12,27,5},{12,27,5},{23,31,3955},{22,31,2260},{21,31,1530}, +{20,31,891},{22,31,4375},{19,31,1194},{18,31,54},{17,28,805},{15,31,3075},{12,29,498},{25,31,1417},{24,31,510},{24,31,149},{23,30,74},{31,19,2249},{21,31,937},{19,31,5},{11,29,482},{31,25,2249},{11,29,482},{21,31,1530},{21,31,1530},{21,31,1530},{20,31,891},{20,31,1251},{18,31,54},{18,31,54},{17,27,76},{12,31,691},{14,27,24},{24,31,149},{24,31,149},{24,31,149},{23,29,5},{29,17,648}, +{19,31,5},{19,31,5},{15,27,5},{27,24,648},{15,27,5},{29,29,481},{27,31,202},{25,31,4},{20,31,1},{29,29,481},{31,28,481},{20,31,1},{0,29,481},{31,28,481},{0,29,481},{20,0,890},{20,0,890},{20,0,890},{20,0,890},{18,31,29},{18,31,29},{18,31,29},{18,25,8},{13,28,5},{13,28,5},{24,31,3609},{23,31,2199},{22,31,1683},{21,31,915},{23,31,3827},{20,31,1071},{19,31,153}, +{18,29,485},{16,31,2690},{13,30,306},{26,31,1133},{25,31,489},{25,31,200},{24,31,20},{29,25,1769},{22,31,710},{21,31,41},{12,30,290},{27,28,1769},{12,30,290},{22,31,1683},{22,31,1683},{22,31,1683},{21,31,915},{21,31,1401},{19,31,153},{19,31,153},{18,28,86},{14,31,769},{14,28,18},{25,31,200},{25,31,200},{25,31,200},{24,30,8},{31,16,648},{21,31,41},{21,31,41},{15,28,2},{30,24,648}, +{15,28,2},{31,27,265},{28,31,113},{27,31,1},{23,31,1},{31,27,265},{31,29,265},{23,31,1},{0,30,289},{31,29,265},{0,30,289},{21,0,890},{21,0,890},{21,0,890},{21,0,890},{19,31,53},{19,31,53},{19,31,53},{19,26,8},{14,29,5},{14,29,5},{24,31,3305},{24,31,2222},{23,31,1795},{22,31,990},{24,31,3438},{22,31,1087},{21,31,306},{19,30,293},{18,31,2403},{15,30,118},{27,31,857}, +{26,31,465},{26,31,269},{25,31,8},{31,23,1374},{24,31,546},{23,31,98},{14,30,114},{31,27,1374},{14,30,114},{23,31,1795},{23,31,1795},{23,31,1795},{22,31,990},{22,31,1587},{21,31,306},{21,31,306},{19,29,86},{16,31,897},{15,29,18},{26,31,269},{26,31,269},{26,31,269},{25,31,8},{31,19,648},{23,31,98},{23,31,98},{16,29,2},{31,25,648},{16,29,2},{31,28,113},{29,31,52},{28,31,1}, +{26,31,1},{31,28,113},{30,30,113},{26,31,1},{0,30,113},{30,30,113},{0,30,113},{22,0,890},{22,0,890},{22,0,890},{22,0,890},{20,31,90},{20,31,90},{20,31,90},{20,27,10},{15,30,5},{15,30,5},{25,31,3092},{25,31,2292},{24,31,1978},{24,31,1123},{25,31,3124},{23,31,1068},{22,31,525},{20,30,140},{20,31,2196},{16,31,41},{28,31,680},{27,31,458},{27,31,337},{26,31,65},{29,29,1032}, +{26,31,456},{24,31,185},{16,31,37},{31,28,1032},{16,31,37},{24,31,1978},{24,31,1978},{24,31,1978},{24,31,1123},{24,31,1769},{22,31,525},{22,31,525},{20,30,76},{18,31,1080},{17,30,24},{27,31,337},{27,31,337},{27,31,337},{26,31,65},{28,28,648},{24,31,185},{24,31,185},{18,30,5},{28,28,648},{18,30,5},{31,30,18},{30,31,9},{30,31,0},{29,31,0},{31,30,18},{30,31,18},{29,31,0}, +{0,31,36},{30,31,18},{0,31,36},{23,0,900},{23,0,900},{23,0,900},{23,0,900},{22,31,164},{22,31,164},{22,31,164},{21,28,8},{16,31,5},{16,31,5},{27,31,2818},{26,31,2254},{25,31,2043},{25,31,1243},{26,31,2829},{24,31,1099},{23,31,684},{21,31,72},{22,31,2007},{18,31,20},{29,31,566},{28,31,420},{28,31,356},{27,31,122},{31,27,771},{27,31,386},{26,31,232},{19,31,1},{31,29,771}, +{19,31,1},{25,31,2043},{25,31,2043},{25,31,2043},{25,31,1243},{25,31,1819},{23,31,684},{23,31,684},{21,31,72},{20,31,1172},{18,31,20},{28,31,356},{28,31,356},{28,31,356},{27,31,122},{31,25,578},{26,31,232},{26,31,232},{19,31,1},{27,30,578},{19,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,890}, +{24,0,890},{24,0,890},{24,0,890},{23,31,200},{23,31,200},{23,31,200},{22,29,8},{18,31,20},{18,31,20},{27,31,2242},{27,31,1879},{26,31,1738},{26,31,1150},{27,31,2209},{24,31,987},{24,31,626},{23,31,20},{23,31,1560},{19,31,53},{29,31,342},{29,31,257},{29,31,221},{28,31,68},{31,28,452},{28,31,228},{27,31,137},{22,31,1},{30,30,452},{22,31,1},{26,31,1738},{26,31,1738},{26,31,1738}, +{26,31,1150},{25,31,1499},{24,31,626},{24,31,626},{23,31,20},{22,31,950},{19,31,53},{29,31,221},{29,31,221},{29,31,221},{28,31,68},{31,26,340},{27,31,137},{27,31,137},{22,31,1},{30,29,340},{22,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,890},{25,0,890},{25,0,890},{25,0,890},{24,31,265}, +{24,31,265},{24,31,265},{23,30,8},{19,31,53},{19,31,53},{28,31,1844},{27,31,1559},{27,31,1438},{27,31,1075},{27,31,1713},{26,31,853},{25,31,635},{24,31,10},{24,31,1207},{21,31,125},{30,31,172},{30,31,145},{29,31,125},{29,31,40},{31,29,216},{29,31,121},{28,31,68},{24,31,1},{31,30,216},{24,31,1},{27,31,1438},{27,31,1438},{27,31,1438},{27,31,1075},{27,31,1229},{25,31,635},{25,31,635}, +{24,31,10},{23,31,756},{21,31,125},{29,31,125},{29,31,125},{29,31,125},{29,31,40},{31,28,164},{28,31,68},{28,31,68},{24,31,1},{30,30,164},{24,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{26,0,890},{26,0,890},{26,0,890},{26,0,890},{25,31,346},{25,31,346},{25,31,346},{24,31,10},{21,31,125}, +{21,31,125},{0,19,1568},{0,13,202},{0,10,13},{0,8,596},{0,13,3371},{0,9,2162},{0,8,1080},{0,5,2539},{0,6,3648},{0,5,2708},{0,19,1568},{0,13,202},{0,10,13},{0,8,596},{6,1,3371},{0,9,2162},{0,8,1080},{0,5,2539},{13,0,3371},{0,5,2539},{0,9,0},{0,9,0},{0,9,0},{0,4,4},{0,4,290},{0,4,125},{0,4,125},{0,2,164},{0,2,321},{0,2,189},{0,9,0}, +{0,9,0},{0,9,0},{0,4,4},{2,1,290},{0,4,125},{0,4,125},{0,2,164},{4,0,290},{0,2,164},{9,1,1568},{0,13,202},{0,10,13},{0,8,596},{9,1,1568},{19,0,1568},{0,8,596},{0,6,1586},{19,0,1568},{0,6,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,22,1568},{0,15,117},{0,11,8}, +{0,9,485},{0,15,3971},{0,10,2369},{0,9,1061},{0,6,2834},{0,7,4341},{0,6,3090},{0,22,1568},{0,15,117},{0,11,8},{0,9,485},{7,1,3968},{0,10,2369},{0,9,1061},{0,6,2834},{11,2,3968},{0,6,2834},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{0,6,512},{0,5,194},{0,5,194},{0,3,320},{0,3,576},{0,2,381},{0,12,1},{0,12,1},{0,12,1},{0,6,0},{3,0,512}, +{0,5,194},{0,5,194},{0,3,320},{6,0,512},{0,3,320},{11,0,1568},{0,15,117},{0,11,8},{0,9,485},{11,0,1568},{22,0,1568},{0,9,485},{0,7,1586},{22,0,1568},{0,7,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1568},{0,17,45},{0,12,58},{0,10,392},{0,17,4652},{0,11,2596},{0,10,1121}, +{0,7,3254},{0,8,5140},{0,6,3570},{0,25,1568},{0,17,45},{0,12,58},{0,10,392},{8,1,4652},{0,11,2596},{0,10,1121},{0,7,3254},{17,0,4652},{0,7,3254},{0,15,1},{0,15,1},{0,15,1},{0,7,4},{0,7,802},{0,6,320},{0,6,320},{0,3,512},{0,3,896},{0,3,576},{0,15,1},{0,15,1},{0,15,1},{0,7,4},{3,2,802},{0,6,320},{0,6,320},{0,3,512},{7,0,802}, +{0,3,512},{12,1,1568},{0,17,45},{1,12,13},{0,10,392},{12,1,1568},{25,0,1568},{0,10,392},{0,8,1576},{25,0,1568},{0,8,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,1570},{0,19,16},{0,13,178},{0,11,340},{0,19,5424},{0,13,2843},{0,11,1240},{0,8,3704},{0,9,6003},{0,7,4095},{0,28,1570}, +{0,19,16},{1,13,122},{0,11,340},{7,5,5419},{0,13,2843},{0,11,1240},{0,8,3704},{15,2,5419},{0,8,3704},{0,18,1},{0,18,1},{0,18,1},{0,9,1},{0,9,1152},{0,7,461},{0,7,461},{0,4,709},{0,4,1281},{0,4,830},{0,18,1},{0,18,1},{0,18,1},{0,9,1},{4,1,1152},{0,7,461},{0,7,461},{0,4,709},{9,0,1152},{0,4,709},{14,0,1568},{0,19,16},{2,13,13}, +{0,11,340},{14,0,1568},{26,1,1568},{0,11,340},{0,9,1576},{26,1,1568},{0,9,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,29,1633},{1,20,75},{1,14,265},{0,13,313},{0,22,5419},{0,14,2571},{0,12,853},{0,9,3410},{0,10,6244},{0,9,3986},{1,29,1569},{1,20,11},{2,14,117},{0,13,313},{11,0,5419}, +{0,14,2571},{0,12,853},{0,9,3410},{22,0,5419},{0,9,3410},{1,19,65},{1,19,65},{1,19,65},{1,10,65},{0,12,1152},{0,9,289},{0,9,289},{0,5,580},{0,5,1393},{0,5,749},{1,19,1},{1,19,1},{1,19,1},{1,10,1},{4,4,1152},{0,9,289},{0,9,289},{0,5,580},{12,0,1152},{0,5,580},{13,5,1568},{0,21,4},{3,14,13},{0,13,232},{13,5,1568},{31,0,1568},{0,13,232}, +{0,10,1586},{31,0,1568},{0,10,1586},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,3,1},{0,3,1},{0,3,1},{0,2,1},{0,1,20},{0,1,20},{1,31,1731},{1,22,149},{2,15,457},{1,14,377},{0,25,5419},{0,16,2347},{0,13,556},{0,10,3179},{0,11,6495},{0,9,3890},{2,30,1569},{2,21,11},{3,15,117},{1,14,313},{12,1,5419},{0,16,2347},{0,13,556},{0,10,3179},{25,0,5419}, +{0,10,3179},{1,22,145},{1,22,145},{1,22,145},{1,11,154},{0,15,1152},{0,11,194},{0,11,194},{0,6,481},{0,7,1531},{0,6,737},{2,20,1},{2,20,1},{2,20,1},{2,11,1},{5,5,1152},{0,11,194},{0,11,194},{0,6,481},{15,0,1152},{0,6,481},{17,0,1568},{1,22,4},{4,15,8},{0,14,157},{17,0,1568},{30,2,1568},{0,14,157},{0,11,1586},{30,2,1568},{0,11,1586},{1,0,145}, +{1,0,145},{1,0,145},{1,0,145},{0,6,1},{0,6,1},{0,6,1},{0,3,1},{0,3,65},{0,3,65},{2,31,1977},{2,23,341},{2,16,707},{1,15,510},{0,28,5424},{0,17,2137},{0,15,373},{0,11,3035},{0,13,6709},{0,10,3860},{3,31,1569},{3,22,11},{4,16,122},{2,15,313},{14,0,5419},{0,17,2137},{0,15,373},{0,11,3035},{26,1,5419},{0,11,3035},{2,23,337},{2,23,337},{2,23,337}, +{2,12,341},{0,18,1152},{0,13,104},{0,13,104},{0,8,410},{0,8,1686},{0,7,786},{3,21,1},{3,21,1},{3,21,1},{3,12,2},{9,0,1152},{0,13,104},{0,13,104},{0,8,410},{18,0,1152},{0,8,410},{18,1,1568},{2,23,4},{5,16,13},{0,15,117},{18,1,1568},{31,3,1568},{0,15,117},{0,12,1576},{31,3,1568},{0,12,1576},{2,0,337},{2,0,337},{2,0,337},{2,0,337},{0,9,1}, +{0,9,1},{0,9,1},{0,5,4},{0,4,130},{0,4,130},{3,31,2353},{2,24,570},{3,17,1027},{2,16,714},{0,31,5424},{0,19,1979},{0,16,195},{0,12,2857},{0,14,7039},{0,11,3919},{4,31,1576},{4,23,16},{5,17,122},{3,16,331},{15,1,5419},{0,19,1979},{0,16,195},{0,12,2857},{27,2,5419},{0,12,2857},{2,26,546},{2,26,546},{2,26,546},{2,14,546},{0,21,1152},{0,14,50},{0,14,50}, +{0,9,305},{0,9,1856},{0,8,830},{4,22,1},{4,22,1},{4,22,1},{4,13,1},{10,1,1152},{0,14,50},{0,14,50},{0,9,305},{21,0,1152},{0,9,305},{19,2,1568},{3,24,10},{6,17,13},{0,16,74},{19,2,1568},{30,5,1568},{0,16,74},{0,13,1576},{30,5,1568},{0,13,1576},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,12,0},{0,12,0},{0,12,0},{0,6,1},{0,5,205}, +{0,5,205},{4,31,2980},{3,26,925},{3,19,1484},{2,17,1032},{1,31,5504},{0,21,1811},{0,17,61},{0,13,2651},{0,16,7420},{0,13,3876},{6,31,1619},{5,24,11},{6,18,117},{4,17,313},{17,0,5419},{0,21,1811},{0,17,61},{0,13,2651},{30,2,5419},{0,13,2651},{3,27,900},{3,27,900},{3,27,900},{3,15,900},{0,24,1152},{0,16,8},{0,16,8},{0,10,208},{0,11,2124},{0,9,881},{5,23,1}, +{5,23,1},{5,23,1},{5,14,1},{12,0,1152},{0,16,8},{0,16,8},{0,10,208},{24,0,1152},{0,10,208},{21,1,1568},{4,25,4},{7,18,13},{0,17,45},{21,1,1568},{27,8,1568},{0,17,45},{0,14,1586},{27,8,1568},{0,14,1586},{3,0,900},{3,0,900},{3,0,900},{3,0,900},{0,15,1},{0,15,1},{0,15,1},{0,8,4},{0,6,356},{0,6,356},{4,31,3668},{3,27,1320},{4,20,1940}, +{3,18,1352},{2,31,5771},{0,23,1737},{0,18,37},{0,14,2486},{0,17,7711},{0,14,3930},{7,31,1635},{6,25,11},{7,19,117},{5,18,313},{18,1,5419},{0,23,1737},{0,18,37},{0,14,2486},{31,3,5419},{0,14,2486},{3,30,1252},{3,30,1252},{3,30,1252},{3,16,1256},{0,27,1152},{0,18,1},{0,18,1},{0,11,164},{0,12,2369},{0,10,1001},{6,24,1},{6,24,1},{6,24,1},{6,15,1},{13,1,1152}, +{0,18,1},{0,18,1},{0,11,164},{27,0,1152},{0,11,164},{23,0,1568},{5,26,4},{8,19,8},{0,18,36},{23,0,1568},{30,8,1568},{0,18,36},{0,15,1586},{30,8,1568},{0,15,1586},{3,0,1252},{3,0,1252},{3,0,1252},{3,0,1252},{0,18,1},{0,18,1},{0,18,1},{0,9,1},{0,7,505},{0,7,505},{5,31,4346},{4,28,1644},{5,21,2372},{4,19,1703},{3,31,6079},{0,24,1644},{0,20,38}, +{0,15,2390},{0,18,7969},{0,15,3907},{8,31,1682},{7,26,11},{8,20,122},{6,19,313},{19,2,5419},{0,24,1640},{0,20,34},{0,15,2386},{30,5,5419},{0,15,2386},{4,31,1587},{4,31,1587},{4,31,1587},{4,17,1590},{0,30,1156},{0,20,29},{0,20,29},{0,12,117},{0,13,2483},{0,11,1044},{7,25,1},{7,25,1},{7,25,1},{7,16,2},{15,0,1152},{1,19,1},{1,19,1},{0,12,113},{30,0,1152}, +{0,12,113},{24,1,1568},{6,27,4},{9,20,13},{0,20,25},{24,1,1568},{31,9,1568},{0,20,25},{0,16,1576},{31,9,1568},{0,16,1576},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{0,21,5},{0,21,5},{0,21,5},{0,11,8},{0,9,565},{0,9,565},{7,31,4580},{5,29,1644},{6,22,2372},{4,20,1692},{4,31,6228},{1,25,1644},{1,21,38},{1,16,2348},{0,20,7577},{0,16,3408},{9,31,1760}, +{8,27,16},{9,21,122},{7,20,331},{19,5,5419},{0,26,1593},{2,20,27},{0,16,2252},{31,6,5419},{0,16,2252},{5,31,1590},{5,31,1590},{5,31,1590},{5,18,1590},{1,31,1156},{1,21,29},{1,21,29},{1,13,117},{0,15,2241},{0,13,699},{8,26,1},{8,26,1},{8,26,1},{8,17,1},{16,1,1152},{2,20,2},{2,20,2},{0,13,74},{31,1,1152},{0,13,74},{26,0,1568},{7,28,10},{10,21,13}, +{0,21,10},{26,0,1568},{30,11,1568},{0,21,10},{0,17,1576},{30,11,1568},{0,17,1576},{5,0,1586},{5,0,1586},{5,0,1586},{5,0,1586},{1,22,5},{1,22,5},{1,22,5},{1,12,8},{0,10,433},{0,10,433},{8,31,4826},{6,30,1644},{7,23,2352},{6,21,1676},{5,31,6463},{2,26,1644},{2,22,38},{2,17,2348},{0,22,7196},{0,17,2863},{11,31,1865},{9,28,11},{10,22,117},{8,21,313},{23,0,5419}, +{1,27,1586},{2,22,29},{0,18,2115},{30,8,5419},{0,18,2115},{6,31,1612},{6,31,1612},{6,31,1612},{6,19,1585},{3,30,1179},{3,21,29},{3,21,29},{2,14,122},{0,17,1953},{0,14,426},{9,27,1},{9,27,1},{9,27,1},{9,18,1},{16,4,1152},{3,21,4},{3,21,4},{0,15,49},{28,4,1152},{0,15,49},{25,5,1568},{8,29,4},{11,22,13},{1,22,4},{25,5,1568},{31,12,1568},{1,22,4}, +{0,18,1586},{31,12,1568},{0,18,1586},{6,0,1576},{6,0,1576},{6,0,1576},{6,0,1576},{2,24,10},{2,24,10},{2,24,10},{2,13,10},{0,13,272},{0,13,272},{9,31,5108},{7,31,1644},{8,24,2372},{7,22,1676},{7,31,6660},{3,27,1644},{3,23,38},{3,18,2348},{0,23,6891},{0,18,2519},{12,31,1952},{10,29,11},{11,23,117},{9,22,313},{24,1,5419},{2,28,1584},{3,23,29},{0,19,2027},{31,9,5419}, +{0,19,2027},{7,31,1640},{7,31,1640},{7,31,1640},{7,20,1580},{4,31,1188},{3,23,34},{3,23,34},{3,15,122},{0,19,1795},{0,15,261},{10,28,1},{10,28,1},{10,28,1},{10,19,1},{17,5,1152},{4,22,1},{4,22,1},{0,16,26},{31,4,1152},{0,16,26},{29,0,1568},{9,30,4},{12,23,8},{2,23,4},{29,0,1568},{30,14,1568},{2,23,4},{0,19,1586},{30,14,1568},{0,19,1586},{7,0,1576}, +{7,0,1576},{7,0,1576},{7,0,1576},{3,24,10},{3,24,10},{3,24,10},{3,14,10},{0,14,170},{0,14,170},{10,31,5426},{8,31,1695},{9,25,2372},{8,23,1703},{8,31,6861},{4,28,1644},{4,24,38},{3,19,2372},{0,25,6573},{0,19,2268},{13,31,2066},{11,30,11},{12,24,122},{10,23,313},{26,0,5419},{3,29,1584},{4,24,34},{0,20,1937},{30,11,5419},{0,20,1937},{8,31,1686},{8,31,1686},{8,31,1686}, +{8,21,1590},{5,31,1206},{4,24,29},{4,24,29},{4,16,117},{0,20,1602},{0,17,126},{11,29,1},{11,29,1},{11,29,1},{11,20,2},{21,0,1152},{5,23,1},{5,23,1},{0,17,5},{30,6,1152},{0,17,5},{30,1,1568},{10,31,4},{13,24,13},{3,24,10},{30,1,1568},{31,15,1568},{3,24,10},{0,20,1576},{31,15,1568},{0,20,1576},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{4,25,5}, +{4,25,5},{4,25,5},{4,15,8},{0,16,90},{0,16,90},{11,31,5658},{9,31,1836},{10,26,2372},{8,24,1692},{9,31,7116},{5,29,1644},{5,25,38},{5,20,2348},{0,26,6379},{0,21,2028},{14,31,2216},{12,31,16},{13,25,122},{11,24,331},{27,1,5419},{2,31,1584},{6,24,27},{0,21,1832},{27,14,5419},{0,21,1832},{9,31,1755},{9,31,1755},{9,31,1755},{9,22,1590},{6,31,1260},{5,25,29},{5,25,29}, +{5,17,117},{0,22,1459},{0,18,38},{12,30,1},{12,30,1},{12,30,1},{12,21,1},{22,1,1152},{6,24,2},{6,24,2},{0,18,2},{31,7,1152},{0,18,2},{31,2,1568},{11,31,13},{14,25,13},{4,25,10},{31,2,1568},{30,17,1568},{4,25,10},{0,21,1576},{30,17,1568},{0,21,1576},{9,0,1586},{9,0,1586},{9,0,1586},{9,0,1586},{5,26,5},{5,26,5},{5,26,5},{5,16,8},{0,18,37}, +{0,18,37},{12,31,6036},{11,31,2033},{11,27,2352},{10,25,1676},{11,31,7423},{6,30,1644},{6,26,38},{6,21,2348},{0,28,6109},{0,22,1794},{15,31,2371},{13,31,50},{14,26,117},{12,25,313},{29,0,5419},{5,31,1586},{6,26,29},{0,22,1730},{30,14,5419},{0,22,1730},{10,31,1865},{10,31,1865},{10,31,1865},{10,23,1585},{7,31,1339},{7,25,29},{7,25,29},{6,18,122},{0,23,1345},{0,19,16},{13,31,1}, +{13,31,1},{13,31,1},{13,22,1},{24,0,1152},{7,25,4},{7,25,4},{2,19,1},{24,12,1152},{2,19,1},{29,9,1568},{14,31,41},{15,26,13},{5,26,4},{29,9,1568},{27,20,1568},{5,26,4},{0,22,1586},{27,20,1568},{0,22,1586},{10,0,1576},{10,0,1576},{10,0,1576},{10,0,1576},{6,28,10},{6,28,10},{6,28,10},{6,17,10},{0,20,13},{0,20,13},{13,31,6450},{12,31,2268},{12,28,2372}, +{11,26,1676},{12,31,7676},{7,31,1644},{7,27,38},{7,22,2348},{0,30,5924},{0,23,1695},{17,31,2536},{15,31,139},{15,27,117},{13,26,313},{30,1,5419},{7,31,1635},{7,27,29},{0,23,1686},{31,15,5419},{0,23,1686},{11,31,1937},{11,31,1937},{11,31,1937},{11,24,1580},{9,31,1420},{7,27,34},{7,27,34},{7,19,122},{0,25,1234},{1,20,17},{14,31,10},{14,31,10},{14,31,10},{14,23,1},{25,1,1152}, +{8,26,1},{8,26,1},{2,20,2},{27,12,1152},{2,20,2},{31,8,1568},{15,31,90},{16,27,8},{6,27,4},{31,8,1568},{30,20,1568},{6,27,4},{0,23,1586},{30,20,1568},{0,23,1586},{11,0,1576},{11,0,1576},{11,0,1576},{11,0,1576},{7,28,10},{7,28,10},{7,28,10},{7,18,10},{0,21,10},{0,21,10},{15,31,6772},{13,31,2595},{13,29,2372},{12,27,1703},{13,31,7985},{8,31,1725},{8,28,38}, +{7,23,2372},{0,31,5773},{0,24,1644},{18,31,2722},{16,31,261},{16,28,122},{14,27,313},{31,2,5419},{8,31,1721},{8,28,34},{0,24,1640},{30,17,5419},{0,24,1640},{12,31,2027},{12,31,2027},{12,31,2027},{12,25,1590},{10,31,1510},{8,28,29},{8,28,29},{8,20,117},{0,27,1188},{2,21,17},{15,31,26},{15,31,26},{15,31,26},{15,24,2},{27,0,1152},{9,27,1},{9,27,1},{3,21,2},{30,12,1152}, +{3,21,2},{31,11,1568},{17,31,180},{17,28,13},{7,28,10},{31,11,1568},{31,21,1568},{7,28,10},{0,24,1576},{31,21,1568},{0,24,1576},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{8,29,5},{8,29,5},{8,29,5},{8,19,8},{1,22,10},{1,22,10},{16,31,7154},{14,31,2955},{14,30,2372},{12,28,1692},{14,31,8348},{10,31,1895},{9,29,38},{9,24,2348},{1,31,5956},{1,25,1644},{19,31,2866}, +{17,31,468},{17,29,122},{15,28,331},{31,5,5419},{10,31,1859},{10,28,27},{0,25,1601},{31,18,5419},{0,25,1601},{13,31,2162},{13,31,2162},{13,31,2162},{13,26,1590},{11,31,1590},{9,29,29},{9,29,29},{9,21,117},{0,28,1161},{3,22,17},{16,31,49},{16,31,49},{16,31,49},{16,25,1},{28,1,1152},{10,28,2},{10,28,2},{4,22,2},{31,13,1152},{4,22,2},{31,14,1568},{19,31,277},{18,29,13}, +{8,29,10},{31,14,1568},{30,23,1568},{8,29,10},{0,25,1576},{30,23,1568},{0,25,1576},{13,0,1586},{13,0,1586},{13,0,1586},{13,0,1586},{9,30,5},{9,30,5},{9,30,5},{9,20,8},{2,23,10},{2,23,10},{17,31,7636},{15,31,3408},{15,31,2352},{14,29,1676},{16,31,8673},{11,31,2187},{10,30,38},{10,25,2348},{3,31,6235},{2,26,1644},{20,31,3112},{19,31,754},{18,30,117},{16,29,313},{31,8,5419}, +{12,31,2060},{10,30,29},{0,26,1587},{30,20,5419},{0,26,1587},{15,31,2252},{15,31,2252},{15,31,2252},{14,27,1585},{12,31,1740},{11,29,29},{11,29,29},{10,22,122},{0,30,1163},{4,23,16},{18,31,85},{18,31,85},{18,31,85},{17,26,1},{28,4,1152},{11,29,4},{11,29,4},{6,23,1},{28,16,1152},{6,23,1},{29,21,1568},{20,31,436},{19,30,13},{9,30,4},{29,21,1568},{31,24,1568},{9,30,4}, +{0,26,1586},{31,24,1568},{0,26,1586},{14,0,1576},{14,0,1576},{14,0,1576},{14,0,1576},{10,31,13},{10,31,13},{10,31,13},{10,21,10},{3,24,10},{3,24,10},{18,31,8122},{16,31,3907},{16,31,2390},{15,30,1676},{17,31,9036},{12,31,2576},{11,31,38},{11,26,2348},{6,31,6555},{3,27,1644},{22,31,3392},{20,31,1044},{19,31,117},{17,30,313},{31,11,5419},{15,31,2284},{11,31,29},{0,27,1587},{31,21,5419}, +{0,27,1587},{16,31,2386},{16,31,2386},{16,31,2386},{15,28,1580},{14,31,1924},{11,31,34},{11,31,34},{11,23,122},{1,31,1163},{5,24,17},{19,31,113},{19,31,113},{19,31,113},{18,27,1},{29,5,1152},{12,30,1},{12,30,1},{6,24,2},{31,16,1152},{6,24,2},{31,20,1568},{22,31,593},{20,31,8},{10,31,4},{31,20,1568},{30,26,1568},{10,31,4},{0,27,1586},{30,26,1568},{0,27,1586},{15,0,1576}, +{15,0,1576},{15,0,1576},{15,0,1576},{11,31,25},{11,31,25},{11,31,25},{11,22,10},{4,25,10},{4,25,10},{19,31,7638},{17,31,4060},{17,31,2539},{16,30,1659},{18,31,8553},{14,31,2430},{13,31,37},{11,27,1940},{7,31,6120},{4,28,1320},{23,31,2996},{20,31,1064},{20,31,164},{19,30,186},{29,17,4803},{16,31,2018},{13,31,1},{1,28,1253},{27,24,4803},{1,28,1253},{17,31,2539},{17,31,2539},{17,31,2539}, +{16,29,1590},{15,31,2028},{13,31,37},{13,31,37},{12,24,117},{3,31,1170},{6,25,17},{20,31,164},{20,31,164},{20,31,164},{19,28,2},{31,4,1152},{13,31,1},{13,31,1},{7,25,2},{30,18,1152},{7,25,2},{31,22,1250},{24,31,505},{22,31,0},{13,31,0},{31,22,1250},{30,27,1250},{13,31,0},{0,28,1252},{30,27,1250},{0,28,1252},{16,0,1586},{16,0,1586},{16,0,1586},{16,0,1586},{13,31,37}, +{13,31,37},{13,31,37},{12,23,8},{5,26,10},{5,26,10},{20,31,7060},{19,31,3955},{18,31,2710},{17,31,1595},{19,31,7717},{15,31,2140},{14,31,77},{13,28,1480},{8,31,5539},{6,28,925},{23,31,2516},{22,31,945},{21,31,233},{20,30,100},{31,15,4056},{18,31,1656},{15,31,8},{4,28,900},{31,23,4056},{4,28,900},{18,31,2710},{18,31,2710},{18,31,2710},{17,30,1590},{16,31,2193},{14,31,77},{14,31,77}, +{13,25,117},{5,31,1233},{7,26,17},{21,31,233},{21,31,233},{21,31,233},{20,29,1},{31,7,1152},{15,31,8},{15,31,8},{8,26,2},{31,19,1152},{8,26,2},{31,23,884},{25,31,370},{23,31,4},{16,31,1},{31,23,884},{31,27,884},{16,31,1},{0,28,900},{31,27,884},{0,28,900},{17,0,1586},{17,0,1586},{17,0,1586},{17,0,1586},{14,31,52},{14,31,52},{14,31,52},{13,24,8},{6,27,10}, +{6,27,10},{21,31,6535},{20,31,3919},{19,31,2857},{18,31,1585},{20,31,6979},{16,31,1942},{15,31,195},{14,28,990},{11,31,4914},{7,29,562},{24,31,2045},{23,31,830},{22,31,338},{21,31,26},{29,21,3318},{19,31,1314},{17,31,52},{5,29,546},{31,24,3318},{5,29,546},{19,31,2857},{19,31,2857},{19,31,2857},{18,31,1585},{17,31,2436},{15,31,195},{15,31,195},{14,26,122},{7,31,1339},{8,27,16},{22,31,338}, +{22,31,338},{22,31,338},{21,30,1},{28,16,1152},{17,31,52},{17,31,52},{10,27,1},{24,24,1152},{10,27,1},{31,25,545},{26,31,221},{25,31,0},{19,31,0},{31,25,545},{31,28,545},{19,31,0},{0,29,545},{31,28,545},{0,29,545},{18,0,1576},{18,0,1576},{18,0,1576},{18,0,1576},{15,31,74},{15,31,74},{15,31,74},{14,25,10},{7,28,10},{7,28,10},{22,31,6151},{20,31,3935},{20,31,3035}, +{19,31,1640},{21,31,6458},{18,31,1902},{16,31,373},{15,29,670},{12,31,4499},{8,29,347},{25,31,1729},{24,31,786},{23,31,410},{22,31,1},{31,19,2753},{20,31,1094},{19,31,113},{8,29,338},{31,25,2753},{8,29,338},{20,31,3035},{20,31,3035},{20,31,3035},{19,31,1640},{19,31,2630},{16,31,373},{16,31,373},{15,27,122},{10,31,1483},{9,28,17},{23,31,410},{23,31,410},{23,31,410},{22,31,1},{29,17,1152}, +{19,31,113},{19,31,113},{10,28,2},{27,24,1152},{10,28,2},{31,26,317},{27,31,130},{26,31,9},{22,31,0},{31,26,317},{30,29,317},{22,31,0},{0,29,337},{30,29,317},{0,29,337},{19,0,1576},{19,0,1576},{19,0,1576},{19,0,1576},{16,31,117},{16,31,117},{16,31,117},{15,26,10},{8,29,10},{8,29,10},{23,31,5691},{22,31,4004},{21,31,3254},{20,31,1755},{22,31,6023},{19,31,1830},{18,31,606}, +{16,29,430},{14,31,4162},{9,30,155},{26,31,1481},{25,31,801},{24,31,505},{23,31,26},{29,25,2273},{22,31,914},{20,31,194},{9,30,146},{27,28,2273},{9,30,146},{21,31,3254},{21,31,3254},{21,31,3254},{20,31,1755},{20,31,2835},{18,31,606},{18,31,606},{16,28,117},{11,31,1665},{10,29,17},{24,31,505},{24,31,505},{24,31,505},{23,31,26},{31,16,1152},{20,31,194},{20,31,194},{11,29,2},{30,24,1152}, +{11,29,2},{31,28,145},{28,31,65},{28,31,1},{25,31,0},{31,28,145},{30,30,145},{25,31,0},{0,30,145},{30,30,145},{0,30,145},{20,0,1586},{20,0,1586},{20,0,1586},{20,0,1586},{17,31,180},{17,31,180},{17,31,180},{16,27,8},{9,30,10},{9,30,10},{24,31,5421},{23,31,3999},{22,31,3491},{21,31,1947},{23,31,5539},{20,31,1879},{19,31,853},{17,30,238},{16,31,3922},{11,30,81},{27,31,1229}, +{26,31,813},{26,31,617},{24,31,100},{31,23,1878},{23,31,822},{22,31,305},{12,30,66},{31,27,1878},{12,30,66},{22,31,3491},{22,31,3491},{22,31,3491},{21,31,1947},{21,31,3081},{19,31,853},{19,31,853},{17,29,117},{14,31,1905},{11,30,17},{26,31,617},{26,31,617},{26,31,617},{24,31,100},{31,19,1152},{22,31,305},{22,31,305},{12,30,2},{31,25,1152},{12,30,2},{31,29,45},{30,31,18},{29,31,4}, +{28,31,1},{31,29,45},{31,30,45},{28,31,1},{0,30,65},{31,30,45},{0,30,65},{21,0,1586},{21,0,1586},{21,0,1586},{21,0,1586},{18,31,261},{18,31,261},{18,31,261},{17,28,8},{10,31,10},{10,31,10},{24,31,5178},{24,31,4095},{23,31,3704},{22,31,2201},{24,31,5197},{21,31,2101},{20,31,1240},{18,31,153},{18,31,3760},{12,31,16},{28,31,1088},{27,31,830},{27,31,709},{26,31,245},{29,29,1536}, +{26,31,792},{24,31,461},{14,31,1},{31,28,1536},{14,31,1},{23,31,3704},{23,31,3704},{23,31,3704},{22,31,2201},{23,31,3396},{20,31,1240},{20,31,1240},{18,30,122},{15,31,2208},{12,31,16},{27,31,709},{27,31,709},{27,31,709},{26,31,245},{28,28,1152},{24,31,461},{24,31,461},{14,31,1},{28,28,1152},{14,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0}, +{0,31,0},{31,31,0},{0,31,0},{22,0,1576},{22,0,1576},{22,0,1576},{22,0,1576},{20,31,340},{20,31,340},{20,31,340},{18,29,10},{12,31,16},{12,31,16},{25,31,4468},{24,31,3615},{24,31,3254},{23,31,2060},{24,31,4413},{22,31,1834},{21,31,1205},{19,31,58},{19,31,3127},{14,31,53},{28,31,768},{28,31,576},{28,31,512},{27,31,170},{31,26,1068},{26,31,536},{25,31,338},{16,31,1},{30,29,1068}, +{16,31,1},{24,31,3254},{24,31,3254},{24,31,3254},{23,31,2060},{23,31,2852},{21,31,1205},{21,31,1205},{19,31,58},{16,31,1878},{14,31,53},{28,31,512},{28,31,512},{28,31,512},{27,31,170},{31,24,802},{25,31,338},{25,31,338},{16,31,1},{30,28,802},{16,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,1576}, +{23,0,1576},{23,0,1576},{23,0,1576},{21,31,421},{21,31,421},{21,31,421},{19,30,10},{14,31,53},{14,31,53},{26,31,3858},{25,31,3188},{25,31,2899},{24,31,1947},{25,31,3700},{23,31,1596},{23,31,1112},{20,31,8},{20,31,2588},{16,31,117},{29,31,498},{28,31,384},{28,31,320},{27,31,122},{31,27,683},{27,31,342},{26,31,212},{19,31,1},{31,29,683},{19,31,1},{25,31,2899},{25,31,2899},{25,31,2899}, +{24,31,1947},{24,31,2441},{23,31,1112},{23,31,1112},{20,31,8},{18,31,1568},{16,31,117},{28,31,320},{28,31,320},{28,31,320},{27,31,122},{29,29,512},{26,31,212},{26,31,212},{19,31,1},{31,28,512},{19,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{24,0,1586},{24,0,1586},{24,0,1586},{24,0,1586},{22,31,520}, +{22,31,520},{22,31,520},{20,31,8},{16,31,117},{16,31,117},{27,31,3258},{26,31,2790},{26,31,2594},{25,31,1875},{26,31,3105},{24,31,1447},{23,31,1080},{21,31,20},{22,31,2151},{18,31,208},{29,31,306},{29,31,221},{29,31,185},{28,31,64},{31,28,384},{28,31,192},{27,31,125},{22,31,1},{30,30,384},{22,31,1},{26,31,2594},{26,31,2594},{26,31,2594},{25,31,1875},{25,31,2131},{23,31,1080},{23,31,1080}, +{21,31,20},{20,31,1336},{18,31,208},{29,31,185},{29,31,185},{29,31,185},{28,31,64},{31,27,290},{27,31,125},{27,31,125},{22,31,1},{31,29,290},{22,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{25,0,1586},{25,0,1586},{25,0,1586},{25,0,1586},{23,31,596},{23,31,596},{23,31,596},{21,31,20},{18,31,208}, +{18,31,208},{0,25,2669},{0,18,320},{0,13,5},{0,11,985},{0,17,5885},{0,11,3745},{0,10,1746},{0,7,4421},{0,8,6385},{0,7,4782},{0,25,2669},{0,18,320},{0,13,5},{0,11,985},{8,1,5885},{0,11,3745},{0,10,1746},{0,7,4421},{17,0,5885},{0,7,4421},{0,12,0},{0,12,0},{0,12,0},{0,6,1},{0,6,545},{0,5,205},{0,5,205},{0,3,337},{0,3,609},{0,3,401},{0,12,0}, +{0,12,0},{0,12,0},{0,6,1},{3,0,545},{0,5,205},{0,5,205},{0,3,337},{6,0,545},{0,3,337},{13,0,2669},{0,18,320},{0,13,5},{0,11,985},{13,0,2669},{25,0,2669},{0,11,985},{0,8,2689},{25,0,2669},{0,8,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,2665},{0,20,212},{0,14,10}, +{0,12,850},{0,19,6669},{0,13,3974},{0,11,1837},{0,8,4865},{0,9,7266},{0,7,5310},{0,28,2665},{0,20,212},{0,14,10},{0,12,850},{9,1,6669},{0,13,3974},{0,11,1837},{0,8,4865},{19,0,6669},{0,8,4865},{0,15,0},{0,15,0},{0,15,0},{0,7,9},{0,7,845},{0,6,337},{0,6,337},{0,3,545},{0,3,945},{0,3,609},{0,15,0},{0,15,0},{0,15,0},{0,7,9},{3,2,841}, +{0,6,337},{0,6,337},{0,3,545},{6,1,841},{0,3,545},{12,4,2665},{0,20,212},{1,14,5},{0,12,850},{12,4,2665},{28,0,2665},{0,12,850},{0,9,2689},{28,0,2665},{0,9,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2665},{0,21,113},{0,15,65},{0,13,709},{0,21,7538},{0,14,4289},{0,12,1907}, +{0,9,5330},{0,10,8294},{0,8,5845},{0,31,2665},{0,21,113},{0,15,65},{0,13,709},{10,1,7538},{0,14,4289},{0,12,1907},{0,9,5330},{21,0,7538},{0,9,5330},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,9,1201},{0,7,482},{0,7,482},{0,4,740},{0,4,1334},{0,4,861},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{4,1,1201},{0,7,482},{0,7,482},{0,4,740},{9,0,1201}, +{0,4,740},{13,5,2665},{0,21,113},{2,15,5},{0,13,709},{13,5,2665},{31,0,2665},{0,13,709},{0,10,2689},{31,0,2665},{0,10,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2809},{0,23,52},{0,16,173},{0,14,586},{0,23,8494},{0,15,4610},{0,13,1950},{0,9,5826},{0,11,9409},{0,9,6402},{1,31,2753}, +{0,23,52},{1,16,132},{0,14,586},{11,1,8493},{0,15,4610},{0,13,1950},{0,9,5826},{19,2,8493},{0,9,5826},{0,21,0},{0,21,0},{0,21,0},{0,10,9},{0,10,1629},{0,9,640},{0,9,640},{0,5,985},{0,5,1798},{0,5,1154},{0,21,0},{0,21,0},{0,21,0},{0,10,9},{3,5,1625},{0,9,640},{0,9,640},{0,5,985},{7,2,1625},{0,5,985},{17,0,2665},{0,23,52},{2,16,13}, +{0,14,586},{17,0,2665},{30,2,2665},{0,14,586},{0,11,2689},{30,2,2665},{0,11,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,31,3105},{0,25,8},{1,17,325},{0,15,512},{0,25,9669},{0,17,4961},{0,14,2120},{0,10,6421},{0,12,10774},{0,10,7150},{2,31,3033},{0,25,8},{1,17,261},{0,15,512},{12,1,9669}, +{0,17,4961},{0,14,2120},{0,10,6421},{25,0,9669},{0,10,6421},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{0,12,2178},{0,9,865},{0,9,865},{0,6,1313},{0,5,2419},{0,5,1523},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{4,4,2178},{0,9,865},{0,9,865},{0,6,1313},{12,0,2178},{0,6,1313},{19,0,2669},{0,25,8},{4,17,5},{0,15,512},{19,0,2669},{31,3,2669},{0,15,512}, +{0,12,2689},{31,3,2669},{0,12,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,3465},{0,27,65},{1,19,434},{0,17,474},{0,28,9670},{0,18,4658},{0,16,1717},{0,11,6209},{0,13,10979},{0,11,7109},{3,31,3101},{1,26,8},{2,18,261},{0,17,474},{14,0,9669},{0,18,4658},{0,16,1717},{0,11,6209},{26,1,9669}, +{0,11,6209},{1,25,64},{1,25,64},{1,25,64},{1,13,64},{0,15,2178},{0,11,680},{0,11,680},{0,7,1189},{0,7,2557},{0,6,1457},{1,25,0},{1,25,0},{1,25,0},{1,13,0},{5,5,2178},{0,11,680},{0,11,680},{0,7,1189},{15,0,2178},{0,7,1189},{20,0,2665},{0,27,1},{5,18,5},{0,17,410},{20,0,2665},{24,8,2665},{0,17,410},{0,13,2689},{24,8,2665},{0,13,2689},{0,0,64}, +{0,0,64},{0,0,64},{0,0,64},{0,3,0},{0,3,0},{0,3,0},{0,2,4},{0,1,13},{0,1,13},{3,31,3917},{1,28,129},{2,20,645},{1,18,538},{0,31,9670},{0,20,4330},{0,17,1246},{0,12,5925},{0,14,11321},{0,12,7014},{4,31,3218},{2,27,8},{3,19,261},{1,18,474},{15,1,9669},{0,20,4330},{0,17,1246},{0,12,5925},{27,2,9669},{0,12,5925},{1,28,128},{1,28,128},{1,28,128}, +{1,15,132},{0,18,2178},{0,13,482},{0,13,482},{0,8,1040},{0,8,2712},{0,7,1470},{2,26,0},{2,26,0},{2,26,0},{2,14,0},{9,0,2178},{0,13,482},{0,13,482},{0,8,1040},{18,0,2178},{0,8,1040},{21,1,2665},{1,28,1},{6,19,5},{0,18,305},{21,1,2665},{27,8,2665},{0,18,305},{0,14,2689},{27,8,2665},{0,14,2689},{1,0,128},{1,0,128},{1,0,128},{1,0,128},{0,6,0}, +{0,6,0},{0,6,0},{0,3,0},{0,2,61},{0,2,61},{3,31,4541},{2,29,321},{2,21,904},{1,19,625},{1,31,9749},{0,21,4018},{0,18,914},{0,14,5633},{0,16,11661},{0,13,6859},{5,31,3374},{3,28,10},{4,20,254},{2,19,474},{17,0,9670},{0,21,4018},{0,18,914},{0,14,5633},{30,2,9670},{0,14,5633},{2,29,320},{2,29,320},{2,29,320},{1,16,320},{0,21,2178},{0,15,353},{0,15,353}, +{0,9,881},{0,9,2882},{0,9,1457},{3,27,0},{3,27,0},{3,27,0},{3,15,0},{10,1,2178},{0,15,353},{0,15,353},{0,9,881},{21,0,2178},{0,9,881},{23,0,2665},{2,29,1},{6,20,13},{0,19,245},{23,0,2665},{30,8,2665},{0,19,245},{0,15,2689},{30,8,2665},{0,15,2689},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,9,0},{0,9,0},{0,9,0},{0,4,4},{0,4,125}, +{0,4,125},{4,31,5378},{2,31,570},{3,22,1267},{2,20,850},{2,31,10045},{0,23,3745},{0,19,642},{0,14,5354},{0,17,11993},{0,14,6798},{7,31,3553},{4,29,8},{5,21,261},{3,20,491},{18,1,9669},{0,23,3745},{0,19,642},{0,14,5354},{31,3,9669},{0,14,5354},{2,31,561},{2,31,561},{2,31,561},{2,17,546},{0,24,2178},{0,17,205},{0,17,205},{0,10,730},{0,11,3150},{0,9,1457},{4,28,0}, +{4,28,0},{4,28,0},{4,16,0},{12,0,2178},{0,17,205},{0,17,205},{0,10,730},{24,0,2178},{0,10,730},{25,0,2669},{3,30,1},{8,21,5},{0,20,170},{25,0,2669},{31,9,2669},{0,20,170},{0,16,2689},{31,9,2669},{0,16,2689},{2,0,545},{2,0,545},{2,0,545},{2,0,545},{0,12,0},{0,12,0},{0,12,0},{0,6,1},{0,5,205},{0,5,205},{5,31,6330},{3,31,905},{4,23,1718}, +{2,21,1099},{3,31,10453},{0,25,3478},{0,21,369},{0,16,5138},{0,18,12455},{0,15,6867},{8,31,3710},{5,30,8},{6,22,261},{4,21,474},{19,2,9669},{0,25,3478},{0,21,369},{0,16,5138},{30,5,9669},{0,16,5138},{3,31,901},{3,31,901},{3,31,901},{3,18,866},{0,27,2178},{0,19,130},{0,19,130},{0,11,650},{0,12,3395},{0,10,1523},{5,29,0},{5,29,0},{5,29,0},{5,17,0},{13,1,2178}, +{0,19,130},{0,19,130},{0,11,650},{27,0,2178},{0,11,650},{24,4,2665},{4,31,1},{9,22,5},{0,21,113},{24,4,2665},{28,12,2665},{0,21,113},{0,17,2689},{28,12,2665},{0,17,2689},{3,0,865},{3,0,865},{3,0,865},{3,0,865},{0,15,0},{0,15,0},{0,15,0},{0,7,9},{0,6,337},{0,6,337},{6,31,7446},{4,31,1458},{4,24,2174},{3,22,1419},{3,31,11045},{0,27,3314},{0,22,195}, +{0,17,4865},{0,20,12855},{0,16,6882},{9,31,3902},{6,31,8},{7,23,261},{5,22,474},{19,5,9669},{0,27,3314},{0,22,195},{0,17,4865},{31,6,9669},{0,17,4865},{3,31,1397},{3,31,1397},{3,31,1397},{3,19,1210},{0,30,2178},{0,20,61},{0,20,61},{0,12,545},{0,13,3645},{0,12,1634},{6,30,0},{6,30,0},{6,30,0},{6,18,0},{15,0,2178},{0,20,61},{0,20,61},{0,12,545},{30,0,2178}, +{0,12,545},{25,5,2665},{6,31,8},{10,23,5},{0,22,74},{25,5,2665},{31,12,2665},{0,22,74},{0,18,2689},{31,12,2665},{0,18,2689},{3,0,1201},{3,0,1201},{3,0,1201},{3,0,1201},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,7,482},{0,7,482},{7,31,8578},{4,31,2146},{5,25,2766},{3,23,1835},{4,31,11766},{0,28,3125},{0,23,94},{0,18,4610},{0,21,13238},{0,17,6837},{10,31,4130}, +{7,31,49},{8,24,254},{6,23,474},{23,0,9670},{0,28,3125},{0,23,94},{0,18,4610},{30,8,9670},{0,18,4610},{4,31,1921},{4,31,1921},{4,31,1921},{3,21,1665},{0,31,2228},{0,22,18},{0,22,18},{0,14,425},{0,15,3987},{0,13,1677},{7,31,0},{7,31,0},{7,31,0},{7,19,0},{16,1,2178},{0,22,18},{0,22,18},{0,14,425},{31,1,2178},{0,14,425},{29,0,2665},{7,31,49},{10,24,13}, +{0,23,58},{29,0,2665},{30,14,2665},{0,23,58},{0,19,2689},{30,14,2665},{0,19,2689},{3,0,1665},{3,0,1665},{3,0,1665},{3,0,1665},{0,21,0},{0,21,0},{0,21,0},{0,10,9},{0,9,640},{0,9,640},{7,31,10135},{5,31,3190},{5,26,3543},{4,24,2348},{5,31,12846},{0,30,2961},{0,25,30},{0,19,4421},{0,23,13846},{0,18,6930},{11,31,4345},{8,31,178},{9,25,261},{7,24,491},{24,1,9669}, +{0,30,2961},{0,25,30},{0,19,4421},{31,9,9669},{0,19,4421},{5,31,2706},{5,31,2706},{5,31,2706},{4,22,2179},{1,31,2404},{0,24,0},{0,24,0},{0,15,337},{0,16,4356},{0,14,1833},{8,31,9},{8,31,9},{8,31,9},{8,20,0},{16,4,2178},{0,24,0},{0,24,0},{0,15,337},{28,4,2178},{0,15,337},{31,0,2669},{10,31,113},{12,25,5},{0,25,26},{31,0,2669},{31,15,2669},{0,25,26}, +{0,20,2689},{31,15,2669},{0,20,2689},{4,0,2178},{4,0,2178},{4,0,2178},{4,0,2178},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{0,9,865},{0,9,865},{8,31,11466},{6,31,4187},{6,27,4166},{4,25,2818},{6,31,13898},{0,31,2871},{0,26,15},{0,20,4226},{0,24,14214},{0,19,7006},{12,31,4590},{10,31,321},{10,26,261},{8,25,474},{26,0,9669},{0,31,2870},{0,26,14},{0,20,4225},{30,11,9669}, +{0,20,4225},{6,31,3458},{6,31,3458},{6,31,3458},{5,23,2690},{2,31,2691},{0,26,14},{0,26,14},{0,16,261},{0,17,4595},{0,15,1953},{9,31,36},{9,31,36},{9,31,36},{9,21,0},{17,5,2178},{1,25,0},{1,25,0},{0,16,260},{31,4,2178},{0,16,260},{28,8,2665},{11,31,194},{13,26,5},{0,26,5},{28,8,2665},{24,20,2665},{0,26,5},{0,21,2689},{24,20,2665},{0,21,2689},{5,0,2689}, +{5,0,2689},{5,0,2689},{5,0,2689},{0,27,1},{0,27,1},{0,27,1},{0,14,5},{0,11,1037},{0,11,1037},{9,31,12054},{7,31,4578},{7,28,4118},{5,26,2818},{7,31,14214},{1,31,3042},{1,27,15},{0,21,4099},{0,25,13683},{0,21,6322},{14,31,4858},{11,31,514},{11,27,261},{9,26,474},{27,1,9669},{2,31,3014},{1,27,14},{0,21,4018},{27,14,9669},{0,21,4018},{7,31,3554},{7,31,3554},{7,31,3554}, +{6,24,2689},{3,31,2795},{1,27,14},{1,27,14},{1,17,261},{0,19,4269},{0,16,1517},{11,31,73},{11,31,73},{11,31,73},{10,22,0},{21,0,2178},{2,26,0},{2,26,0},{0,17,185},{30,6,2178},{0,17,185},{29,9,2665},{13,31,320},{14,27,5},{0,27,1},{29,9,2665},{27,20,2665},{0,27,1},{0,22,2689},{27,20,2665},{0,22,2689},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{1,28,1}, +{1,28,1},{1,28,1},{1,15,5},{0,13,797},{0,13,797},{11,31,12506},{8,31,5075},{8,29,4166},{6,27,2818},{8,31,14651},{3,31,3255},{2,28,23},{1,22,4099},{0,27,13238},{0,21,5650},{15,31,5054},{12,31,782},{12,28,254},{10,27,474},{29,0,9670},{3,31,3206},{2,28,22},{0,22,3829},{30,14,9670},{0,22,3829},{8,31,3706},{8,31,3706},{8,31,3706},{7,25,2689},{4,31,2946},{2,28,19},{2,28,19}, +{2,18,261},{0,21,3906},{0,17,1106},{12,31,106},{12,31,106},{12,31,106},{11,23,0},{22,1,2178},{3,27,0},{3,27,0},{0,18,128},{31,7,2178},{0,18,128},{31,8,2665},{15,31,445},{14,28,13},{1,28,4},{31,8,2665},{30,20,2665},{1,28,4},{0,23,2689},{30,20,2665},{0,23,2689},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{2,29,1},{2,29,1},{2,29,1},{2,15,10},{0,14,637}, +{0,14,637},{12,31,13094},{10,31,5782},{9,30,4166},{7,28,2838},{10,31,15213},{4,31,3618},{3,29,25},{2,23,4101},{0,29,12686},{0,23,5075},{16,31,5378},{14,31,1172},{13,29,261},{11,28,491},{30,1,9669},{6,31,3469},{3,29,21},{0,23,3706},{31,15,9669},{0,23,3706},{9,31,3890},{9,31,3890},{9,31,3890},{8,26,2690},{6,31,3157},{3,29,24},{3,29,24},{3,19,254},{0,23,3619},{0,19,782},{13,31,145}, +{13,31,145},{13,31,145},{12,24,0},{24,0,2178},{4,28,0},{4,28,0},{0,19,106},{24,12,2178},{0,19,106},{31,11,2669},{16,31,640},{16,29,5},{2,29,2},{31,11,2669},{31,21,2669},{2,29,2},{0,24,2689},{31,21,2669},{0,24,2689},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{3,30,5},{3,30,5},{3,30,5},{3,17,8},{0,17,436},{0,17,436},{13,31,13718},{11,31,6325},{10,31,4166}, +{8,29,2818},{11,31,15565},{6,31,4094},{4,30,15},{3,24,4118},{0,31,12355},{0,24,4578},{17,31,5738},{15,31,1517},{14,30,261},{12,29,474},{31,2,9669},{7,31,3761},{4,30,14},{0,24,3554},{30,17,9669},{0,24,3554},{10,31,4085},{10,31,4085},{10,31,4085},{9,27,2690},{7,31,3285},{4,30,14},{4,30,14},{4,20,261},{0,24,3330},{0,20,514},{14,31,208},{14,31,208},{14,31,208},{13,25,0},{25,1,2178}, +{5,29,0},{5,29,0},{0,21,64},{27,12,2178},{0,21,64},{28,20,2665},{18,31,829},{17,30,5},{3,30,2},{28,20,2665},{28,24,2665},{3,30,2},{0,25,2689},{28,24,2665},{0,25,2689},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{4,31,1},{4,31,1},{4,31,1},{4,18,5},{0,18,306},{0,18,306},{14,31,14378},{12,31,7006},{11,31,4226},{9,30,2818},{12,31,16054},{7,31,4578},{5,31,15}, +{4,25,4099},{0,31,12051},{0,25,4089},{19,31,5970},{16,31,1953},{15,31,261},{13,30,474},{31,5,9669},{10,31,4081},{5,31,14},{0,25,3413},{31,18,9669},{0,25,3413},{11,31,4225},{11,31,4225},{11,31,4225},{10,28,2689},{8,31,3476},{5,31,14},{5,31,14},{5,21,261},{0,26,3091},{0,21,289},{15,31,260},{15,31,260},{15,31,260},{14,26,0},{27,0,2178},{6,30,0},{6,30,0},{0,22,25},{30,12,2178}, +{0,22,25},{29,21,2665},{20,31,1037},{18,31,5},{4,31,1},{29,21,2665},{31,24,2665},{4,31,1},{0,26,2689},{31,24,2665},{0,26,2689},{10,0,2689},{10,0,2689},{10,0,2689},{10,0,2689},{5,31,10},{5,31,10},{5,31,10},{5,19,5},{0,20,194},{0,20,194},{15,31,13557},{13,31,7094},{12,31,4421},{10,31,2769},{13,31,15228},{8,31,4270},{6,31,46},{5,26,3476},{0,31,11020},{0,26,3108},{20,31,5400}, +{17,31,1931},{16,31,337},{15,30,320},{31,7,8712},{11,31,3630},{7,31,0},{0,26,2667},{31,19,8712},{0,26,2667},{12,31,4421},{12,31,4421},{12,31,4421},{11,29,2689},{9,31,3722},{6,31,46},{6,31,46},{6,22,261},{0,27,2882},{0,22,173},{16,31,337},{16,31,337},{16,31,337},{15,27,0},{28,1,2178},{7,31,0},{7,31,0},{0,23,9},{31,13,2178},{0,23,9},{31,19,2178},{22,31,881},{19,31,0}, +{7,31,0},{31,19,2178},{31,25,2178},{7,31,0},{0,27,2178},{31,25,2178},{0,27,2178},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{6,31,37},{6,31,37},{6,31,37},{6,19,10},{0,22,109},{0,22,109},{16,31,12678},{14,31,7003},{13,31,4693},{12,31,2714},{15,31,14026},{10,31,3943},{8,31,94},{6,26,2766},{2,31,10074},{0,27,2146},{20,31,4698},{19,31,1746},{17,31,464},{16,30,164},{29,13,7578}, +{12,31,3090},{9,31,20},{0,27,1921},{31,20,7578},{0,27,1921},{13,31,4693},{13,31,4693},{13,31,4693},{12,30,2690},{11,31,3939},{8,31,94},{8,31,94},{7,23,254},{0,29,2650},{0,24,49},{17,31,464},{17,31,464},{17,31,464},{16,28,0},{28,4,2178},{9,31,20},{9,31,20},{0,24,0},{28,16,2178},{0,24,0},{31,21,1625},{23,31,653},{21,31,4},{10,31,1},{31,21,1625},{31,26,1625},{10,31,1}, +{0,27,1665},{31,26,1625},{0,27,1665},{12,0,2689},{12,0,2689},{12,0,2689},{12,0,2689},{8,31,58},{8,31,58},{8,31,58},{7,21,8},{0,24,49},{0,24,49},{17,31,12042},{15,31,6882},{15,31,4946},{13,31,2690},{16,31,13127},{11,31,3615},{9,31,229},{7,27,2174},{3,31,9313},{0,27,1458},{21,31,4150},{19,31,1634},{19,31,545},{17,30,89},{31,11,6661},{14,31,2654},{11,31,61},{0,28,1397},{31,21,6661}, +{0,28,1397},{15,31,4946},{15,31,4946},{15,31,4946},{13,31,2690},{12,31,4170},{9,31,229},{9,31,229},{8,24,261},{0,31,2520},{0,25,10},{19,31,545},{19,31,545},{19,31,545},{17,29,0},{29,5,2178},{11,31,61},{11,31,61},{1,25,0},{31,16,2178},{1,25,0},{31,22,1201},{24,31,482},{22,31,1},{13,31,1},{31,22,1201},{30,27,1201},{13,31,1},{0,28,1201},{30,27,1201},{0,28,1201},{13,0,2689}, +{13,0,2689},{13,0,2689},{13,0,2689},{9,31,85},{9,31,85},{9,31,85},{8,22,5},{0,25,10},{0,25,10},{18,31,11474},{16,31,6867},{15,31,5138},{14,31,2725},{16,31,12279},{12,31,3410},{10,31,419},{8,27,1718},{4,31,8678},{0,28,905},{23,31,3626},{20,31,1550},{20,31,650},{18,31,25},{29,17,5829},{15,31,2306},{12,31,130},{0,28,901},{27,24,5829},{0,28,901},{15,31,5138},{15,31,5138},{15,31,5138}, +{14,31,2725},{13,31,4452},{10,31,419},{10,31,419},{9,25,261},{0,31,2520},{1,26,10},{20,31,650},{20,31,650},{20,31,650},{18,30,0},{31,4,2178},{12,31,130},{12,31,130},{2,26,0},{30,18,2178},{2,26,0},{31,23,845},{25,31,353},{23,31,9},{16,31,0},{31,23,845},{31,27,845},{16,31,0},{0,28,865},{31,27,845},{0,28,865},{14,0,2689},{14,0,2689},{14,0,2689},{14,0,2689},{10,31,130}, +{10,31,130},{10,31,130},{9,23,5},{0,27,1},{0,27,1},{19,31,10774},{17,31,6962},{16,31,5378},{15,31,2810},{17,31,11598},{12,31,3346},{12,31,642},{9,28,1222},{6,31,8113},{0,29,570},{23,31,3146},{22,31,1539},{21,31,773},{19,31,0},{31,15,5082},{16,31,2034},{14,31,221},{0,29,554},{31,23,5082},{0,29,554},{16,31,5378},{16,31,5378},{16,31,5378},{15,31,2810},{15,31,4746},{12,31,642},{12,31,642}, +{10,26,261},{2,31,2714},{2,27,10},{21,31,773},{21,31,773},{21,31,773},{19,31,0},{31,7,2178},{14,31,221},{14,31,221},{3,27,0},{31,19,2178},{3,27,0},{31,25,545},{26,31,221},{25,31,0},{19,31,0},{31,25,545},{31,28,545},{19,31,0},{0,29,545},{31,28,545},{0,29,545},{15,0,2689},{15,0,2689},{15,0,2689},{15,0,2689},{11,31,170},{11,31,170},{11,31,170},{10,23,10},{1,28,1}, +{1,28,1},{20,31,10225},{18,31,7025},{18,31,5729},{16,31,2978},{19,31,10792},{14,31,3283},{13,31,982},{10,29,861},{8,31,7588},{2,29,325},{24,31,2729},{23,31,1460},{22,31,932},{20,31,36},{29,21,4344},{19,31,1746},{16,31,353},{2,29,321},{31,24,4344},{2,29,321},{18,31,5729},{18,31,5729},{18,31,5729},{16,31,2978},{16,31,5028},{13,31,982},{13,31,982},{11,27,254},{4,31,2981},{3,28,10},{22,31,932}, +{22,31,932},{22,31,932},{20,31,36},{28,16,2178},{16,31,353},{16,31,353},{4,28,0},{24,24,2178},{4,28,0},{31,27,290},{27,31,125},{27,31,4},{22,31,1},{31,27,290},{31,29,290},{22,31,1},{0,29,320},{31,29,290},{0,29,320},{16,0,2689},{16,0,2689},{16,0,2689},{16,0,2689},{12,31,245},{12,31,245},{12,31,245},{11,25,8},{2,29,5},{2,29,5},{20,31,9825},{19,31,7014},{19,31,5925}, +{17,31,3218},{20,31,10245},{15,31,3285},{14,31,1330},{11,29,612},{10,31,7225},{3,30,133},{25,31,2467},{24,31,1470},{23,31,1040},{21,31,144},{31,19,3779},{20,31,1580},{18,31,500},{3,30,129},{31,25,3779},{3,30,129},{19,31,5925},{19,31,5925},{19,31,5925},{17,31,3218},{17,31,5346},{14,31,1330},{14,31,1330},{12,28,261},{6,31,3267},{4,29,10},{23,31,1040},{23,31,1040},{23,31,1040},{21,31,144},{29,17,2178}, +{18,31,500},{18,31,500},{5,29,0},{27,24,2178},{5,29,0},{31,28,128},{29,31,61},{28,31,0},{25,31,1},{31,28,128},{30,30,128},{25,31,1},{0,30,128},{30,30,128},{0,30,128},{17,0,2689},{17,0,2689},{17,0,2689},{17,0,2689},{13,31,338},{13,31,338},{13,31,338},{12,26,5},{3,30,5},{3,30,5},{21,31,9523},{20,31,7109},{20,31,6209},{18,31,3473},{20,31,9749},{16,31,3410},{15,31,1717}, +{12,30,401},{11,31,6964},{4,31,65},{26,31,2273},{25,31,1539},{24,31,1189},{23,31,260},{29,25,3299},{22,31,1490},{20,31,680},{6,30,64},{27,28,3299},{6,30,64},{20,31,6209},{20,31,6209},{20,31,6209},{18,31,3473},{18,31,5700},{15,31,1717},{15,31,1717},{13,29,261},{8,31,3587},{5,30,10},{24,31,1189},{24,31,1189},{24,31,1189},{23,31,260},{31,16,2178},{20,31,680},{20,31,680},{6,30,0},{30,24,2178}, +{6,30,0},{31,30,34},{30,31,13},{30,31,4},{28,31,0},{31,30,34},{30,31,34},{28,31,0},{0,30,64},{30,31,34},{0,30,64},{18,0,2689},{18,0,2689},{18,0,2689},{18,0,2689},{15,31,421},{15,31,421},{15,31,421},{13,27,5},{4,31,1},{4,31,1},{23,31,9201},{21,31,7314},{21,31,6530},{19,31,3778},{21,31,9420},{18,31,3652},{16,31,2193},{14,30,325},{14,31,6804},{6,31,10},{27,31,2057}, +{26,31,1605},{25,31,1378},{24,31,442},{31,23,2904},{23,31,1452},{22,31,881},{7,31,0},{31,27,2904},{7,31,0},{21,31,6530},{21,31,6530},{21,31,6530},{19,31,3778},{19,31,5956},{16,31,2193},{16,31,2193},{14,30,261},{10,31,3957},{6,31,10},{25,31,1378},{25,31,1378},{25,31,1378},{24,31,442},{31,19,2178},{22,31,881},{22,31,881},{7,31,0},{31,25,2178},{7,31,0},{31,31,0},{31,31,0},{31,31,0}, +{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{19,0,2689},{19,0,2689},{19,0,2689},{19,0,2689},{16,31,512},{16,31,512},{16,31,512},{14,27,10},{6,31,10},{6,31,10},{23,31,8049},{22,31,6550},{22,31,5925},{20,31,3589},{23,31,8137},{19,31,3220},{18,31,2050},{15,31,173},{15,31,5805},{8,31,52},{27,31,1544},{27,31,1181},{26,31,1040},{25,31,353},{31,24,2166}, +{24,31,1083},{23,31,653},{10,31,1},{30,28,2166},{10,31,1},{22,31,5925},{22,31,5925},{22,31,5925},{20,31,3589},{20,31,5209},{18,31,2050},{18,31,2050},{15,30,117},{12,31,3405},{8,31,52},{26,31,1040},{26,31,1040},{26,31,1040},{25,31,353},{31,21,1625},{23,31,653},{23,31,653},{10,31,1},{31,26,1625},{10,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0}, +{0,31,0},{31,31,0},{0,31,0},{20,0,2689},{20,0,2689},{20,0,2689},{20,0,2689},{17,31,625},{17,31,625},{17,31,625},{15,29,8},{8,31,52},{8,31,52},{24,31,7177},{23,31,5845},{23,31,5361},{21,31,3473},{23,31,7033},{20,31,2945},{19,31,1907},{16,31,65},{16,31,5026},{10,31,117},{28,31,1137},{27,31,861},{27,31,740},{26,31,260},{29,29,1601},{26,31,833},{24,31,482},{13,31,1},{31,28,1601}, +{13,31,1},{23,31,5361},{23,31,5361},{23,31,5361},{21,31,3473},{21,31,4661},{19,31,1907},{19,31,1907},{16,31,65},{14,31,2997},{10,31,117},{27,31,740},{27,31,740},{27,31,740},{26,31,260},{31,22,1201},{24,31,482},{24,31,482},{13,31,1},{30,27,1201},{13,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{21,0,2689}, +{21,0,2689},{21,0,2689},{21,0,2689},{18,31,754},{18,31,754},{18,31,754},{16,30,5},{10,31,117},{10,31,117},{24,31,6393},{24,31,5310},{23,31,4865},{22,31,3314},{24,31,6146},{20,31,2737},{20,31,1837},{17,31,5},{18,31,4381},{11,31,212},{28,31,801},{28,31,609},{28,31,545},{27,31,185},{31,26,1121},{26,31,561},{25,31,353},{16,31,0},{30,29,1121},{16,31,0},{23,31,4865},{23,31,4865},{23,31,4865}, +{22,31,3314},{22,31,4181},{20,31,1837},{20,31,1837},{17,31,5},{15,31,2621},{11,31,212},{28,31,545},{28,31,545},{28,31,545},{27,31,185},{31,23,845},{25,31,353},{25,31,353},{16,31,0},{31,27,845},{16,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{22,0,2689},{22,0,2689},{22,0,2689},{22,0,2689},{19,31,850}, +{19,31,850},{19,31,850},{17,31,5},{11,31,212},{11,31,212},{25,31,5683},{24,31,4782},{24,31,4421},{23,31,3173},{24,31,5314},{22,31,2563},{21,31,1844},{18,31,10},{18,31,3757},{13,31,338},{29,31,531},{28,31,401},{28,31,337},{27,31,121},{31,27,726},{27,31,363},{26,31,221},{19,31,0},{31,29,726},{19,31,0},{24,31,4421},{24,31,4421},{24,31,4421},{23,31,3173},{23,31,3657},{21,31,1844},{21,31,1844}, +{18,31,10},{16,31,2321},{13,31,338},{28,31,337},{28,31,337},{28,31,337},{27,31,121},{31,25,545},{26,31,221},{26,31,221},{19,31,0},{31,28,545},{19,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{23,0,2689},{23,0,2689},{23,0,2689},{23,0,2689},{20,31,985},{20,31,985},{20,31,985},{18,31,10},{13,31,338}, +{13,31,338},{2,31,10560},{0,30,1586},{0,22,173},{0,18,3826},{0,28,18065},{0,19,12194},{0,17,6081},{0,11,14098},{0,13,19386},{0,11,14998},{3,31,10216},{0,30,1586},{0,22,173},{0,18,3826},{12,4,18065},{0,19,12194},{0,17,6081},{0,11,14098},{28,0,18065},{0,11,14098},{0,17,1},{0,17,1},{0,17,1},{0,9,4},{0,9,1105},{0,7,442},{0,7,442},{0,4,680},{0,4,1230},{0,4,801},{0,17,1}, +{0,17,1},{0,17,1},{0,9,4},{4,1,1105},{0,7,442},{0,7,442},{0,4,680},{9,0,1105},{0,4,680},{21,0,9248},{0,30,1586},{0,22,173},{0,18,3826},{21,0,9248},{30,6,9248},{0,18,3826},{0,14,9248},{30,6,9248},{0,14,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,11328},{0,31,1341},{0,23,68}, +{0,19,3626},{0,30,19334},{0,20,12611},{0,18,6099},{0,12,14756},{0,14,20886},{0,12,15845},{3,31,10792},{0,31,1341},{0,23,68},{0,19,3626},{15,0,19334},{0,20,12611},{0,18,6099},{0,12,14756},{30,0,19334},{0,12,14756},{0,20,0},{0,20,0},{0,20,0},{0,10,1},{0,10,1513},{0,8,605},{0,8,605},{0,5,925},{0,5,1682},{0,4,1089},{0,20,0},{0,20,0},{0,20,0},{0,10,1},{5,0,1513}, +{0,8,605},{0,8,605},{0,5,925},{10,0,1513},{0,5,925},{22,1,9248},{0,31,1341},{0,23,68},{0,19,3626},{22,1,9248},{31,7,9248},{0,19,3626},{0,15,9248},{31,7,9248},{0,15,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,12200},{0,31,1325},{0,24,10},{0,20,3365},{0,31,20705},{0,21,13009},{0,18,6227}, +{0,13,15441},{0,15,22455},{0,13,16666},{4,31,11489},{0,31,1325},{0,24,10},{0,20,3365},{15,2,20689},{0,21,13009},{0,18,6227},{0,13,15441},{30,1,20689},{0,13,15441},{0,23,0},{0,23,0},{0,23,0},{0,11,9},{0,11,1989},{0,9,772},{0,9,772},{0,5,1213},{0,5,2194},{0,5,1382},{0,23,0},{0,23,0},{0,23,0},{0,11,9},{6,0,1985},{0,9,772},{0,9,772},{0,5,1213},{10,1,1985}, +{0,5,1213},{23,2,9248},{0,31,1325},{0,24,10},{0,20,3365},{23,2,9248},{30,9,9248},{0,20,3365},{0,16,9250},{30,9,9248},{0,16,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,13288},{0,31,1565},{0,25,10},{0,22,3077},{1,31,22214},{0,23,13555},{0,20,6310},{0,14,16176},{0,16,24130},{0,13,17562},{4,31,12385}, +{0,31,1565},{0,25,10},{0,22,3077},{17,0,22129},{0,23,13555},{0,20,6310},{0,14,16176},{30,2,22129},{0,14,16176},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{0,13,2521},{0,10,1018},{0,10,1018},{0,6,1508},{0,6,2801},{0,6,1764},{0,26,0},{0,26,0},{0,26,0},{0,13,0},{6,1,2521},{0,10,1018},{0,10,1018},{0,6,1508},{13,0,2521},{0,6,1508},{23,5,9248},{0,31,1565},{0,25,10}, +{0,22,3077},{23,5,9248},{31,10,9248},{0,22,3077},{0,17,9250},{31,10,9248},{0,17,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,14788},{0,31,2141},{0,27,72},{0,22,2825},{1,31,24140},{0,25,14114},{0,21,6323},{0,14,17202},{0,17,26063},{0,14,18646},{5,31,13521},{1,31,2100},{0,27,72},{0,22,2825},{16,4,23851}, +{0,25,14114},{0,21,6323},{0,14,17202},{28,4,23851},{0,14,17202},{0,29,1},{0,29,1},{0,29,1},{0,15,4},{0,15,3202},{0,12,1285},{0,12,1285},{0,7,1973},{0,7,3569},{0,6,2241},{0,29,1},{0,29,1},{0,29,1},{0,15,4},{7,1,3200},{0,12,1285},{0,12,1285},{0,7,1973},{11,2,3200},{0,7,1973},{27,0,9248},{3,31,1885},{2,26,8},{0,22,2825},{27,0,9248},{30,12,9248},{0,22,2825}, +{0,18,9248},{30,12,9248},{0,18,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,16228},{1,31,2836},{0,28,170},{0,24,2612},{2,31,25971},{0,25,14594},{0,22,6473},{0,16,18144},{0,17,27951},{0,14,19830},{7,31,14675},{2,31,2706},{1,27,149},{0,24,2612},{19,0,25472},{0,25,14594},{0,22,6473},{0,16,18144},{30,4,25472}, +{0,16,18144},{0,31,9},{0,31,9},{0,31,9},{0,16,0},{0,16,3872},{0,13,1514},{0,13,1514},{0,7,2405},{0,7,4305},{0,7,2766},{0,31,9},{0,31,9},{0,31,9},{0,16,0},{8,0,3872},{0,13,1514},{0,13,1514},{0,7,2405},{16,0,3872},{0,7,2405},{28,1,9248},{4,31,2210},{3,27,8},{0,24,2612},{28,1,9248},{31,13,9248},{0,24,2612},{0,19,9248},{31,13,9248},{0,19,9248},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{4,31,17796},{2,31,3702},{1,29,270},{0,25,2361},{3,31,27563},{0,27,14944},{0,23,6470},{0,17,18681},{0,19,29556},{0,16,20628},{7,31,15635},{3,31,3425},{1,29,206},{0,25,2361},{20,0,26744},{0,27,14944},{0,23,6470},{0,17,18681},{24,8,26744},{0,17,18681},{0,31,125},{0,31,125},{0,31,125}, +{0,18,8},{0,18,4418},{0,14,1696},{0,14,1696},{0,8,2664},{0,8,4952},{0,8,3148},{1,31,72},{1,31,72},{1,31,72},{0,18,8},{9,0,4418},{0,14,1696},{0,14,1696},{0,8,2664},{18,0,4418},{0,8,2664},{30,0,9248},{6,31,2557},{3,28,10},{0,25,2357},{30,0,9248},{30,15,9248},{0,25,2357},{0,20,9250},{30,15,9248},{0,20,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,0}, +{0,1,0},{0,1,0},{0,0,4},{0,0,4},{0,0,4},{5,31,19090},{2,31,4598},{1,30,406},{0,26,2220},{3,31,28187},{0,29,14347},{0,25,5609},{0,18,18144},{0,20,29961},{0,17,20301},{8,31,16082},{4,31,4019},{2,30,206},{0,26,2220},{21,1,26744},{0,29,14347},{0,25,5609},{0,18,18144},{27,8,26744},{0,18,18144},{1,31,264},{1,31,264},{1,31,264},{1,19,72},{0,21,4418},{0,16,1412},{0,16,1412}, +{0,10,2420},{0,9,5122},{0,9,2997},{2,31,117},{2,31,117},{2,31,117},{1,19,8},{10,1,4418},{0,16,1412},{0,16,1412},{0,10,2420},{21,0,4418},{0,10,2420},{31,1,9248},{8,31,2929},{4,29,10},{0,26,2120},{31,1,9248},{27,18,9248},{0,26,2120},{0,21,9250},{27,18,9248},{0,21,9250},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{0,4,1},{0,4,1},{0,4,1},{0,2,0},{0,2,25}, +{0,2,25},{7,31,20669},{3,31,5786},{2,31,625},{1,27,2283},{4,31,29033},{0,30,13795},{0,26,4770},{0,18,17667},{0,21,30425},{0,18,20068},{9,31,16691},{5,31,4841},{3,31,205},{1,27,2219},{23,0,26747},{0,30,13795},{0,26,4770},{0,18,17667},{30,8,26747},{0,18,17667},{2,31,589},{2,31,589},{2,31,589},{1,20,186},{0,24,4418},{0,18,1125},{0,18,1125},{0,10,2186},{0,11,5390},{0,10,2915},{3,31,169}, +{3,31,169},{3,31,169},{2,20,13},{12,0,4418},{0,18,1125},{0,18,1125},{0,10,2186},{24,0,4418},{0,10,2186},{31,4,9248},{10,31,3380},{6,30,8},{0,27,1954},{31,4,9248},{30,18,9248},{0,27,1954},{0,22,9248},{30,18,9248},{0,22,9248},{1,0,185},{1,0,185},{1,0,185},{1,0,185},{0,7,0},{0,7,0},{0,7,0},{0,3,9},{0,3,73},{0,3,73},{7,31,21577},{4,31,6797},{3,31,985}, +{1,28,2226},{5,31,29436},{0,31,12990},{0,27,4027},{0,20,16925},{0,23,30436},{0,18,19620},{11,31,16645},{7,31,5260},{4,31,232},{2,28,2141},{24,1,26259},{0,31,12990},{0,27,4027},{0,20,16925},{31,9,26259},{0,20,16925},{3,31,985},{3,31,985},{3,31,985},{2,21,378},{0,27,4418},{0,20,905},{0,20,905},{0,12,2005},{0,12,5635},{0,11,2950},{4,31,232},{4,31,232},{4,31,232},{3,21,13},{13,1,4418}, +{0,20,905},{0,20,905},{0,12,2005},{27,0,4418},{0,12,2005},{31,7,8980},{11,31,3601},{7,31,4},{0,28,1665},{31,7,8980},{31,19,8980},{0,28,1665},{0,23,8980},{31,19,8980},{0,23,8980},{2,0,377},{2,0,377},{2,0,377},{2,0,377},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,4,146},{0,4,146},{7,31,21193},{4,31,7053},{3,31,1481},{2,28,2093},{6,31,28313},{0,31,11406},{0,28,2965}, +{0,20,15021},{0,23,28900},{0,19,17995},{11,31,15381},{7,31,4876},{5,31,325},{3,28,1786},{25,1,24371},{0,31,11406},{0,28,2965},{0,20,15021},{27,12,24371},{0,20,15021},{3,31,1481},{3,31,1481},{3,31,1481},{2,23,621},{0,30,4418},{0,21,680},{0,21,680},{0,13,1780},{0,13,5885},{0,12,2950},{5,31,325},{5,31,325},{5,31,325},{4,22,8},{15,0,4418},{0,21,680},{0,21,680},{0,13,1780},{30,0,4418}, +{0,13,1780},{31,8,7938},{12,31,3188},{8,31,0},{0,29,1156},{31,8,7938},{30,20,7938},{0,29,1156},{0,23,7956},{30,20,7938},{0,23,7956},{2,0,617},{2,0,617},{2,0,617},{2,0,617},{0,13,0},{0,13,0},{0,13,0},{0,6,9},{0,5,233},{0,5,233},{8,31,20825},{5,31,7494},{4,31,2089},{2,29,1970},{7,31,27269},{0,31,10078},{0,28,2021},{0,21,13204},{0,25,27384},{0,20,16398},{12,31,14148}, +{8,31,4562},{7,31,392},{4,29,1445},{26,1,22568},{0,31,10078},{0,28,2021},{0,21,13204},{31,11,22568},{0,21,13204},{4,31,2089},{4,31,2089},{4,31,2089},{3,23,946},{0,31,4468},{0,23,521},{0,23,521},{0,14,1573},{0,15,6227},{0,13,2909},{7,31,392},{7,31,392},{7,31,392},{5,23,8},{16,1,4418},{0,23,521},{0,23,521},{0,14,1573},{31,1,4418},{0,14,1573},{31,10,6964},{14,31,2785},{10,31,4}, +{0,29,740},{31,10,6964},{31,20,6964},{0,29,740},{0,24,6970},{31,20,6964},{0,24,6970},{3,0,937},{3,0,937},{3,0,937},{3,0,937},{0,16,1},{0,16,1},{0,16,1},{0,8,1},{0,6,377},{0,6,377},{8,31,20717},{6,31,8012},{5,31,2958},{3,29,2057},{7,31,26243},{0,31,8890},{0,29,1154},{0,22,11325},{0,25,25854},{0,21,14671},{13,31,12926},{10,31,4313},{8,31,485},{5,29,1106},{25,5,20642}, +{0,31,8890},{0,29,1154},{0,22,11325},{31,12,20642},{0,22,11325},{5,31,2958},{5,31,2958},{5,31,2958},{3,25,1361},{1,31,4644},{0,25,337},{0,25,337},{0,15,1429},{0,16,6596},{0,14,2981},{8,31,485},{8,31,485},{8,31,485},{6,24,13},{16,4,4418},{0,25,337},{0,25,337},{0,15,1429},{28,4,4418},{0,15,1429},{31,11,5941},{15,31,2377},{11,31,1},{0,30,388},{31,11,5941},{31,21,5941},{0,30,388}, +{0,24,5953},{31,21,5941},{0,24,5953},{3,0,1360},{3,0,1360},{3,0,1360},{3,0,1360},{0,19,0},{0,19,0},{0,19,0},{0,10,4},{0,8,548},{0,8,548},{9,31,20713},{7,31,8575},{5,31,3806},{3,30,2260},{7,31,25603},{0,31,8106},{0,29,642},{0,22,9805},{0,26,24678},{0,21,13359},{15,31,11882},{11,31,4006},{9,31,596},{6,29,818},{28,1,19021},{2,31,8066},{0,29,642},{0,22,9805},{31,13,19021}, +{0,22,9805},{5,31,3806},{5,31,3806},{5,31,3806},{4,26,1819},{2,31,4962},{0,27,232},{0,27,232},{0,16,1268},{0,17,6926},{0,15,3126},{9,31,596},{9,31,596},{9,31,596},{7,25,13},{17,5,4418},{0,27,232},{0,27,232},{0,16,1268},{31,4,4418},{0,16,1268},{31,13,5101},{16,31,2042},{13,31,4},{0,30,164},{31,13,5101},{31,22,5101},{0,30,164},{0,25,5105},{31,22,5101},{0,25,5105},{4,0,1818}, +{4,0,1818},{4,0,1818},{4,0,1818},{0,22,0},{0,22,0},{0,22,0},{0,11,0},{0,9,697},{0,9,697},{10,31,20905},{7,31,9247},{6,31,4787},{4,30,2547},{8,31,25042},{1,31,7537},{0,30,264},{0,23,8449},{0,27,23521},{0,22,12141},{15,31,10794},{12,31,3786},{10,31,725},{8,29,621},{29,1,17485},{3,31,7274},{0,30,264},{0,23,8449},{27,16,17485},{0,23,8449},{6,31,4787},{6,31,4787},{6,31,4787}, +{4,27,2323},{3,31,5386},{0,29,130},{0,29,130},{0,18,1096},{0,19,7364},{0,17,3225},{10,31,725},{10,31,725},{10,31,725},{8,26,8},{21,0,4418},{0,29,130},{0,29,130},{0,18,1096},{30,6,4418},{0,18,1096},{31,14,4325},{18,31,1737},{14,31,1},{0,31,64},{31,14,4325},{30,23,4325},{0,31,64},{0,25,4337},{30,23,4325},{0,25,4337},{4,0,2314},{4,0,2314},{4,0,2314},{4,0,2314},{0,25,0}, +{0,25,0},{0,25,0},{0,12,4},{0,10,925},{0,10,925},{11,31,21021},{8,31,10106},{7,31,5819},{4,30,3027},{8,31,24722},{2,31,7042},{0,31,81},{0,24,7169},{0,29,22467},{0,22,11133},{16,31,9869},{12,31,3594},{11,31,821},{8,30,420},{30,1,16034},{4,31,6558},{0,31,81},{0,24,7169},{31,15,16034},{0,24,7169},{7,31,5819},{7,31,5819},{7,31,5819},{5,28,2915},{3,31,5962},{0,30,72},{0,30,72}, +{0,18,968},{0,20,7781},{0,17,3305},{11,31,821},{11,31,821},{11,31,821},{9,27,8},{22,1,4418},{0,30,72},{0,30,72},{0,18,968},{31,7,4418},{0,18,968},{31,15,3617},{19,31,1450},{15,31,9},{0,31,0},{31,15,3617},{31,23,3617},{0,31,0},{0,26,3617},{31,23,3617},{0,26,3617},{5,0,2906},{5,0,2906},{5,0,2906},{5,0,2906},{0,28,1},{0,28,1},{0,28,1},{0,14,0},{0,11,1156}, +{0,11,1156},{11,31,21381},{8,31,11186},{7,31,7169},{5,31,3633},{9,31,24543},{3,31,6762},{0,31,81},{0,24,5819},{0,29,21333},{0,23,10106},{17,31,8955},{14,31,3433},{12,31,980},{10,30,242},{29,5,14504},{6,31,5834},{1,31,74},{0,24,5819},{31,16,14504},{0,24,5819},{7,31,7169},{7,31,7169},{7,31,7169},{5,30,3618},{4,31,6757},{0,31,81},{0,31,81},{0,20,821},{0,21,8245},{0,18,3531},{12,31,980}, +{12,31,980},{12,31,980},{10,28,13},{24,0,4418},{1,31,74},{1,31,74},{0,20,821},{24,12,4418},{0,20,821},{29,21,2888},{20,31,1156},{17,31,1},{3,31,1},{29,21,2888},{31,24,2888},{3,31,1},{0,26,2906},{31,24,2888},{0,26,2906},{5,0,3617},{5,0,3617},{5,0,3617},{5,0,3617},{0,31,0},{0,31,0},{0,31,0},{0,15,9},{0,13,1421},{0,13,1421},{12,31,21949},{9,31,12367},{8,31,8449}, +{6,31,4338},{10,31,24600},{3,31,6650},{1,31,298},{0,25,4698},{0,30,20575},{0,24,9247},{17,31,8219},{15,31,3236},{13,31,1157},{11,30,122},{31,3,13235},{7,31,5260},{3,31,145},{0,25,4698},{31,17,13235},{0,25,4698},{8,31,8449},{8,31,8449},{8,31,8449},{6,31,4338},{5,31,7667},{1,31,298},{1,31,298},{0,21,680},{0,23,8779},{0,19,3786},{13,31,1157},{13,31,1157},{13,31,1157},{11,29,13},{25,1,4418}, +{3,31,145},{3,31,145},{0,21,680},{27,12,4418},{0,21,680},{31,19,2314},{22,31,949},{19,31,4},{6,31,1},{31,19,2314},{31,25,2314},{6,31,1},{0,27,2314},{31,25,2314},{0,27,2314},{6,0,4337},{6,0,4337},{6,0,4337},{6,0,4337},{0,31,64},{0,31,64},{0,31,64},{0,17,0},{0,13,1709},{0,13,1709},{12,31,22557},{10,31,13585},{9,31,9926},{6,31,5186},{11,31,24636},{3,31,6794},{2,31,692}, +{0,26,3723},{0,31,19836},{0,25,8442},{19,31,7417},{16,31,3126},{15,31,1268},{12,31,68},{29,9,12051},{8,31,4762},{4,31,232},{0,26,3723},{27,20,12051},{0,26,3723},{9,31,9926},{9,31,9926},{9,31,9926},{6,31,5186},{5,31,8691},{2,31,692},{2,31,692},{0,22,557},{0,25,9284},{0,21,3929},{15,31,1268},{15,31,1268},{15,31,1268},{12,30,8},{27,0,4418},{4,31,232},{4,31,232},{0,22,557},{30,12,4418}, +{0,22,557},{31,20,1800},{22,31,725},{20,31,0},{9,31,1},{31,20,1800},{30,26,1800},{9,31,1},{0,27,1818},{30,26,1800},{0,27,1818},{6,0,5105},{6,0,5105},{6,0,5105},{6,0,5105},{1,31,185},{1,31,185},{1,31,185},{0,18,9},{0,15,2042},{0,15,2042},{12,31,23421},{11,31,14850},{9,31,11462},{7,31,6149},{11,31,24860},{4,31,7053},{2,31,1236},{0,26,2891},{0,31,19260},{0,25,7818},{19,31,6761}, +{17,31,3107},{16,31,1429},{13,31,8},{31,7,10952},{10,31,4300},{6,31,353},{0,26,2891},{31,19,10952},{0,26,2891},{9,31,11462},{9,31,11462},{9,31,11462},{7,31,6149},{7,31,9845},{2,31,1236},{2,31,1236},{0,23,485},{0,25,9764},{0,21,4185},{16,31,1429},{16,31,1429},{16,31,1429},{13,31,8},{28,1,4418},{6,31,353},{6,31,353},{0,23,485},{31,13,4418},{0,23,485},{31,22,1354},{23,31,548},{22,31,4}, +{12,31,0},{31,22,1354},{30,27,1354},{12,31,0},{0,28,1360},{30,27,1354},{0,28,1360},{7,0,5953},{7,0,5953},{7,0,5953},{7,0,5953},{1,31,425},{1,31,425},{1,31,425},{0,20,1},{0,17,2372},{0,17,2372},{13,31,24507},{11,31,16398},{10,31,13349},{8,31,7460},{11,31,25418},{4,31,7647},{3,31,2021},{0,27,2089},{0,31,18918},{0,26,7302},{20,31,6098},{18,31,3037},{17,31,1640},{14,31,25},{29,13,9818}, +{12,31,3874},{8,31,521},{0,27,2089},{31,20,9818},{0,27,2089},{10,31,13349},{10,31,13349},{10,31,13349},{8,31,7460},{7,31,11195},{3,31,2021},{3,31,2021},{0,24,392},{0,27,10472},{0,23,4562},{17,31,1640},{17,31,1640},{17,31,1640},{14,31,25},{28,4,4418},{8,31,521},{8,31,521},{0,24,392},{28,16,4418},{0,24,392},{31,23,925},{24,31,386},{23,31,1},{15,31,1},{31,23,925},{31,27,925},{15,31,1}, +{0,28,937},{31,27,925},{0,28,937},{7,0,6970},{7,0,6970},{7,0,6970},{7,0,6970},{2,31,785},{2,31,785},{2,31,785},{0,22,4},{0,17,2741},{0,17,2741},{14,31,25663},{12,31,17995},{11,31,15021},{8,31,8740},{12,31,26003},{6,31,8399},{3,31,2965},{0,28,1481},{0,31,18886},{0,26,7014},{21,31,5634},{19,31,2950},{18,31,1853},{16,31,72},{31,11,8901},{14,31,3578},{10,31,698},{0,28,1481},{31,21,8901}, +{0,28,1481},{11,31,15021},{11,31,15021},{11,31,15021},{8,31,8740},{8,31,12646},{3,31,2965},{3,31,2965},{0,26,292},{0,29,11051},{0,24,4876},{18,31,1853},{18,31,1853},{18,31,1853},{16,31,72},{29,5,4418},{10,31,698},{10,31,698},{0,26,292},{31,16,4418},{0,26,292},{31,25,613},{26,31,245},{25,31,4},{18,31,1},{31,25,613},{27,30,613},{18,31,1},{0,29,617},{27,30,613},{0,29,617},{8,0,7956}, +{8,0,7956},{8,0,7956},{8,0,7956},{3,31,1201},{3,31,1201},{3,31,1201},{0,23,0},{0,18,3185},{0,18,3185},{15,31,26715},{12,31,19659},{11,31,16925},{9,31,10232},{12,31,26835},{6,31,9215},{4,31,4027},{0,28,985},{0,31,19110},{0,27,6797},{22,31,5238},{20,31,2950},{19,31,2005},{17,31,180},{29,17,8069},{15,31,3314},{11,31,905},{0,28,985},{27,24,8069},{0,28,985},{11,31,16925},{11,31,16925},{11,31,16925}, +{9,31,10232},{8,31,14182},{4,31,4027},{4,31,4027},{0,27,232},{0,29,11627},{0,25,5117},{19,31,2005},{19,31,2005},{19,31,2005},{17,31,180},{31,4,4418},{11,31,905},{11,31,905},{0,27,232},{30,18,4418},{0,27,232},{31,26,365},{27,31,146},{26,31,1},{21,31,1},{31,26,365},{30,29,365},{21,31,1},{0,29,377},{30,29,365},{0,29,377},{8,0,8980},{8,0,8980},{8,0,8980},{8,0,8980},{3,31,1665}, +{3,31,1665},{3,31,1665},{0,24,4},{0,20,3601},{0,20,3601},{15,31,26555},{13,31,20326},{12,31,17723},{10,31,10897},{13,31,26598},{7,31,9527},{5,31,4934},{0,29,590},{0,31,18606},{0,28,5786},{23,31,4770},{21,31,3041},{20,31,2210},{18,31,325},{31,15,7322},{16,31,3126},{14,31,1145},{0,29,554},{31,23,7322},{0,29,554},{12,31,17723},{12,31,17723},{12,31,17723},{10,31,10897},{9,31,15092},{5,31,4934},{5,31,4934}, +{0,28,205},{0,31,11381},{0,26,4709},{20,31,2210},{20,31,2210},{20,31,2210},{18,31,325},{31,7,4418},{14,31,1145},{14,31,1145},{0,28,169},{31,19,4418},{0,28,169},{31,27,185},{28,31,73},{27,31,9},{24,31,0},{31,27,185},{31,29,185},{24,31,0},{0,30,185},{31,29,185},{0,30,185},{9,0,9248},{9,0,9248},{9,0,9248},{9,0,9248},{4,31,1954},{4,31,1954},{4,31,1954},{1,25,8},{0,21,3330}, +{0,21,3330},{16,31,25958},{15,31,20468},{13,31,18321},{11,31,11371},{15,31,25748},{8,31,9863},{7,31,5684},{1,30,373},{0,31,18111},{0,29,4452},{24,31,4437},{23,31,3084},{22,31,2500},{19,31,554},{29,21,6584},{18,31,2996},{15,31,1412},{0,30,237},{31,24,6584},{0,30,237},{13,31,18321},{13,31,18321},{13,31,18321},{11,31,11371},{11,31,15661},{7,31,5684},{7,31,5684},{1,29,206},{0,31,10886},{0,27,4019},{22,31,2500}, +{22,31,2500},{22,31,2500},{19,31,554},{28,16,4418},{15,31,1412},{15,31,1412},{0,29,100},{24,24,4418},{0,29,100},{31,29,52},{30,31,25},{29,31,1},{27,31,1},{31,29,52},{31,30,52},{27,31,1},{0,30,68},{31,30,52},{0,30,68},{10,0,9250},{10,0,9250},{10,0,9250},{10,0,9250},{5,31,2197},{5,31,2197},{5,31,2197},{2,27,5},{0,23,2929},{0,23,2929},{17,31,25604},{15,31,20628},{15,31,18692}, +{12,31,11876},{16,31,25201},{10,31,10381},{8,31,6470},{2,30,270},{2,31,17924},{0,29,3588},{25,31,4259},{23,31,3148},{23,31,2664},{20,31,820},{31,19,6019},{19,31,2950},{16,31,1717},{0,30,125},{31,25,6019},{0,30,125},{15,31,18692},{15,31,18692},{15,31,18692},{12,31,11876},{12,31,16244},{8,31,6470},{8,31,6470},{2,30,206},{0,31,10854},{0,29,3332},{23,31,2664},{23,31,2664},{23,31,2664},{20,31,820},{29,17,4418}, +{16,31,1717},{16,31,1717},{0,30,61},{27,24,4418},{0,30,61},{31,31,4},{31,31,4},{31,31,4},{30,31,1},{31,31,4},{31,31,4},{30,31,1},{0,31,4},{31,31,4},{0,31,4},{11,0,9250},{11,0,9250},{11,0,9250},{11,0,9250},{6,31,2440},{6,31,2440},{6,31,2440},{3,27,10},{0,25,2509},{0,25,2509},{18,31,24418},{16,31,19831},{15,31,18144},{13,31,11876},{16,31,23685},{11,31,10015},{8,31,6638}, +{3,31,170},{3,31,16879},{0,30,2738},{25,31,3699},{24,31,2766},{24,31,2405},{21,31,820},{31,20,5164},{20,31,2584},{18,31,1552},{0,31,9},{30,26,5164},{0,31,9},{15,31,18144},{15,31,18144},{15,31,18144},{13,31,11876},{12,31,15696},{8,31,6638},{8,31,6638},{4,30,132},{0,31,10150},{0,29,2624},{24,31,2405},{24,31,2405},{24,31,2405},{21,31,820},{31,15,3872},{18,31,1552},{18,31,1552},{0,31,9},{31,23,3872}, +{0,31,9},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{12,0,9248},{12,0,9248},{12,0,9248},{12,0,9248},{7,31,2612},{7,31,2612},{7,31,2612},{4,28,8},{0,27,2210},{0,27,2210},{19,31,22762},{17,31,18876},{16,31,17222},{14,31,11585},{17,31,22068},{11,31,9551},{10,31,6509},{5,31,68},{4,31,15612},{0,30,2098},{26,31,3089}, +{24,31,2334},{24,31,1973},{22,31,661},{29,25,4267},{22,31,2150},{19,31,1285},{2,31,0},{27,28,4267},{2,31,0},{16,31,17222},{16,31,17222},{16,31,17222},{14,31,11585},{13,31,14786},{10,31,6509},{10,31,6509},{5,31,68},{0,31,9366},{0,30,2034},{24,31,1973},{24,31,1973},{24,31,1973},{22,31,661},{31,16,3202},{19,31,1285},{19,31,1285},{2,31,0},{30,24,3202},{2,31,0},{31,31,0},{31,31,0},{31,31,0}, +{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{13,0,9248},{13,0,9248},{13,0,9248},{13,0,9248},{8,31,2845},{8,31,2845},{8,31,2845},{5,29,8},{0,29,1856},{0,29,1856},{19,31,21160},{18,31,17776},{17,31,16329},{15,31,11282},{17,31,20358},{12,31,9098},{11,31,6310},{6,31,5},{6,31,14287},{0,31,1565},{27,31,2412},{25,31,1862},{25,31,1573},{23,31,509},{28,28,3361}, +{22,31,1691},{20,31,1021},{5,31,1},{28,28,3361},{5,31,1},{17,31,16329},{17,31,16329},{17,31,16329},{15,31,11282},{15,31,13658},{11,31,6310},{11,31,6310},{6,31,5},{2,31,8690},{0,31,1565},{25,31,1573},{25,31,1573},{25,31,1573},{23,31,509},{31,18,2521},{20,31,1021},{20,31,1021},{5,31,1},{30,25,2521},{5,31,1},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0}, +{0,31,0},{31,31,0},{0,31,0},{14,0,9250},{14,0,9250},{14,0,9250},{14,0,9250},{9,31,3176},{9,31,3176},{9,31,3176},{6,31,5},{0,30,1556},{0,30,1556},{20,31,19810},{19,31,16741},{18,31,15584},{16,31,11057},{19,31,18721},{14,31,8860},{12,31,6234},{7,31,10},{7,31,13210},{0,31,1325},{27,31,1868},{26,31,1464},{26,31,1268},{24,31,397},{31,23,2649},{23,31,1329},{22,31,794},{8,31,0},{31,27,2649}, +{8,31,0},{18,31,15584},{18,31,15584},{18,31,15584},{16,31,11057},{15,31,12858},{12,31,6234},{12,31,6234},{7,31,10},{3,31,8150},{0,31,1325},{26,31,1268},{26,31,1268},{26,31,1268},{24,31,397},{31,19,1989},{22,31,794},{22,31,794},{8,31,0},{31,25,1989},{8,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{15,0,9250}, +{15,0,9250},{15,0,9250},{15,0,9250},{11,31,3365},{11,31,3365},{11,31,3365},{7,31,10},{0,31,1325},{0,31,1325},{20,31,18626},{19,31,15845},{19,31,14756},{17,31,10897},{19,31,17297},{15,31,8442},{13,31,6285},{8,31,68},{8,31,12227},{0,31,1341},{27,31,1452},{27,31,1089},{27,31,968},{25,31,325},{31,24,2018},{24,31,1011},{23,31,605},{11,31,0},{30,28,2018},{11,31,0},{19,31,14756},{19,31,14756},{19,31,14756}, +{17,31,10897},{16,31,12077},{13,31,6285},{13,31,6285},{8,31,68},{4,31,7686},{0,31,1341},{27,31,968},{27,31,968},{27,31,968},{25,31,325},{31,21,1513},{23,31,605},{23,31,605},{11,31,0},{31,26,1513},{11,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{16,0,9248},{16,0,9248},{16,0,9248},{16,0,9248},{12,31,3626}, +{12,31,3626},{12,31,3626},{8,31,68},{0,31,1341},{0,31,1341},{21,31,17476},{20,31,14998},{20,31,14098},{18,31,10672},{20,31,16018},{15,31,8154},{15,31,6218},{9,31,200},{10,31,11338},{0,31,1613},{28,31,1041},{27,31,801},{27,31,680},{26,31,232},{29,29,1473},{26,31,753},{24,31,442},{14,31,0},{31,28,1473},{14,31,0},{20,31,14098},{20,31,14098},{20,31,14098},{18,31,10672},{17,31,11453},{15,31,6218},{15,31,6218}, +{9,31,200},{6,31,7270},{0,31,1613},{27,31,680},{27,31,680},{27,31,680},{26,31,232},{28,28,1105},{24,31,442},{24,31,442},{14,31,0},{28,28,1105},{14,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{31,31,0},{0,31,0},{31,31,0},{0,31,0},{17,0,9248},{17,0,9248},{17,0,9248},{17,0,9248},{13,31,3929},{13,31,3929},{13,31,3929},{9,31,200},{0,31,1613}, +{0,31,1613}, diff --git a/ext/basis_universal/basisu_transcoder_tables_dxt1_6.inc b/ext/basis_universal/basisu_transcoder_tables_dxt1_6.inc new file mode 100644 index 0000000000..fad45fe22d --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_dxt1_6.inc @@ -0,0 +1,494 @@ +// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +{0,4,18},{0,3,4},{0,2,0},{0,2,9},{0,3,36},{0,2,22},{0,2,13},{0,1,24},{0,1,41},{0,1,25},{0,4,18},{0,3,4},{0,2,0},{0,2,9},{1,1,36},{0,2,22},{0,2,13},{0,1,24},{3,0,36},{0,1,24},{0,2,0},{0,2,0},{0,2,0},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,2,0}, +{0,2,0},{0,2,0},{0,1,0},{0,1,2},{0,1,1},{0,1,1},{0,0,4},{1,0,2},{0,0,4},{2,0,18},{0,3,4},{0,2,0},{0,2,9},{2,0,18},{4,0,18},{0,2,9},{0,1,20},{4,0,18},{0,1,20},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,8,38},{1,6,21},{1,4,24}, +{1,4,24},{0,8,52},{0,5,18},{0,4,1},{0,3,24},{0,4,77},{0,3,40},{2,6,22},{1,6,5},{2,4,4},{1,4,8},{4,0,52},{0,5,18},{0,4,1},{0,3,24},{8,0,52},{0,3,24},{1,6,20},{1,6,20},{1,6,20},{1,3,21},{0,6,8},{0,4,1},{0,4,1},{0,2,5},{0,3,24},{0,2,9},{2,4,4},{2,4,4},{2,4,4},{2,3,4},{3,0,8}, +{1,3,1},{1,3,1},{1,2,4},{6,0,8},{1,2,4},{5,0,18},{1,6,1},{2,4,0},{0,4,0},{5,0,18},{10,0,18},{0,4,0},{0,3,20},{10,0,18},{0,3,20},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,5,0},{0,5,0},{0,5,0},{0,2,1},{0,2,5},{0,2,5},{3,10,38},{3,8,21},{3,6,24},{3,6,24},{2,10,52},{2,7,18},{2,6,1}, +{2,5,24},{0,7,53},{1,5,21},{4,8,22},{3,8,5},{4,6,4},{3,6,8},{7,0,52},{2,7,18},{2,6,1},{1,5,20},{14,0,52},{1,5,20},{3,8,20},{3,8,20},{3,8,20},{3,5,21},{2,8,8},{2,6,1},{2,6,1},{2,4,5},{0,6,8},{1,5,5},{4,6,4},{4,6,4},{4,6,4},{4,5,4},{6,0,8},{3,5,1},{3,5,1},{3,4,4},{12,0,8}, +{3,4,4},{8,0,18},{3,8,1},{4,6,0},{2,6,0},{8,0,18},{16,0,18},{2,6,0},{0,5,20},{16,0,18},{0,5,20},{3,0,20},{3,0,20},{3,0,20},{3,0,20},{2,7,0},{2,7,0},{2,7,0},{2,4,1},{1,5,1},{1,5,1},{5,12,38},{5,10,21},{5,8,24},{5,8,24},{4,12,52},{4,9,18},{4,8,1},{4,7,24},{2,9,53},{3,7,21},{6,10,22}, +{5,10,5},{6,8,4},{5,8,8},{2,16,51},{4,9,18},{4,8,1},{3,7,20},{20,0,51},{3,7,20},{5,10,20},{5,10,20},{5,10,20},{5,7,21},{4,10,8},{4,8,1},{4,8,1},{4,6,5},{2,8,8},{3,7,5},{6,8,4},{6,8,4},{6,8,4},{6,7,4},{9,0,8},{5,7,1},{5,7,1},{5,6,4},{18,0,8},{5,6,4},{11,0,18},{5,10,1},{6,8,0}, +{4,8,0},{11,0,18},{22,0,18},{4,8,0},{0,7,20},{22,0,18},{0,7,20},{5,0,20},{5,0,20},{5,0,20},{5,0,20},{4,9,0},{4,9,0},{4,9,0},{4,6,1},{3,7,1},{3,7,1},{7,15,36},{7,12,19},{7,10,28},{7,10,20},{6,15,52},{6,11,22},{6,10,7},{6,9,28},{3,12,52},{5,9,27},{8,13,19},{8,11,3},{8,10,3},{8,10,6},{13,1,51}, +{6,11,21},{7,10,3},{5,9,27},{27,0,51},{5,9,27},{7,12,19},{7,12,19},{7,12,19},{7,10,19},{6,13,9},{6,10,6},{6,10,6},{6,9,3},{5,10,9},{5,9,2},{8,10,2},{8,10,2},{8,10,2},{8,9,2},{12,1,8},{7,10,2},{7,10,2},{5,9,2},{25,0,8},{5,9,2},{14,1,18},{7,12,1},{8,10,2},{6,10,2},{14,1,18},{15,7,18},{6,10,2}, +{0,9,26},{15,7,18},{0,9,26},{7,0,18},{7,0,18},{7,0,18},{7,0,18},{6,11,2},{6,11,2},{6,11,2},{6,9,2},{5,9,1},{5,9,1},{9,16,38},{9,14,19},{9,12,28},{9,12,20},{8,17,52},{8,13,22},{8,12,7},{8,11,28},{5,14,52},{7,11,27},{10,15,19},{10,13,3},{10,12,3},{10,12,6},{16,1,51},{8,13,21},{9,12,3},{7,11,27},{33,0,51}, +{7,11,27},{9,14,19},{9,14,19},{9,14,19},{9,12,19},{8,15,9},{8,12,6},{8,12,6},{8,11,3},{7,12,9},{7,11,2},{10,12,2},{10,12,2},{10,12,2},{10,11,2},{15,1,8},{9,12,2},{9,12,2},{7,11,2},{31,0,8},{7,11,2},{17,0,18},{9,14,1},{10,12,2},{8,12,2},{17,0,18},{34,0,18},{8,12,2},{0,11,26},{34,0,18},{0,11,26},{9,0,18}, +{9,0,18},{9,0,18},{9,0,18},{8,13,2},{8,13,2},{8,13,2},{8,11,2},{7,11,1},{7,11,1},{11,18,38},{11,16,19},{11,14,28},{11,14,20},{10,19,52},{10,15,22},{10,14,7},{10,13,28},{7,16,52},{9,13,27},{12,16,21},{12,15,3},{12,14,3},{12,14,6},{19,1,51},{10,15,21},{11,14,3},{9,13,27},{39,0,51},{9,13,27},{11,16,18},{11,16,18},{11,16,18}, +{11,14,19},{10,17,9},{10,14,6},{10,14,6},{10,13,3},{9,14,9},{9,13,2},{12,14,2},{12,14,2},{12,14,2},{12,13,2},{15,7,8},{11,14,2},{11,14,2},{9,13,2},{31,3,8},{9,13,2},{20,0,18},{11,16,1},{12,14,2},{10,14,2},{20,0,18},{40,0,18},{10,14,2},{0,13,26},{40,0,18},{0,13,26},{11,0,18},{11,0,18},{11,0,18},{11,0,18},{10,15,2}, +{10,15,2},{10,15,2},{10,13,2},{9,13,1},{9,13,1},{13,20,38},{13,18,19},{13,16,27},{13,16,19},{12,21,52},{12,17,19},{12,16,5},{12,15,28},{10,17,52},{11,15,27},{14,18,21},{14,17,3},{14,16,1},{13,16,10},{22,1,51},{12,17,18},{13,16,2},{11,15,27},{45,0,51},{11,15,27},{13,18,18},{13,18,18},{13,18,18},{13,16,19},{12,19,9},{12,16,5},{12,16,5}, +{12,15,3},{10,16,11},{11,15,2},{14,16,1},{14,16,1},{14,16,1},{14,15,2},{15,13,8},{13,16,2},{13,16,2},{11,15,2},{31,6,8},{11,15,2},{23,0,18},{13,18,1},{14,16,0},{12,16,0},{23,0,18},{46,0,18},{12,16,0},{0,15,26},{46,0,18},{0,15,26},{13,0,18},{13,0,18},{13,0,18},{13,0,18},{12,17,1},{12,17,1},{12,17,1},{12,15,2},{11,15,1}, +{11,15,1},{15,23,38},{15,20,21},{15,18,37},{15,18,21},{15,22,55},{15,19,23},{15,18,5},{14,17,30},{13,19,56},{13,17,28},{16,21,19},{16,19,3},{16,18,3},{16,18,6},{17,17,51},{15,19,19},{15,18,1},{14,17,26},{51,0,51},{14,17,26},{15,21,20},{15,21,20},{15,21,20},{15,18,20},{15,19,14},{15,18,4},{15,18,4},{14,17,5},{13,18,9},{13,17,3},{16,18,2}, +{16,18,2},{16,18,2},{16,17,2},{24,1,8},{15,18,0},{15,18,0},{14,17,1},{49,0,8},{14,17,1},{26,1,18},{15,20,1},{16,18,2},{15,18,1},{26,1,18},{53,0,18},{15,18,1},{0,17,26},{53,0,18},{0,17,26},{15,0,20},{15,0,20},{15,0,20},{15,0,20},{15,18,4},{15,18,4},{15,18,4},{14,17,4},{13,17,2},{13,17,2},{17,25,36},{17,22,19},{17,20,28}, +{17,20,20},{16,25,52},{16,21,22},{16,20,7},{16,19,28},{15,21,56},{15,19,28},{18,23,19},{18,21,3},{18,20,3},{18,20,6},{20,17,51},{16,21,21},{17,20,3},{14,20,26},{57,0,51},{14,20,26},{17,22,19},{17,22,19},{17,22,19},{17,20,19},{16,23,9},{16,20,6},{16,20,6},{16,19,3},{15,20,9},{15,19,3},{18,20,2},{18,20,2},{18,20,2},{18,19,2},{27,1,8}, +{17,20,2},{17,20,2},{15,19,2},{55,0,8},{15,19,2},{29,1,18},{17,22,1},{18,20,2},{16,20,2},{29,1,18},{59,0,18},{16,20,2},{0,19,26},{59,0,18},{0,19,26},{17,0,18},{17,0,18},{17,0,18},{17,0,18},{16,21,2},{16,21,2},{16,21,2},{16,19,2},{15,19,2},{15,19,2},{19,27,36},{19,24,19},{19,22,28},{19,22,20},{18,27,52},{18,23,22},{18,22,7}, +{18,21,28},{15,24,56},{17,21,27},{20,25,19},{20,23,3},{20,22,3},{20,22,6},{23,17,51},{18,23,21},{19,22,3},{17,21,27},{63,0,51},{17,21,27},{19,24,19},{19,24,19},{19,24,19},{19,22,19},{18,25,9},{18,22,6},{18,22,6},{18,21,3},{17,22,9},{17,21,2},{20,22,2},{20,22,2},{20,22,2},{20,21,2},{30,1,8},{19,22,2},{19,22,2},{17,21,2},{61,0,8}, +{17,21,2},{31,3,18},{19,24,1},{20,22,2},{18,22,2},{31,3,18},{63,1,18},{18,22,2},{0,21,26},{63,1,18},{0,21,26},{19,0,18},{19,0,18},{19,0,18},{19,0,18},{18,23,2},{18,23,2},{18,23,2},{18,21,2},{17,21,1},{17,21,1},{21,29,36},{21,26,19},{21,24,28},{21,24,20},{20,29,52},{20,25,22},{20,24,7},{20,23,28},{17,26,52},{19,23,27},{22,27,19}, +{22,25,3},{22,24,3},{22,24,6},{34,1,51},{20,25,21},{21,24,3},{19,23,27},{63,3,51},{19,23,27},{21,26,19},{21,26,19},{21,26,19},{21,24,19},{20,27,9},{20,24,6},{20,24,6},{20,23,3},{19,24,9},{19,23,2},{22,24,2},{22,24,2},{22,24,2},{22,23,2},{33,1,8},{21,24,2},{21,24,2},{19,23,2},{63,2,8},{19,23,2},{31,9,18},{21,26,1},{22,24,2}, +{20,24,2},{31,9,18},{63,4,18},{20,24,2},{0,23,26},{63,4,18},{0,23,26},{21,0,18},{21,0,18},{21,0,18},{21,0,18},{20,25,2},{20,25,2},{20,25,2},{20,23,2},{19,23,1},{19,23,1},{23,31,40},{23,29,24},{23,27,33},{23,26,24},{23,30,55},{22,28,24},{23,26,8},{22,26,28},{20,28,51},{21,26,21},{24,29,20},{24,28,1},{24,27,4},{24,26,5},{38,0,51}, +{22,28,20},{23,26,4},{20,26,20},{62,7,51},{20,26,20},{23,29,20},{23,29,20},{23,29,20},{23,26,20},{23,28,12},{23,26,4},{23,26,4},{22,25,4},{20,27,9},{22,25,4},{24,27,0},{24,27,0},{24,27,0},{24,26,1},{31,12,8},{23,26,0},{23,26,0},{22,25,0},{62,6,8},{22,25,0},{38,1,18},{24,28,1},{24,27,4},{23,26,4},{38,1,18},{45,16,18},{23,26,4}, +{0,26,20},{45,16,18},{0,26,20},{23,0,20},{23,0,20},{23,0,20},{23,0,20},{23,26,4},{23,26,4},{23,26,4},{22,25,4},{21,26,1},{21,26,1},{25,33,38},{25,31,24},{25,29,33},{25,28,24},{25,32,55},{24,30,24},{25,28,8},{24,28,28},{22,30,51},{23,28,21},{26,31,20},{26,30,1},{26,29,4},{26,28,5},{41,0,51},{24,30,20},{25,28,4},{22,28,20},{62,10,51}, +{22,28,20},{25,31,20},{25,31,20},{25,31,20},{25,28,20},{25,30,12},{25,28,4},{25,28,4},{24,27,4},{22,29,9},{24,27,4},{26,29,0},{26,29,0},{26,29,0},{26,28,1},{31,18,8},{25,28,0},{25,28,0},{24,27,0},{62,9,8},{24,27,0},{41,1,18},{26,30,1},{26,29,4},{25,28,4},{41,1,18},{51,16,18},{25,28,4},{0,28,20},{51,16,18},{0,28,20},{25,0,20}, +{25,0,20},{25,0,20},{25,0,20},{25,28,4},{25,28,4},{25,28,4},{24,27,4},{23,28,1},{23,28,1},{27,35,38},{27,32,21},{27,31,33},{27,30,24},{27,34,55},{26,32,24},{27,30,8},{26,30,28},{25,31,56},{25,30,21},{28,33,18},{28,32,2},{28,31,4},{28,30,5},{44,0,51},{26,32,20},{27,30,4},{24,30,20},{62,13,51},{24,30,20},{27,33,20},{27,33,20},{27,33,20}, +{27,30,20},{27,31,14},{27,30,4},{27,30,4},{26,29,4},{24,31,9},{26,29,4},{28,31,0},{28,31,0},{28,31,0},{28,30,1},{34,17,8},{27,30,0},{27,30,0},{26,29,0},{62,12,8},{26,29,0},{44,1,18},{27,32,1},{28,31,4},{27,30,4},{44,1,18},{57,16,18},{27,30,4},{0,30,20},{57,16,18},{0,30,20},{27,0,20},{27,0,20},{27,0,20},{27,0,20},{27,30,4}, +{27,30,4},{27,30,4},{26,29,4},{25,30,1},{25,30,1},{29,37,38},{29,34,21},{29,32,37},{29,32,21},{29,36,55},{29,33,23},{29,32,5},{28,32,39},{27,33,56},{26,32,30},{30,35,18},{30,34,2},{30,32,2},{30,32,5},{47,0,51},{29,33,19},{29,32,1},{26,32,26},{46,24,51},{26,32,26},{29,35,20},{29,35,20},{29,35,20},{29,32,20},{29,33,14},{29,32,4},{29,32,4}, +{28,31,4},{27,32,9},{28,31,4},{30,33,0},{30,33,0},{30,33,0},{30,31,4},{37,17,8},{29,32,0},{29,32,0},{28,31,0},{62,15,8},{28,31,0},{47,1,18},{29,34,1},{30,32,2},{29,32,1},{47,1,18},{63,16,18},{29,32,1},{0,32,26},{63,16,18},{0,32,26},{29,0,20},{29,0,20},{29,0,20},{29,0,20},{29,32,4},{29,32,4},{29,32,4},{28,31,4},{28,31,4}, +{28,31,4},{31,40,44},{31,37,28},{32,35,40},{31,34,31},{31,38,53},{31,35,21},{31,34,7},{31,34,30},{28,36,51},{29,34,21},{32,37,20},{32,36,1},{32,35,4},{32,34,5},{50,0,51},{30,36,19},{31,34,6},{28,34,21},{62,19,51},{28,34,21},{31,38,26},{31,38,26},{31,38,26},{31,34,27},{31,36,9},{31,34,3},{31,34,3},{31,33,2},{29,34,10},{30,33,2},{32,35,0}, +{32,35,0},{32,35,0},{32,34,1},{49,0,8},{31,34,2},{31,34,2},{30,33,1},{62,18,8},{30,33,1},{47,8,18},{32,36,1},{32,35,4},{31,34,5},{47,8,18},{62,20,18},{31,34,5},{0,34,20},{62,20,18},{0,34,20},{31,0,26},{31,0,26},{31,0,26},{31,0,26},{31,35,1},{31,35,1},{31,35,1},{31,33,2},{29,34,1},{29,34,1},{33,41,40},{33,39,24},{33,37,33}, +{33,36,24},{33,40,55},{32,38,24},{33,36,8},{32,36,28},{30,38,51},{31,36,21},{34,39,20},{34,38,1},{34,37,4},{34,36,5},{53,0,51},{32,38,20},{33,36,4},{30,36,21},{62,22,51},{30,36,21},{33,39,20},{33,39,20},{33,39,20},{33,36,20},{33,38,12},{33,36,4},{33,36,4},{32,35,4},{31,36,10},{32,35,4},{34,37,0},{34,37,0},{34,37,0},{34,36,1},{52,0,8}, +{33,36,0},{33,36,0},{32,35,0},{62,21,8},{32,35,0},{47,14,18},{34,38,1},{34,37,4},{33,36,4},{47,14,18},{62,23,18},{33,36,4},{0,36,20},{62,23,18},{0,36,20},{33,0,20},{33,0,20},{33,0,20},{33,0,20},{33,36,4},{33,36,4},{33,36,4},{32,35,4},{31,36,1},{31,36,1},{35,43,40},{35,41,24},{35,39,33},{35,38,24},{35,42,55},{34,40,24},{35,38,8}, +{34,38,28},{32,40,51},{33,38,21},{36,41,20},{36,40,1},{36,39,4},{36,38,5},{56,0,51},{34,40,20},{35,38,4},{32,38,20},{62,25,51},{32,38,20},{35,41,20},{35,41,20},{35,41,20},{35,38,20},{35,40,12},{35,38,4},{35,38,4},{34,37,4},{32,39,9},{34,37,4},{36,39,0},{36,39,0},{36,39,0},{36,38,1},{55,0,8},{35,38,0},{35,38,0},{34,37,0},{62,24,8}, +{34,37,0},{48,17,18},{36,40,1},{36,39,4},{35,38,4},{48,17,18},{62,26,18},{35,38,4},{0,38,20},{62,26,18},{0,38,20},{35,0,20},{35,0,20},{35,0,20},{35,0,20},{35,38,4},{35,38,4},{35,38,4},{34,37,4},{33,38,1},{33,38,1},{37,45,40},{37,43,24},{37,41,33},{37,40,24},{37,44,55},{36,42,24},{37,40,8},{36,40,28},{34,42,51},{35,40,21},{38,43,20}, +{38,42,1},{38,41,4},{38,40,5},{59,0,51},{36,42,20},{37,40,4},{34,40,20},{62,28,51},{34,40,20},{37,43,20},{37,43,20},{37,43,20},{37,40,20},{37,42,12},{37,40,4},{37,40,4},{36,39,4},{34,41,9},{36,39,4},{38,41,0},{38,41,0},{38,41,0},{38,40,1},{58,0,8},{37,40,0},{37,40,0},{36,39,0},{62,27,8},{36,39,0},{51,17,18},{38,42,1},{38,41,4}, +{37,40,4},{51,17,18},{62,29,18},{37,40,4},{0,40,20},{62,29,18},{0,40,20},{37,0,20},{37,0,20},{37,0,20},{37,0,20},{37,40,4},{37,40,4},{37,40,4},{36,39,4},{35,40,1},{35,40,1},{40,46,44},{40,44,27},{40,43,28},{39,43,28},{39,47,52},{39,44,22},{39,43,3},{38,42,28},{36,44,53},{37,42,19},{40,46,19},{40,44,2},{40,43,3},{40,42,10},{62,1,51}, +{38,44,19},{39,43,2},{37,42,18},{63,31,51},{37,42,18},{40,44,26},{40,44,26},{40,44,26},{40,42,26},{39,44,11},{39,43,2},{39,43,2},{39,41,2},{37,43,11},{38,41,3},{40,44,1},{40,44,1},{40,44,1},{40,42,1},{53,16,8},{40,42,1},{40,42,1},{39,41,1},{63,30,8},{39,41,1},{63,0,18},{40,44,1},{40,43,2},{38,43,1},{63,0,18},{62,32,18},{38,43,1}, +{0,42,18},{62,32,18},{0,42,18},{39,0,26},{39,0,26},{39,0,26},{39,0,26},{39,43,1},{39,43,1},{39,43,1},{39,41,1},{37,42,1},{37,42,1},{42,48,44},{42,46,27},{42,45,28},{41,45,28},{41,48,53},{41,46,22},{41,45,3},{40,44,28},{38,46,53},{39,44,19},{42,48,19},{42,46,2},{42,45,3},{42,44,10},{63,5,51},{40,46,19},{41,45,2},{39,44,18},{47,42,51}, +{39,44,18},{42,46,26},{42,46,26},{42,46,26},{42,44,26},{41,46,11},{41,45,2},{41,45,2},{41,43,2},{39,45,11},{40,43,3},{42,46,1},{42,46,1},{42,46,1},{42,44,1},{56,16,8},{42,44,1},{42,44,1},{41,43,1},{62,33,8},{41,43,1},{63,6,18},{42,46,1},{42,45,2},{40,45,1},{63,6,18},{62,35,18},{40,45,1},{0,44,18},{62,35,18},{0,44,18},{41,0,26}, +{41,0,26},{41,0,26},{41,0,26},{41,45,1},{41,45,1},{41,45,1},{41,43,1},{39,44,1},{39,44,1},{44,50,44},{44,48,26},{44,47,28},{43,47,28},{43,50,53},{43,47,27},{43,47,3},{42,46,28},{40,48,51},{41,46,19},{44,50,19},{44,48,1},{44,47,3},{44,46,10},{63,11,51},{42,48,19},{43,47,2},{41,46,18},{47,45,51},{41,46,18},{44,48,26},{44,48,26},{44,48,26}, +{44,46,26},{43,48,9},{43,47,2},{43,47,2},{43,45,2},{41,47,11},{42,45,3},{44,48,1},{44,48,1},{44,48,1},{44,46,1},{59,16,8},{44,46,1},{44,46,1},{43,45,1},{62,36,8},{43,45,1},{63,12,18},{44,48,0},{44,47,2},{42,47,1},{63,12,18},{62,38,18},{42,47,1},{0,46,18},{62,38,18},{0,46,18},{43,0,26},{43,0,26},{43,0,26},{43,0,26},{43,47,1}, +{43,47,1},{43,47,1},{43,45,1},{41,46,1},{41,46,1},{46,52,44},{46,50,26},{46,49,31},{45,48,31},{45,52,53},{45,49,21},{45,48,7},{45,48,30},{42,50,51},{43,48,21},{46,52,19},{46,50,1},{46,49,6},{46,48,6},{55,32,51},{44,50,19},{45,48,6},{42,48,21},{46,48,51},{42,48,21},{46,50,26},{46,50,26},{46,50,26},{45,48,27},{45,50,9},{45,48,3},{45,48,3}, +{45,47,2},{43,48,10},{44,47,3},{46,50,1},{46,50,1},{46,50,1},{46,48,2},{62,16,8},{45,48,2},{45,48,2},{45,47,1},{62,39,8},{45,47,1},{63,18,18},{46,50,0},{47,48,4},{45,48,5},{63,18,18},{62,41,18},{45,48,5},{0,48,20},{62,41,18},{0,48,20},{45,0,26},{45,0,26},{45,0,26},{45,0,26},{45,49,1},{45,49,1},{45,49,1},{45,47,1},{43,48,1}, +{43,48,1},{48,54,44},{48,52,27},{48,51,28},{48,50,35},{47,55,51},{47,52,21},{47,51,3},{47,50,22},{45,52,52},{45,50,19},{48,54,19},{48,52,2},{48,51,3},{48,50,10},{63,23,51},{47,52,21},{47,51,3},{45,50,18},{63,43,51},{45,50,18},{48,52,26},{48,52,26},{48,52,26},{48,50,26},{47,53,8},{47,51,2},{47,51,2},{47,49,1},{45,51,8},{46,49,5},{48,52,1}, +{48,52,1},{48,52,1},{48,50,1},{63,21,8},{48,50,1},{48,50,1},{47,49,1},{63,42,8},{47,49,1},{63,25,18},{48,52,1},{48,51,2},{46,51,1},{63,25,18},{63,44,18},{46,51,1},{0,50,18},{63,44,18},{0,50,18},{48,0,26},{48,0,26},{48,0,26},{48,0,26},{47,51,1},{47,51,1},{47,51,1},{47,49,0},{45,50,1},{45,50,1},{50,56,44},{50,54,27},{50,53,28}, +{49,53,28},{49,57,52},{49,54,22},{49,53,3},{48,52,28},{47,54,52},{47,52,19},{50,56,19},{50,54,2},{50,53,3},{50,52,10},{63,29,51},{48,54,19},{49,53,2},{47,52,18},{63,46,51},{47,52,18},{50,54,26},{50,54,26},{50,54,26},{50,52,26},{49,54,11},{49,53,2},{49,53,2},{49,51,2},{47,53,8},{48,51,3},{50,54,1},{50,54,1},{50,54,1},{50,52,1},{63,27,8}, +{50,52,1},{50,52,1},{49,51,1},{63,45,8},{49,51,1},{63,31,18},{50,54,1},{50,53,2},{48,53,1},{63,31,18},{63,47,18},{48,53,1},{0,52,18},{63,47,18},{0,52,18},{49,0,26},{49,0,26},{49,0,26},{49,0,26},{49,53,1},{49,53,1},{49,53,1},{49,51,1},{47,52,1},{47,52,1},{52,58,44},{52,56,27},{52,55,28},{51,55,28},{51,59,52},{51,56,22},{51,55,3}, +{50,54,28},{48,56,53},{49,54,19},{52,58,19},{52,56,2},{52,55,3},{52,54,10},{63,35,51},{50,56,19},{51,55,2},{49,54,18},{63,49,51},{49,54,18},{52,56,26},{52,56,26},{52,56,26},{52,54,26},{51,56,11},{51,55,2},{51,55,2},{51,53,2},{49,55,11},{50,53,3},{52,56,1},{52,56,1},{52,56,1},{52,54,1},{63,33,8},{52,54,1},{52,54,1},{51,53,1},{47,56,8}, +{51,53,1},{57,48,18},{52,56,1},{52,55,2},{50,55,1},{57,48,18},{62,50,18},{50,55,1},{0,54,18},{62,50,18},{0,54,18},{51,0,26},{51,0,26},{51,0,26},{51,0,26},{51,55,1},{51,55,1},{51,55,1},{51,53,1},{49,54,1},{49,54,1},{54,60,44},{54,58,27},{54,57,28},{53,57,28},{53,61,52},{53,58,22},{53,57,3},{52,56,28},{50,58,53},{51,56,19},{54,60,19}, +{54,58,2},{54,57,3},{54,56,10},{63,41,51},{52,58,19},{53,57,2},{51,56,18},{63,52,51},{51,56,18},{54,58,26},{54,58,26},{54,58,26},{54,56,26},{53,58,11},{53,57,2},{53,57,2},{53,55,2},{51,57,11},{52,55,3},{54,58,1},{54,58,1},{54,58,1},{54,56,1},{63,39,8},{54,56,1},{54,56,1},{53,55,1},{47,59,8},{53,55,1},{60,48,18},{54,58,1},{54,57,2}, +{52,57,1},{60,48,18},{62,53,18},{52,57,1},{0,56,18},{62,53,18},{0,56,18},{53,0,26},{53,0,26},{53,0,26},{53,0,26},{53,57,1},{53,57,1},{53,57,1},{53,55,1},{51,56,1},{51,56,1},{56,63,38},{56,61,21},{56,59,24},{56,59,24},{55,63,52},{55,60,18},{55,59,1},{55,58,24},{53,60,53},{54,58,21},{57,61,22},{56,61,5},{57,59,4},{56,59,8},{63,47,52}, +{55,60,18},{55,59,1},{54,58,20},{63,55,52},{54,58,20},{56,61,20},{56,61,20},{56,61,20},{56,58,21},{55,61,8},{55,59,1},{55,59,1},{55,57,5},{53,59,8},{54,58,5},{57,59,4},{57,59,4},{57,59,4},{57,58,4},{61,49,8},{56,58,1},{56,58,1},{56,57,4},{63,54,8},{56,57,4},{63,49,18},{56,61,1},{57,59,0},{55,59,0},{63,49,18},{63,56,18},{55,59,0}, +{0,58,20},{63,56,18},{0,58,20},{56,0,20},{56,0,20},{56,0,20},{56,0,20},{55,60,0},{55,60,0},{55,60,0},{55,57,1},{54,58,1},{54,58,1},{58,63,56},{58,63,21},{58,61,24},{58,61,24},{58,63,68},{57,62,18},{57,61,1},{57,60,24},{55,62,53},{56,60,21},{59,63,22},{58,63,5},{59,61,4},{58,61,8},{63,53,52},{57,62,18},{57,61,1},{56,60,20},{63,58,52}, +{56,60,20},{58,63,20},{58,63,20},{58,63,20},{58,60,21},{57,63,8},{57,61,1},{57,61,1},{57,59,5},{55,61,8},{56,60,5},{59,61,4},{59,61,4},{59,61,4},{59,60,4},{63,51,8},{58,60,1},{58,60,1},{58,59,4},{63,57,8},{58,59,4},{63,55,18},{58,63,1},{59,61,0},{57,61,0},{63,55,18},{63,59,18},{57,61,0},{0,60,20},{63,59,18},{0,60,20},{58,0,20}, +{58,0,20},{58,0,20},{58,0,20},{57,62,0},{57,62,0},{57,62,0},{57,59,1},{56,60,1},{56,60,1},{60,63,88},{60,63,40},{60,63,24},{60,63,24},{60,63,88},{59,63,37},{59,63,1},{59,62,24},{58,63,63},{58,62,21},{61,63,40},{61,63,13},{61,63,4},{60,63,8},{63,59,52},{60,63,24},{59,63,1},{58,62,20},{63,61,52},{58,62,20},{60,63,24},{60,63,24},{60,63,24}, +{60,62,21},{60,63,24},{59,63,1},{59,63,1},{59,61,5},{57,63,8},{58,62,5},{61,63,4},{61,63,4},{61,63,4},{61,62,4},{63,57,8},{60,62,1},{60,62,1},{60,61,4},{63,60,8},{60,61,4},{63,61,18},{61,63,9},{61,63,0},{59,63,0},{63,61,18},{63,62,18},{59,63,0},{0,62,20},{63,62,18},{0,62,20},{60,0,20},{60,0,20},{60,0,20},{60,0,20},{59,63,1}, +{59,63,1},{59,63,1},{59,61,1},{58,62,1},{58,62,1},{62,63,38},{62,63,33},{62,63,29},{62,63,24},{62,63,35},{62,63,25},{62,63,21},{61,63,1},{61,63,23},{60,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{62,63,0},{63,63,4},{62,63,0},{62,63,29},{62,63,29},{62,63,29},{62,63,24},{62,63,26},{62,63,21},{62,63,21}, +{61,63,1},{61,63,14},{60,63,4},{63,63,4},{63,63,4},{63,63,4},{63,63,4},{63,62,4},{63,63,4},{63,63,4},{62,63,0},{62,63,4},{62,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{62,0,20},{62,0,20},{62,0,20},{62,0,20},{61,63,16},{61,63,16},{61,63,16},{61,63,1},{60,63,4}, +{60,63,4},{0,8,74},{0,6,10},{0,4,1},{0,4,26},{0,6,154},{0,4,99},{0,3,50},{0,2,115},{0,3,170},{0,2,119},{0,8,74},{0,6,10},{0,4,1},{0,4,26},{3,0,154},{0,4,99},{0,3,50},{0,2,115},{6,0,154},{0,2,115},{0,4,0},{0,4,0},{0,4,0},{0,2,0},{0,2,13},{0,2,4},{0,2,4},{0,1,5},{0,1,14},{0,1,6},{0,4,0}, +{0,4,0},{0,4,0},{0,2,0},{1,0,13},{0,2,4},{0,2,4},{0,1,5},{2,0,13},{0,1,5},{4,0,74},{0,6,10},{0,4,1},{0,4,26},{4,0,74},{8,0,74},{0,4,26},{0,3,74},{8,0,74},{0,3,74},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,14,83},{0,10,10},{1,6,27}, +{0,6,19},{0,11,243},{0,7,110},{0,5,34},{0,4,139},{0,5,280},{0,4,164},{1,12,75},{1,9,2},{1,6,11},{1,6,18},{5,1,243},{0,7,110},{0,5,34},{0,4,139},{11,0,243},{0,4,139},{0,10,9},{0,10,9},{0,10,9},{0,5,9},{0,6,50},{0,5,9},{0,5,9},{0,3,26},{0,3,66},{0,2,33},{1,8,1},{1,8,1},{1,8,1},{1,4,2},{3,0,50}, +{0,5,9},{0,5,9},{0,3,26},{6,0,50},{0,3,26},{7,0,74},{1,9,1},{2,6,1},{0,6,10},{7,0,74},{14,0,74},{0,6,10},{0,5,74},{14,0,74},{0,5,74},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,2},{0,1,2},{1,18,137},{1,12,74},{2,9,98},{1,8,67},{0,16,244},{0,10,78},{0,8,2}, +{0,6,115},{0,8,344},{0,6,179},{3,14,75},{3,11,2},{3,8,11},{3,8,18},{8,1,243},{0,10,78},{0,8,2},{0,6,115},{15,1,243},{0,6,115},{1,14,65},{1,14,65},{1,14,65},{1,7,66},{0,12,50},{0,8,1},{0,8,1},{0,5,5},{0,5,104},{0,5,41},{3,10,1},{3,10,1},{3,10,1},{3,6,2},{6,0,50},{0,8,1},{0,8,1},{0,5,5},{12,0,50}, +{0,5,5},{2,16,72},{3,11,1},{4,8,1},{0,8,1},{2,16,72},{20,0,72},{0,8,1},{0,7,74},{20,0,72},{0,7,74},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,3,25},{0,3,25},{3,20,146},{3,14,83},{4,11,115},{3,10,76},{2,18,245},{2,12,79},{2,10,3},{1,8,108},{0,11,293},{0,8,103},{5,16,73}, +{5,13,2},{5,10,11},{5,10,18},{11,1,243},{1,13,75},{2,10,2},{0,8,94},{15,4,243},{0,8,94},{3,16,74},{3,16,74},{3,16,74},{3,9,75},{2,14,51},{2,10,2},{2,10,2},{2,7,6},{0,9,75},{0,7,6},{5,12,1},{5,12,1},{5,12,1},{5,8,2},{9,0,50},{2,10,1},{2,10,1},{0,7,2},{18,0,50},{0,7,2},{5,16,72},{5,13,1},{6,10,1}, +{2,10,1},{5,16,72},{26,0,72},{2,10,1},{0,9,74},{26,0,72},{0,9,74},{3,0,74},{3,0,74},{3,0,74},{3,0,74},{2,10,2},{2,10,2},{2,10,2},{2,6,2},{0,7,5},{0,7,5},{6,21,152},{6,16,82},{6,13,109},{5,12,84},{4,21,243},{4,15,78},{4,13,8},{4,11,108},{0,14,255},{0,11,77},{7,19,72},{7,15,1},{7,13,8},{7,12,13},{6,17,243}, +{3,15,72},{5,12,5},{0,11,73},{29,0,243},{0,11,73},{6,16,81},{6,16,81},{6,16,81},{5,12,80},{4,17,50},{4,13,4},{4,13,4},{4,9,5},{0,12,52},{1,10,4},{7,15,0},{7,15,0},{7,15,0},{7,11,0},{12,1,50},{5,12,1},{5,12,1},{3,9,4},{25,0,50},{3,9,4},{16,1,72},{7,15,1},{8,13,4},{5,12,4},{16,1,72},{33,0,72},{5,12,4}, +{0,11,72},{33,0,72},{0,11,72},{5,0,80},{5,0,80},{5,0,80},{5,0,80},{4,13,0},{4,13,0},{4,13,0},{4,9,1},{1,10,0},{1,10,0},{8,23,152},{8,18,82},{8,15,109},{7,14,84},{6,23,243},{6,16,75},{6,15,8},{6,13,108},{1,17,244},{2,13,77},{9,21,72},{9,17,1},{9,15,8},{9,14,13},{17,1,243},{5,17,72},{7,14,5},{1,13,72},{35,0,243}, +{1,13,72},{8,18,81},{8,18,81},{8,18,81},{7,14,80},{6,19,50},{6,15,4},{6,15,4},{6,11,5},{2,14,52},{3,12,4},{9,16,1},{9,16,1},{9,16,1},{9,13,0},{15,1,50},{7,14,1},{7,14,1},{5,11,4},{31,0,50},{5,11,4},{19,1,72},{9,17,1},{10,15,4},{7,14,4},{19,1,72},{39,0,72},{7,14,4},{0,13,72},{39,0,72},{0,13,72},{7,0,80}, +{7,0,80},{7,0,80},{7,0,80},{6,15,0},{6,15,0},{6,15,0},{6,11,1},{3,12,0},{3,12,0},{10,25,152},{10,20,82},{10,17,114},{9,16,82},{8,25,243},{8,18,75},{8,16,2},{8,15,108},{3,19,244},{4,15,77},{11,23,72},{11,19,1},{11,16,10},{11,16,17},{20,1,243},{7,19,72},{8,16,2},{3,15,72},{41,0,243},{3,15,72},{10,20,81},{10,20,81},{10,20,81}, +{10,15,81},{8,21,50},{8,16,1},{8,16,1},{8,13,5},{4,16,52},{5,14,4},{11,18,1},{11,18,1},{11,18,1},{11,15,0},{15,7,50},{8,16,1},{8,16,1},{7,13,4},{31,3,50},{7,13,4},{22,1,72},{11,19,1},{12,16,2},{8,16,1},{22,1,72},{45,0,72},{8,16,1},{0,15,72},{45,0,72},{0,15,72},{9,0,80},{9,0,80},{9,0,80},{9,0,80},{8,17,0}, +{8,17,0},{8,17,0},{8,13,1},{5,14,0},{5,14,0},{12,27,152},{12,22,82},{12,19,114},{11,18,82},{10,27,243},{10,20,75},{10,18,2},{10,16,106},{5,21,244},{6,17,79},{13,25,72},{13,21,1},{13,18,10},{13,18,17},{23,1,243},{9,21,72},{10,18,2},{5,17,74},{47,0,243},{5,17,74},{12,22,81},{12,22,81},{12,22,81},{12,17,80},{10,23,50},{10,18,1},{10,18,1}, +{10,15,5},{6,18,52},{8,15,9},{13,20,1},{13,20,1},{13,20,1},{13,17,1},{15,13,50},{10,18,1},{10,18,1},{9,15,4},{31,6,50},{9,15,4},{25,1,72},{13,21,1},{14,18,2},{10,18,1},{25,1,72},{47,2,72},{10,18,1},{0,17,74},{47,2,72},{0,17,74},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{10,19,0},{10,19,0},{10,19,0},{10,15,1},{7,16,0}, +{7,16,0},{14,30,146},{14,24,78},{14,21,114},{14,20,79},{12,30,244},{12,23,79},{12,21,7},{12,19,109},{7,23,244},{9,19,76},{15,28,73},{15,23,2},{15,21,14},{15,20,14},{27,0,243},{11,23,75},{13,20,4},{7,19,73},{46,4,243},{7,19,73},{14,25,74},{14,25,74},{14,25,74},{14,19,75},{12,25,53},{12,21,3},{12,21,3},{12,17,6},{8,21,52},{9,18,6},{15,23,1}, +{15,23,1},{15,23,1},{15,19,1},{24,1,50},{13,20,0},{13,20,0},{11,17,5},{49,0,50},{11,17,5},{20,17,72},{15,23,1},{16,21,4},{13,20,4},{20,17,72},{57,0,72},{13,20,4},{0,19,72},{57,0,72},{0,19,72},{14,0,74},{14,0,74},{14,0,74},{14,0,74},{12,22,1},{12,22,1},{12,22,1},{12,17,2},{9,18,2},{9,18,2},{16,31,152},{16,26,81},{16,23,109}, +{16,22,88},{14,32,244},{14,25,79},{14,23,7},{14,21,109},{9,25,244},{11,21,76},{17,29,72},{17,25,1},{17,23,8},{17,22,13},{30,0,243},{13,25,75},{15,22,4},{9,21,73},{46,7,243},{9,21,73},{16,27,80},{16,27,80},{16,27,80},{16,21,81},{14,27,53},{14,23,3},{14,23,3},{14,19,6},{10,23,52},{11,20,6},{17,25,0},{17,25,0},{17,25,0},{17,21,0},{27,1,50}, +{15,22,0},{15,22,0},{13,19,5},{55,0,50},{13,19,5},{23,17,72},{17,25,1},{18,23,4},{15,22,4},{23,17,72},{63,0,72},{15,22,4},{0,21,72},{63,0,72},{0,21,72},{16,0,80},{16,0,80},{16,0,80},{16,0,80},{14,24,1},{14,24,1},{14,24,1},{14,19,2},{11,20,2},{11,20,2},{18,33,152},{18,28,81},{18,25,109},{17,24,84},{16,33,243},{16,27,78},{16,25,8}, +{16,23,108},{11,27,244},{13,23,76},{19,31,72},{19,27,1},{19,25,8},{19,24,13},{32,1,243},{15,27,75},{17,24,5},{11,23,73},{46,10,243},{11,23,73},{18,29,80},{18,29,80},{18,29,80},{17,24,80},{16,29,50},{16,25,4},{16,25,4},{16,21,5},{12,25,52},{13,22,6},{19,27,0},{19,27,0},{19,27,0},{19,23,0},{30,1,50},{17,24,1},{17,24,1},{15,21,5},{61,0,50}, +{15,21,5},{34,1,72},{19,27,1},{20,25,4},{17,24,4},{34,1,72},{63,3,72},{17,24,4},{0,23,72},{63,3,72},{0,23,72},{17,0,80},{17,0,80},{17,0,80},{17,0,80},{16,25,0},{16,25,0},{16,25,0},{16,21,1},{13,22,2},{13,22,2},{20,35,152},{20,30,81},{20,27,109},{19,26,84},{18,35,243},{18,29,78},{18,27,8},{18,25,108},{13,29,244},{15,25,76},{21,33,72}, +{21,29,1},{21,27,8},{21,26,13},{35,1,243},{17,29,72},{19,26,5},{13,25,73},{46,13,243},{13,25,73},{20,31,80},{20,31,80},{20,31,80},{19,26,80},{18,31,50},{18,27,4},{18,27,4},{18,23,5},{14,27,52},{15,24,6},{21,29,0},{21,29,0},{21,29,0},{21,25,0},{33,1,50},{19,26,1},{19,26,1},{17,23,4},{63,2,50},{17,23,4},{37,1,72},{21,29,1},{22,27,4}, +{19,26,4},{37,1,72},{63,6,72},{19,26,4},{0,25,72},{63,6,72},{0,25,72},{19,0,80},{19,0,80},{19,0,80},{19,0,80},{18,27,0},{18,27,0},{18,27,0},{18,23,1},{15,24,2},{15,24,2},{22,38,146},{22,32,78},{22,29,111},{22,28,84},{20,38,244},{20,31,74},{20,29,4},{20,27,100},{14,32,247},{17,27,75},{23,36,73},{23,32,3},{23,29,11},{23,28,14},{39,0,243}, +{20,31,73},{20,29,3},{16,27,74},{62,8,243},{16,27,74},{22,33,74},{22,33,74},{22,33,74},{22,28,75},{20,33,53},{20,29,3},{20,29,3},{20,25,10},{16,29,50},{18,26,2},{23,31,2},{23,31,2},{23,31,2},{23,27,2},{31,12,50},{21,28,1},{21,28,1},{18,26,1},{62,6,50},{18,26,1},{41,0,72},{23,32,2},{24,29,2},{19,29,2},{41,0,72},{62,10,72},{19,29,2}, +{0,27,74},{62,10,72},{0,27,74},{22,0,74},{22,0,74},{22,0,74},{22,0,74},{20,30,1},{20,30,1},{20,30,1},{20,25,1},{18,26,1},{18,26,1},{24,40,146},{24,34,78},{24,31,111},{24,30,84},{22,40,244},{22,33,79},{22,31,4},{22,29,100},{17,33,244},{19,29,75},{25,38,73},{25,33,2},{25,31,11},{25,30,14},{42,0,243},{21,33,75},{22,31,3},{18,29,74},{62,11,243}, +{18,29,74},{24,35,74},{24,35,74},{24,35,74},{24,30,75},{22,35,53},{22,31,3},{22,31,3},{22,27,10},{18,31,50},{20,28,2},{25,33,1},{25,33,1},{25,33,1},{25,29,2},{31,18,50},{23,30,1},{23,30,1},{20,28,1},{62,9,50},{20,28,1},{44,0,72},{25,33,1},{26,31,2},{21,31,2},{44,0,72},{62,13,72},{21,31,2},{0,29,74},{62,13,72},{0,29,74},{24,0,74}, +{24,0,74},{24,0,74},{24,0,74},{22,32,1},{22,32,1},{22,32,1},{22,27,1},{20,28,1},{20,28,1},{26,42,146},{26,36,78},{26,33,114},{26,32,79},{24,42,244},{24,35,79},{24,33,7},{24,31,100},{19,35,244},{21,31,75},{27,40,73},{27,35,2},{28,33,13},{27,32,14},{45,0,243},{23,35,75},{25,32,4},{20,31,74},{62,14,243},{20,31,74},{26,37,74},{26,37,74},{26,37,74}, +{26,32,75},{24,37,53},{24,33,3},{24,33,3},{24,29,10},{20,33,52},{22,30,2},{27,35,1},{27,35,1},{27,35,1},{27,31,2},{34,17,50},{25,32,0},{25,32,0},{22,30,1},{62,12,50},{22,30,1},{47,0,72},{27,35,1},{28,33,4},{25,32,4},{47,0,72},{46,24,72},{25,32,4},{0,31,74},{46,24,72},{0,31,74},{26,0,74},{26,0,74},{26,0,74},{26,0,74},{24,34,1}, +{24,34,1},{24,34,1},{24,29,1},{22,30,1},{22,30,1},{28,44,146},{28,38,78},{28,35,114},{28,34,79},{26,44,244},{26,37,79},{26,35,7},{26,33,109},{21,37,244},{23,33,76},{29,42,73},{29,37,2},{30,35,13},{29,34,14},{47,2,243},{25,37,75},{27,34,4},{21,33,73},{62,17,243},{21,33,73},{28,39,74},{28,39,74},{28,39,74},{28,33,75},{26,39,53},{26,35,3},{26,35,3}, +{26,31,10},{22,35,52},{23,32,6},{29,37,1},{29,37,1},{29,37,1},{29,33,1},{37,17,50},{27,34,0},{27,34,0},{23,32,5},{62,15,50},{23,32,5},{49,1,72},{29,37,1},{30,35,4},{27,34,4},{49,1,72},{46,27,72},{27,34,4},{0,33,72},{46,27,72},{0,33,72},{28,0,74},{28,0,74},{28,0,74},{28,0,74},{26,36,1},{26,36,1},{26,36,1},{26,31,1},{23,32,2}, +{23,32,2},{30,46,146},{30,41,77},{31,37,121},{30,36,81},{29,45,247},{28,39,77},{28,37,9},{28,35,103},{24,39,248},{25,35,76},{31,44,78},{31,40,4},{32,37,11},{31,36,17},{51,0,243},{28,39,73},{28,37,5},{24,35,74},{47,28,243},{24,35,74},{30,42,72},{30,42,72},{30,42,72},{30,36,72},{29,40,54},{29,36,6},{29,36,6},{28,34,9},{24,37,51},{26,34,2},{31,40,4}, +{31,40,4},{31,40,4},{31,35,5},{49,0,50},{29,36,2},{29,36,2},{26,34,1},{62,18,50},{26,34,1},{53,0,72},{31,40,0},{32,37,2},{28,37,1},{53,0,72},{62,22,72},{28,37,1},{0,35,74},{62,22,72},{0,35,74},{30,0,72},{30,0,72},{30,0,72},{30,0,72},{29,36,5},{29,36,5},{29,36,5},{28,33,4},{26,34,1},{26,34,1},{32,48,146},{32,42,79},{32,39,111}, +{32,38,84},{31,47,247},{30,41,77},{30,39,9},{30,37,103},{26,41,248},{27,37,76},{33,46,73},{33,42,3},{33,39,11},{33,38,14},{54,0,243},{30,41,73},{30,39,5},{26,37,74},{47,31,243},{26,37,74},{32,43,75},{32,43,75},{32,43,75},{32,38,75},{31,42,54},{31,38,6},{31,38,6},{30,36,9},{26,39,51},{28,36,2},{33,41,2},{33,41,2},{33,41,2},{33,37,2},{52,0,50}, +{31,38,2},{31,38,2},{28,36,1},{62,21,50},{28,36,1},{56,0,72},{33,42,2},{34,39,2},{30,39,1},{56,0,72},{62,25,72},{30,39,1},{0,37,74},{62,25,72},{0,37,74},{32,0,74},{32,0,74},{32,0,74},{32,0,74},{31,38,5},{31,38,5},{31,38,5},{30,35,4},{28,36,1},{28,36,1},{34,50,146},{34,44,79},{34,41,111},{34,40,84},{32,50,244},{32,43,74},{32,41,4}, +{32,39,100},{28,43,248},{29,39,76},{35,48,73},{35,44,3},{35,41,11},{35,40,14},{57,0,243},{32,43,73},{32,41,3},{28,39,74},{50,32,243},{28,39,74},{34,45,75},{34,45,75},{34,45,75},{34,40,75},{32,46,51},{32,41,3},{32,41,3},{32,37,10},{28,41,51},{30,38,2},{35,43,2},{35,43,2},{35,43,2},{35,39,2},{55,0,50},{33,40,1},{33,40,1},{30,38,1},{62,24,50}, +{30,38,1},{59,0,72},{35,44,2},{36,41,2},{31,41,2},{59,0,72},{62,28,72},{31,41,2},{0,39,74},{62,28,72},{0,39,74},{34,0,74},{34,0,74},{34,0,74},{34,0,74},{32,42,1},{32,42,1},{32,42,1},{32,37,1},{30,38,1},{30,38,1},{36,52,146},{36,46,79},{36,43,111},{36,42,84},{34,52,244},{34,45,74},{34,43,4},{34,41,100},{30,45,248},{31,41,76},{37,50,73}, +{37,46,3},{37,43,11},{37,42,14},{60,0,243},{34,45,73},{34,43,3},{30,41,74},{56,32,243},{30,41,74},{36,47,75},{36,47,75},{36,47,75},{36,42,75},{34,47,53},{34,43,3},{34,43,3},{34,39,10},{30,43,51},{32,40,2},{37,45,2},{37,45,2},{37,45,2},{37,41,2},{58,0,50},{35,42,1},{35,42,1},{32,40,1},{62,27,50},{32,40,1},{62,0,72},{37,46,2},{38,43,2}, +{33,43,2},{62,0,72},{62,31,72},{33,43,2},{0,41,74},{62,31,72},{0,41,74},{36,0,74},{36,0,74},{36,0,74},{36,0,74},{34,44,1},{34,44,1},{34,44,1},{34,39,1},{32,40,1},{32,40,1},{38,54,146},{38,49,77},{39,45,120},{38,45,76},{37,53,247},{36,47,78},{37,45,5},{36,43,100},{31,48,243},{33,43,81},{40,50,78},{39,48,4},{40,45,8},{39,45,20},{63,1,243}, +{36,47,74},{37,45,1},{33,43,80},{63,32,243},{33,43,80},{38,50,72},{38,50,72},{38,50,72},{38,44,72},{37,48,54},{37,45,5},{37,45,5},{36,42,8},{32,45,53},{34,42,1},{40,46,4},{40,46,4},{40,46,4},{40,43,4},{53,16,50},{37,45,1},{37,45,1},{35,42,0},{63,30,50},{35,42,0},{63,5,72},{39,48,0},{41,45,1},{36,45,0},{63,5,72},{47,42,72},{36,45,0}, +{0,43,80},{47,42,72},{0,43,80},{38,0,72},{38,0,72},{38,0,72},{38,0,72},{37,45,4},{37,45,4},{37,45,4},{37,41,4},{34,42,1},{34,42,1},{40,56,146},{40,51,77},{41,47,120},{40,47,76},{39,55,247},{38,49,77},{39,47,5},{38,45,100},{34,49,248},{35,45,81},{42,52,78},{41,50,4},{42,47,8},{41,47,20},{63,7,243},{38,49,73},{39,47,1},{35,45,80},{63,35,243}, +{35,45,80},{40,52,72},{40,52,72},{40,52,72},{40,46,72},{39,50,54},{39,47,5},{39,47,5},{38,44,8},{34,47,53},{36,44,1},{42,48,4},{42,48,4},{42,48,4},{42,45,4},{56,16,50},{39,47,1},{39,47,1},{37,44,0},{62,33,50},{37,44,0},{63,11,72},{41,50,0},{43,47,1},{38,47,0},{63,11,72},{47,45,72},{38,47,0},{0,45,80},{47,45,72},{0,45,80},{40,0,72}, +{40,0,72},{40,0,72},{40,0,72},{39,47,4},{39,47,4},{39,47,4},{39,43,4},{36,44,1},{36,44,1},{42,58,146},{42,53,77},{43,49,121},{42,48,81},{41,57,247},{40,51,77},{40,49,9},{40,47,100},{36,51,248},{37,47,81},{44,54,78},{43,52,4},{44,49,6},{43,48,17},{63,13,243},{40,51,73},{40,49,5},{37,47,80},{63,38,243},{37,47,80},{42,54,72},{42,54,72},{42,54,72}, +{42,48,72},{41,52,54},{41,48,6},{41,48,6},{40,46,8},{36,49,51},{38,46,1},{44,50,4},{44,50,4},{44,50,4},{44,47,4},{59,16,50},{41,48,2},{41,48,2},{39,46,0},{62,36,50},{39,46,0},{55,32,72},{43,52,0},{44,49,2},{40,49,1},{55,32,72},{46,48,72},{40,49,1},{0,47,80},{46,48,72},{0,47,80},{42,0,72},{42,0,72},{42,0,72},{42,0,72},{41,48,5}, +{41,48,5},{41,48,5},{41,45,4},{38,46,1},{38,46,1},{44,60,146},{44,55,77},{45,51,121},{44,50,81},{43,59,247},{42,53,77},{42,51,9},{42,49,103},{38,53,248},{39,49,76},{46,56,78},{45,54,4},{46,51,6},{45,50,17},{63,19,243},{42,53,73},{42,51,5},{38,49,74},{63,41,243},{38,49,74},{44,56,72},{44,56,72},{44,56,72},{44,50,72},{43,54,54},{43,50,6},{43,50,6}, +{42,48,9},{38,51,51},{40,48,2},{46,52,4},{46,52,4},{46,52,4},{46,49,4},{62,16,50},{43,50,2},{43,50,2},{40,48,1},{62,39,50},{40,48,1},{58,32,72},{45,54,0},{46,51,2},{42,51,1},{58,32,72},{52,48,72},{42,51,1},{0,49,74},{52,48,72},{0,49,74},{44,0,72},{44,0,72},{44,0,72},{44,0,72},{43,50,5},{43,50,5},{43,50,5},{43,47,4},{40,48,1}, +{40,48,1},{46,63,146},{46,57,79},{47,53,115},{46,53,78},{45,61,245},{45,55,77},{45,53,2},{44,51,105},{39,56,243},{42,51,82},{48,59,76},{48,55,9},{48,53,8},{47,53,18},{59,33,243},{44,55,74},{45,53,1},{41,51,80},{55,48,243},{41,51,80},{46,59,74},{46,59,74},{46,59,74},{46,52,75},{45,57,51},{45,53,2},{45,53,2},{44,50,10},{41,53,51},{42,50,1},{48,54,4}, +{48,54,4},{48,54,4},{48,51,4},{63,21,50},{45,53,1},{45,53,1},{43,50,0},{63,42,50},{43,50,0},{63,29,72},{47,56,2},{49,53,1},{44,53,1},{63,29,72},{63,46,72},{44,53,1},{0,51,80},{63,46,72},{0,51,80},{46,0,74},{46,0,74},{46,0,74},{46,0,74},{45,53,1},{45,53,1},{45,53,1},{45,49,1},{42,50,1},{42,50,1},{48,63,152},{48,59,77},{49,55,120}, +{48,55,76},{47,63,245},{47,57,77},{47,55,2},{46,53,105},{41,58,243},{44,53,82},{50,61,76},{49,58,4},{50,55,8},{49,55,20},{62,33,243},{46,57,74},{47,55,1},{43,53,80},{61,48,243},{43,53,80},{48,60,72},{48,60,72},{48,60,72},{48,54,72},{47,59,51},{47,55,2},{47,55,2},{46,52,10},{43,55,51},{44,52,1},{50,56,4},{50,56,4},{50,56,4},{50,53,4},{63,27,50}, +{47,55,1},{47,55,1},{45,52,0},{63,45,50},{45,52,0},{63,35,72},{49,58,0},{51,55,1},{46,55,1},{63,35,72},{63,49,72},{46,55,1},{0,53,80},{63,49,72},{0,53,80},{48,0,72},{48,0,72},{48,0,72},{48,0,72},{47,55,1},{47,55,1},{47,55,1},{47,51,1},{44,52,1},{44,52,1},{51,63,184},{50,61,77},{51,57,120},{50,57,76},{49,63,268},{48,59,78},{49,57,5}, +{48,55,100},{43,60,243},{46,55,82},{52,63,76},{51,60,4},{52,57,8},{51,57,20},{63,37,243},{48,59,74},{49,57,1},{45,55,80},{63,50,243},{45,55,80},{50,62,72},{50,62,72},{50,62,72},{50,56,72},{49,60,56},{49,57,5},{49,57,5},{48,54,8},{45,57,51},{46,54,1},{52,58,4},{52,58,4},{52,58,4},{52,55,4},{63,33,50},{49,57,1},{49,57,1},{47,54,0},{47,56,50}, +{47,54,0},{63,41,72},{51,60,0},{53,57,1},{48,57,0},{63,41,72},{63,52,72},{48,57,0},{0,55,80},{63,52,72},{0,55,80},{50,0,72},{50,0,72},{50,0,72},{50,0,72},{49,57,4},{49,57,4},{49,57,4},{49,53,4},{46,54,1},{46,54,1},{53,63,226},{52,63,77},{53,59,120},{52,59,76},{52,63,300},{50,61,78},{51,59,5},{50,57,100},{45,62,243},{47,57,84},{54,63,84}, +{53,62,4},{54,59,8},{53,59,20},{63,43,243},{49,62,73},{51,59,1},{47,57,80},{63,53,243},{47,57,80},{52,63,76},{52,63,76},{52,63,76},{52,58,72},{51,62,56},{51,59,5},{51,59,5},{50,56,8},{47,59,51},{48,56,1},{54,60,4},{54,60,4},{54,60,4},{54,57,4},{63,39,50},{51,59,1},{51,59,1},{49,56,0},{47,59,50},{49,56,0},{63,47,72},{53,62,0},{55,59,1}, +{50,59,0},{63,47,72},{63,55,72},{50,59,0},{0,57,80},{63,55,72},{0,57,80},{52,0,72},{52,0,72},{52,0,72},{52,0,72},{51,59,4},{51,59,4},{51,59,4},{51,55,4},{48,56,1},{48,56,1},{56,63,314},{55,63,115},{55,62,115},{54,61,76},{54,63,364},{53,63,79},{53,61,3},{52,59,108},{48,63,252},{49,60,79},{57,63,115},{56,63,10},{56,61,11},{56,61,18},{63,50,243}, +{53,63,78},{53,61,2},{47,60,75},{62,57,243},{47,60,75},{54,63,99},{54,63,99},{54,63,99},{54,60,75},{53,63,69},{53,61,2},{53,61,2},{53,58,6},{49,61,51},{50,58,6},{56,63,1},{56,63,1},{56,63,1},{56,59,2},{61,49,50},{53,61,1},{53,61,1},{51,58,2},{63,54,50},{51,58,2},{63,53,74},{56,63,9},{57,61,1},{53,61,1},{63,53,74},{63,58,74},{53,61,1}, +{0,60,74},{63,58,74},{0,60,74},{54,0,74},{54,0,74},{54,0,74},{54,0,74},{53,61,2},{53,61,2},{53,61,2},{53,57,2},{50,59,2},{50,59,2},{57,63,371},{57,63,179},{57,63,115},{56,63,75},{57,63,387},{55,63,123},{55,63,2},{54,61,91},{52,63,286},{51,62,70},{59,63,146},{58,63,59},{58,63,10},{58,63,17},{63,55,221},{57,63,98},{55,63,1},{49,62,66},{63,59,221}, +{49,62,66},{57,63,115},{57,63,115},{57,63,115},{56,62,75},{56,63,93},{55,63,2},{55,63,2},{55,60,6},{51,63,51},{52,60,6},{58,63,10},{58,63,10},{58,63,10},{58,61,2},{63,51,50},{55,63,1},{55,63,1},{53,60,2},{63,57,50},{53,60,2},{63,59,61},{60,63,25},{59,63,0},{55,63,0},{63,59,61},{63,61,61},{55,63,0},{0,62,65},{63,61,61},{0,62,65},{56,0,74}, +{56,0,74},{56,0,74},{56,0,74},{55,63,2},{55,63,2},{55,63,2},{55,59,2},{52,61,2},{52,61,2},{60,63,259},{59,63,190},{59,63,154},{58,63,90},{59,63,270},{58,63,91},{57,63,35},{57,62,22},{56,63,194},{54,63,11},{61,63,70},{60,63,42},{60,63,26},{60,63,2},{63,59,94},{60,63,42},{59,63,13},{53,63,10},{63,61,94},{53,63,10},{59,63,154},{59,63,154},{59,63,154}, +{58,63,90},{58,63,147},{57,63,35},{57,63,35},{57,62,6},{55,63,77},{54,62,6},{60,63,26},{60,63,26},{60,63,26},{60,63,2},{63,57,50},{59,63,13},{59,63,13},{55,62,2},{63,60,50},{55,62,2},{63,62,5},{62,63,4},{62,63,0},{61,63,0},{63,62,5},{62,63,5},{61,63,0},{0,63,9},{62,63,5},{0,63,9},{58,0,74},{58,0,74},{58,0,74},{58,0,74},{57,63,10}, +{57,63,10},{57,63,10},{57,61,2},{54,63,2},{54,63,2},{61,63,162},{61,63,135},{61,63,126},{60,63,90},{61,63,154},{60,63,66},{60,63,50},{59,63,2},{59,63,109},{57,63,10},{62,63,19},{62,63,14},{62,63,10},{62,63,5},{63,62,17},{62,63,12},{62,63,8},{59,63,1},{62,63,17},{59,63,1},{61,63,126},{61,63,126},{61,63,126},{60,63,90},{60,63,98},{60,63,50},{60,63,50}, +{59,63,2},{58,63,62},{57,63,10},{62,63,10},{62,63,10},{62,63,10},{62,63,5},{63,61,13},{62,63,8},{62,63,8},{59,63,1},{63,62,13},{59,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{60,0,74},{60,0,74},{60,0,74},{60,0,74},{60,63,34},{60,63,34},{60,63,34},{59,63,2},{57,63,10}, +{57,63,10},{0,14,202},{0,10,25},{0,7,1},{0,6,74},{0,10,441},{0,6,282},{0,5,133},{0,4,318},{0,5,477},{0,4,343},{0,14,202},{0,10,25},{0,7,1},{0,6,74},{5,0,441},{0,6,282},{0,5,133},{0,4,318},{10,0,441},{0,4,318},{0,7,0},{0,7,0},{0,7,0},{0,3,1},{0,3,41},{0,3,17},{0,3,17},{0,2,26},{0,2,45},{0,1,30},{0,7,0}, +{0,7,0},{0,7,0},{0,3,1},{2,0,41},{0,3,17},{0,3,17},{0,2,26},{3,0,41},{0,2,26},{7,0,202},{0,10,25},{0,7,1},{0,6,74},{7,0,202},{14,0,202},{0,6,74},{0,5,202},{14,0,202},{0,5,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,200},{0,14,1},{0,10,25}, +{0,8,41},{0,14,686},{0,9,362},{0,8,141},{0,5,467},{0,6,762},{0,5,503},{0,20,200},{0,14,1},{0,10,25},{0,8,41},{7,0,686},{0,9,362},{0,8,141},{0,5,467},{14,0,686},{0,5,467},{0,13,0},{0,13,0},{0,13,0},{0,6,1},{0,6,145},{0,5,52},{0,5,52},{0,3,89},{0,3,161},{0,3,105},{0,13,0},{0,13,0},{0,13,0},{0,6,1},{3,0,145}, +{0,5,52},{0,5,52},{0,3,89},{6,0,145},{0,3,89},{2,16,200},{0,14,1},{2,9,1},{0,8,41},{2,16,200},{20,0,200},{0,8,41},{0,7,202},{20,0,200},{0,7,202},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,24,225},{1,16,27},{1,12,83},{1,11,51},{0,19,724},{0,12,299},{0,10,62}, +{0,8,414},{0,9,875},{0,7,500},{2,22,201},{2,16,6},{2,12,26},{1,11,35},{10,0,723},{0,12,299},{0,10,62},{0,8,414},{14,3,723},{0,8,414},{1,17,25},{1,17,25},{1,17,25},{1,9,25},{0,12,162},{0,8,25},{0,8,25},{0,5,61},{0,5,216},{0,5,97},{2,15,1},{2,15,1},{2,15,1},{2,8,2},{6,0,162},{0,8,25},{0,8,25},{0,5,61},{12,0,162}, +{0,5,61},{5,16,200},{1,16,2},{4,11,1},{0,11,17},{5,16,200},{26,0,200},{0,11,17},{0,9,202},{26,0,200},{0,9,202},{1,0,25},{1,0,25},{1,0,25},{1,0,25},{0,5,1},{0,5,1},{0,5,1},{0,3,1},{0,2,8},{0,2,8},{2,28,313},{2,19,118},{2,14,203},{2,13,130},{0,25,724},{0,16,236},{0,13,6},{0,10,339},{0,11,984},{0,10,508},{4,24,201}, +{4,17,5},{4,14,26},{3,13,35},{13,0,723},{0,16,236},{0,13,6},{0,10,339},{14,6,723},{0,10,339},{2,21,113},{2,21,113},{2,21,113},{2,11,114},{0,18,162},{0,12,2},{0,12,2},{0,7,34},{0,8,280},{0,7,115},{4,17,1},{4,17,1},{4,17,1},{4,10,2},{9,0,162},{0,12,2},{0,12,2},{0,7,34},{18,0,162},{0,7,34},{16,0,200},{3,18,2},{6,13,1}, +{0,13,2},{16,0,200},{32,0,200},{0,13,2},{0,11,202},{32,0,200},{0,11,202},{2,0,113},{2,0,113},{2,0,113},{2,0,113},{0,11,1},{0,11,1},{0,11,1},{0,6,1},{0,5,40},{0,5,40},{4,31,408},{4,22,216},{4,16,317},{3,15,216},{1,30,723},{1,19,216},{1,15,9},{0,12,312},{0,15,1000},{0,12,440},{6,27,200},{6,20,1},{7,16,29},{5,15,36},{16,0,723}, +{0,19,203},{2,15,5},{0,12,296},{32,0,723},{0,12,296},{4,23,209},{4,23,209},{4,23,209},{4,14,208},{1,23,162},{1,16,4},{1,16,4},{1,10,20},{0,11,294},{0,10,89},{6,19,1},{6,19,1},{6,19,1},{6,13,0},{12,1,162},{2,15,1},{2,15,1},{0,10,8},{25,0,162},{0,10,8},{19,1,200},{6,20,1},{8,15,5},{2,15,4},{19,1,200},{39,0,200},{2,15,4}, +{0,13,200},{39,0,200},{0,13,200},{3,0,208},{3,0,208},{3,0,208},{3,0,208},{1,16,0},{1,16,0},{1,16,0},{1,9,1},{0,8,45},{0,8,45},{6,33,408},{6,24,216},{6,18,317},{5,17,213},{3,32,723},{3,21,216},{3,17,2},{2,14,312},{0,18,888},{0,14,293},{8,29,200},{8,22,1},{9,17,26},{8,17,37},{19,0,723},{1,22,200},{3,17,2},{0,14,257},{38,0,723}, +{0,14,257},{6,25,209},{6,25,209},{6,25,209},{5,16,208},{3,25,162},{3,17,1},{3,17,1},{3,12,20},{0,15,228},{0,12,20},{8,21,1},{8,21,1},{8,21,1},{8,15,0},{15,1,162},{3,17,1},{3,17,1},{0,12,4},{31,0,162},{0,12,4},{22,1,200},{8,22,1},{10,17,2},{3,17,1},{22,1,200},{45,0,200},{3,17,1},{0,15,200},{45,0,200},{0,15,200},{5,0,208}, +{5,0,208},{5,0,208},{5,0,208},{3,18,0},{3,18,0},{3,18,0},{3,11,1},{0,11,13},{0,11,13},{8,35,408},{8,26,216},{8,20,317},{7,19,213},{5,34,723},{5,23,216},{5,19,2},{4,16,298},{0,22,804},{0,16,228},{10,31,200},{10,24,1},{11,19,26},{10,19,37},{22,0,723},{3,24,200},{5,19,2},{0,16,227},{44,0,723},{0,16,227},{8,27,209},{8,27,209},{8,27,209}, +{7,18,208},{5,27,162},{5,19,1},{5,19,1},{5,14,20},{0,18,180},{0,15,4},{10,23,1},{10,23,1},{10,23,1},{10,17,1},{15,7,162},{5,19,1},{5,19,1},{2,14,4},{31,3,162},{2,14,4},{25,1,200},{10,24,1},{12,19,2},{5,19,1},{25,1,200},{47,2,200},{5,19,1},{0,17,202},{47,2,200},{0,17,202},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{5,20,0}, +{5,20,0},{5,20,0},{5,13,1},{0,15,0},{0,15,0},{10,37,408},{10,28,216},{10,22,317},{9,21,213},{7,36,723},{7,25,216},{7,21,2},{6,18,298},{0,25,748},{1,19,218},{12,33,200},{12,26,1},{13,21,26},{12,21,37},{25,0,723},{5,26,200},{7,21,2},{0,19,211},{50,0,723},{0,19,211},{10,29,209},{10,29,209},{10,29,209},{9,20,208},{7,29,162},{7,21,1},{7,21,1}, +{7,16,17},{0,21,164},{3,16,3},{12,25,1},{12,25,1},{12,25,1},{12,19,1},{15,13,162},{7,21,1},{7,21,1},{4,16,1},{31,6,162},{4,16,1},{28,1,200},{12,26,1},{14,21,2},{7,21,1},{28,1,200},{47,5,200},{7,21,1},{0,19,202},{47,5,200},{0,19,202},{9,0,208},{9,0,208},{9,0,208},{9,0,208},{7,22,0},{7,22,0},{7,22,0},{7,15,1},{2,17,0}, +{2,17,0},{12,39,404},{12,30,212},{13,24,318},{12,23,215},{9,39,724},{9,27,212},{9,24,7},{8,20,306},{0,28,724},{3,21,210},{14,35,203},{14,28,2},{15,24,22},{14,23,30},{28,1,723},{7,28,203},{10,23,4},{0,21,201},{47,5,723},{0,21,201},{12,32,202},{12,32,202},{12,32,202},{12,22,202},{9,31,165},{9,24,3},{9,24,3},{9,18,14},{2,24,164},{4,19,6},{14,28,1}, +{14,28,1},{14,28,1},{14,21,1},{24,1,162},{10,23,0},{10,23,0},{6,18,5},{49,0,162},{6,18,5},{23,17,200},{14,28,1},{16,24,4},{10,23,4},{23,17,200},{63,0,200},{10,23,4},{0,21,200},{63,0,200},{0,21,200},{12,0,202},{12,0,202},{12,0,202},{12,0,202},{9,25,1},{9,25,1},{9,25,1},{9,17,2},{4,19,2},{4,19,2},{14,41,404},{14,32,215},{15,26,318}, +{14,25,215},{11,41,724},{11,29,212},{11,26,7},{10,22,306},{2,30,724},{5,23,210},{16,37,200},{16,30,1},{17,26,24},{16,25,40},{31,1,723},{9,30,203},{12,25,4},{2,23,201},{47,8,723},{2,23,201},{14,34,202},{14,34,202},{14,34,202},{14,24,202},{11,33,163},{11,26,3},{11,26,3},{11,20,14},{4,26,164},{6,21,6},{16,30,0},{16,30,0},{16,30,0},{16,23,0},{27,1,162}, +{12,25,0},{12,25,0},{8,20,5},{55,0,162},{8,20,5},{34,1,200},{16,30,1},{18,26,4},{12,25,4},{34,1,200},{63,3,200},{12,25,4},{0,23,200},{63,3,200},{0,23,200},{14,0,202},{14,0,202},{14,0,202},{14,0,202},{11,27,1},{11,27,1},{11,27,1},{11,19,2},{6,21,2},{6,21,2},{16,43,408},{16,34,216},{16,28,312},{16,27,221},{13,43,724},{13,31,212},{13,28,7}, +{12,24,306},{4,32,724},{7,25,210},{18,39,200},{18,32,1},{19,28,24},{17,27,36},{34,0,723},{11,32,201},{14,27,4},{4,25,201},{47,11,723},{4,25,201},{16,35,209},{16,35,209},{16,35,209},{16,26,208},{13,35,163},{13,28,3},{13,28,3},{13,22,14},{6,28,164},{8,23,6},{18,31,1},{18,31,1},{18,31,1},{18,25,0},{30,1,162},{14,27,0},{14,27,0},{10,22,5},{61,0,162}, +{10,22,5},{37,1,200},{18,32,1},{20,28,4},{14,27,4},{37,1,200},{63,6,200},{14,27,4},{0,25,200},{63,6,200},{0,25,200},{16,0,208},{16,0,208},{16,0,208},{16,0,208},{13,29,1},{13,29,1},{13,29,1},{13,21,2},{8,23,2},{8,23,2},{18,45,408},{18,36,216},{18,30,312},{17,29,216},{15,45,724},{15,33,210},{15,30,7},{14,26,306},{6,34,724},{9,27,210},{20,41,200}, +{20,34,1},{21,30,24},{19,29,36},{37,0,723},{13,34,201},{16,29,5},{6,27,201},{47,14,723},{6,27,201},{18,37,209},{18,37,209},{18,37,209},{18,28,208},{15,37,163},{15,30,3},{15,30,3},{15,24,14},{8,30,164},{10,25,6},{20,33,1},{20,33,1},{20,33,1},{20,27,0},{33,1,162},{16,29,1},{16,29,1},{12,24,5},{63,2,162},{12,24,5},{40,1,200},{20,34,1},{22,30,4}, +{16,29,4},{40,1,200},{63,9,200},{16,29,4},{0,27,200},{63,9,200},{0,27,200},{17,0,208},{17,0,208},{17,0,208},{17,0,208},{15,31,1},{15,31,1},{15,31,1},{15,23,2},{10,25,2},{10,25,2},{20,47,404},{20,38,212},{21,32,318},{20,31,215},{17,47,724},{17,35,212},{17,32,7},{16,29,308},{8,36,724},{11,29,210},{22,44,201},{22,36,2},{23,32,22},{22,31,35},{40,1,723}, +{15,36,206},{17,32,6},{9,29,202},{63,9,723},{9,29,202},{20,40,202},{20,40,202},{20,40,202},{20,30,203},{17,39,165},{17,32,3},{17,32,3},{17,26,19},{10,32,164},{13,27,2},{22,36,1},{22,36,1},{22,36,1},{22,29,2},{31,12,162},{18,31,1},{18,31,1},{13,27,1},{62,6,162},{13,27,1},{44,0,200},{22,36,1},{24,32,4},{16,32,4},{44,0,200},{62,13,200},{16,32,4}, +{0,29,202},{62,13,200},{0,29,202},{20,0,202},{20,0,202},{20,0,202},{20,0,202},{17,33,1},{17,33,1},{17,33,1},{17,25,1},{13,27,1},{13,27,1},{22,49,404},{22,40,212},{23,34,318},{22,33,215},{19,49,724},{19,37,212},{19,34,7},{18,31,308},{10,38,724},{13,31,210},{24,46,201},{24,38,2},{25,34,22},{24,33,30},{43,1,723},{17,38,203},{20,33,4},{11,31,202},{63,12,723}, +{11,31,202},{22,42,202},{22,42,202},{22,42,202},{22,32,202},{19,41,165},{19,34,3},{19,34,3},{19,28,19},{12,34,164},{15,29,2},{24,38,1},{24,38,1},{24,38,1},{24,31,2},{31,18,162},{20,33,0},{20,33,0},{15,29,1},{62,9,162},{15,29,1},{47,0,200},{24,38,1},{26,34,4},{20,33,4},{47,0,200},{46,24,200},{20,33,4},{0,31,202},{46,24,200},{0,31,202},{22,0,202}, +{22,0,202},{22,0,202},{22,0,202},{19,35,1},{19,35,1},{19,35,1},{19,27,1},{15,29,1},{15,29,1},{24,51,404},{24,42,212},{25,36,318},{24,35,215},{21,51,724},{21,39,212},{21,36,7},{20,32,306},{12,40,724},{15,33,213},{26,47,203},{26,40,2},{27,36,22},{26,35,30},{46,1,723},{19,40,203},{22,35,4},{13,33,200},{63,15,723},{13,33,200},{24,44,202},{24,44,202},{24,44,202}, +{24,34,202},{21,43,165},{21,36,3},{21,36,3},{21,30,19},{14,36,164},{17,31,2},{26,40,1},{26,40,1},{26,40,1},{26,33,1},{34,17,162},{22,35,0},{22,35,0},{17,31,1},{62,12,162},{17,31,1},{49,1,200},{26,40,1},{28,36,4},{22,35,4},{49,1,200},{46,27,200},{22,35,4},{0,33,200},{46,27,200},{0,33,200},{24,0,202},{24,0,202},{24,0,202},{24,0,202},{21,37,1}, +{21,37,1},{21,37,1},{21,29,1},{17,31,1},{17,31,1},{26,53,404},{26,44,212},{27,38,318},{26,37,215},{23,53,724},{23,41,212},{23,38,7},{22,34,306},{14,42,724},{17,35,210},{28,49,203},{28,42,2},{29,38,22},{28,37,30},{47,5,723},{21,42,203},{24,37,4},{15,35,200},{63,18,723},{15,35,200},{26,46,202},{26,46,202},{26,46,202},{26,36,202},{23,45,165},{23,38,3},{23,38,3}, +{23,32,14},{16,38,164},{18,33,6},{28,42,1},{28,42,1},{28,42,1},{28,35,1},{37,17,162},{24,37,0},{24,37,0},{20,32,5},{62,15,162},{20,32,5},{52,1,200},{28,42,1},{30,38,4},{24,37,4},{52,1,200},{46,30,200},{24,37,4},{0,35,200},{46,30,200},{0,35,200},{26,0,202},{26,0,202},{26,0,202},{26,0,202},{23,39,1},{23,39,1},{23,39,1},{23,31,1},{18,33,2}, +{18,33,2},{28,56,400},{28,46,216},{29,40,314},{28,39,213},{26,53,728},{25,44,215},{25,40,9},{25,37,306},{17,44,728},{19,37,210},{31,50,204},{30,45,4},{31,40,21},{30,39,29},{52,1,723},{24,44,201},{25,40,5},{17,37,202},{46,30,723},{17,37,202},{28,49,200},{28,49,200},{28,49,200},{28,38,201},{26,46,166},{26,39,6},{26,39,6},{25,34,17},{18,40,163},{21,35,2},{31,43,4}, +{31,43,4},{31,43,4},{31,37,4},{49,0,162},{26,39,2},{26,39,2},{21,35,1},{62,18,162},{21,35,1},{56,0,200},{30,45,0},{32,40,2},{25,40,1},{56,0,200},{62,25,200},{25,40,1},{0,37,202},{62,25,200},{0,37,202},{28,0,200},{28,0,200},{28,0,200},{28,0,200},{26,39,5},{26,39,5},{26,39,5},{25,33,4},{21,35,1},{21,35,1},{30,58,400},{30,48,217},{31,42,314}, +{30,41,213},{28,55,728},{27,46,215},{27,42,9},{27,39,306},{19,46,728},{21,39,210},{32,54,201},{32,47,3},{33,42,19},{32,41,35},{55,1,723},{26,46,201},{27,42,5},{19,39,202},{47,32,723},{19,39,202},{30,51,200},{30,51,200},{30,51,200},{30,40,201},{28,48,166},{28,41,6},{28,41,6},{27,36,17},{20,42,163},{23,37,2},{32,46,2},{32,46,2},{32,46,2},{32,39,2},{52,0,162}, +{28,41,2},{28,41,2},{23,37,1},{62,21,162},{23,37,1},{59,0,200},{32,47,2},{34,42,2},{27,42,1},{59,0,200},{62,28,200},{27,42,1},{0,39,202},{62,28,200},{0,39,202},{30,0,200},{30,0,200},{30,0,200},{30,0,200},{28,41,5},{28,41,5},{28,41,5},{27,35,4},{23,37,1},{23,37,1},{32,60,402},{32,50,212},{32,44,324},{32,43,215},{30,57,728},{29,47,216},{29,44,9}, +{29,41,306},{20,48,724},{23,41,210},{34,56,201},{34,48,2},{35,44,19},{34,43,35},{58,1,723},{28,48,201},{29,44,5},{21,41,202},{53,32,723},{21,41,202},{32,52,202},{32,52,202},{32,52,202},{32,42,203},{30,50,166},{30,43,6},{30,43,6},{29,38,17},{22,44,163},{25,39,2},{34,48,1},{34,48,1},{34,48,1},{34,41,2},{55,0,162},{30,43,2},{30,43,2},{25,39,1},{62,24,162}, +{25,39,1},{62,0,200},{34,48,1},{36,44,2},{29,44,1},{62,0,200},{62,31,200},{29,44,1},{0,41,202},{62,31,200},{0,41,202},{32,0,202},{32,0,202},{32,0,202},{32,0,202},{30,43,5},{30,43,5},{30,43,5},{29,37,4},{25,39,1},{25,39,1},{34,62,402},{34,52,212},{34,46,324},{34,45,215},{31,61,728},{31,49,210},{31,46,9},{31,43,306},{22,50,724},{25,43,210},{36,58,201}, +{36,50,2},{37,46,19},{36,45,35},{61,1,723},{30,50,201},{31,46,5},{23,43,202},{59,32,723},{23,43,202},{34,54,202},{34,54,202},{34,54,202},{34,44,203},{31,54,166},{31,46,8},{31,46,8},{31,40,17},{24,46,163},{27,41,2},{36,50,1},{36,50,1},{36,50,1},{36,43,2},{58,0,162},{32,45,1},{32,45,1},{27,41,1},{62,27,162},{27,41,1},{63,4,200},{36,50,1},{38,46,2}, +{31,46,1},{63,4,200},{62,34,200},{31,46,1},{0,43,202},{62,34,200},{0,43,202},{34,0,202},{34,0,202},{34,0,202},{34,0,202},{31,47,5},{31,47,5},{31,47,5},{31,39,4},{27,41,1},{27,41,1},{36,63,408},{36,54,216},{37,48,314},{36,47,217},{34,62,727},{33,52,215},{33,48,9},{32,45,308},{24,53,723},{28,45,217},{39,58,206},{38,53,4},{39,48,21},{38,47,36},{63,4,723}, +{32,52,201},{33,48,5},{26,45,208},{62,34,723},{26,45,208},{36,57,200},{36,57,200},{36,57,200},{36,47,201},{34,54,166},{33,48,8},{33,48,8},{33,43,20},{26,48,163},{29,43,1},{39,51,4},{39,51,4},{39,51,4},{39,45,4},{53,16,162},{35,47,4},{35,47,4},{30,43,0},{63,30,162},{30,43,0},{63,11,200},{38,53,0},{40,48,2},{33,48,1},{63,11,200},{47,45,200},{33,48,1}, +{0,45,208},{47,45,200},{0,45,208},{36,0,200},{36,0,200},{36,0,200},{36,0,200},{34,47,5},{34,47,5},{34,47,5},{34,41,4},{29,43,1},{29,43,1},{39,63,440},{38,56,216},{39,50,314},{38,49,213},{36,63,728},{35,54,215},{35,50,9},{34,47,308},{26,55,723},{30,47,217},{41,60,206},{40,55,4},{41,50,21},{40,49,29},{63,10,723},{34,54,201},{35,50,5},{28,47,208},{62,37,723}, +{28,47,208},{38,59,200},{38,59,200},{38,59,200},{38,48,201},{36,56,166},{36,49,6},{36,49,6},{35,45,20},{28,50,163},{31,45,1},{41,53,4},{41,53,4},{41,53,4},{41,47,4},{56,16,162},{36,49,2},{36,49,2},{32,45,0},{62,33,162},{32,45,0},{55,32,200},{40,55,0},{42,50,2},{35,50,1},{55,32,200},{46,48,200},{35,50,1},{0,47,208},{46,48,200},{0,47,208},{38,0,200}, +{38,0,200},{38,0,200},{38,0,200},{36,49,5},{36,49,5},{36,49,5},{36,43,4},{31,45,1},{31,45,1},{41,63,482},{40,58,216},{41,52,314},{40,51,213},{39,63,760},{37,56,215},{37,52,9},{37,49,306},{28,57,723},{31,49,215},{43,62,206},{42,57,4},{43,52,21},{42,51,29},{63,16,723},{36,56,201},{37,52,5},{29,49,203},{62,40,723},{29,49,203},{40,61,200},{40,61,200},{40,61,200}, +{40,50,201},{38,58,166},{38,51,6},{38,51,6},{37,47,20},{30,52,163},{33,47,1},{43,55,4},{43,55,4},{43,55,4},{43,49,4},{59,16,162},{38,51,2},{38,51,2},{34,47,0},{62,36,162},{34,47,0},{58,32,200},{42,57,0},{44,52,2},{37,52,1},{58,32,200},{52,48,200},{37,52,1},{0,49,202},{52,48,200},{0,49,202},{40,0,200},{40,0,200},{40,0,200},{40,0,200},{38,51,5}, +{38,51,5},{38,51,5},{38,45,4},{33,47,1},{33,47,1},{43,63,530},{42,60,216},{43,54,314},{42,53,213},{41,63,799},{39,58,215},{39,54,9},{39,51,306},{30,59,723},{33,51,210},{45,63,212},{44,59,4},{45,54,21},{44,53,29},{63,22,723},{38,58,201},{39,54,5},{31,51,203},{62,43,723},{31,51,203},{42,63,200},{42,63,200},{42,63,200},{42,52,201},{40,60,166},{40,53,6},{40,53,6}, +{39,48,17},{32,54,163},{35,49,2},{45,57,4},{45,57,4},{45,57,4},{45,51,4},{62,16,162},{40,53,2},{40,53,2},{35,49,1},{62,39,162},{35,49,1},{61,32,200},{44,59,0},{46,54,2},{39,54,1},{61,32,200},{58,48,200},{39,54,1},{0,51,202},{58,48,200},{0,51,202},{42,0,200},{42,0,200},{42,0,200},{42,0,200},{40,53,5},{40,53,5},{40,53,5},{40,47,4},{35,49,1}, +{35,49,1},{46,63,626},{44,63,222},{45,57,315},{44,56,211},{44,63,869},{41,60,213},{42,56,2},{41,53,298},{32,61,723},{36,53,217},{48,63,244},{47,60,5},{47,56,26},{46,55,34},{61,32,723},{40,60,202},{42,56,1},{34,53,208},{58,48,723},{34,53,208},{44,63,218},{44,63,218},{44,63,218},{44,55,203},{42,63,163},{42,56,2},{42,56,2},{41,51,25},{35,56,163},{37,51,1},{47,60,1}, +{47,60,1},{47,60,1},{47,53,2},{63,21,162},{42,56,1},{42,56,1},{38,51,0},{63,42,162},{38,51,0},{63,35,200},{46,61,2},{49,56,1},{41,56,1},{63,35,200},{63,49,200},{41,56,1},{0,53,208},{63,49,200},{0,53,208},{44,0,202},{44,0,202},{44,0,202},{44,0,202},{42,56,1},{42,56,1},{42,56,1},{42,49,1},{37,51,1},{37,51,1},{48,63,728},{47,63,238},{47,59,315}, +{46,58,211},{46,63,937},{43,62,213},{44,58,2},{43,55,298},{34,63,723},{38,55,217},{50,63,286},{48,63,4},{49,58,20},{48,57,36},{63,34,723},{42,62,202},{44,58,1},{36,55,208},{62,49,723},{36,55,208},{47,63,234},{47,63,234},{47,63,234},{46,57,203},{44,63,181},{44,58,2},{44,58,2},{43,53,25},{37,58,163},{39,53,1},{49,61,4},{49,61,4},{49,61,4},{49,55,4},{63,27,162}, +{44,58,1},{44,58,1},{40,53,0},{63,45,162},{40,53,0},{63,41,200},{48,63,0},{51,58,1},{43,58,1},{63,41,200},{63,52,200},{43,58,1},{0,55,208},{63,52,200},{0,55,208},{46,0,202},{46,0,202},{46,0,202},{46,0,202},{44,58,1},{44,58,1},{44,58,1},{44,51,1},{39,53,1},{39,53,1},{50,63,866},{49,63,317},{49,61,312},{48,60,216},{48,63,1048},{46,63,219},{46,60,2}, +{45,57,298},{38,63,748},{40,57,217},{53,63,350},{51,63,20},{51,60,20},{50,59,36},{63,40,723},{46,63,218},{46,60,1},{38,57,208},{62,52,723},{38,57,208},{48,63,264},{48,63,264},{48,63,264},{48,59,201},{47,63,205},{46,60,2},{46,60,2},{45,55,25},{39,60,163},{41,55,1},{51,63,4},{51,63,4},{51,63,4},{51,57,4},{63,33,162},{46,60,1},{46,60,1},{42,55,0},{47,56,162}, +{42,55,0},{63,47,200},{52,63,13},{53,60,1},{45,60,1},{63,47,200},{63,55,200},{45,60,1},{0,57,208},{63,55,200},{0,57,208},{48,0,200},{48,0,200},{48,0,200},{48,0,200},{46,60,1},{46,60,1},{46,60,1},{46,53,1},{41,55,1},{41,55,1},{53,63,1026},{51,63,440},{51,63,312},{50,62,216},{51,63,1144},{48,63,280},{48,62,5},{47,59,298},{43,63,827},{42,59,217},{55,63,428}, +{54,63,100},{53,62,20},{52,61,36},{63,46,723},{49,63,266},{48,62,1},{40,59,208},{62,55,723},{40,59,208},{51,63,296},{51,63,296},{51,63,296},{50,61,201},{49,63,248},{48,62,5},{48,62,5},{47,57,25},{41,62,163},{43,57,1},{53,63,13},{53,63,13},{53,63,13},{53,59,4},{63,39,162},{48,62,1},{48,62,1},{44,57,0},{47,59,162},{44,57,0},{63,53,200},{55,63,53},{55,62,1}, +{47,62,1},{63,53,200},{63,58,200},{47,62,1},{0,59,208},{63,58,200},{0,59,208},{50,0,200},{50,0,200},{50,0,200},{50,0,200},{48,62,4},{48,62,4},{48,62,4},{48,55,4},{43,57,1},{43,57,1},{54,63,955},{54,63,523},{53,63,362},{52,63,202},{54,63,1027},{51,63,283},{50,63,14},{49,60,198},{47,63,735},{44,61,118},{57,63,338},{56,63,141},{56,63,41},{55,63,17},{63,51,546}, +{53,63,233},{51,63,2},{43,61,113},{63,57,546},{43,61,113},{53,63,362},{53,63,362},{53,63,362},{52,63,202},{51,63,315},{50,63,14},{50,63,14},{49,59,19},{44,63,171},{46,59,3},{56,63,41},{56,63,41},{56,63,41},{55,61,2},{61,49,162},{51,63,2},{51,63,2},{47,59,1},{63,54,162},{47,59,1},{63,57,113},{58,63,50},{57,63,1},{52,63,0},{63,57,113},{63,60,113},{52,63,0}, +{0,61,113},{63,60,113},{0,61,113},{52,0,202},{52,0,202},{52,0,202},{52,0,202},{50,63,5},{50,63,5},{50,63,5},{50,57,2},{45,60,0},{45,60,0},{57,63,779},{56,63,542},{56,63,442},{54,63,227},{56,63,830},{54,63,251},{53,63,78},{51,62,70},{51,63,587},{47,62,25},{59,63,218},{58,63,123},{58,63,74},{57,63,2},{63,55,333},{56,63,145},{55,63,25},{47,62,25},{63,59,333}, +{47,62,25},{56,63,442},{56,63,442},{56,63,442},{54,63,227},{54,63,371},{53,63,78},{53,63,78},{51,61,19},{48,63,219},{47,61,6},{58,63,74},{58,63,74},{58,63,74},{57,63,2},{63,51,162},{55,63,25},{55,63,25},{48,61,2},{63,57,162},{48,61,2},{63,60,25},{61,63,10},{60,63,1},{58,63,0},{63,60,25},{62,62,25},{58,63,0},{0,62,25},{62,62,25},{0,62,25},{54,0,202}, +{54,0,202},{54,0,202},{54,0,202},{52,63,26},{52,63,26},{52,63,26},{52,59,2},{47,62,0},{47,62,0},{59,63,684},{57,63,538},{57,63,474},{57,63,282},{57,63,682},{56,63,285},{55,63,171},{53,63,18},{54,63,482},{49,63,5},{60,63,153},{60,63,105},{60,63,89},{59,63,37},{63,59,193},{58,63,107},{58,63,58},{50,63,1},{63,61,193},{50,63,1},{57,63,474},{57,63,474},{57,63,474}, +{57,63,282},{57,63,426},{55,63,171},{55,63,171},{53,63,18},{52,63,278},{49,63,5},{60,63,89},{60,63,89},{60,63,89},{59,63,37},{63,57,145},{58,63,58},{58,63,58},{50,63,1},{63,60,145},{50,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{56,0,202},{56,0,202},{56,0,202},{56,0,202},{54,63,50}, +{54,63,50},{54,63,50},{54,61,2},{49,63,5},{49,63,5},{60,63,426},{59,63,375},{59,63,339},{58,63,251},{59,63,415},{57,63,202},{57,63,138},{56,63,2},{55,63,295},{53,63,29},{62,63,43},{62,63,38},{62,63,34},{61,63,10},{63,61,54},{61,63,27},{60,63,17},{56,63,1},{63,62,54},{56,63,1},{59,63,339},{59,63,339},{59,63,339},{58,63,251},{59,63,294},{57,63,138},{57,63,138}, +{56,63,2},{55,63,174},{53,63,29},{62,63,34},{62,63,34},{62,63,34},{61,63,10},{63,60,41},{60,63,17},{60,63,17},{56,63,1},{62,62,41},{56,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{58,0,202},{58,0,202},{58,0,202},{58,0,202},{57,63,74},{57,63,74},{57,63,74},{56,63,2},{53,63,29}, +{53,63,29},{0,20,421},{0,14,50},{0,10,4},{0,9,157},{0,14,925},{0,9,589},{0,8,264},{0,6,701},{0,6,1005},{0,5,738},{0,20,421},{0,14,50},{0,10,4},{0,9,157},{7,0,925},{0,9,589},{0,8,264},{0,6,701},{14,0,925},{0,6,701},{0,10,0},{0,10,0},{0,10,0},{0,5,0},{0,5,85},{0,4,34},{0,4,34},{0,2,50},{0,2,93},{0,2,54},{0,10,0}, +{0,10,0},{0,10,0},{0,5,0},{2,1,85},{0,4,34},{0,4,34},{0,2,50},{5,0,85},{0,2,50},{10,1,421},{0,14,50},{0,10,4},{0,9,157},{10,1,421},{20,0,421},{0,9,157},{0,7,421},{20,0,421},{0,7,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,26,421},{0,18,13},{0,13,20}, +{0,11,100},{0,18,1261},{0,11,701},{0,10,294},{0,7,857},{0,8,1382},{0,7,938},{0,26,421},{0,18,13},{0,13,20},{0,11,100},{9,0,1261},{0,11,701},{0,10,294},{0,7,857},{18,0,1261},{0,7,857},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{0,8,221},{0,6,89},{0,6,89},{0,4,125},{0,4,246},{0,4,150},{0,16,0},{0,16,0},{0,16,0},{0,8,0},{4,0,221}, +{0,6,89},{0,6,89},{0,4,125},{8,0,221},{0,4,125},{13,1,421},{0,18,13},{2,12,4},{0,11,100},{13,1,421},{26,0,421},{0,11,100},{0,9,421},{26,0,421},{0,9,421},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,32,430},{0,22,10},{1,15,70},{0,13,70},{0,22,1517},{0,14,730},{0,13,257}, +{0,9,974},{0,11,1713},{0,8,1109},{1,30,422},{1,21,5},{2,15,45},{0,13,70},{11,1,1514},{0,14,730},{0,13,257},{0,9,974},{15,4,1514},{0,9,974},{0,22,9},{0,22,9},{0,22,9},{0,11,9},{0,12,338},{0,9,106},{0,9,106},{0,5,181},{0,5,392},{0,5,217},{1,20,1},{1,20,1},{1,20,1},{1,10,2},{6,0,338},{0,9,106},{0,9,106},{0,5,181},{12,0,338}, +{0,5,181},{16,0,421},{0,22,1},{4,14,4},{0,13,61},{16,0,421},{32,0,421},{0,13,61},{0,11,421},{32,0,421},{0,11,421},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,2},{0,1,2},{1,36,486},{1,24,69},{2,17,163},{1,16,115},{0,28,1517},{0,18,614},{0,15,126},{0,11,857},{0,14,1841},{0,11,1053},{3,32,422}, +{3,23,5},{3,17,46},{2,15,70},{14,1,1514},{0,18,614},{0,15,126},{0,11,857},{15,7,1514},{0,11,857},{1,26,65},{1,26,65},{1,26,65},{1,13,66},{0,18,338},{0,13,45},{0,13,45},{0,8,125},{0,8,456},{0,7,211},{3,22,1},{3,22,1},{3,22,1},{3,12,2},{9,0,338},{0,13,45},{0,13,45},{0,8,125},{18,0,338},{0,8,125},{19,0,421},{2,24,1},{6,16,1}, +{0,16,37},{19,0,421},{38,0,421},{0,16,37},{0,13,421},{38,0,421},{0,13,421},{1,0,65},{1,0,65},{1,0,65},{1,0,65},{0,8,1},{0,8,1},{0,8,1},{0,4,1},{0,3,25},{0,3,25},{3,39,629},{3,27,213},{3,20,365},{2,18,237},{0,35,1514},{0,22,506},{0,18,24},{0,14,750},{0,16,2003},{0,13,1050},{5,35,421},{5,25,2},{6,19,45},{5,17,72},{17,1,1514}, +{0,22,506},{0,18,24},{0,14,750},{35,0,1514},{0,14,750},{3,28,209},{3,28,209},{3,28,209},{2,16,208},{0,25,338},{0,17,9},{0,17,9},{0,10,72},{0,11,566},{0,10,241},{5,24,1},{5,24,1},{5,24,1},{5,15,0},{12,1,338},{0,17,9},{0,17,9},{0,10,72},{25,0,338},{0,10,72},{22,1,421},{4,26,1},{8,18,5},{0,18,8},{22,1,421},{45,0,421},{0,18,8}, +{0,15,421},{45,0,421},{0,15,421},{2,0,208},{2,0,208},{2,0,208},{2,0,208},{0,15,0},{0,15,0},{0,15,0},{0,8,1},{0,6,80},{0,6,80},{4,43,821},{4,30,418},{5,22,621},{3,20,420},{0,41,1514},{0,25,450},{0,20,5},{0,16,670},{0,19,2187},{0,15,1109},{7,37,421},{7,27,2},{8,21,45},{7,19,72},{20,1,1514},{0,25,450},{0,20,5},{0,16,670},{41,0,1514}, +{0,16,670},{4,32,400},{4,32,400},{4,32,400},{4,18,400},{0,31,338},{0,20,1},{0,20,1},{0,13,40},{0,14,694},{0,11,297},{7,26,1},{7,26,1},{7,26,1},{7,17,1},{15,1,338},{0,20,1},{0,20,1},{0,13,40},{31,0,338},{0,13,40},{25,1,421},{6,28,1},{10,20,5},{0,20,4},{25,1,421},{51,0,421},{0,20,4},{0,17,421},{51,0,421},{0,17,421},{3,0,400}, +{3,0,400},{3,0,400},{3,0,400},{0,21,0},{0,21,0},{0,21,0},{0,11,1},{0,8,149},{0,8,149},{5,47,846},{6,32,451},{6,23,662},{5,22,445},{2,43,1515},{1,28,446},{2,22,6},{0,18,638},{0,22,2046},{0,18,878},{9,39,421},{9,29,2},{10,23,45},{9,21,72},{23,1,1514},{0,28,426},{2,22,5},{0,18,589},{47,0,1514},{0,18,589},{5,36,425},{5,36,425},{5,36,425}, +{5,21,426},{2,32,341},{2,22,2},{2,22,2},{1,15,38},{0,16,606},{0,14,158},{9,28,1},{9,28,1},{9,28,1},{9,19,1},{15,7,338},{2,22,1},{2,22,1},{0,15,20},{31,3,338},{0,15,20},{28,1,421},{8,30,1},{12,22,5},{2,22,4},{28,1,421},{57,0,421},{2,22,4},{0,19,421},{57,0,421},{0,19,421},{5,0,425},{5,0,425},{5,0,425},{5,0,425},{2,23,1}, +{2,23,1},{2,23,1},{2,13,2},{0,12,97},{0,12,97},{7,49,846},{8,33,450},{8,25,662},{7,24,445},{4,45,1515},{3,30,446},{4,24,6},{2,20,638},{0,25,1886},{0,19,682},{11,41,421},{11,31,2},{12,25,45},{11,23,72},{26,1,1514},{1,31,421},{4,24,5},{0,20,545},{53,0,1514},{0,20,545},{7,38,425},{7,38,425},{7,38,425},{7,23,426},{4,34,341},{4,24,2},{4,24,2}, +{4,16,42},{0,20,500},{0,16,62},{11,30,1},{11,30,1},{11,30,1},{11,21,1},{15,13,338},{4,24,1},{4,24,1},{0,17,5},{31,6,338},{0,17,5},{31,1,421},{10,32,1},{14,24,5},{4,24,4},{31,1,421},{63,0,421},{4,24,4},{0,21,421},{63,0,421},{0,21,421},{7,0,425},{7,0,425},{7,0,425},{7,0,425},{4,25,1},{4,25,1},{4,25,1},{4,15,2},{0,16,37}, +{0,16,37},{10,49,846},{10,36,445},{11,28,650},{10,26,450},{6,47,1517},{5,32,446},{6,27,3},{4,22,646},{0,29,1751},{0,22,522},{13,44,422},{13,34,3},{14,27,46},{13,26,74},{30,0,1514},{3,33,422},{6,27,3},{0,22,497},{46,7,1514},{0,22,497},{10,39,425},{10,39,425},{10,39,425},{10,24,426},{6,37,338},{6,27,2},{6,27,2},{6,19,40},{0,24,410},{0,19,9},{13,33,1}, +{13,33,1},{13,33,1},{13,23,1},{24,1,338},{7,26,0},{7,26,0},{1,19,5},{49,0,338},{1,19,5},{35,0,421},{12,34,1},{16,27,1},{5,27,1},{35,0,421},{63,3,421},{5,27,1},{0,23,421},{63,3,421},{0,23,421},{10,0,425},{10,0,425},{10,0,425},{10,0,425},{6,28,0},{6,28,0},{6,28,0},{6,17,1},{0,19,5},{0,19,5},{12,51,846},{12,38,445},{13,30,650}, +{12,28,450},{8,49,1517},{7,34,446},{8,29,3},{6,24,646},{0,32,1647},{0,25,458},{15,46,422},{15,36,3},{16,29,42},{15,28,74},{32,1,1514},{5,35,422},{8,29,3},{0,25,457},{46,10,1514},{0,25,457},{12,41,425},{12,41,425},{12,41,425},{12,26,426},{8,39,338},{8,29,2},{8,29,2},{8,21,40},{0,27,362},{1,22,5},{15,35,1},{15,35,1},{15,35,1},{15,25,1},{27,1,338}, +{9,28,0},{9,28,0},{3,21,5},{55,0,338},{3,21,5},{38,0,421},{14,36,1},{18,29,1},{7,29,1},{38,0,421},{63,6,421},{7,29,1},{0,25,421},{63,6,421},{0,25,421},{12,0,425},{12,0,425},{12,0,425},{12,0,425},{8,30,0},{8,30,0},{8,30,0},{8,19,1},{1,22,1},{1,22,1},{14,53,846},{14,40,445},{15,32,661},{14,30,450},{10,51,1517},{9,36,446},{10,31,3}, +{8,26,646},{0,35,1575},{0,27,446},{17,47,421},{17,37,2},{18,31,42},{17,30,73},{35,1,1514},{7,37,422},{10,31,3},{0,27,430},{46,13,1514},{0,27,430},{14,43,425},{14,43,425},{14,43,425},{14,28,426},{10,41,338},{10,31,2},{10,31,2},{10,23,40},{0,31,341},{3,24,5},{17,36,1},{17,36,1},{17,36,1},{17,27,0},{30,1,338},{11,30,0},{11,30,0},{5,23,5},{61,0,338}, +{5,23,5},{41,0,421},{16,38,1},{20,31,1},{9,31,1},{41,0,421},{63,9,421},{9,31,1},{0,27,421},{63,9,421},{0,27,421},{14,0,425},{14,0,425},{14,0,425},{14,0,425},{10,31,1},{10,31,1},{10,31,1},{10,21,1},{3,24,1},{3,24,1},{16,55,854},{16,42,451},{16,33,662},{15,32,446},{12,53,1517},{11,38,446},{12,32,9},{10,28,646},{0,39,1533},{2,29,446},{19,49,421}, +{19,39,2},{20,33,45},{18,31,81},{38,1,1514},{9,39,422},{13,32,6},{0,29,422},{45,16,1514},{0,29,422},{15,47,433},{15,47,433},{15,47,433},{15,31,433},{12,43,338},{12,32,5},{12,32,5},{12,25,40},{1,33,339},{5,26,5},{19,38,1},{19,38,1},{19,38,1},{19,29,0},{33,1,338},{13,32,2},{13,32,2},{7,25,5},{63,2,338},{7,25,5},{44,0,421},{18,40,1},{22,32,5}, +{12,32,5},{44,0,421},{63,12,421},{12,32,5},{0,29,421},{63,12,421},{0,29,421},{15,0,433},{15,0,433},{15,0,433},{15,0,433},{12,33,1},{12,33,1},{12,33,1},{12,23,1},{5,26,1},{5,26,1},{18,58,846},{18,44,445},{19,36,650},{18,34,450},{14,56,1515},{14,40,447},{14,35,7},{13,31,646},{0,42,1515},{5,31,445},{21,52,422},{21,42,2},{22,35,46},{21,34,74},{42,0,1514}, +{12,41,422},{14,35,6},{2,31,425},{62,11,1514},{2,31,425},{18,47,425},{18,47,425},{18,47,425},{18,32,426},{14,46,339},{14,35,6},{14,35,6},{14,27,35},{4,35,341},{8,28,5},{21,41,1},{21,41,1},{21,41,1},{21,31,2},{31,12,338},{15,34,0},{15,34,0},{8,28,1},{62,6,338},{8,28,1},{47,0,421},{21,42,1},{24,35,1},{13,35,1},{47,0,421},{62,16,421},{13,35,1}, +{0,31,425},{62,16,421},{0,31,425},{18,0,425},{18,0,425},{18,0,425},{18,0,425},{14,36,1},{14,36,1},{14,36,1},{14,25,1},{7,29,1},{7,29,1},{20,60,846},{20,46,445},{21,38,650},{20,36,450},{16,58,1514},{16,41,449},{16,37,3},{15,32,630},{2,44,1515},{7,33,441},{23,54,422},{23,44,2},{24,37,46},{23,36,74},{45,0,1514},{14,43,422},{16,37,3},{4,33,421},{62,14,1514}, +{4,33,421},{20,49,425},{20,49,425},{20,49,425},{20,34,426},{16,47,340},{16,37,2},{16,37,2},{16,29,34},{6,37,341},{10,30,5},{23,43,1},{23,43,1},{23,43,1},{23,33,1},{31,18,338},{17,36,0},{17,36,0},{10,30,1},{62,9,338},{10,30,1},{50,0,421},{23,44,1},{26,37,1},{15,37,1},{50,0,421},{62,19,421},{15,37,1},{0,33,421},{62,19,421},{0,33,421},{20,0,425}, +{20,0,425},{20,0,425},{20,0,425},{16,38,0},{16,38,0},{16,38,0},{16,27,0},{9,31,1},{9,31,1},{22,62,846},{22,48,445},{23,40,650},{22,38,450},{18,60,1514},{18,43,449},{18,39,3},{16,34,646},{4,46,1515},{9,35,441},{25,56,422},{25,46,2},{26,39,46},{25,38,74},{47,2,1514},{16,45,425},{18,39,3},{6,35,421},{62,17,1514},{6,35,421},{22,51,425},{22,51,425},{22,51,425}, +{22,36,426},{18,49,338},{18,39,2},{18,39,2},{18,31,34},{8,39,341},{11,32,6},{25,45,1},{25,45,1},{25,45,1},{25,35,1},{34,17,338},{19,38,0},{19,38,0},{12,32,4},{62,12,338},{12,32,4},{53,0,421},{25,46,1},{28,39,1},{17,39,1},{53,0,421},{62,22,421},{17,39,1},{0,35,421},{62,22,421},{0,35,421},{22,0,425},{22,0,425},{22,0,425},{22,0,425},{18,40,0}, +{18,40,0},{18,40,0},{18,29,0},{11,32,2},{11,32,2},{24,63,850},{24,50,445},{25,42,650},{24,40,450},{20,62,1514},{20,45,449},{20,41,3},{18,36,646},{6,48,1517},{11,37,441},{27,58,422},{27,48,3},{28,41,46},{27,40,74},{47,8,1514},{18,47,425},{20,41,3},{8,37,421},{62,20,1514},{8,37,421},{24,53,425},{24,53,425},{24,53,425},{24,38,426},{20,51,338},{20,41,2},{20,41,2}, +{20,33,40},{10,41,341},{13,34,6},{27,47,1},{27,47,1},{27,47,1},{27,37,1},{37,17,338},{21,40,0},{21,40,0},{14,34,4},{62,15,338},{14,34,4},{56,0,421},{26,48,1},{30,41,1},{19,41,1},{56,0,421},{62,25,421},{19,41,1},{0,37,421},{62,25,421},{0,37,421},{24,0,425},{24,0,425},{24,0,425},{24,0,425},{20,42,0},{20,42,0},{20,42,0},{20,31,0},{13,34,2}, +{13,34,2},{26,63,882},{26,52,447},{27,44,646},{26,42,446},{23,62,1526},{22,48,447},{22,43,5},{21,39,646},{8,50,1515},{13,39,443},{30,58,425},{29,50,4},{30,44,45},{29,42,69},{54,0,1514},{20,49,422},{22,43,4},{10,39,426},{47,31,1514},{10,39,426},{26,56,421},{26,56,421},{26,56,421},{26,41,421},{22,54,339},{22,43,5},{22,43,5},{22,35,35},{12,43,338},{16,36,5},{30,48,4}, +{30,48,4},{30,48,4},{30,39,4},{49,0,338},{23,42,2},{23,42,2},{16,36,1},{62,18,338},{16,36,1},{59,0,421},{29,50,0},{32,43,1},{22,43,0},{59,0,421},{62,28,421},{22,43,0},{0,39,425},{62,28,421},{0,39,425},{26,0,421},{26,0,421},{26,0,421},{26,0,421},{22,44,2},{22,44,2},{22,44,2},{22,33,1},{15,37,1},{15,37,1},{29,63,922},{28,54,447},{29,46,646}, +{28,44,446},{25,63,1535},{24,50,447},{24,45,5},{23,41,646},{10,52,1515},{15,41,443},{31,62,425},{31,52,4},{32,45,45},{31,44,69},{57,0,1514},{22,51,422},{24,45,4},{12,41,426},{50,32,1514},{12,41,426},{28,58,421},{28,58,421},{28,58,421},{28,43,421},{24,56,339},{24,45,5},{24,45,5},{24,37,35},{14,45,338},{18,38,5},{31,52,4},{31,52,4},{31,52,4},{31,41,5},{52,0,338}, +{25,44,2},{25,44,2},{18,38,1},{62,21,338},{18,38,1},{62,0,421},{31,52,0},{34,45,1},{24,45,0},{62,0,421},{62,31,421},{24,45,0},{0,41,425},{62,31,421},{0,41,425},{28,0,421},{28,0,421},{28,0,421},{28,0,421},{24,46,2},{24,46,2},{24,46,2},{24,35,1},{17,39,1},{17,39,1},{31,63,994},{30,56,447},{31,48,655},{30,46,446},{28,63,1575},{26,52,447},{26,47,5}, +{25,43,646},{12,54,1515},{17,43,445},{33,63,426},{33,54,2},{34,47,45},{33,46,66},{60,0,1514},{24,53,422},{26,47,4},{14,43,426},{56,32,1514},{14,43,426},{30,60,421},{30,60,421},{30,60,421},{30,45,421},{26,58,339},{26,47,5},{26,47,5},{26,39,35},{16,47,338},{20,40,5},{33,53,1},{33,53,1},{33,53,1},{33,43,2},{55,0,338},{27,46,2},{27,46,2},{20,40,1},{62,24,338}, +{20,40,1},{63,4,421},{33,54,1},{36,47,1},{26,47,0},{63,4,421},{62,34,421},{26,47,0},{0,43,425},{62,34,421},{0,43,425},{30,0,421},{30,0,421},{30,0,421},{30,0,421},{26,48,1},{26,48,1},{26,48,1},{26,37,1},{19,41,1},{19,41,1},{33,63,1082},{32,58,445},{33,50,650},{32,48,450},{30,63,1638},{28,54,447},{28,49,7},{27,45,646},{14,56,1515},{19,45,445},{36,63,434}, +{35,56,2},{36,49,46},{35,48,74},{63,0,1514},{26,55,422},{28,49,6},{16,45,425},{62,32,1514},{16,45,425},{32,61,425},{32,61,425},{32,61,425},{32,47,426},{28,60,339},{28,49,6},{28,49,6},{28,41,35},{18,49,341},{22,42,5},{35,55,1},{35,55,1},{35,55,1},{35,45,2},{58,0,338},{29,48,0},{29,48,0},{22,42,1},{62,27,338},{22,42,1},{63,10,421},{35,56,1},{38,49,1}, +{27,49,1},{63,10,421},{62,37,421},{27,49,1},{0,45,425},{62,37,421},{0,45,425},{32,0,425},{32,0,425},{32,0,425},{32,0,425},{28,50,1},{28,50,1},{28,50,1},{28,39,1},{21,43,1},{21,43,1},{36,63,1206},{34,61,446},{35,52,646},{34,50,446},{33,63,1710},{30,56,445},{31,51,5},{29,47,638},{17,58,1515},{22,47,450},{39,63,469},{37,58,5},{38,52,45},{37,50,69},{63,7,1514}, +{27,58,422},{31,51,1},{19,47,433},{63,35,1514},{19,47,433},{34,63,422},{34,63,422},{34,63,422},{34,49,421},{31,61,342},{31,51,5},{31,51,5},{30,43,36},{20,51,338},{24,44,2},{38,56,4},{38,56,4},{38,56,4},{38,47,4},{53,16,338},{31,51,1},{31,51,1},{25,44,0},{63,30,338},{25,44,0},{63,17,421},{37,58,1},{40,51,1},{30,51,0},{63,17,421},{63,40,421},{30,51,0}, +{0,47,433},{63,40,421},{0,47,433},{34,0,421},{34,0,421},{34,0,421},{34,0,421},{31,51,4},{31,51,4},{31,51,4},{31,41,4},{23,45,1},{23,45,1},{38,63,1350},{36,63,446},{37,54,646},{36,52,446},{36,63,1814},{32,58,447},{32,53,5},{31,48,638},{19,60,1515},{23,49,443},{41,63,517},{39,60,5},{40,54,45},{39,52,69},{63,13,1514},{29,60,422},{32,53,4},{20,49,426},{63,38,1514}, +{20,49,426},{36,63,437},{36,63,437},{36,63,437},{36,51,421},{33,62,347},{32,53,5},{32,53,5},{32,45,33},{22,53,338},{26,46,2},{40,58,4},{40,58,4},{40,58,4},{40,49,4},{56,16,338},{33,52,2},{33,52,2},{27,46,0},{62,33,338},{27,46,0},{63,23,421},{39,60,1},{42,53,1},{32,53,0},{63,23,421},{63,43,421},{32,53,0},{0,49,425},{63,43,421},{0,49,425},{36,0,421}, +{36,0,421},{36,0,421},{36,0,421},{32,54,2},{32,54,2},{32,54,2},{32,43,2},{25,47,1},{25,47,1},{40,63,1466},{38,63,474},{39,56,646},{38,54,446},{38,63,1931},{34,60,447},{34,55,5},{33,51,646},{21,62,1515},{25,51,443},{43,63,569},{41,62,5},{42,56,45},{41,54,69},{63,19,1514},{32,61,422},{34,55,4},{22,51,426},{63,41,1514},{22,51,426},{38,63,470},{38,63,470},{38,63,470}, +{38,53,421},{35,63,355},{34,55,5},{34,55,5},{34,47,33},{24,55,338},{28,48,3},{42,60,4},{42,60,4},{42,60,4},{42,51,4},{59,16,338},{35,54,2},{35,54,2},{28,48,2},{62,36,338},{28,48,2},{63,29,421},{41,62,1},{44,55,1},{34,55,0},{63,29,421},{63,46,421},{34,55,0},{0,51,425},{63,46,421},{0,51,425},{38,0,421},{38,0,421},{38,0,421},{38,0,421},{34,56,2}, +{34,56,2},{34,56,2},{34,45,2},{27,49,1},{27,49,1},{43,63,1634},{41,63,546},{41,58,646},{40,56,446},{40,63,2039},{36,62,447},{36,57,5},{35,53,646},{24,63,1521},{27,53,443},{46,63,633},{44,63,9},{44,58,45},{43,56,69},{63,25,1514},{34,63,422},{36,57,4},{24,53,426},{63,44,1514},{24,53,426},{40,63,502},{40,63,502},{40,63,502},{40,55,421},{37,63,379},{36,57,5},{36,57,5}, +{36,49,35},{26,57,338},{30,50,3},{44,62,4},{44,62,4},{44,62,4},{44,53,4},{62,16,338},{37,56,2},{37,56,2},{30,50,2},{62,39,338},{30,50,2},{63,34,421},{44,63,5},{46,57,1},{36,57,0},{63,34,421},{62,49,421},{36,57,0},{0,53,425},{62,49,421},{0,53,425},{40,0,421},{40,0,421},{40,0,421},{40,0,421},{36,58,2},{36,58,2},{36,58,2},{36,47,2},{29,51,1}, +{29,51,1},{45,63,1866},{43,63,689},{43,60,650},{42,59,447},{43,63,2201},{38,63,469},{39,59,6},{37,55,638},{29,63,1590},{30,55,450},{48,63,741},{46,63,69},{46,60,46},{45,58,70},{62,33,1514},{38,63,465},{39,59,2},{25,56,425},{61,48,1514},{25,56,425},{43,63,545},{43,63,545},{43,63,545},{42,57,422},{40,63,424},{39,59,5},{39,59,5},{38,51,36},{29,59,339},{32,52,2},{46,63,5}, +{46,63,5},{46,63,5},{46,55,2},{63,21,338},{39,59,1},{39,59,1},{33,52,0},{63,42,338},{33,52,0},{63,41,421},{48,63,41},{49,59,2},{38,59,2},{63,41,421},{63,52,421},{38,59,2},{0,56,425},{63,52,421},{0,56,425},{42,0,421},{42,0,421},{42,0,421},{42,0,421},{39,59,4},{39,59,4},{39,59,4},{39,49,4},{31,53,1},{31,53,1},{48,63,2070},{46,63,889},{45,62,650}, +{44,61,447},{46,63,2361},{41,63,573},{41,61,6},{39,57,638},{32,63,1710},{32,57,450},{51,63,837},{49,63,184},{48,62,49},{47,60,70},{63,37,1514},{43,63,545},{41,61,2},{27,58,425},{63,50,1514},{27,58,425},{45,63,614},{45,63,614},{45,63,614},{44,59,422},{43,63,488},{41,61,5},{41,61,5},{40,53,36},{31,61,339},{34,54,2},{48,63,20},{48,63,20},{48,63,20},{48,57,4},{63,27,338}, +{41,61,1},{41,61,1},{35,54,0},{63,45,338},{35,54,0},{63,47,421},{51,63,97},{51,61,2},{40,61,2},{63,47,421},{63,55,421},{40,61,2},{0,58,425},{63,55,421},{0,58,425},{44,0,421},{44,0,421},{44,0,421},{44,0,421},{41,61,4},{41,61,4},{41,61,4},{41,51,4},{33,55,1},{33,55,1},{50,63,2239},{48,63,1109},{47,63,701},{46,62,441},{48,63,2469},{44,63,720},{43,63,5}, +{41,59,605},{37,63,1804},{34,59,417},{54,63,916},{51,63,308},{51,63,52},{49,62,56},{63,43,1459},{46,63,618},{43,63,1},{31,59,400},{63,53,1459},{31,59,400},{47,63,701},{47,63,701},{47,63,701},{46,61,422},{45,63,566},{43,63,5},{43,63,5},{42,55,36},{32,63,341},{36,56,2},{51,63,52},{51,63,52},{51,63,52},{50,59,4},{63,33,338},{43,63,1},{43,63,1},{37,56,0},{47,56,338}, +{37,56,0},{63,53,392},{55,63,157},{53,63,1},{42,63,1},{63,53,392},{63,58,392},{42,63,1},{0,59,400},{63,58,392},{0,59,400},{46,0,421},{46,0,421},{46,0,421},{46,0,421},{43,63,4},{43,63,4},{43,63,4},{43,53,4},{35,57,1},{35,57,1},{51,63,1901},{50,63,1114},{49,63,785},{48,63,421},{51,63,2093},{46,63,574},{45,63,38},{44,60,356},{40,63,1476},{36,60,213},{55,63,684}, +{54,63,260},{53,63,85},{51,63,20},{63,47,1064},{49,63,426},{47,63,8},{35,60,208},{63,55,1064},{35,60,208},{49,63,785},{49,63,785},{49,63,785},{48,63,421},{48,63,661},{45,63,38},{45,63,38},{44,57,36},{37,63,371},{38,58,2},{53,63,85},{53,63,85},{53,63,85},{52,61,4},{63,39,338},{47,63,8},{47,63,8},{39,58,0},{47,59,338},{39,58,0},{63,56,200},{57,63,80},{56,63,1}, +{48,63,0},{63,56,200},{62,60,200},{48,63,0},{0,60,208},{62,60,200},{0,60,208},{48,0,421},{48,0,421},{48,0,421},{48,0,421},{45,63,13},{45,63,13},{45,63,13},{45,55,4},{37,59,1},{37,59,1},{54,63,1646},{52,63,1119},{51,63,886},{50,63,470},{53,63,1761},{48,63,526},{48,63,126},{46,61,146},{44,63,1218},{39,62,69},{57,63,450},{56,63,245},{56,63,145},{54,63,2},{63,51,722}, +{52,63,290},{51,63,50},{38,62,65},{63,57,722},{38,62,65},{51,63,886},{51,63,886},{51,63,886},{50,63,470},{50,63,776},{48,63,126},{48,63,126},{47,59,42},{41,63,446},{40,60,5},{56,63,145},{56,63,145},{56,63,145},{54,63,2},{61,49,338},{51,63,50},{51,63,50},{42,60,1},{63,54,338},{42,60,1},{63,59,61},{60,63,25},{59,63,0},{55,63,0},{63,59,61},{63,61,61},{55,63,0}, +{0,62,65},{63,61,61},{0,62,65},{50,0,421},{50,0,421},{50,0,421},{50,0,421},{48,63,45},{48,63,45},{48,63,45},{47,57,2},{40,61,1},{40,61,1},{56,63,1518},{54,63,1118},{54,63,974},{52,63,565},{54,63,1526},{51,63,534},{51,63,278},{48,62,57},{47,63,1090},{42,63,10},{59,63,354},{58,63,251},{57,63,194},{56,63,50},{63,55,509},{55,63,234},{54,63,106},{42,63,9},{63,59,509}, +{42,63,9},{54,63,974},{54,63,974},{54,63,974},{52,63,565},{53,63,904},{51,63,278},{51,63,278},{48,61,38},{44,63,574},{42,62,5},{57,63,194},{57,63,194},{57,63,194},{56,63,50},{63,51,338},{54,63,106},{54,63,106},{44,62,1},{63,57,338},{44,62,1},{63,62,5},{62,63,4},{62,63,0},{61,63,0},{63,62,5},{62,63,5},{61,63,0},{0,63,9},{62,63,5},{0,63,9},{52,0,421}, +{52,0,421},{52,0,421},{52,0,421},{50,63,72},{50,63,72},{50,63,72},{49,59,5},{42,63,1},{42,63,1},{57,63,1197},{56,63,994},{56,63,894},{54,63,565},{56,63,1210},{54,63,493},{53,63,332},{50,63,13},{51,63,861},{45,63,17},{60,63,209},{60,63,161},{60,63,145},{58,63,50},{63,58,294},{58,63,147},{57,63,89},{47,63,1},{62,61,294},{47,63,1},{56,63,894},{56,63,894},{56,63,894}, +{54,63,565},{54,63,781},{53,63,332},{53,63,332},{50,63,13},{48,63,501},{45,63,17},{60,63,145},{60,63,145},{60,63,145},{58,63,50},{63,55,221},{57,63,89},{57,63,89},{47,63,1},{63,59,221},{47,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{54,0,421},{54,0,421},{54,0,421},{54,0,421},{52,63,117}, +{52,63,117},{52,63,117},{51,61,5},{45,63,17},{45,63,17},{58,63,925},{57,63,765},{57,63,701},{57,63,509},{57,63,845},{55,63,423},{54,63,301},{53,63,5},{52,63,598},{49,63,52},{61,63,97},{61,63,70},{61,63,61},{60,63,17},{63,60,113},{60,63,57},{59,63,40},{53,63,1},{62,62,113},{53,63,1},{57,63,701},{57,63,701},{57,63,701},{57,63,509},{57,63,589},{54,63,301},{54,63,301}, +{53,63,5},{51,63,365},{49,63,52},{61,63,61},{61,63,61},{61,63,61},{60,63,17},{63,58,85},{59,63,40},{59,63,40},{53,63,1},{62,61,85},{53,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{56,0,421},{56,0,421},{56,0,421},{56,0,421},{54,63,157},{54,63,157},{54,63,157},{53,63,5},{49,63,52}, +{49,63,52},{0,29,882},{0,21,116},{0,15,4},{0,13,320},{0,19,1899},{0,14,1214},{0,11,573},{0,8,1421},{0,9,2052},{0,8,1521},{0,29,882},{0,21,116},{0,15,4},{0,13,320},{10,0,1896},{0,14,1214},{0,11,573},{0,8,1421},{14,3,1896},{0,8,1421},{0,14,0},{0,14,0},{0,14,0},{0,7,0},{0,7,162},{0,5,61},{0,5,61},{0,3,100},{0,3,180},{0,3,116},{0,14,0}, +{0,14,0},{0,14,0},{0,7,0},{3,1,162},{0,5,61},{0,5,61},{0,3,100},{7,0,162},{0,3,100},{6,17,882},{0,21,116},{0,15,4},{0,13,320},{6,17,882},{29,0,882},{0,13,320},{0,10,884},{29,0,882},{0,10,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,35,882},{0,25,50},{0,17,10}, +{0,15,260},{0,23,2355},{0,16,1355},{0,14,589},{0,10,1656},{0,11,2567},{0,10,1825},{0,35,882},{0,25,50},{0,17,10},{0,15,260},{3,17,2355},{0,16,1355},{0,14,589},{0,10,1656},{23,0,2355},{0,10,1656},{0,19,1},{0,19,1},{0,19,1},{0,10,0},{0,10,338},{0,8,125},{0,8,125},{0,4,200},{0,5,374},{0,4,225},{0,19,1},{0,19,1},{0,19,1},{0,10,0},{5,0,338}, +{0,8,125},{0,8,125},{0,4,200},{10,0,338},{0,4,200},{17,1,882},{0,25,50},{1,17,2},{0,15,260},{17,1,882},{35,0,882},{0,15,260},{0,12,884},{35,0,882},{0,12,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,41,882},{0,28,10},{1,19,69},{0,17,193},{0,28,2899},{0,19,1539},{0,16,643}, +{0,11,1965},{0,13,3209},{0,11,2161},{0,41,882},{0,28,10},{1,19,53},{0,17,193},{14,0,2899},{0,19,1539},{0,16,643},{0,11,1965},{28,0,2899},{0,11,1965},{0,25,1},{0,25,1},{0,25,1},{0,13,0},{0,13,578},{0,11,221},{0,11,221},{0,6,356},{0,6,644},{0,5,401},{0,25,1},{0,25,1},{0,25,1},{0,13,0},{6,1,578},{0,11,221},{0,11,221},{0,6,356},{13,0,578}, +{0,6,356},{20,1,882},{0,28,10},{3,19,2},{0,17,193},{20,1,882},{41,0,882},{0,17,193},{0,14,884},{41,0,882},{0,14,884},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,45,902},{1,31,24},{1,21,142},{0,19,166},{0,33,3048},{0,22,1443},{0,18,481},{0,13,1908},{0,16,3492},{0,13,2197},{2,43,886}, +{1,31,8},{3,21,73},{1,19,153},{16,1,3048},{0,22,1443},{0,18,481},{0,13,1908},{33,0,3048},{0,13,1908},{1,29,21},{1,29,21},{1,29,21},{1,15,21},{0,18,648},{0,14,169},{0,14,169},{0,8,325},{0,8,766},{0,7,421},{2,27,5},{2,27,5},{2,27,5},{2,15,4},{9,0,648},{0,14,169},{0,14,169},{0,8,325},{18,0,648},{0,8,325},{23,1,882},{0,31,2},{5,21,2}, +{0,19,130},{23,1,882},{47,0,882},{0,19,130},{0,16,890},{47,0,882},{0,16,890},{1,0,20},{1,0,20},{1,0,20},{1,0,20},{0,5,0},{0,5,0},{0,5,0},{0,2,1},{0,2,5},{0,2,5},{2,49,997},{2,34,114},{3,24,290},{1,22,234},{0,39,3051},{0,25,1256},{0,21,258},{0,16,1764},{0,19,3685},{0,15,2195},{4,46,883},{3,33,10},{5,23,74},{3,21,154},{15,10,3048}, +{0,25,1256},{0,21,258},{0,16,1764},{30,5,3048},{0,16,1764},{2,34,113},{2,34,113},{2,34,113},{2,18,113},{0,25,648},{0,17,89},{0,17,89},{0,10,242},{0,11,876},{0,10,411},{4,30,1},{4,30,1},{4,30,1},{4,17,1},{12,1,648},{0,17,89},{0,17,89},{0,10,242},{25,0,648},{0,10,242},{27,0,882},{3,33,1},{8,23,1},{0,22,80},{27,0,882},{46,4,882},{0,22,80}, +{0,18,884},{46,4,882},{0,18,884},{2,0,113},{2,0,113},{2,0,113},{2,0,113},{0,11,1},{0,11,1},{0,11,1},{0,6,1},{0,5,40},{0,5,40},{3,53,1149},{3,36,274},{4,27,513},{3,24,362},{0,45,3051},{0,28,1128},{0,24,122},{0,18,1605},{0,22,3901},{0,16,2173},{6,47,885},{5,35,10},{7,25,74},{5,23,154},{15,16,3048},{0,28,1128},{0,24,122},{0,18,1605},{30,8,3048}, +{0,18,1605},{3,38,265},{3,38,265},{3,38,265},{3,20,266},{0,31,648},{0,21,34},{0,21,34},{0,13,170},{0,14,1004},{0,11,457},{6,32,1},{6,32,1},{6,32,1},{6,19,1},{15,1,648},{0,21,34},{0,21,34},{0,13,170},{31,0,648},{0,13,170},{30,0,882},{5,35,1},{10,25,1},{0,24,41},{30,0,882},{46,7,882},{0,24,41},{0,20,884},{46,7,882},{0,20,884},{3,0,265}, +{3,0,265},{3,0,265},{3,0,265},{0,17,0},{0,17,0},{0,17,0},{0,9,1},{0,8,104},{0,8,104},{4,57,1365},{4,39,498},{5,28,793},{4,26,561},{0,51,3048},{0,31,1032},{0,26,41},{0,20,1509},{0,24,4147},{0,19,2149},{8,49,885},{7,37,10},{9,27,74},{7,25,154},{17,17,3048},{0,31,1032},{0,26,41},{0,20,1509},{51,0,3048},{0,20,1509},{4,42,481},{4,42,481},{4,42,481}, +{4,23,481},{0,36,650},{0,25,4},{0,25,4},{0,15,130},{0,16,1161},{0,14,481},{8,34,1},{8,34,1},{8,34,1},{8,21,1},{15,7,648},{0,25,4},{0,25,4},{0,15,130},{31,3,648},{0,15,130},{32,1,882},{7,37,1},{12,27,1},{0,26,25},{32,1,882},{46,10,882},{0,26,25},{0,22,884},{46,10,882},{0,22,884},{4,0,481},{4,0,481},{4,0,481},{4,0,481},{0,23,0}, +{0,23,0},{0,23,0},{0,12,1},{0,9,193},{0,9,193},{5,61,1645},{5,42,795},{7,30,1177},{4,28,826},{0,57,3048},{0,35,954},{0,29,9},{0,22,1380},{0,27,4419},{0,21,2197},{10,51,885},{9,39,10},{11,29,74},{9,27,154},{20,17,3048},{0,35,954},{0,29,9},{0,22,1380},{57,0,3048},{0,22,1380},{5,46,761},{5,46,761},{5,46,761},{5,25,762},{0,42,650},{0,28,4},{0,28,4}, +{0,17,85},{0,19,1345},{0,16,557},{10,36,1},{10,36,1},{10,36,1},{10,23,1},{15,13,648},{1,27,1},{1,27,1},{0,17,85},{31,6,648},{0,17,85},{35,1,882},{9,39,1},{14,29,1},{0,29,9},{35,1,882},{46,13,882},{0,29,9},{0,24,884},{46,13,882},{0,24,884},{5,0,761},{5,0,761},{5,0,761},{5,0,761},{0,29,0},{0,29,0},{0,29,0},{0,15,1},{0,11,296}, +{0,11,296},{7,63,1774},{7,44,924},{8,33,1320},{6,30,941},{2,60,3052},{1,38,924},{2,31,10},{0,24,1302},{0,31,4300},{0,24,1942},{12,54,882},{12,40,8},{13,32,68},{11,29,161},{32,0,3048},{0,39,898},{2,31,6},{0,24,1266},{62,1,3048},{0,24,1266},{7,48,885},{7,48,885},{7,48,885},{7,28,884},{2,45,652},{2,31,9},{2,31,9},{1,20,62},{0,22,1275},{0,19,419},{12,39,0}, +{12,39,0},{12,39,0},{12,25,1},{24,1,648},{3,30,0},{3,30,0},{0,20,45},{49,0,648},{0,20,45},{39,0,882},{11,41,1},{16,31,2},{1,31,1},{39,0,882},{62,8,882},{1,31,1},{0,26,882},{62,8,882},{0,26,882},{7,0,884},{7,0,884},{7,0,884},{7,0,884},{2,32,4},{2,32,4},{2,32,4},{2,17,4},{0,16,250},{0,16,250},{9,63,1798},{9,46,924},{10,35,1320}, +{9,32,936},{4,62,3052},{3,40,924},{4,33,9},{2,26,1302},{0,33,4023},{0,26,1647},{14,56,882},{14,42,8},{15,34,68},{13,31,161},{35,0,3048},{0,42,882},{4,33,5},{0,27,1170},{62,4,3048},{0,27,1170},{9,50,885},{9,50,885},{9,50,885},{9,30,884},{4,47,652},{4,32,8},{4,32,8},{3,22,62},{0,25,1107},{0,22,243},{14,41,0},{14,41,0},{14,41,0},{14,27,1},{27,1,648}, +{5,32,1},{5,32,1},{0,22,18},{55,0,648},{0,22,18},{42,0,882},{13,43,1},{18,33,1},{2,33,0},{42,0,882},{62,11,882},{2,33,0},{0,28,882},{62,11,882},{0,28,882},{9,0,884},{9,0,884},{9,0,884},{9,0,884},{4,34,4},{4,34,4},{4,34,4},{4,19,4},{0,19,146},{0,19,146},{12,63,1846},{11,48,924},{12,37,1320},{11,34,936},{6,63,3055},{5,42,924},{6,35,9}, +{4,28,1302},{0,36,3799},{0,28,1356},{16,58,883},{16,44,9},{17,35,74},{15,33,161},{38,0,3048},{2,44,882},{6,35,5},{0,29,1110},{62,7,3048},{0,29,1110},{11,52,885},{11,52,885},{11,52,885},{11,32,885},{6,49,652},{6,34,8},{6,34,8},{5,24,62},{0,29,969},{0,24,109},{16,42,1},{16,42,1},{16,42,1},{16,29,2},{30,1,648},{7,34,1},{7,34,1},{0,24,9},{61,0,648}, +{0,24,9},{45,0,882},{15,45,1},{20,35,1},{4,35,0},{45,0,882},{62,14,882},{4,35,0},{0,30,882},{62,14,882},{0,30,882},{11,0,884},{11,0,884},{11,0,884},{11,0,884},{6,36,4},{6,36,4},{6,36,4},{6,21,4},{0,22,74},{0,22,74},{14,63,1912},{13,50,924},{14,39,1320},{13,36,936},{9,63,3087},{7,44,924},{8,37,9},{6,30,1302},{0,39,3607},{0,31,1156},{18,60,883}, +{18,46,9},{19,37,74},{17,35,154},{41,0,3048},{4,46,882},{8,37,5},{0,31,1035},{62,10,3048},{0,31,1035},{13,54,885},{13,54,885},{13,54,885},{13,34,885},{8,51,652},{8,36,8},{8,36,8},{7,26,62},{0,33,846},{0,27,37},{18,44,1},{18,44,1},{18,44,1},{18,31,2},{33,1,648},{9,36,1},{9,36,1},{0,27,1},{63,2,648},{0,27,1},{47,2,882},{16,48,1},{22,37,1}, +{6,37,0},{47,2,882},{62,17,882},{6,37,0},{0,32,884},{62,17,882},{0,32,884},{13,0,884},{13,0,884},{13,0,884},{13,0,884},{8,38,4},{8,38,4},{8,38,4},{8,23,4},{0,26,29},{0,26,29},{16,63,2014},{15,52,932},{16,40,1341},{15,38,932},{12,63,3141},{9,46,924},{10,39,7},{9,32,1308},{0,43,3436},{0,33,1003},{20,62,884},{20,48,8},{21,40,74},{19,37,161},{36,16,3048}, +{6,48,882},{10,39,6},{0,33,978},{63,13,3048},{0,33,978},{15,57,882},{15,57,882},{15,57,882},{15,36,882},{10,54,649},{10,39,6},{10,39,6},{9,28,61},{0,36,737},{1,29,8},{20,47,0},{20,47,0},{20,47,0},{20,33,1},{31,12,648},{11,38,1},{11,38,1},{2,29,1},{62,6,648},{2,29,1},{51,0,882},{19,49,1},{24,39,1},{9,39,1},{51,0,882},{47,28,882},{9,39,1}, +{0,34,882},{47,28,882},{0,34,882},{15,0,882},{15,0,882},{15,0,882},{15,0,882},{10,40,2},{10,40,2},{10,40,2},{10,25,2},{0,30,2},{0,30,2},{19,63,2126},{17,54,924},{18,42,1341},{16,40,941},{14,63,3204},{11,48,924},{12,41,7},{11,34,1308},{0,46,3300},{0,35,939},{22,63,890},{22,50,8},{23,42,74},{21,39,161},{39,16,3048},{8,50,882},{12,41,6},{0,35,939},{62,16,3048}, +{0,35,939},{17,59,884},{17,59,884},{17,59,884},{17,38,884},{12,56,649},{12,41,6},{12,41,6},{11,30,61},{0,39,681},{3,31,8},{22,49,0},{22,49,0},{22,49,0},{22,35,1},{31,18,648},{13,40,1},{13,40,1},{4,31,1},{62,9,648},{4,31,1},{54,0,882},{21,51,1},{26,41,1},{11,41,1},{54,0,882},{47,31,882},{11,41,1},{0,36,882},{47,31,882},{0,36,882},{17,0,884}, +{17,0,884},{17,0,884},{17,0,884},{12,42,2},{12,42,2},{12,42,2},{12,27,2},{2,32,1},{2,32,1},{20,63,2264},{19,56,924},{20,44,1341},{18,42,941},{17,63,3292},{13,50,924},{14,43,7},{13,36,1308},{0,50,3192},{0,38,923},{25,63,906},{24,52,8},{25,44,74},{23,41,161},{50,0,3048},{10,52,882},{14,43,6},{0,38,907},{62,19,3048},{0,38,907},{19,61,884},{19,61,884},{19,61,884}, +{19,40,884},{14,58,649},{14,43,6},{14,43,6},{13,32,67},{0,42,657},{4,33,10},{24,51,0},{24,51,0},{24,51,0},{24,37,1},{34,17,648},{15,42,1},{15,42,1},{6,33,1},{62,12,648},{6,33,1},{57,0,882},{23,53,1},{28,43,1},{13,43,1},{57,0,882},{50,32,882},{13,43,1},{0,38,882},{50,32,882},{0,38,882},{19,0,884},{19,0,884},{19,0,884},{19,0,884},{14,44,2}, +{14,44,2},{14,44,2},{14,29,2},{4,34,1},{4,34,1},{23,63,2376},{21,58,924},{22,46,1341},{20,44,941},{19,63,3391},{15,52,924},{16,45,10},{15,38,1308},{0,53,3112},{2,40,923},{27,63,948},{26,54,8},{27,46,74},{25,43,161},{53,0,3048},{12,54,882},{16,45,6},{0,40,891},{62,22,3048},{0,40,891},{21,63,884},{21,63,884},{21,63,884},{21,42,884},{16,59,652},{16,45,9},{16,45,9}, +{15,34,67},{1,45,650},{6,35,10},{26,53,0},{26,53,0},{26,53,0},{26,39,1},{37,17,648},{17,44,0},{17,44,0},{8,35,1},{62,15,648},{8,35,1},{60,0,882},{25,55,1},{30,45,1},{15,45,1},{60,0,882},{56,32,882},{15,45,1},{0,40,882},{56,32,882},{0,40,882},{21,0,884},{21,0,884},{21,0,884},{21,0,884},{16,46,4},{16,46,4},{16,46,4},{16,31,4},{6,36,1}, +{6,36,1},{26,63,2564},{23,61,927},{24,49,1324},{23,47,935},{22,63,3529},{17,54,924},{18,47,10},{17,41,1302},{0,56,3060},{5,42,924},{30,63,1003},{28,57,6},{29,48,67},{28,46,158},{56,1,3048},{15,56,883},{19,47,8},{1,42,884},{63,25,3048},{1,42,884},{23,63,891},{23,63,891},{23,63,891},{23,44,883},{18,62,649},{18,47,6},{18,47,6},{17,36,61},{4,47,652},{9,37,8},{28,55,2}, +{28,55,2},{28,55,2},{28,42,2},{49,0,648},{19,46,2},{19,46,2},{11,37,0},{62,18,648},{11,37,0},{63,1,882},{27,58,2},{32,47,4},{17,47,5},{63,1,882},{63,32,882},{17,47,5},{0,42,884},{63,32,882},{0,42,884},{23,0,882},{23,0,882},{23,0,882},{23,0,882},{18,48,2},{18,48,2},{18,48,2},{18,33,2},{8,38,1},{8,38,1},{28,63,2774},{25,63,927},{26,51,1324}, +{25,48,932},{25,63,3681},{19,56,924},{20,49,7},{19,43,1302},{0,59,3052},{7,44,924},{32,63,1074},{30,59,6},{31,50,67},{30,48,170},{59,1,3048},{16,58,885},{20,49,6},{3,44,884},{63,28,3048},{3,44,884},{25,63,918},{25,63,918},{25,63,918},{25,46,883},{20,63,651},{20,49,6},{20,49,6},{19,38,61},{5,49,651},{11,39,8},{30,57,2},{30,57,2},{30,57,2},{30,44,2},{52,0,648}, +{21,48,1},{21,48,1},{13,39,0},{62,21,648},{13,39,0},{63,7,882},{29,60,2},{34,49,1},{19,49,1},{63,7,882},{63,35,882},{19,49,1},{0,44,884},{63,35,882},{0,44,884},{25,0,882},{25,0,882},{25,0,882},{25,0,882},{20,50,2},{20,50,2},{20,50,2},{20,35,2},{10,40,1},{10,40,1},{31,63,2998},{28,63,951},{28,53,1324},{27,50,932},{26,63,3844},{21,58,924},{22,51,7}, +{21,45,1302},{2,61,3052},{9,46,924},{34,63,1146},{32,61,9},{33,52,74},{32,50,169},{62,1,3048},{18,60,885},{22,51,6},{5,46,884},{63,31,3048},{5,46,884},{28,63,950},{28,63,950},{28,63,950},{27,48,882},{23,63,675},{22,51,6},{22,51,6},{21,40,61},{7,51,651},{13,41,8},{32,59,0},{32,59,0},{32,59,0},{32,46,1},{55,0,648},{23,50,1},{23,50,1},{15,41,0},{62,24,648}, +{15,41,0},{63,13,882},{31,62,2},{36,51,1},{21,51,1},{63,13,882},{63,38,882},{21,51,1},{0,46,884},{63,38,882},{0,46,884},{27,0,882},{27,0,882},{27,0,882},{27,0,882},{22,52,2},{22,52,2},{22,52,2},{22,37,2},{12,42,1},{12,42,1},{33,63,3224},{30,63,1031},{30,55,1324},{29,52,932},{29,63,3996},{23,60,924},{24,53,7},{23,47,1302},{4,63,3052},{11,48,922},{37,63,1226}, +{34,63,9},{35,54,74},{33,51,161},{63,5,3048},{20,62,885},{24,53,6},{6,48,882},{47,42,3048},{6,48,882},{30,63,995},{30,63,995},{30,63,995},{29,50,882},{25,63,705},{24,53,6},{24,53,6},{23,42,61},{9,53,651},{15,43,8},{34,61,0},{34,61,0},{34,61,0},{34,47,4},{58,0,648},{25,52,1},{25,52,1},{16,43,1},{62,27,648},{16,43,1},{63,19,882},{33,63,4},{38,53,1}, +{23,53,1},{63,19,882},{63,41,882},{23,53,1},{0,48,882},{63,41,882},{0,48,882},{29,0,882},{29,0,882},{29,0,882},{29,0,882},{24,54,2},{24,54,2},{24,54,2},{24,39,2},{14,44,1},{14,44,1},{34,63,3510},{32,63,1202},{33,57,1335},{31,54,936},{33,63,4252},{25,63,925},{26,55,13},{25,49,1309},{9,63,3091},{13,50,918},{40,63,1349},{37,63,38},{37,56,77},{36,54,158},{60,17,3048}, +{24,63,894},{27,55,8},{9,50,884},{63,37,3048},{9,50,884},{32,63,1058},{32,63,1058},{32,63,1058},{31,52,885},{28,63,762},{26,55,9},{26,55,9},{26,44,61},{11,56,650},{17,45,11},{36,63,2},{36,63,2},{36,63,2},{36,50,2},{53,16,648},{28,54,1},{28,54,1},{19,45,1},{63,30,648},{19,45,1},{59,33,882},{37,63,29},{40,56,4},{26,55,4},{59,33,882},{55,48,882},{26,55,4}, +{0,50,884},{55,48,882},{0,50,884},{31,0,884},{31,0,884},{31,0,884},{31,0,884},{26,57,0},{26,57,0},{26,57,0},{26,42,1},{16,47,2},{16,47,2},{37,63,3734},{34,63,1399},{35,59,1335},{33,57,935},{34,63,4441},{28,63,957},{28,57,13},{27,51,1309},{13,63,3192},{15,52,918},{43,63,1485},{39,63,131},{39,58,77},{38,56,158},{63,17,3048},{28,63,957},{29,57,8},{11,52,884},{63,40,3048}, +{11,52,884},{34,63,1110},{34,63,1110},{34,63,1110},{33,54,883},{30,63,840},{28,57,9},{28,57,9},{28,46,61},{13,58,650},{19,47,11},{39,63,10},{39,63,10},{39,63,10},{38,52,2},{56,16,648},{30,56,1},{30,56,1},{21,47,1},{62,33,648},{21,47,1},{62,33,882},{41,63,80},{42,58,4},{28,57,4},{62,33,882},{61,48,882},{28,57,4},{0,52,884},{61,48,882},{0,52,884},{33,0,882}, +{33,0,882},{33,0,882},{33,0,882},{28,59,0},{28,59,0},{28,59,0},{28,44,1},{18,48,1},{18,48,1},{40,63,4022},{37,63,1647},{37,61,1335},{35,59,935},{37,63,4657},{31,63,1085},{30,59,13},{29,53,1309},{18,63,3339},{17,54,924},{45,63,1635},{42,63,275},{41,60,77},{40,58,158},{63,23,3048},{32,63,1044},{31,59,8},{13,54,884},{63,43,3048},{13,54,884},{36,63,1203},{36,63,1203},{36,63,1203}, +{35,56,883},{33,63,915},{30,59,9},{30,59,9},{30,48,65},{15,60,650},{21,49,8},{41,63,25},{41,63,25},{41,63,25},{40,54,2},{59,16,648},{32,57,4},{32,57,4},{23,49,0},{62,36,648},{23,49,0},{63,37,882},{44,63,160},{44,60,4},{30,59,4},{63,37,882},{63,50,882},{30,59,4},{0,54,884},{63,50,882},{0,54,884},{35,0,882},{35,0,882},{35,0,882},{35,0,882},{30,61,0}, +{30,61,0},{30,61,0},{30,46,1},{20,50,1},{20,50,1},{42,63,4364},{40,63,1991},{39,63,1335},{37,61,935},{40,63,4905},{34,63,1287},{32,61,10},{31,55,1309},{21,63,3555},{19,56,924},{48,63,1796},{44,63,465},{43,62,77},{42,60,158},{63,29,3048},{35,63,1188},{33,61,8},{15,56,884},{63,46,3048},{15,56,884},{39,63,1299},{39,63,1299},{39,63,1299},{37,58,883},{34,63,1017},{32,61,6},{32,61,6}, +{32,50,66},{17,62,650},{23,51,8},{43,63,45},{43,63,45},{43,63,45},{42,56,2},{62,16,648},{33,60,2},{33,60,2},{25,51,0},{62,39,648},{25,51,0},{63,43,882},{48,63,260},{46,62,4},{30,62,4},{63,43,882},{63,53,882},{30,62,4},{0,56,884},{63,53,882},{0,56,884},{37,0,882},{37,0,882},{37,0,882},{37,0,882},{32,63,1},{32,63,1},{32,63,1},{32,47,2},{22,52,1}, +{22,52,1},{45,63,4441},{43,63,2286},{41,63,1421},{39,62,916},{43,63,4878},{37,63,1410},{34,63,9},{33,57,1141},{26,63,3535},{21,58,795},{50,63,1770},{47,63,609},{46,63,85},{44,62,120},{63,35,2814},{40,63,1194},{35,63,2},{17,58,762},{63,49,2814},{17,58,762},{41,63,1421},{41,63,1421},{41,63,1421},{39,61,885},{37,63,1130},{34,63,9},{34,63,9},{34,52,61},{20,63,651},{25,53,11},{46,63,85}, +{46,63,85},{46,63,85},{44,58,4},{63,21,648},{36,62,1},{36,62,1},{27,53,2},{63,42,648},{27,53,2},{63,48,761},{51,63,305},{48,63,1},{34,63,0},{63,48,761},{62,56,761},{34,63,0},{0,58,761},{62,56,761},{0,58,761},{39,0,884},{39,0,884},{39,0,884},{39,0,884},{34,63,9},{34,63,9},{34,63,9},{34,50,1},{24,55,2},{24,55,2},{46,63,3945},{43,63,2238},{43,63,1509}, +{41,63,885},{45,63,4345},{38,63,1230},{37,63,41},{34,58,781},{30,63,3066},{24,59,494},{51,63,1386},{48,63,530},{48,63,130},{46,62,45},{63,39,2249},{43,63,914},{39,63,8},{21,59,482},{47,59,2249},{21,59,482},{43,63,1509},{43,63,1509},{43,63,1509},{41,63,885},{40,63,1242},{37,63,41},{37,63,41},{36,54,61},{24,63,689},{27,55,11},{48,63,130},{48,63,130},{48,63,130},{46,60,4},{63,27,648}, +{39,63,8},{39,63,8},{29,55,2},{63,45,648},{29,55,2},{63,51,481},{54,63,193},{51,63,1},{40,63,0},{63,51,481},{63,57,481},{40,63,0},{0,59,481},{63,57,481},{0,59,481},{41,0,884},{41,0,884},{41,0,884},{41,0,884},{37,63,25},{37,63,25},{37,63,25},{36,52,1},{26,57,2},{26,57,2},{48,63,3571},{46,63,2182},{46,63,1653},{43,63,900},{46,63,3838},{41,63,1094},{40,63,137}, +{37,59,490},{32,63,2703},{27,60,270},{53,63,1106},{51,63,458},{50,63,193},{48,63,10},{63,43,1769},{46,63,698},{42,63,40},{25,60,266},{63,53,1769},{25,60,266},{46,63,1653},{46,63,1653},{46,63,1653},{43,63,900},{43,63,1386},{40,63,137},{40,63,137},{38,56,61},{29,63,779},{29,57,11},{50,63,193},{50,63,193},{50,63,193},{48,62,1},{63,33,648},{42,63,40},{42,63,40},{31,57,2},{47,56,648}, +{31,57,2},{63,54,265},{57,63,113},{54,63,1},{46,63,0},{63,54,265},{62,59,265},{46,63,0},{0,60,265},{62,59,265},{0,60,265},{43,0,884},{43,0,884},{43,0,884},{43,0,884},{39,63,52},{39,63,52},{39,63,52},{38,54,1},{28,59,2},{28,59,2},{50,63,3307},{48,63,2195},{48,63,1795},{46,63,964},{48,63,3435},{43,63,1026},{42,63,296},{39,60,269},{37,63,2410},{30,61,115},{54,63,882}, +{54,63,450},{53,63,265},{50,63,10},{63,47,1374},{48,63,546},{46,63,89},{29,61,114},{63,55,1374},{29,61,114},{48,63,1795},{48,63,1795},{48,63,1795},{46,63,964},{45,63,1560},{42,63,296},{42,63,296},{40,58,61},{32,63,891},{31,59,11},{53,63,265},{53,63,265},{53,63,265},{50,63,10},{63,39,648},{46,63,89},{46,63,89},{33,59,1},{47,59,648},{33,59,1},{63,57,113},{58,63,50},{57,63,1}, +{52,63,0},{63,57,113},{63,60,113},{52,63,0},{0,61,113},{63,60,113},{0,61,113},{45,0,884},{45,0,884},{45,0,884},{45,0,884},{41,63,97},{41,63,97},{41,63,97},{40,56,1},{30,61,2},{30,61,2},{51,63,3032},{51,63,2264},{50,63,1965},{48,63,1096},{51,63,3096},{46,63,1059},{46,63,530},{41,62,126},{40,63,2191},{33,62,25},{57,63,680},{56,63,465},{55,63,356},{53,63,68},{63,51,1032}, +{52,63,450},{49,63,185},{34,62,20},{63,57,1032},{34,62,20},{50,63,1965},{50,63,1965},{50,63,1965},{48,63,1096},{48,63,1736},{46,63,530},{46,63,530},{42,60,62},{37,63,1086},{33,62,9},{55,63,356},{55,63,356},{55,63,356},{53,63,68},{61,49,648},{49,63,185},{49,63,185},{36,61,4},{63,54,648},{36,61,4},{63,61,18},{61,63,9},{61,63,0},{59,63,0},{63,61,18},{63,62,18},{59,63,0}, +{0,62,20},{63,62,18},{0,62,20},{47,0,890},{47,0,890},{47,0,890},{47,0,890},{44,63,149},{44,63,149},{44,63,149},{42,58,1},{32,63,0},{32,63,0},{54,63,2756},{52,63,2249},{51,63,2004},{50,63,1224},{53,63,2803},{48,63,1092},{48,63,692},{44,62,58},{43,63,1991},{35,63,16},{59,63,566},{57,63,420},{57,63,356},{55,63,125},{63,55,771},{55,63,386},{52,63,241},{38,63,0},{63,59,771}, +{38,63,0},{51,63,2004},{51,63,2004},{51,63,2004},{50,63,1224},{50,63,1802},{48,63,692},{48,63,692},{44,62,42},{40,63,1166},{35,63,16},{57,63,356},{57,63,356},{57,63,356},{55,63,125},{63,50,580},{52,63,241},{52,63,241},{38,63,0},{62,57,580},{38,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{49,0,884}, +{49,0,884},{49,0,884},{49,0,884},{46,63,193},{46,63,193},{46,63,193},{44,60,1},{35,63,16},{35,63,16},{54,63,2276},{54,63,1844},{54,63,1700},{52,63,1125},{54,63,2180},{51,63,948},{49,63,649},{46,63,10},{46,63,1551},{39,63,58},{60,63,324},{59,63,257},{59,63,221},{57,63,68},{63,57,452},{57,63,228},{55,63,137},{44,63,0},{63,60,452},{44,63,0},{54,63,1700},{54,63,1700},{54,63,1700}, +{52,63,1125},{51,63,1460},{49,63,649},{49,63,649},{46,63,10},{43,63,926},{39,63,58},{59,63,221},{59,63,221},{59,63,221},{57,63,68},{63,53,340},{55,63,137},{55,63,137},{44,63,0},{63,58,340},{44,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{51,0,884},{51,0,884},{51,0,884},{51,0,884},{48,63,260}, +{48,63,260},{48,63,260},{46,62,1},{39,63,58},{39,63,58},{57,63,1844},{55,63,1585},{55,63,1464},{54,63,1044},{56,63,1747},{52,63,850},{51,63,596},{48,63,4},{48,63,1204},{43,63,117},{60,63,164},{60,63,116},{60,63,100},{59,63,40},{63,59,216},{58,63,114},{58,63,65},{50,63,0},{63,61,216},{50,63,0},{55,63,1464},{55,63,1464},{55,63,1464},{54,63,1044},{54,63,1188},{51,63,596},{51,63,596}, +{48,63,4},{46,63,750},{43,63,117},{60,63,100},{60,63,100},{60,63,100},{59,63,40},{63,56,164},{58,63,65},{58,63,65},{50,63,0},{62,60,164},{50,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{53,0,884},{53,0,884},{53,0,884},{53,0,884},{51,63,340},{51,63,340},{51,63,340},{48,63,4},{43,63,117}, +{43,63,117},{0,39,1568},{0,28,194},{0,19,10},{0,16,586},{0,26,3371},{0,17,2169},{0,16,1027},{0,10,2532},{0,12,3648},{0,10,2701},{0,39,1568},{0,28,194},{0,19,10},{0,16,586},{5,16,3371},{0,17,2169},{0,16,1027},{0,10,2532},{26,0,3371},{0,10,2532},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,9,288},{0,8,109},{0,8,109},{0,4,164},{0,4,321},{0,4,189},{0,18,0}, +{0,18,0},{0,18,0},{0,9,0},{4,1,288},{0,8,109},{0,8,109},{0,4,164},{9,0,288},{0,4,164},{19,1,1568},{0,28,194},{0,19,10},{0,16,586},{19,1,1568},{39,0,1568},{0,16,586},{0,13,1568},{39,0,1568},{0,13,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,45,1568},{0,31,106},{0,22,10}, +{0,18,481},{0,30,3968},{0,19,2355},{0,18,1057},{0,13,2852},{0,14,4319},{0,11,3117},{0,45,1568},{0,31,106},{0,22,10},{0,18,481},{15,0,3968},{0,19,2355},{0,18,1057},{0,13,2852},{30,0,3968},{0,13,2852},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{0,12,512},{0,10,205},{0,10,205},{0,5,313},{0,5,566},{0,5,349},{0,24,0},{0,24,0},{0,24,0},{0,12,0},{6,0,512}, +{0,10,205},{0,10,205},{0,5,313},{12,0,512},{0,5,313},{22,1,1568},{0,31,106},{1,22,1},{0,18,481},{22,1,1568},{45,0,1568},{0,18,481},{0,15,1568},{45,0,1568},{0,15,1568},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,50,1570},{0,34,52},{1,24,58},{0,21,377},{0,34,4652},{0,22,2571},{0,19,1107}, +{0,14,3225},{0,16,5108},{0,13,3525},{0,50,1570},{0,34,52},{1,24,42},{0,21,377},{15,4,4651},{0,22,2571},{0,19,1107},{0,14,3225},{30,2,4651},{0,14,3225},{0,30,0},{0,30,0},{0,30,0},{0,15,0},{0,15,800},{0,11,317},{0,11,317},{0,7,468},{0,7,889},{0,7,549},{0,30,0},{0,30,0},{0,30,0},{0,15,0},{7,1,800},{0,11,317},{0,11,317},{0,7,468},{15,0,800}, +{0,7,468},{25,1,1568},{0,34,52},{3,24,1},{0,21,377},{25,1,1568},{47,2,1568},{0,21,377},{0,17,1570},{47,2,1568},{0,17,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,56,1570},{0,38,13},{1,27,138},{0,24,305},{0,38,5419},{0,25,2819},{0,22,1187},{0,16,3659},{0,17,6013},{0,14,4061},{0,56,1570}, +{0,38,13},{1,27,122},{0,24,305},{19,0,5419},{0,25,2819},{0,22,1187},{0,16,3659},{38,0,5419},{0,16,3659},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{0,18,1152},{0,14,445},{0,14,445},{0,8,697},{0,8,1270},{0,8,797},{0,36,0},{0,36,0},{0,36,0},{0,18,0},{9,0,1152},{0,14,445},{0,14,445},{0,8,697},{18,0,1152},{0,8,697},{28,1,1568},{0,38,13},{5,26,1}, +{0,24,305},{28,1,1568},{47,5,1568},{0,24,305},{0,19,1570},{47,5,1568},{0,19,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,61,1609},{1,41,43},{2,29,250},{1,26,301},{0,45,5419},{0,28,2552},{0,25,820},{0,18,3377},{0,21,6243},{0,18,3953},{2,59,1569},{2,41,10},{3,29,125},{1,26,285},{22,1,5419}, +{0,28,2552},{0,25,820},{0,18,3377},{45,0,5419},{0,18,3377},{1,40,42},{1,40,42},{1,40,42},{1,21,42},{0,25,1152},{0,19,292},{0,19,292},{0,11,569},{0,11,1380},{0,10,747},{2,38,2},{2,38,2},{2,38,2},{2,20,2},{12,1,1152},{0,19,292},{0,19,292},{0,11,569},{25,0,1152},{0,11,569},{23,17,1568},{0,42,1},{7,28,1},{0,26,233},{23,17,1568},{63,0,1568},{0,26,233}, +{0,21,1568},{63,0,1568},{0,21,1568},{1,0,41},{1,0,41},{1,0,41},{1,0,41},{0,7,0},{0,7,0},{0,7,0},{0,3,1},{0,3,17},{0,3,17},{2,63,1731},{2,44,146},{3,31,441},{1,28,370},{0,50,5420},{0,33,2329},{0,27,554},{0,21,3217},{0,23,6476},{0,19,3861},{4,61,1569},{4,43,10},{5,31,125},{3,28,285},{25,1,5419},{0,33,2329},{0,27,554},{0,21,3217},{47,2,5419}, +{0,21,3217},{2,44,146},{2,44,146},{2,44,146},{2,23,146},{0,31,1152},{0,22,180},{0,22,180},{0,13,458},{0,14,1508},{0,13,747},{4,40,2},{4,40,2},{4,40,2},{4,22,2},{15,1,1152},{0,22,180},{0,22,180},{0,13,458},{31,0,1152},{0,13,458},{34,1,1568},{2,44,1},{9,30,1},{0,28,164},{34,1,1568},{63,3,1568},{0,28,164},{0,23,1568},{63,3,1568},{0,23,1568},{2,0,145}, +{2,0,145},{2,0,145},{2,0,145},{0,13,0},{0,13,0},{0,13,0},{0,6,1},{0,5,52},{0,5,52},{4,63,1977},{3,47,318},{5,33,675},{3,30,498},{0,56,5420},{0,36,2129},{0,30,338},{0,22,3012},{0,25,6733},{0,21,3825},{6,63,1569},{6,45,10},{8,33,123},{5,30,285},{28,1,5419},{0,36,2129},{0,30,338},{0,22,3012},{47,5,5419},{0,22,3012},{3,48,313},{3,48,313},{3,48,313}, +{3,26,314},{0,36,1154},{0,25,100},{0,25,100},{0,16,388},{0,16,1665},{0,14,757},{6,42,2},{6,42,2},{6,42,2},{6,24,2},{15,7,1152},{0,25,100},{0,25,100},{0,16,388},{31,3,1152},{0,16,388},{37,1,1568},{4,46,1},{11,32,2},{0,30,113},{37,1,1568},{63,6,1568},{0,30,113},{0,25,1568},{63,6,1568},{0,25,1568},{3,0,313},{3,0,313},{3,0,313},{3,0,313},{0,19,0}, +{0,19,0},{0,19,0},{0,9,1},{0,8,116},{0,8,116},{6,63,2353},{4,49,562},{6,35,1006},{3,32,715},{0,62,5420},{0,39,1961},{0,32,174},{0,24,2817},{0,28,7013},{0,24,3841},{9,63,1577},{8,47,10},{10,35,123},{7,31,290},{31,1,5419},{0,39,1961},{0,32,174},{0,24,2817},{47,8,5419},{0,24,2817},{4,52,545},{4,52,545},{4,52,545},{4,28,546},{0,42,1154},{0,29,45},{0,29,45}, +{0,18,289},{0,19,1849},{0,16,797},{8,44,2},{8,44,2},{8,44,2},{8,26,2},{15,13,1152},{0,29,45},{0,29,45},{0,18,289},{31,6,1152},{0,18,289},{40,1,1568},{6,48,1},{13,34,2},{0,33,73},{40,1,1568},{63,9,1568},{0,33,73},{0,27,1568},{63,9,1568},{0,27,1568},{4,0,545},{4,0,545},{4,0,545},{4,0,545},{0,25,0},{0,25,0},{0,25,0},{0,12,1},{0,11,212}, +{0,11,212},{8,63,2980},{6,52,920},{7,38,1444},{5,34,1012},{2,63,5504},{0,42,1814},{0,35,57},{0,27,2630},{0,31,7380},{0,25,3860},{11,63,1604},{10,49,13},{12,37,116},{10,33,292},{34,1,5419},{0,42,1814},{0,35,57},{0,27,2630},{63,3,5419},{0,27,2630},{5,57,884},{5,57,884},{5,57,884},{5,31,884},{0,49,1152},{0,33,5},{0,33,5},{0,21,221},{0,22,2091},{0,19,875},{11,45,4}, +{11,45,4},{11,45,4},{11,28,4},{24,1,1152},{0,33,5},{0,33,5},{0,21,221},{49,0,1152},{0,21,221},{44,0,1568},{8,50,1},{15,36,4},{0,35,32},{44,0,1568},{62,13,1568},{0,35,32},{0,29,1570},{62,13,1568},{0,29,1570},{5,0,884},{5,0,884},{5,0,884},{5,0,884},{0,31,1},{0,31,1},{0,31,1},{0,16,1},{0,14,349},{0,14,349},{9,63,3638},{7,55,1309},{8,39,1940}, +{6,36,1365},{3,63,5739},{0,45,1718},{0,38,17},{0,29,2514},{0,34,7760},{0,28,3900},{14,63,1636},{12,51,13},{14,39,116},{12,35,292},{37,1,5419},{0,45,1718},{0,38,17},{0,29,2514},{63,6,5419},{0,29,2514},{6,61,1252},{6,61,1252},{6,61,1252},{6,33,1253},{0,55,1152},{0,37,4},{0,37,4},{0,22,162},{0,25,2339},{0,21,989},{13,47,4},{13,47,4},{13,47,4},{13,30,4},{27,1,1152}, +{1,36,1},{1,36,1},{0,22,162},{55,0,1152},{0,22,162},{47,0,1568},{10,52,1},{17,38,1},{0,38,16},{47,0,1568},{46,24,1568},{0,38,16},{0,31,1570},{46,24,1568},{0,31,1570},{6,0,1252},{6,0,1252},{6,0,1252},{6,0,1252},{0,37,0},{0,37,0},{0,37,0},{0,19,1},{0,16,490},{0,16,490},{11,63,4328},{8,57,1644},{10,41,2360},{7,39,1656},{6,63,6079},{0,49,1644},{1,40,17}, +{0,31,2359},{0,36,7943},{0,30,3834},{16,63,1689},{14,53,13},{16,41,129},{14,37,292},{40,1,5419},{0,49,1640},{1,40,13},{0,31,2355},{63,9,5419},{0,31,2355},{8,63,1576},{8,63,1576},{8,63,1576},{7,36,1576},{1,59,1156},{1,39,13},{1,39,13},{0,25,110},{0,28,2475},{0,24,1017},{15,49,4},{15,49,4},{15,49,4},{15,32,4},{30,1,1152},{3,38,1},{3,38,1},{0,25,106},{61,0,1152}, +{0,25,106},{49,1,1568},{12,54,1},{19,40,1},{0,40,4},{49,1,1568},{46,27,1568},{0,40,4},{0,33,1568},{46,27,1568},{0,33,1568},{7,0,1576},{7,0,1576},{7,0,1576},{7,0,1576},{1,41,4},{1,41,4},{1,41,4},{1,21,4},{0,19,578},{0,19,578},{14,63,4584},{10,59,1644},{12,43,2360},{9,41,1656},{8,63,6244},{2,51,1644},{3,42,17},{1,33,2308},{0,42,7575},{0,32,3345},{19,63,1761}, +{16,55,10},{17,43,125},{16,40,290},{43,1,5419},{0,52,1592},{3,42,13},{0,33,2225},{63,12,5419},{0,33,2225},{10,63,1585},{10,63,1585},{10,63,1585},{9,38,1576},{3,61,1156},{3,41,13},{3,41,13},{2,27,110},{0,31,2211},{0,25,699},{16,52,2},{16,52,2},{16,52,2},{16,34,2},{33,1,1152},{5,40,1},{5,40,1},{0,27,61},{63,2,1152},{0,27,61},{52,1,1568},{14,56,1},{21,42,1}, +{1,42,0},{52,1,1568},{46,30,1568},{1,42,0},{0,35,1568},{46,30,1568},{0,35,1568},{9,0,1576},{9,0,1576},{9,0,1576},{9,0,1576},{3,43,4},{3,43,4},{3,43,4},{3,23,4},{0,22,410},{0,22,410},{15,63,4826},{12,62,1650},{14,46,2355},{11,43,1660},{11,63,6452},{4,54,1641},{5,44,15},{3,35,2308},{0,45,7165},{0,35,2875},{22,63,1862},{18,57,9},{20,45,126},{18,42,281},{47,0,5419}, +{0,56,1568},{6,44,10},{0,35,2091},{46,24,5419},{0,35,2091},{12,63,1606},{12,63,1606},{12,63,1606},{12,40,1571},{5,63,1155},{5,44,14},{5,44,14},{4,29,109},{0,33,1977},{0,28,424},{19,53,4},{19,53,4},{19,53,4},{19,36,4},{31,12,1152},{7,42,1},{7,42,1},{0,30,29},{62,6,1152},{0,30,29},{56,0,1568},{17,58,1},{24,44,2},{3,44,2},{56,0,1568},{62,25,1568},{3,44,2}, +{0,37,1570},{62,25,1568},{0,37,1570},{12,0,1570},{12,0,1570},{12,0,1570},{12,0,1570},{5,46,1},{5,46,1},{5,46,1},{5,25,2},{0,25,260},{0,25,260},{17,63,5096},{14,63,1652},{15,48,2358},{13,45,1660},{14,63,6668},{6,56,1641},{7,46,15},{5,37,2308},{0,47,6891},{0,36,2543},{23,63,1956},{20,59,9},{22,47,126},{20,44,281},{49,1,5419},{2,58,1568},{8,46,10},{0,38,1979},{46,27,5419}, +{0,38,1979},{14,63,1651},{14,63,1651},{14,63,1651},{14,42,1571},{8,63,1179},{7,46,14},{7,46,14},{6,31,109},{0,38,1778},{0,31,232},{21,55,4},{21,55,4},{21,55,4},{21,38,4},{31,18,1152},{9,44,1},{9,44,1},{0,32,10},{62,9,1152},{0,32,10},{59,0,1568},{19,60,1},{26,46,2},{5,46,2},{59,0,1568},{62,28,1568},{5,46,2},{0,39,1570},{62,28,1568},{0,39,1570},{14,0,1570}, +{14,0,1570},{14,0,1570},{14,0,1570},{7,48,1},{7,48,1},{7,48,1},{7,27,2},{0,28,164},{0,28,164},{20,63,5352},{17,63,1708},{18,49,2360},{15,47,1660},{15,63,6877},{8,58,1641},{9,48,14},{7,39,2308},{0,50,6576},{0,39,2215},{26,63,2052},{22,61,9},{24,49,116},{22,46,281},{52,1,5419},{4,60,1568},{9,48,13},{0,40,1907},{46,30,5419},{0,40,1907},{16,63,1697},{16,63,1697},{16,63,1697}, +{16,44,1577},{10,63,1209},{9,48,14},{9,48,14},{8,33,115},{0,42,1601},{0,33,110},{23,57,4},{23,57,4},{23,57,4},{23,40,4},{34,17,1152},{11,46,1},{11,46,1},{0,34,2},{62,12,1152},{0,34,2},{62,0,1568},{21,62,1},{28,48,1},{7,48,0},{62,0,1568},{62,31,1568},{7,48,0},{0,41,1570},{62,31,1568},{0,41,1570},{16,0,1576},{16,0,1576},{16,0,1576},{16,0,1576},{9,50,1}, +{9,50,1},{9,50,1},{9,29,2},{0,33,85},{0,33,85},{23,63,5672},{19,63,1825},{20,51,2360},{17,49,1656},{19,63,7135},{10,60,1641},{11,50,14},{9,41,2308},{0,53,6336},{0,42,1983},{29,63,2180},{24,63,9},{26,51,116},{24,48,293},{55,1,5419},{6,62,1568},{11,50,13},{0,42,1814},{47,32,5419},{0,42,1814},{19,63,1761},{19,63,1761},{19,63,1761},{17,46,1576},{12,63,1249},{11,50,14},{11,50,14}, +{10,35,115},{0,45,1449},{0,36,30},{25,59,4},{25,59,4},{25,59,4},{25,42,4},{37,17,1152},{13,48,0},{13,48,0},{1,36,2},{62,15,1152},{1,36,2},{63,4,1568},{23,63,4},{30,50,1},{9,50,0},{63,4,1568},{62,34,1568},{9,50,0},{0,43,1570},{62,34,1568},{0,43,1570},{17,0,1576},{17,0,1576},{17,0,1576},{17,0,1576},{11,52,1},{11,52,1},{11,52,1},{11,31,2},{0,36,29}, +{0,36,29},{25,63,6066},{21,63,2039},{22,54,2355},{19,51,1660},{20,63,7420},{12,62,1635},{13,52,14},{11,43,2316},{0,57,6109},{0,44,1789},{31,63,2369},{27,63,38},{28,53,115},{26,50,286},{59,0,5419},{9,63,1577},{14,52,11},{0,44,1740},{62,28,5419},{0,44,1740},{21,63,1843},{21,63,1843},{21,63,1843},{20,48,1571},{15,63,1314},{13,52,13},{13,52,13},{12,37,116},{0,48,1329},{0,39,13},{27,62,1}, +{27,62,1},{27,62,1},{27,44,2},{49,0,1152},{15,50,2},{15,50,2},{4,38,4},{62,18,1152},{4,38,4},{63,11,1568},{27,63,37},{32,52,2},{12,52,1},{63,11,1568},{47,45,1568},{12,52,1},{0,45,1576},{47,45,1568},{0,45,1576},{20,0,1570},{20,0,1570},{20,0,1570},{20,0,1570},{13,54,1},{13,54,1},{13,54,1},{13,34,1},{0,40,4},{0,40,4},{28,63,6434},{23,63,2268},{24,56,2355}, +{21,53,1660},{23,63,7668},{14,63,1652},{15,54,14},{13,45,2316},{0,61,5924},{0,47,1685},{34,63,2502},{29,63,123},{30,55,115},{28,52,286},{62,0,5419},{13,63,1627},{16,54,10},{0,47,1676},{62,31,5419},{0,47,1676},{23,63,1907},{23,63,1907},{23,63,1907},{22,50,1571},{17,63,1395},{15,54,13},{15,54,13},{14,39,116},{0,51,1241},{2,41,13},{29,63,2},{29,63,2},{29,63,2},{29,46,2},{52,0,1152}, +{17,52,1},{17,52,1},{6,40,4},{62,21,1152},{6,40,4},{55,32,1568},{31,63,97},{34,54,2},{14,54,1},{55,32,1568},{46,48,1568},{14,54,1},{0,47,1576},{46,48,1568},{0,47,1576},{22,0,1570},{22,0,1570},{22,0,1570},{22,0,1570},{15,56,1},{15,56,1},{15,56,1},{15,36,1},{1,43,1},{1,43,1},{29,63,6756},{26,63,2548},{26,58,2355},{23,55,1660},{26,63,7948},{17,63,1716},{17,56,15}, +{15,47,2316},{0,63,5773},{0,49,1638},{37,63,2694},{32,63,262},{32,57,126},{30,54,286},{63,4,5419},{17,63,1715},{18,56,10},{0,49,1634},{62,34,5419},{0,49,1634},{25,63,2018},{25,63,2018},{25,63,2018},{24,52,1571},{20,63,1483},{17,56,14},{17,56,14},{16,41,109},{0,54,1185},{4,43,13},{31,63,17},{31,63,17},{31,63,17},{31,48,2},{55,0,1152},{19,54,1},{19,54,1},{8,42,4},{62,24,1152}, +{8,42,4},{58,32,1568},{34,63,169},{36,56,2},{15,56,2},{58,32,1568},{52,48,1568},{15,56,2},{0,49,1570},{52,48,1568},{0,49,1570},{24,0,1570},{24,0,1570},{24,0,1570},{24,0,1570},{17,58,1},{17,58,1},{17,58,1},{17,37,2},{3,45,1},{3,45,1},{31,63,7218},{29,63,2924},{28,60,2355},{25,57,1660},{29,63,8260},{20,63,1884},{19,58,15},{17,49,2308},{3,63,5933},{2,51,1638},{39,63,2892}, +{34,63,445},{34,59,126},{32,56,281},{63,10,5419},{21,63,1849},{20,58,10},{0,51,1606},{62,37,5419},{0,51,1606},{28,63,2130},{28,63,2130},{28,63,2130},{26,54,1571},{23,63,1603},{19,58,14},{19,58,14},{18,43,109},{0,58,1156},{6,45,13},{33,63,40},{33,63,40},{33,63,40},{33,50,4},{58,0,1152},{21,56,1},{21,56,1},{10,44,4},{62,27,1152},{10,44,4},{61,32,1568},{38,63,274},{38,58,2}, +{17,58,2},{61,32,1568},{58,48,1568},{17,58,2},{0,51,1570},{58,48,1568},{0,51,1570},{26,0,1570},{26,0,1570},{26,0,1570},{26,0,1570},{19,60,1},{19,60,1},{19,60,1},{19,39,2},{5,47,1},{5,47,1},{34,63,7586},{31,63,3453},{30,62,2357},{28,59,1668},{31,63,8699},{23,63,2180},{21,60,21},{19,51,2316},{7,63,6224},{4,53,1634},{42,63,3131},{37,63,722},{36,62,125},{34,58,278},{55,32,5419}, +{26,63,2052},{22,60,9},{0,53,1580},{46,48,5419},{0,53,1580},{30,63,2272},{30,63,2272},{30,63,2272},{28,56,1568},{25,63,1746},{21,60,17},{21,60,17},{21,45,113},{1,61,1154},{9,47,14},{36,63,74},{36,63,74},{36,63,74},{35,52,2},{53,16,1152},{23,59,1},{23,59,1},{11,47,1},{63,30,1152},{11,47,1},{63,35,1568},{43,63,433},{40,60,4},{20,60,4},{63,35,1568},{63,49,1568},{20,60,4}, +{0,53,1576},{63,49,1568},{0,53,1576},{28,0,1568},{28,0,1568},{28,0,1568},{28,0,1568},{21,63,0},{21,63,0},{21,63,0},{21,42,0},{7,49,1},{7,49,1},{37,63,8018},{34,63,3915},{32,63,2410},{30,61,1668},{34,63,8985},{26,63,2548},{23,62,21},{21,53,2316},{12,63,6555},{6,55,1634},{43,63,3345},{40,63,1026},{38,63,129},{36,60,278},{58,32,5419},{30,63,2274},{24,62,9},{0,55,1577},{52,48,5419}, +{0,55,1577},{32,63,2406},{32,63,2406},{32,63,2406},{30,58,1568},{28,63,1890},{23,62,17},{23,62,17},{23,47,113},{3,63,1154},{11,49,12},{38,63,125},{38,63,125},{38,63,125},{37,54,2},{56,16,1152},{25,61,1},{25,61,1},{14,48,5},{62,33,1152},{14,48,5},{63,41,1568},{46,63,585},{42,62,4},{22,62,4},{63,41,1568},{63,52,1568},{22,62,4},{0,55,1576},{63,52,1568},{0,55,1576},{30,0,1568}, +{30,0,1568},{30,0,1568},{30,0,1568},{23,63,4},{23,63,4},{23,63,4},{23,44,0},{9,51,1},{9,51,1},{39,63,7700},{35,63,4026},{34,63,2514},{32,62,1611},{37,63,8485},{29,63,2424},{26,63,20},{23,55,1896},{15,63,6115},{9,56,1308},{46,63,2973},{43,63,1034},{40,63,169},{37,61,194},{63,27,4803},{32,63,2024},{27,63,1},{2,57,1253},{63,45,4803},{2,57,1253},{34,63,2514},{34,63,2514},{34,63,2514}, +{32,60,1570},{29,63,2056},{26,63,20},{26,63,20},{24,49,116},{7,63,1164},{13,51,12},{40,63,169},{40,63,169},{40,63,169},{39,56,2},{59,16,1152},{27,63,1},{27,63,1},{16,50,4},{62,36,1152},{16,50,4},{63,45,1250},{48,63,500},{45,63,1},{26,63,0},{63,45,1250},{47,62,1250},{26,63,0},{0,57,1252},{47,62,1250},{0,57,1252},{32,0,1570},{32,0,1570},{32,0,1570},{32,0,1570},{26,63,20}, +{26,63,20},{26,63,20},{25,46,0},{11,53,1},{11,53,1},{40,63,7062},{37,63,3915},{37,63,2690},{34,63,1579},{37,63,7765},{30,63,2178},{28,63,77},{26,56,1437},{18,63,5499},{11,57,918},{48,63,2504},{44,63,945},{43,63,225},{40,62,89},{63,31,4056},{35,63,1656},{30,63,9},{6,58,885},{63,47,4056},{6,58,885},{37,63,2690},{37,63,2690},{37,63,2690},{34,62,1570},{33,63,2227},{28,63,77},{28,63,77}, +{26,51,116},{11,63,1227},{15,53,12},{43,63,225},{43,63,225},{43,63,225},{41,58,2},{62,16,1152},{30,63,9},{30,63,9},{18,52,4},{62,39,1152},{18,52,4},{63,47,884},{51,63,356},{47,63,4},{32,63,0},{63,47,884},{63,55,884},{32,63,0},{0,58,884},{63,55,884},{0,58,884},{34,0,1570},{34,0,1570},{34,0,1570},{34,0,1570},{28,63,41},{28,63,41},{28,63,41},{27,48,1},{13,55,1}, +{13,55,1},{43,63,6493},{40,63,3882},{39,63,2880},{36,63,1584},{40,63,6982},{34,63,1966},{31,63,206},{28,57,971},{23,63,4927},{14,59,562},{50,63,2070},{46,63,842},{46,63,313},{43,62,25},{63,35,3318},{38,63,1326},{34,63,45},{11,59,545},{63,49,3318},{11,59,545},{39,63,2880},{39,63,2880},{39,63,2880},{36,63,1584},{34,63,2434},{31,63,206},{31,63,206},{29,53,114},{15,63,1329},{17,55,14},{46,63,313}, +{46,63,313},{46,63,313},{43,61,0},{63,21,1152},{34,63,45},{34,63,45},{19,55,1},{63,42,1152},{19,55,1},{63,51,545},{54,63,225},{51,63,1},{39,63,0},{63,51,545},{63,57,545},{39,63,0},{0,59,545},{63,57,545},{0,59,545},{36,0,1568},{36,0,1568},{36,0,1568},{36,0,1568},{31,63,85},{31,63,85},{31,63,85},{29,50,1},{15,57,1},{15,57,1},{45,63,6113},{43,63,3938},{40,63,3065}, +{38,63,1649},{43,63,6422},{35,63,1878},{34,63,365},{30,59,651},{26,63,4495},{16,60,318},{51,63,1698},{48,63,794},{48,63,394},{45,63,0},{63,39,2753},{41,63,1094},{38,63,106},{15,60,313},{47,59,2753},{15,60,313},{40,63,3065},{40,63,3065},{40,63,3065},{38,63,1649},{37,63,2610},{34,63,365},{34,63,365},{31,55,114},{20,63,1483},{19,57,14},{48,63,394},{48,63,394},{48,63,394},{45,63,0},{63,27,1152}, +{38,63,106},{38,63,106},{21,57,1},{63,45,1152},{21,57,1},{63,54,313},{55,63,130},{54,63,1},{45,63,0},{63,54,313},{62,59,313},{45,63,0},{0,60,313},{62,59,313},{0,60,313},{38,0,1568},{38,0,1568},{38,0,1568},{38,0,1568},{33,63,128},{33,63,128},{33,63,128},{31,52,1},{17,59,1},{17,59,1},{46,63,5677},{43,63,3954},{43,63,3225},{40,63,1764},{45,63,5985},{37,63,1830},{37,63,605}, +{32,60,410},{29,63,4159},{19,61,146},{53,63,1454},{51,63,770},{50,63,493},{47,63,25},{63,43,2273},{44,63,926},{41,63,194},{19,61,145},{63,53,2273},{19,61,145},{43,63,3225},{43,63,3225},{43,63,3225},{40,63,1764},{40,63,2818},{37,63,605},{37,63,605},{33,57,113},{23,63,1659},{21,59,14},{50,63,493},{50,63,493},{50,63,493},{47,63,25},{63,33,1152},{41,63,194},{41,63,194},{23,59,1},{47,56,1152}, +{23,59,1},{63,57,145},{58,63,58},{57,63,1},{50,63,1},{63,57,145},{63,60,145},{50,63,1},{0,61,145},{63,60,145},{0,61,145},{40,0,1568},{40,0,1568},{40,0,1568},{40,0,1568},{34,63,185},{34,63,185},{34,63,185},{33,54,0},{19,61,1},{19,61,1},{48,63,5379},{46,63,3978},{46,63,3449},{43,63,1924},{46,63,5542},{40,63,1870},{38,63,890},{34,61,225},{32,63,3919},{22,62,43},{54,63,1242}, +{53,63,809},{51,63,610},{49,63,101},{63,47,1878},{48,63,810},{44,63,314},{23,62,41},{63,55,1878},{23,62,41},{46,63,3449},{46,63,3449},{46,63,3449},{43,63,1924},{43,63,3058},{38,63,890},{38,63,890},{35,59,113},{27,63,1889},{23,61,14},{51,63,610},{51,63,610},{51,63,610},{49,63,101},{63,39,1152},{44,63,314},{44,63,314},{25,61,1},{47,59,1152},{25,61,1},{63,60,41},{60,63,17},{60,63,1}, +{56,63,1},{63,60,41},{62,62,41},{56,63,1},{0,62,41},{62,62,41},{0,62,41},{42,0,1568},{42,0,1568},{42,0,1568},{42,0,1568},{37,63,233},{37,63,233},{37,63,233},{35,56,0},{21,63,1},{21,63,1},{50,63,5170},{48,63,4080},{48,63,3680},{46,63,2195},{48,63,5200},{43,63,2023},{41,63,1269},{37,62,133},{35,63,3772},{25,63,17},{57,63,1088},{55,63,861},{54,63,720},{52,63,241},{63,51,1536}, +{51,63,768},{49,63,461},{28,63,0},{63,57,1536},{28,63,0},{48,63,3680},{48,63,3680},{48,63,3680},{46,63,2195},{46,63,3345},{41,63,1269},{41,63,1269},{37,61,114},{32,63,2200},{25,63,17},{54,63,720},{54,63,720},{54,63,720},{52,63,241},{61,49,1152},{49,63,461},{49,63,461},{28,63,0},{63,54,1152},{28,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0}, +{0,63,0},{63,63,0},{0,63,0},{44,0,1570},{44,0,1570},{44,0,1570},{44,0,1570},{40,63,317},{40,63,317},{40,63,317},{37,58,2},{25,63,17},{25,63,17},{51,63,4416},{50,63,3629},{48,63,3296},{47,63,2070},{50,63,4411},{46,63,1823},{43,63,1150},{39,63,50},{38,63,3132},{29,63,52},{57,63,768},{57,63,576},{56,63,505},{54,63,160},{63,53,1068},{54,63,544},{51,63,320},{33,63,1},{63,58,1068}, +{33,63,1},{48,63,3296},{48,63,3296},{48,63,3296},{47,63,2070},{46,63,2881},{43,63,1150},{43,63,1150},{39,62,42},{34,63,1846},{29,63,52},{56,63,505},{56,63,505},{56,63,505},{54,63,160},{63,48,800},{51,63,320},{51,63,320},{33,63,1},{62,56,800},{33,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{46,0,1570}, +{46,0,1570},{46,0,1570},{46,0,1570},{42,63,410},{42,63,410},{42,63,410},{39,60,2},{29,63,52},{29,63,52},{53,63,3826},{51,63,3136},{51,63,2880},{49,63,1961},{51,63,3648},{46,63,1615},{46,63,1086},{41,63,5},{41,63,2588},{32,63,116},{59,63,498},{57,63,384},{57,63,320},{56,63,116},{63,55,683},{55,63,342},{54,63,208},{39,63,1},{63,59,683},{39,63,1},{51,63,2880},{51,63,2880},{51,63,2880}, +{49,63,1961},{48,63,2448},{46,63,1086},{46,63,1086},{41,63,5},{37,63,1558},{32,63,116},{57,63,320},{57,63,320},{57,63,320},{56,63,116},{63,51,512},{54,63,208},{54,63,208},{39,63,1},{63,57,512},{39,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{48,0,1568},{48,0,1568},{48,0,1568},{48,0,1568},{45,63,514}, +{45,63,514},{45,63,514},{41,62,2},{32,63,116},{32,63,116},{54,63,3232},{53,63,2781},{53,63,2585},{51,63,1856},{53,63,3067},{48,63,1456},{48,63,1056},{43,63,10},{44,63,2140},{35,63,212},{60,63,272},{59,63,221},{59,63,185},{57,63,64},{63,57,384},{57,63,192},{55,63,125},{45,63,1},{63,60,384},{45,63,1},{53,63,2585},{53,63,2585},{53,63,2585},{51,63,1856},{51,63,2112},{48,63,1056},{48,63,1056}, +{43,63,10},{40,63,1334},{35,63,212},{59,63,185},{59,63,185},{59,63,185},{57,63,64},{63,54,288},{55,63,125},{55,63,125},{45,63,1},{62,59,288},{45,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{50,0,1568},{50,0,1568},{50,0,1568},{50,0,1568},{46,63,605},{46,63,605},{46,63,605},{43,63,10},{35,63,212}, +{35,63,212},{0,51,2665},{0,36,306},{0,26,5},{0,22,965},{0,34,5885},{0,22,3726},{0,21,1754},{0,14,4398},{0,16,6359},{0,13,4722},{0,51,2665},{0,36,306},{0,26,5},{0,22,965},{17,0,5885},{0,22,3726},{0,21,1754},{0,14,4398},{34,0,5885},{0,14,4398},{0,25,0},{0,25,0},{0,25,0},{0,12,1},{0,12,545},{0,11,212},{0,11,212},{0,6,337},{0,5,605},{0,5,374},{0,25,0}, +{0,25,0},{0,25,0},{0,12,1},{6,0,545},{0,11,212},{0,11,212},{0,6,337},{12,0,545},{0,6,337},{26,0,2665},{0,36,306},{0,26,5},{0,22,965},{26,0,2665},{51,0,2665},{0,22,965},{0,17,2665},{51,0,2665},{0,17,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,57,2665},{0,39,202},{0,29,13}, +{0,24,818},{0,39,6669},{0,25,3974},{0,22,1790},{0,16,4826},{0,18,7285},{0,16,5267},{0,57,2665},{0,39,202},{0,29,13},{0,24,818},{19,1,6669},{0,25,3974},{0,22,1790},{0,16,4826},{39,0,6669},{0,16,4826},{0,31,0},{0,31,0},{0,31,0},{0,15,1},{0,15,841},{0,12,337},{0,12,337},{0,7,493},{0,7,934},{0,7,574},{0,31,0},{0,31,0},{0,31,0},{0,15,1},{8,0,841}, +{0,12,337},{0,12,337},{0,7,493},{15,0,841},{0,7,493},{29,0,2665},{0,39,202},{1,28,2},{0,24,818},{29,0,2665},{57,0,2665},{0,24,818},{0,19,2665},{57,0,2665},{0,19,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,63,2665},{0,44,116},{1,31,66},{0,27,698},{0,42,7541},{0,28,4254},{0,25,1854}, +{0,18,5281},{0,19,8271},{0,16,5795},{0,63,2665},{0,44,116},{1,31,50},{0,27,698},{15,13,7538},{0,28,4254},{0,25,1854},{0,18,5281},{31,6,7538},{0,18,5281},{0,36,1},{0,36,1},{0,36,1},{0,18,1},{0,18,1201},{0,14,468},{0,14,468},{0,8,730},{0,8,1325},{0,8,830},{0,36,1},{0,36,1},{0,36,1},{0,18,1},{9,0,1201},{0,14,468},{0,14,468},{0,8,730},{18,0,1201}, +{0,8,730},{32,0,2665},{0,44,116},{3,30,2},{0,27,698},{32,0,2665},{63,0,2665},{0,27,698},{0,21,2665},{63,0,2665},{0,21,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,63,2781},{0,47,52},{1,33,148},{0,29,610},{0,46,8493},{0,31,4566},{0,27,1962},{0,18,5809},{0,22,9367},{0,18,6385},{2,63,2753}, +{0,47,52},{2,33,129},{0,29,610},{23,0,8493},{0,31,4566},{0,27,1962},{0,18,5809},{46,0,8493},{0,18,5809},{0,42,1},{0,42,1},{0,42,1},{0,21,1},{0,21,1625},{0,16,637},{0,16,637},{0,10,965},{0,10,1806},{0,10,1134},{0,42,1},{0,42,1},{0,42,1},{0,21,1},{11,0,1625},{0,16,637},{0,16,637},{0,10,965},{21,0,1625},{0,10,965},{35,0,2665},{0,47,52},{5,32,1}, +{0,29,610},{35,0,2665},{63,3,2665},{0,29,610},{0,23,2665},{63,3,2665},{0,23,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,63,3105},{0,51,10},{1,35,297},{0,32,481},{0,51,9670},{0,33,4965},{0,30,2120},{0,21,6413},{0,24,10749},{0,19,7191},{3,63,2989},{0,51,10},{2,36,257},{0,32,481},{25,1,9669}, +{0,33,4965},{0,30,2120},{0,21,6413},{47,2,9669},{0,21,6413},{0,49,0},{0,49,0},{0,49,0},{0,25,1},{0,25,2178},{0,19,850},{0,19,850},{0,11,1325},{0,11,2406},{0,10,1521},{0,49,0},{0,49,0},{0,49,0},{0,25,1},{12,1,2178},{0,19,850},{0,19,850},{0,11,1325},{25,0,2178},{0,11,1325},{38,0,2665},{0,51,10},{8,34,2},{0,32,481},{38,0,2665},{62,7,2665},{0,32,481}, +{0,25,2669},{62,7,2665},{0,25,2669},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,63,3437},{1,54,33},{3,37,425},{1,33,457},{0,57,9670},{0,36,4629},{0,31,1654},{0,24,6165},{0,26,11014},{0,22,7031},{6,63,3101},{2,53,10},{4,38,257},{1,33,441},{28,1,9669},{0,36,4629},{0,31,1654},{0,24,6165},{47,5,9669}, +{0,24,6165},{1,53,32},{1,53,32},{1,53,32},{1,27,32},{0,31,2178},{0,22,666},{0,22,666},{0,13,1160},{0,14,2534},{0,13,1449},{2,51,0},{2,51,0},{2,51,0},{2,27,1},{15,1,2178},{0,22,666},{0,22,666},{0,13,1160},{31,0,2178},{0,13,1160},{41,0,2665},{1,54,1},{10,36,2},{0,33,394},{41,0,2665},{62,10,2665},{0,33,394},{0,27,2669},{62,10,2665},{0,27,2669},{1,0,32}, +{1,0,32},{1,0,32},{1,0,32},{0,6,0},{0,6,0},{0,6,0},{0,3,0},{0,2,13},{0,2,13},{6,63,3917},{2,57,129},{3,40,609},{1,36,497},{0,63,9670},{0,39,4325},{0,33,1274},{0,25,5878},{0,28,11299},{0,24,6917},{8,63,3233},{4,55,10},{6,40,257},{3,35,441},{31,1,9669},{0,39,4325},{0,33,1274},{0,25,5878},{47,8,9669},{0,25,5878},{2,57,128},{2,57,128},{2,57,128}, +{2,30,129},{0,36,2180},{0,28,490},{0,28,490},{0,16,1018},{0,16,2691},{0,14,1441},{4,53,0},{4,53,0},{4,53,0},{4,29,1},{15,7,2178},{0,28,490},{0,28,490},{0,16,1018},{31,3,2178},{0,16,1018},{44,0,2665},{3,56,1},{12,38,2},{0,36,306},{44,0,2665},{62,13,2665},{0,36,306},{0,29,2669},{62,13,2665},{0,29,2669},{2,0,128},{2,0,128},{2,0,128},{2,0,128},{0,12,0}, +{0,12,0},{0,12,0},{0,6,0},{0,5,45},{0,5,45},{6,63,4541},{3,59,297},{5,42,865},{3,38,625},{2,63,9749},{0,45,4021},{0,36,914},{0,27,5581},{0,31,11611},{0,27,6877},{11,63,3377},{6,57,10},{8,42,257},{5,37,441},{34,0,9669},{0,45,4021},{0,36,914},{0,27,5581},{47,11,9669},{0,27,5581},{3,61,288},{3,61,288},{3,61,288},{3,32,288},{0,42,2180},{0,31,338},{0,31,338}, +{0,18,865},{0,19,2875},{0,16,1427},{6,55,0},{6,55,0},{6,55,0},{6,31,1},{15,13,2178},{0,31,338},{0,31,338},{0,18,865},{31,6,2178},{0,18,865},{47,0,2665},{5,58,1},{14,40,2},{0,38,225},{47,0,2665},{62,16,2665},{0,38,225},{0,31,2669},{62,16,2665},{0,31,2669},{3,0,288},{3,0,288},{3,0,288},{3,0,288},{0,18,0},{0,18,0},{0,18,0},{0,9,0},{0,8,109}, +{0,8,109},{9,63,5374},{4,62,570},{6,44,1269},{4,40,841},{3,63,10021},{0,47,3745},{0,39,593},{0,30,5294},{0,36,12029},{0,28,6810},{14,63,3558},{8,59,9},{10,44,254},{7,39,446},{37,1,9669},{0,47,3745},{0,39,593},{0,30,5294},{63,6,9669},{0,30,5294},{4,63,561},{4,63,561},{4,63,561},{4,35,546},{0,49,2178},{0,34,218},{0,34,218},{0,21,725},{0,22,3117},{0,19,1433},{8,58,1}, +{8,58,1},{8,58,1},{8,33,2},{24,1,2178},{0,34,218},{0,34,218},{0,21,725},{49,0,2178},{0,21,725},{50,0,2665},{7,60,1},{16,42,5},{0,41,157},{50,0,2665},{62,19,2665},{0,41,157},{0,33,2669},{62,19,2665},{0,33,2669},{4,0,545},{4,0,545},{4,0,545},{4,0,545},{0,25,0},{0,25,0},{0,25,0},{0,12,1},{0,11,212},{0,11,212},{11,63,6350},{6,63,905},{7,47,1678}, +{4,42,1102},{6,63,10453},{0,50,3485},{0,42,361},{0,32,5054},{0,36,12429},{0,31,6794},{15,63,3710},{10,61,9},{12,46,254},{9,41,446},{40,1,9669},{0,50,3485},{0,42,361},{0,32,5054},{63,9,9669},{0,32,5054},{6,63,901},{6,63,901},{6,63,901},{5,37,842},{0,55,2178},{0,38,125},{0,38,125},{0,24,629},{0,25,3365},{0,22,1489},{10,60,1},{10,60,1},{10,60,1},{10,35,2},{27,1,2178}, +{0,38,125},{0,38,125},{0,24,629},{55,0,2178},{0,24,629},{53,0,2665},{9,62,1},{18,44,5},{0,43,117},{53,0,2665},{62,22,2665},{0,43,117},{0,35,2669},{62,22,2665},{0,35,2669},{5,0,841},{5,0,841},{5,0,841},{5,0,841},{0,31,0},{0,31,0},{0,31,0},{0,15,1},{0,12,337},{0,12,337},{12,63,7350},{7,63,1450},{9,48,2190},{6,44,1422},{6,63,11045},{0,53,3293},{0,45,193}, +{0,35,4870},{0,39,12829},{0,32,6807},{17,63,3905},{12,63,9},{14,48,267},{11,43,446},{43,1,9669},{0,53,3293},{0,45,193},{0,35,4870},{63,12,9669},{0,35,4870},{7,63,1369},{7,63,1369},{7,63,1369},{6,40,1202},{0,61,2178},{0,42,53},{0,42,53},{0,25,520},{0,28,3645},{0,24,1573},{12,62,1},{12,62,1},{12,62,1},{12,37,2},{30,1,2178},{0,42,53},{0,42,53},{0,25,520},{61,0,2178}, +{0,25,520},{56,0,2665},{12,63,8},{20,46,5},{0,45,72},{56,0,2665},{62,25,2665},{0,45,72},{0,37,2669},{62,25,2665},{0,37,2669},{6,0,1201},{6,0,1201},{6,0,1201},{6,0,1201},{0,36,1},{0,36,1},{0,36,1},{0,18,1},{0,14,468},{0,14,468},{14,63,8614},{9,63,2129},{9,51,2758},{6,47,1822},{9,63,11765},{0,57,3125},{0,47,81},{0,36,4629},{0,42,13261},{0,35,6855},{20,63,4081}, +{15,63,49},{16,50,257},{13,45,446},{46,1,9669},{0,57,3125},{0,47,81},{0,36,4629},{63,15,9669},{0,36,4629},{9,63,1933},{9,63,1933},{9,63,1933},{7,42,1626},{1,63,2212},{0,45,13},{0,45,13},{0,27,421},{0,31,3957},{0,25,1673},{14,63,2},{14,63,2},{14,63,2},{14,39,2},{33,1,2178},{0,45,13},{0,45,13},{0,27,421},{63,2,2178},{0,27,421},{59,0,2665},{15,63,40},{22,48,2}, +{0,47,45},{59,0,2665},{62,28,2665},{0,47,45},{0,39,2669},{62,28,2665},{0,39,2669},{7,0,1625},{7,0,1625},{7,0,1625},{7,0,1625},{0,42,1},{0,42,1},{0,42,1},{0,21,1},{0,16,637},{0,16,637},{15,63,10085},{11,63,3185},{11,53,3481},{8,49,2337},{11,63,12845},{0,62,2958},{0,50,14},{0,38,4381},{0,45,13802},{0,36,6942},{23,63,4318},{17,63,154},{18,52,254},{14,48,456},{49,1,9669}, +{0,62,2958},{0,50,14},{0,38,4381},{46,27,9669},{0,38,4381},{10,63,2717},{10,63,2717},{10,63,2717},{8,45,2180},{3,63,2394},{0,49,0},{0,49,0},{0,30,317},{0,33,4314},{0,28,1811},{17,63,10},{17,63,10},{17,63,10},{16,41,1},{31,12,2178},{0,49,0},{0,49,0},{0,30,317},{62,6,2178},{0,30,317},{62,1,2665},{20,63,113},{24,50,4},{0,50,13},{62,1,2665},{63,31,2665},{0,50,13}, +{0,42,2669},{63,31,2665},{0,42,2669},{8,0,2180},{8,0,2180},{8,0,2180},{8,0,2180},{0,49,0},{0,49,0},{0,49,0},{0,25,1},{0,19,850},{0,19,850},{17,63,11454},{12,63,4143},{12,55,4141},{9,51,2805},{12,63,13803},{0,63,2871},{1,52,18},{0,41,4182},{0,50,14186},{0,39,6911},{26,63,4550},{20,63,306},{20,54,254},{17,49,446},{52,1,9669},{0,63,2870},{1,52,9},{0,41,4181},{46,30,9669}, +{0,41,4181},{12,63,3414},{12,63,3414},{12,63,3414},{9,47,2673},{3,63,2691},{1,52,14},{1,52,14},{0,32,245},{0,36,4587},{0,31,1906},{19,63,25},{19,63,25},{19,63,25},{18,43,1},{31,18,2178},{2,51,0},{2,51,0},{0,32,244},{62,9,2178},{0,32,244},{63,5,2665},{23,63,193},{26,52,4},{0,52,4},{63,5,2665},{63,34,2665},{0,52,4},{0,44,2669},{63,34,2665},{0,44,2669},{9,0,2669}, +{9,0,2669},{9,0,2669},{9,0,2669},{0,55,1},{0,55,1},{0,55,1},{0,28,2},{0,22,1009},{0,22,1009},{20,63,11990},{15,63,4575},{14,57,4141},{11,53,2805},{15,63,14195},{3,63,3015},{3,54,18},{0,43,4122},{0,53,13674},{0,41,6249},{29,63,4814},{23,63,522},{22,56,254},{19,51,446},{55,1,9669},{3,63,3006},{3,54,9},{0,43,4041},{47,32,9669},{0,43,4041},{14,63,3561},{14,63,3561},{14,63,3561}, +{11,49,2670},{6,63,2795},{3,54,14},{3,54,14},{2,34,245},{0,39,4227},{0,33,1470},{21,63,58},{21,63,58},{21,63,58},{20,45,1},{34,17,2178},{4,53,0},{4,53,0},{0,35,180},{62,12,2178},{0,35,180},{63,11,2665},{26,63,305},{28,54,4},{2,54,4},{63,11,2665},{63,37,2665},{2,54,4},{0,46,2669},{63,37,2665},{0,46,2669},{11,0,2669},{11,0,2669},{11,0,2669},{11,0,2669},{2,57,1}, +{2,57,1},{2,57,1},{2,30,2},{0,25,801},{0,25,801},{22,63,12554},{17,63,5066},{16,59,4118},{13,55,2805},{17,63,14614},{6,63,3255},{5,56,18},{1,45,4078},{0,56,13194},{0,44,5633},{31,63,5090},{26,63,802},{24,58,254},{21,53,446},{58,1,9669},{7,63,3198},{5,56,9},{0,45,3846},{53,32,9669},{0,45,3846},{15,63,3710},{15,63,3710},{15,63,3710},{13,51,2670},{9,63,2931},{5,56,14},{5,56,14}, +{4,36,245},{0,42,3899},{0,36,1110},{23,63,90},{23,63,90},{23,63,90},{22,47,1},{37,17,2178},{6,55,0},{6,55,0},{0,37,136},{62,15,2178},{0,37,136},{63,17,2665},{30,63,442},{30,56,4},{4,56,4},{63,17,2665},{63,40,2665},{4,56,4},{0,47,2677},{63,40,2665},{0,47,2677},{13,0,2669},{13,0,2669},{13,0,2669},{13,0,2669},{4,59,1},{4,59,1},{4,59,1},{4,31,5},{0,28,625}, +{0,28,625},{23,63,13130},{20,63,5706},{18,61,4122},{15,57,2807},{20,63,15102},{9,63,3625},{7,59,15},{3,47,4086},{0,59,12686},{0,47,5027},{34,63,5386},{29,63,1169},{26,60,257},{23,56,446},{62,0,9669},{12,63,3469},{7,59,11},{0,47,3658},{62,31,9669},{0,47,3658},{17,63,3905},{17,63,3905},{17,63,3905},{16,53,2677},{12,63,3112},{7,58,9},{7,58,9},{6,38,246},{0,45,3576},{0,38,755},{26,63,136}, +{26,63,136},{26,63,136},{24,49,4},{49,0,2178},{8,57,2},{8,57,2},{0,39,85},{62,18,2178},{0,39,85},{63,23,2665},{34,63,628},{32,59,2},{4,59,2},{63,23,2665},{63,43,2665},{4,59,2},{0,50,2669},{63,43,2665},{0,50,2669},{15,0,2677},{15,0,2677},{15,0,2677},{15,0,2677},{7,60,4},{7,60,4},{7,60,4},{7,33,5},{0,33,424},{0,33,424},{26,63,13650},{23,63,6378},{20,63,4122}, +{17,59,2799},{23,63,15558},{12,63,4065},{9,61,15},{6,49,4074},{0,62,12278},{0,49,4534},{36,63,5698},{30,63,1556},{28,62,257},{25,58,446},{63,4,9669},{15,63,3749},{9,61,11},{0,49,3510},{62,34,9669},{0,49,3510},{20,63,4041},{20,63,4041},{20,63,4041},{17,56,2670},{15,63,3304},{9,60,9},{9,60,9},{8,40,246},{0,50,3317},{0,41,499},{29,63,200},{29,63,200},{29,63,200},{26,51,4},{52,0,2178}, +{10,59,2},{10,59,2},{0,42,45},{62,21,2178},{0,42,45},{63,29,2665},{37,63,820},{34,61,2},{6,61,2},{63,29,2665},{63,46,2665},{6,61,2},{0,52,2669},{63,46,2665},{0,52,2669},{17,0,2669},{17,0,2669},{17,0,2669},{17,0,2669},{9,62,4},{9,62,4},{9,62,4},{9,35,5},{0,36,296},{0,36,296},{29,63,14234},{23,63,7050},{23,63,4242},{19,61,2799},{26,63,16046},{15,63,4601},{11,63,15}, +{8,51,4074},{0,63,12051},{0,50,4110},{37,63,6002},{34,63,1989},{31,63,270},{27,60,446},{63,10,9669},{20,63,4081},{11,63,11},{0,52,3374},{62,37,9669},{0,52,3374},{23,63,4241},{23,63,4241},{23,63,4241},{19,58,2670},{17,63,3485},{11,62,9},{11,62,9},{10,42,246},{0,53,3069},{0,43,306},{31,63,269},{31,63,269},{31,63,269},{28,53,4},{55,0,2178},{12,61,2},{12,61,2},{0,44,18},{62,24,2178}, +{0,44,18},{63,35,2665},{41,63,1037},{36,63,2},{8,63,2},{63,35,2665},{63,49,2665},{8,63,2},{0,54,2669},{63,49,2665},{0,54,2669},{19,0,2669},{19,0,2669},{19,0,2669},{19,0,2669},{11,63,5},{11,63,5},{11,63,5},{11,37,5},{0,40,193},{0,40,193},{31,63,13639},{26,63,7005},{25,63,4454},{21,62,2721},{28,63,15204},{17,63,4285},{13,63,24},{9,52,3457},{0,63,11020},{0,52,3109},{40,63,5381}, +{34,63,1890},{33,63,346},{29,61,296},{62,16,8712},{23,63,3636},{14,63,2},{0,53,2676},{62,39,8712},{0,53,2676},{25,63,4454},{25,63,4454},{25,63,4454},{21,60,2670},{19,63,3707},{13,63,24},{13,63,24},{12,44,246},{0,56,2853},{0,45,153},{33,63,346},{33,63,346},{33,63,346},{30,55,4},{58,0,2178},{14,63,2},{14,63,2},{0,46,10},{62,27,2178},{0,46,10},{63,39,2178},{44,63,872},{39,63,1}, +{14,63,1},{63,39,2178},{47,59,2178},{14,63,1},{0,55,2180},{47,59,2178},{0,55,2180},{21,0,2669},{21,0,2669},{21,0,2669},{21,0,2669},{13,63,20},{13,63,20},{13,63,20},{13,39,5},{0,45,104},{0,45,104},{33,63,12766},{29,63,6930},{26,63,4694},{24,63,2685},{29,63,14014},{20,63,3898},{16,63,101},{13,53,2722},{3,63,10057},{0,54,2129},{43,63,4689},{37,63,1718},{36,63,452},{32,62,164},{63,19,7578}, +{26,63,3078},{18,63,17},{0,55,1905},{63,41,7578},{0,55,1905},{26,63,4694},{26,63,4694},{26,63,4694},{24,61,2670},{22,63,3960},{16,63,101},{16,63,101},{14,47,242},{0,59,2650},{0,48,49},{36,63,452},{36,63,452},{36,63,452},{33,57,4},{53,16,2178},{18,63,17},{18,63,17},{0,49,1},{63,30,2178},{0,49,1},{63,42,1625},{46,63,650},{42,63,0},{21,63,0},{63,42,1625},{62,53,1625},{21,63,0}, +{0,56,1625},{62,53,1625},{0,56,1625},{24,0,2669},{24,0,2669},{24,0,2669},{24,0,2669},{15,63,50},{15,63,50},{15,63,50},{15,42,2},{0,48,40},{0,48,40},{34,63,11970},{31,63,6969},{29,63,4878},{26,63,2670},{31,63,13161},{21,63,3638},{18,63,229},{15,55,2146},{6,63,9313},{0,56,1410},{43,63,4097},{40,63,1614},{37,63,541},{34,62,69},{58,32,6661},{29,63,2654},{21,63,65},{0,56,1346},{52,48,6661}, +{0,56,1346},{29,63,4878},{29,63,4878},{29,63,4878},{26,63,2670},{23,63,4206},{18,63,229},{18,63,229},{15,49,242},{0,62,2506},{0,51,9},{37,63,541},{37,63,541},{37,63,541},{35,59,4},{56,16,2178},{21,63,65},{21,63,65},{2,51,1},{62,33,2178},{2,51,1},{63,45,1201},{48,63,481},{45,63,0},{27,63,0},{63,45,1201},{63,54,1201},{27,63,0},{0,57,1201},{63,54,1201},{0,57,1201},{26,0,2669}, +{26,0,2669},{26,0,2669},{26,0,2669},{17,63,85},{17,63,85},{17,63,85},{16,44,4},{0,51,8},{0,51,8},{37,63,11370},{33,63,6958},{31,63,5145},{28,63,2718},{34,63,12263},{23,63,3410},{21,63,405},{17,56,1665},{9,63,8665},{0,57,905},{46,63,3585},{43,63,1574},{40,63,637},{36,63,20},{63,27,5829},{32,63,2294},{26,63,130},{0,57,901},{63,45,5829},{0,57,901},{31,63,5145},{31,63,5145},{31,63,5145}, +{28,63,2718},{26,63,4430},{21,63,405},{21,63,405},{18,50,246},{0,63,2520},{2,53,9},{40,63,637},{40,63,637},{40,63,637},{37,61,4},{59,16,2178},{26,63,130},{26,63,130},{4,53,1},{62,36,2178},{4,53,1},{63,48,841},{51,63,337},{48,63,1},{33,63,0},{63,48,841},{62,56,841},{33,63,0},{0,58,841},{62,56,841},{0,58,841},{28,0,2669},{28,0,2669},{28,0,2669},{28,0,2669},{20,63,117}, +{20,63,117},{20,63,117},{18,46,4},{1,54,1},{1,54,1},{37,63,10794},{34,63,6895},{34,63,5374},{30,63,2813},{36,63,11574},{26,63,3274},{23,63,622},{19,57,1222},{13,63,8106},{1,59,562},{48,63,3170},{43,63,1494},{43,63,765},{39,63,4},{63,31,5082},{34,63,1998},{29,63,218},{0,59,554},{63,47,5082},{0,59,554},{34,63,5374},{34,63,5374},{34,63,5374},{30,63,2813},{29,63,4686},{23,63,622},{23,63,622}, +{20,52,246},{4,63,2714},{4,55,9},{43,63,765},{43,63,765},{43,63,765},{39,63,4},{62,16,2178},{29,63,218},{29,63,218},{6,55,1},{62,39,2178},{6,55,1},{63,51,545},{54,63,225},{51,63,1},{39,63,0},{63,51,545},{63,57,545},{39,63,0},{0,59,545},{63,57,545},{0,59,545},{30,0,2669},{30,0,2669},{30,0,2669},{30,0,2669},{22,63,180},{22,63,180},{22,63,180},{21,47,5},{3,56,1}, +{3,56,1},{40,63,10197},{37,63,6930},{36,63,5678},{32,63,2993},{37,63,10780},{29,63,3229},{26,63,945},{21,59,853},{17,63,7593},{4,60,293},{48,63,2756},{46,63,1454},{45,63,914},{41,63,37},{63,35,4344},{38,63,1740},{32,63,360},{2,60,289},{63,49,4344},{2,60,289},{36,63,5678},{36,63,5678},{36,63,5678},{32,63,2993},{31,63,5067},{26,63,945},{26,63,945},{22,55,242},{9,63,2979},{6,57,10},{45,63,914}, +{45,63,914},{45,63,914},{41,63,37},{63,21,2178},{32,63,360},{32,63,360},{8,57,1},{63,42,2178},{8,57,1},{63,54,288},{55,63,125},{54,63,0},{45,63,1},{63,54,288},{62,59,288},{45,63,1},{0,60,288},{62,59,288},{0,60,288},{32,0,2669},{32,0,2669},{32,0,2669},{32,0,2669},{25,63,250},{25,63,250},{25,63,250},{23,50,2},{5,59,2},{5,59,2},{43,63,9837},{40,63,7042},{37,63,5945}, +{34,63,3198},{40,63,10204},{32,63,3344},{29,63,1289},{24,59,589},{20,63,7225},{7,61,130},{51,63,2436},{48,63,1460},{48,63,1060},{43,63,122},{63,39,3779},{41,63,1580},{37,63,505},{6,61,129},{47,59,3779},{6,61,129},{37,63,5945},{37,63,5945},{37,63,5945},{34,63,3198},{34,63,5304},{29,63,1289},{29,63,1289},{24,57,242},{13,63,3261},{8,59,10},{48,63,1060},{48,63,1060},{48,63,1060},{43,63,122},{63,27,2178}, +{37,63,505},{37,63,505},{10,59,1},{63,45,2178},{10,59,1},{63,57,128},{58,63,53},{57,63,0},{51,63,0},{63,57,128},{63,60,128},{51,63,0},{0,61,128},{63,60,128},{0,61,128},{34,0,2669},{34,0,2669},{34,0,2669},{34,0,2669},{27,63,337},{27,63,337},{27,63,337},{25,52,2},{7,61,2},{7,61,2},{43,63,9437},{40,63,7154},{40,63,6193},{37,63,3454},{42,63,9783},{34,63,3398},{32,63,1740}, +{26,61,397},{23,63,6953},{9,62,37},{53,63,2246},{51,63,1508},{50,63,1213},{46,63,250},{63,43,3299},{44,63,1484},{40,63,673},{10,62,33},{63,53,3299},{10,62,33},{40,63,6193},{40,63,6193},{40,63,6193},{37,63,3454},{37,63,5624},{32,63,1740},{32,63,1740},{26,59,242},{17,63,3589},{10,61,10},{50,63,1213},{50,63,1213},{50,63,1213},{46,63,250},{63,33,2178},{40,63,673},{40,63,673},{12,61,1},{47,56,2178}, +{12,61,1},{63,60,32},{61,63,13},{60,63,0},{57,63,0},{63,60,32},{62,62,32},{57,63,0},{0,62,32},{62,62,32},{0,62,32},{36,0,2669},{36,0,2669},{36,0,2669},{36,0,2669},{29,63,405},{29,63,405},{29,63,405},{27,54,2},{9,63,2},{9,63,2},{46,63,9141},{43,63,7234},{43,63,6505},{40,63,3806},{43,63,9340},{37,63,3622},{34,63,2149},{27,62,277},{27,63,6772},{12,63,10},{54,63,2052}, +{53,63,1601},{51,63,1348},{48,63,436},{63,47,2904},{47,63,1452},{44,63,872},{14,63,1},{63,55,2904},{14,63,1},{43,63,6505},{43,63,6505},{43,63,6505},{40,63,3806},{40,63,5976},{34,63,2149},{34,63,2149},{28,61,242},{21,63,3955},{12,63,10},{51,63,1348},{51,63,1348},{51,63,1348},{48,63,436},{63,39,2178},{44,63,872},{44,63,872},{14,63,1},{47,59,2178},{14,63,1},{63,63,0},{63,63,0},{63,63,0}, +{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{38,0,2669},{38,0,2669},{38,0,2669},{38,0,2669},{32,63,520},{32,63,520},{32,63,520},{29,56,2},{12,63,10},{12,63,10},{46,63,8097},{46,63,6510},{43,63,5893},{41,63,3605},{46,63,8074},{37,63,3244},{37,63,2019},{30,62,129},{30,63,5794},{16,63,58},{56,63,1563},{54,63,1161},{54,63,1017},{51,63,337},{63,49,2166}, +{49,63,1083},{46,63,650},{21,63,0},{63,56,2166},{21,63,0},{43,63,5893},{43,63,5893},{43,63,5893},{41,63,3605},{40,63,5238},{37,63,2019},{37,63,2019},{30,62,113},{24,63,3401},{16,63,58},{54,63,1017},{54,63,1017},{54,63,1017},{51,63,337},{63,42,1625},{46,63,650},{46,63,650},{21,63,0},{62,53,1625},{21,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0}, +{0,63,0},{63,63,0},{0,63,0},{40,0,2665},{40,0,2665},{40,0,2665},{40,0,2665},{34,63,610},{34,63,610},{34,63,610},{31,58,0},{16,63,58},{16,63,58},{48,63,7165},{46,63,5854},{46,63,5325},{43,63,3434},{46,63,7050},{40,63,2932},{37,63,1955},{32,62,57},{32,63,5021},{20,63,117},{57,63,1137},{54,63,889},{54,63,745},{52,63,250},{63,51,1601},{51,63,801},{48,63,481},{27,63,0},{63,57,1601}, +{27,63,0},{46,63,5325},{46,63,5325},{46,63,5325},{43,63,3434},{43,63,4622},{37,63,1955},{37,63,1955},{32,62,41},{27,63,2977},{20,63,117},{54,63,745},{54,63,745},{54,63,745},{52,63,250},{63,45,1201},{48,63,481},{48,63,481},{27,63,0},{63,54,1201},{27,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{42,0,2665}, +{42,0,2665},{42,0,2665},{42,0,2665},{37,63,730},{37,63,730},{37,63,730},{33,60,1},{20,63,117},{20,63,117},{50,63,6415},{48,63,5277},{48,63,4877},{45,63,3330},{48,63,6117},{43,63,2716},{40,63,1843},{35,63,10},{35,63,4341},{23,63,205},{57,63,801},{57,63,609},{56,63,530},{54,63,169},{63,53,1121},{52,63,571},{51,63,337},{33,63,0},{63,58,1121},{33,63,0},{48,63,4877},{48,63,4877},{48,63,4877}, +{45,63,3330},{45,63,4146},{40,63,1843},{40,63,1843},{35,63,10},{30,63,2617},{23,63,205},{56,63,530},{56,63,530},{56,63,530},{54,63,169},{63,48,841},{51,63,337},{51,63,337},{33,63,0},{62,56,841},{33,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{44,0,2665},{44,0,2665},{44,0,2665},{44,0,2665},{39,63,865}, +{39,63,865},{39,63,865},{35,62,1},{23,63,205},{23,63,205},{51,63,5637},{50,63,4826},{48,63,4445},{47,63,3189},{48,63,5365},{43,63,2524},{43,63,1795},{37,63,5},{37,63,3750},{27,63,320},{59,63,531},{57,63,401},{57,63,337},{55,63,122},{63,55,726},{55,63,363},{54,63,225},{39,63,0},{63,59,726},{39,63,0},{48,63,4445},{48,63,4445},{48,63,4445},{47,63,3189},{46,63,3654},{43,63,1795},{43,63,1795}, +{37,63,5},{32,63,2329},{27,63,320},{57,63,337},{57,63,337},{57,63,337},{55,63,122},{63,51,545},{54,63,225},{54,63,225},{39,63,0},{63,57,545},{39,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{46,0,2665},{46,0,2665},{46,0,2665},{46,0,2665},{40,63,1010},{40,63,1010},{40,63,1010},{37,63,5},{27,63,320}, +{27,63,320},{3,63,10504},{0,62,1552},{0,44,169},{0,38,3866},{0,57,18065},{0,39,12152},{0,35,6099},{0,24,13992},{0,26,19423},{0,22,14922},{6,63,10216},{0,62,1552},{0,44,169},{0,38,3866},{20,17,18065},{0,39,12152},{0,35,6099},{0,24,13992},{57,0,18065},{0,24,13992},{0,35,0},{0,35,0},{0,35,0},{0,17,1},{0,17,1105},{0,14,424},{0,14,424},{0,8,666},{0,8,1217},{0,7,766},{0,35,0}, +{0,35,0},{0,35,0},{0,17,1},{9,0,1105},{0,14,424},{0,14,424},{0,8,666},{17,0,1105},{0,8,666},{34,17,9248},{0,62,1552},{0,44,169},{0,38,3866},{34,17,9248},{62,12,9248},{0,38,3866},{0,28,9256},{62,12,9248},{0,28,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{5,63,11298},{0,63,1341},{0,47,65}, +{0,38,3578},{0,61,19334},{0,42,12584},{0,36,6093},{0,24,14696},{0,28,20850},{0,24,15720},{6,63,10792},{0,63,1341},{0,47,65},{0,38,3578},{30,1,19334},{0,42,12584},{0,36,6093},{0,24,14696},{61,0,19334},{0,24,14696},{0,41,0},{0,41,0},{0,41,0},{0,20,1},{0,20,1513},{0,16,585},{0,16,585},{0,10,901},{0,9,1681},{0,8,1070},{0,41,0},{0,41,0},{0,41,0},{0,20,1},{10,1,1513}, +{0,16,585},{0,16,585},{0,10,901},{20,0,1513},{0,10,901},{37,17,9248},{0,63,1341},{0,47,65},{0,38,3578},{37,17,9248},{62,15,9248},{0,38,3578},{0,30,9256},{62,15,9248},{0,30,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,12200},{0,63,1325},{0,49,9},{0,41,3298},{0,63,20705},{0,42,13032},{0,38,6147}, +{0,27,15400},{0,31,22426},{0,25,16626},{9,63,11512},{0,63,1325},{0,49,9},{0,41,3298},{31,3,20689},{0,42,13032},{0,38,6147},{0,27,15400},{63,1,20689},{0,27,15400},{0,47,0},{0,47,0},{0,47,0},{0,23,1},{0,23,1985},{0,19,769},{0,19,769},{0,11,1202},{0,11,2193},{0,10,1374},{0,47,0},{0,47,0},{0,47,0},{0,23,1},{12,0,1985},{0,19,769},{0,19,769},{0,11,1202},{23,0,1985}, +{0,11,1202},{48,1,9248},{0,63,1325},{0,49,9},{0,41,3298},{48,1,9248},{63,17,9248},{0,41,3298},{0,32,9250},{63,17,9248},{0,32,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,13288},{0,63,1565},{0,51,4},{0,44,3050},{2,63,22214},{0,45,13496},{0,41,6227},{0,28,16225},{0,31,24090},{0,27,17528},{9,63,12344}, +{0,63,1565},{0,51,4},{0,44,3050},{34,1,22129},{0,45,13496},{0,41,6227},{0,28,16225},{63,3,22129},{0,28,16225},{0,53,0},{0,53,0},{0,53,0},{0,26,1},{0,26,2521},{0,22,985},{0,22,985},{0,13,1517},{0,11,2801},{0,11,1766},{0,53,0},{0,53,0},{0,53,0},{0,26,1},{13,1,2521},{0,22,985},{0,22,985},{0,13,1517},{26,0,2521},{0,13,1517},{51,1,9248},{1,63,1552},{1,51,0}, +{0,44,3050},{51,1,9248},{63,20,9248},{0,44,3050},{0,34,9250},{63,20,9248},{0,34,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{6,63,14818},{1,63,2106},{0,54,58},{0,47,2792},{3,63,24091},{0,50,14075},{0,42,6341},{0,30,17106},{0,33,26067},{0,28,18692},{12,63,13474},{3,63,2077},{1,54,50},{0,47,2792},{31,12,23851}, +{0,50,14075},{0,42,6341},{0,30,17106},{62,6,23851},{0,30,17106},{0,59,1},{0,59,1},{0,59,1},{0,30,0},{0,30,3200},{0,25,1258},{0,25,1258},{0,13,1940},{0,14,3542},{0,13,2229},{0,59,1},{0,59,1},{0,59,1},{0,30,0},{15,0,3200},{0,25,1258},{0,25,1258},{0,13,1940},{30,0,3200},{0,13,1940},{55,0,9248},{6,63,1885},{3,53,2},{0,47,2792},{55,0,9248},{62,24,9248},{0,47,2792}, +{0,36,9256},{62,24,9248},{0,36,9256},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{9,63,16258},{3,63,2813},{1,56,141},{0,49,2561},{4,63,25971},{0,50,14619},{0,45,6453},{0,32,17996},{0,36,27923},{0,30,19698},{12,63,14594},{3,63,2669},{2,56,122},{0,49,2561},{38,1,25472},{0,50,14619},{0,45,6453},{0,32,17996},{45,16,25472}, +{0,32,17996},{0,63,9},{0,63,9},{0,63,9},{0,33,1},{0,33,3872},{0,25,1530},{0,25,1530},{0,16,2378},{0,14,4294},{0,14,2717},{0,63,9},{0,63,9},{0,63,9},{0,33,1},{16,1,3872},{0,25,1530},{0,25,1530},{0,16,2378},{33,0,3872},{0,16,2378},{58,0,9248},{9,63,2205},{5,55,2},{0,49,2561},{58,0,9248},{62,27,9248},{0,49,2561},{0,38,9256},{62,27,9248},{0,38,9256},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{9,63,17750},{3,63,3617},{1,58,254},{0,50,2366},{6,63,27563},{0,53,14891},{0,47,6385},{0,32,18616},{0,39,29523},{0,32,20465},{15,63,15654},{6,63,3425},{2,59,206},{0,50,2366},{41,0,26744},{0,53,14891},{0,47,6385},{0,32,18616},{62,10,26744},{0,32,18616},{1,63,101},{1,63,101},{1,63,101}, +{0,36,5},{0,36,4420},{0,28,1666},{0,28,1666},{0,16,2642},{0,16,4931},{0,16,3083},{2,63,72},{2,63,72},{2,63,72},{1,35,4},{15,7,4418},{0,28,1666},{0,28,1666},{0,16,2642},{31,3,4418},{0,16,2642},{61,0,9248},{13,63,2554},{7,57,2},{0,50,2362},{61,0,9248},{62,30,9248},{0,50,2362},{0,40,9256},{62,30,9248},{0,40,9256},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,2,0}, +{0,2,0},{0,2,0},{0,1,0},{0,1,1},{0,1,1},{12,63,19046},{4,63,4598},{3,60,382},{0,52,2237},{6,63,28187},{0,59,14347},{0,50,5579},{0,35,18104},{0,39,29955},{0,33,20313},{17,63,16091},{7,63,4046},{4,61,206},{0,52,2237},{44,0,26744},{0,59,14347},{0,50,5579},{0,35,18104},{62,13,26744},{0,35,18104},{2,63,264},{2,63,264},{2,63,264},{1,38,52},{0,42,4420},{0,33,1381},{0,33,1381}, +{0,18,2405},{0,19,5115},{0,18,2981},{4,63,117},{4,63,117},{4,63,117},{3,37,4},{15,13,4418},{0,33,1381},{0,33,1381},{0,18,2405},{31,6,4418},{0,18,2405},{63,2,9248},{17,63,2938},{9,59,2},{0,52,2137},{63,2,9248},{46,41,9248},{0,52,2137},{0,42,9256},{46,41,9248},{0,42,9256},{1,0,52},{1,0,52},{1,0,52},{1,0,52},{0,8,0},{0,8,0},{0,8,0},{0,4,0},{0,3,20}, +{0,3,20},{12,63,20585},{6,63,5786},{4,63,625},{1,56,2246},{9,63,29012},{0,62,13736},{0,53,4760},{0,38,17595},{0,45,30452},{0,36,20086},{20,63,16620},{9,63,4794},{6,63,205},{1,56,2230},{39,16,26744},{0,62,13736},{0,53,4760},{0,38,17595},{62,16,26744},{0,38,17595},{4,63,589},{4,63,589},{4,63,589},{2,41,185},{0,49,4418},{0,36,1097},{0,36,1097},{0,21,2153},{0,22,5357},{0,21,2937},{6,63,169}, +{6,63,169},{6,63,169},{5,39,2},{24,1,4418},{0,36,1097},{0,36,1097},{0,21,2153},{49,0,4418},{0,21,2153},{59,16,9248},{20,63,3380},{11,62,4},{0,55,1901},{59,16,9248},{62,36,9248},{0,55,1901},{0,45,9250},{62,36,9248},{0,45,9250},{2,0,185},{2,0,185},{2,0,185},{2,0,185},{0,14,1},{0,14,1},{0,14,1},{0,7,1},{0,5,72},{0,5,72},{15,63,21605},{9,63,6850},{5,63,978}, +{2,57,2226},{11,63,29435},{0,63,12990},{0,55,3962},{0,41,16835},{0,45,30392},{0,38,19516},{22,63,16694},{12,63,5218},{9,63,225},{4,56,2130},{49,1,26259},{0,63,12990},{0,55,3962},{0,41,16835},{46,27,26259},{0,41,16835},{5,63,978},{5,63,978},{5,63,978},{3,43,370},{0,55,4418},{0,39,881},{0,39,881},{0,24,1945},{0,25,5605},{0,22,2889},{9,63,225},{9,63,225},{9,63,225},{7,41,2},{27,1,4418}, +{0,39,881},{0,39,881},{0,24,1945},{55,0,4418},{0,24,1945},{63,14,8978},{23,63,3592},{14,63,1},{0,58,1625},{63,14,8978},{46,47,8978},{0,58,1625},{0,46,8986},{46,47,8978},{0,46,8986},{3,0,369},{3,0,369},{3,0,369},{3,0,369},{0,20,0},{0,20,0},{0,20,0},{0,10,1},{0,8,136},{0,8,136},{15,63,21141},{9,63,7026},{6,63,1481},{3,58,2034},{12,63,28216},{0,63,11406},{0,56,2868}, +{0,41,14915},{0,48,28876},{0,39,17854},{23,63,15352},{15,63,4866},{11,63,306},{6,58,1746},{52,0,24371},{0,63,11406},{0,56,2868},{0,41,14915},{62,21,24371},{0,41,14915},{6,63,1481},{6,63,1481},{6,63,1481},{4,46,617},{0,61,4418},{0,45,689},{0,45,689},{0,27,1769},{0,28,5885},{0,24,2889},{11,63,306},{11,63,306},{11,63,306},{9,43,2},{30,1,4418},{0,45,689},{0,45,689},{0,27,1769},{61,0,4418}, +{0,27,1769},{55,32,7938},{26,63,3176},{16,63,1},{0,58,1129},{55,32,7938},{46,48,7938},{0,58,1129},{0,47,7946},{46,48,7938},{0,47,7946},{4,0,617},{4,0,617},{4,0,617},{4,0,617},{0,26,0},{0,26,0},{0,26,0},{0,13,1},{0,11,232},{0,11,232},{17,63,20849},{9,63,7458},{8,63,2106},{4,59,1970},{12,63,27224},{0,63,10078},{0,58,1986},{0,42,13214},{0,50,27357},{0,41,16276},{26,63,14168}, +{17,63,4556},{14,63,394},{9,58,1410},{47,14,22568},{0,63,10078},{0,58,1986},{0,42,13214},{62,23,22568},{0,42,13214},{8,63,2106},{8,63,2106},{8,63,2106},{5,48,930},{1,63,4452},{0,47,521},{0,47,521},{0,28,1600},{0,31,6197},{0,27,2921},{14,63,394},{14,63,394},{14,63,394},{11,45,2},{33,1,4418},{0,47,521},{0,47,521},{0,28,1600},{63,2,4418},{0,28,1600},{56,33,6962},{29,63,2792},{19,63,1}, +{0,59,740},{56,33,6962},{49,48,6962},{0,59,740},{0,48,6964},{49,48,6962},{0,48,6964},{5,0,929},{5,0,929},{5,0,929},{5,0,929},{0,32,0},{0,32,0},{0,32,0},{0,16,0},{0,14,360},{0,14,360},{17,63,20651},{12,63,7922},{9,63,2921},{5,60,2052},{15,63,26270},{0,63,8890},{0,59,1154},{0,44,11309},{0,53,25875},{0,42,14658},{26,63,12890},{20,63,4254},{16,63,493},{10,59,1076},{56,0,20642}, +{0,63,8890},{0,59,1154},{0,44,11309},{62,25,20642},{0,44,11309},{9,63,2921},{9,63,2921},{9,63,2921},{6,51,1360},{3,63,4634},{0,50,346},{0,50,346},{0,31,1402},{0,33,6554},{0,28,2987},{16,63,493},{16,63,493},{16,63,493},{13,48,1},{31,12,4418},{0,50,346},{0,50,346},{0,31,1402},{62,6,4418},{0,31,1402},{63,23,5941},{30,63,2386},{23,63,1},{0,61,388},{63,23,5941},{63,43,5941},{0,61,388}, +{0,49,5945},{63,43,5941},{0,49,5945},{6,0,1360},{6,0,1360},{6,0,1360},{6,0,1360},{0,39,0},{0,39,0},{0,39,0},{0,19,1},{0,16,522},{0,16,522},{20,63,20683},{12,63,8578},{11,63,3792},{7,60,2241},{15,63,25566},{1,63,8090},{0,59,642},{0,45,9834},{0,53,24595},{0,44,13350},{29,63,11794},{20,63,4030},{17,63,610},{13,59,804},{58,0,19021},{3,63,8050},{0,59,642},{0,45,9834},{62,27,19021}, +{0,45,9834},{11,63,3792},{11,63,3792},{11,63,3792},{8,53,1808},{3,63,4954},{0,55,232},{0,55,232},{0,33,1241},{0,36,6922},{0,31,3051},{17,63,610},{17,63,610},{17,63,610},{15,50,1},{31,18,4418},{0,55,232},{0,55,232},{0,33,1241},{62,9,4418},{0,33,1241},{63,26,5101},{34,63,2050},{26,63,1},{0,61,164},{63,26,5101},{62,45,5101},{0,61,164},{0,50,5105},{62,45,5101},{0,50,5105},{7,0,1808}, +{7,0,1808},{7,0,1808},{7,0,1808},{0,45,0},{0,45,0},{0,45,0},{0,22,1},{0,19,706},{0,19,706},{20,63,20715},{15,63,9258},{12,63,4729},{8,61,2553},{17,63,25067},{3,63,7474},{0,61,264},{0,47,8373},{0,56,23451},{0,45,12138},{31,63,10854},{23,63,3766},{20,63,698},{16,60,594},{60,0,17485},{6,63,7274},{0,61,264},{0,47,8373},{56,32,17485},{0,47,8373},{12,63,4729},{12,63,4729},{12,63,4729}, +{8,56,2320},{6,63,5386},{0,59,130},{0,59,130},{0,35,1076},{0,39,7322},{0,33,3161},{20,63,698},{20,63,698},{20,63,698},{17,51,2},{34,17,4418},{0,59,130},{0,59,130},{0,35,1076},{62,12,4418},{0,35,1076},{63,29,4325},{35,63,1733},{29,63,1},{0,62,41},{63,29,4325},{63,46,4325},{0,62,41},{0,51,4329},{63,46,4325},{0,51,4329},{8,0,2320},{8,0,2320},{8,0,2320},{8,0,2320},{0,50,1}, +{0,50,1},{0,50,1},{0,25,1},{0,19,914},{0,19,914},{20,63,21003},{15,63,10106},{14,63,5840},{9,62,2993},{17,63,24683},{3,63,7010},{0,62,74},{0,49,7113},{0,56,22427},{0,47,11094},{33,63,9941},{26,63,3566},{23,63,818},{17,61,402},{62,0,16034},{9,63,6562},{0,62,74},{0,49,7113},{62,31,16034},{0,49,7113},{14,63,5840},{14,63,5840},{14,63,5840},{10,58,2896},{6,63,5962},{0,62,58},{0,62,58}, +{0,38,932},{0,42,7754},{0,35,3317},{23,63,818},{23,63,818},{23,63,818},{19,53,2},{37,17,4418},{0,62,58},{0,62,58},{0,38,932},{62,15,4418},{0,38,932},{63,32,3613},{38,63,1445},{32,63,1},{0,63,0},{63,32,3613},{61,48,3613},{0,63,0},{0,52,3617},{61,48,3613},{0,52,3617},{9,0,2896},{9,0,2896},{9,0,2896},{9,0,2896},{0,56,1},{0,56,1},{0,56,1},{0,28,1},{0,22,1130}, +{0,22,1130},{23,63,21401},{17,63,11165},{15,63,7141},{10,63,3641},{20,63,24533},{6,63,6762},{0,63,81},{0,49,5745},{0,59,21333},{0,47,9996},{34,63,8897},{29,63,3396},{26,63,976},{20,61,224},{56,16,14504},{12,63,5834},{1,63,68},{0,49,5745},{62,33,14504},{0,49,5745},{15,63,7141},{15,63,7141},{15,63,7141},{11,61,3617},{9,63,6772},{0,63,81},{0,63,81},{0,41,794},{0,45,8260},{0,38,3515},{26,63,976}, +{26,63,976},{26,63,976},{21,56,0},{49,0,4418},{1,63,68},{1,63,68},{0,41,794},{62,18,4418},{0,41,794},{63,35,2888},{41,63,1156},{35,63,0},{7,63,0},{63,35,2888},{63,49,2888},{7,63,0},{0,53,2896},{63,49,2888},{0,53,2896},{11,0,3617},{11,0,3617},{11,0,3617},{11,0,3617},{0,63,0},{0,63,0},{0,63,0},{0,32,1},{0,25,1413},{0,25,1413},{23,63,21913},{17,63,12317},{17,63,8473}, +{12,63,4330},{20,63,24437},{6,63,6650},{2,63,298},{0,52,4721},{0,62,20509},{0,49,9157},{37,63,8153},{29,63,3268},{28,63,1129},{23,61,128},{63,6,13235},{15,63,5258},{6,63,145},{0,52,4721},{62,35,13235},{0,52,4721},{17,63,8473},{17,63,8473},{17,63,8473},{12,63,4330},{9,63,7636},{2,63,298},{2,63,298},{0,42,689},{0,45,8740},{0,39,3689},{28,63,1129},{28,63,1129},{28,63,1129},{23,58,0},{52,0,4418}, +{6,63,145},{6,63,145},{0,42,689},{62,21,4418},{0,42,689},{63,38,2312},{43,63,925},{38,63,0},{13,63,0},{63,38,2312},{62,51,2312},{13,63,0},{0,54,2320},{62,51,2312},{0,54,2320},{12,0,4329},{12,0,4329},{12,0,4329},{12,0,4329},{1,63,52},{1,63,52},{1,63,52},{0,34,1},{0,28,1693},{0,28,1693},{26,63,22641},{20,63,13461},{17,63,9881},{13,63,5169},{20,63,24597},{6,63,6794},{3,63,649}, +{0,52,3713},{0,62,19773},{0,50,8413},{37,63,7401},{32,63,3181},{29,63,1280},{24,62,48},{63,11,12051},{18,63,4746},{9,63,233},{0,52,3713},{47,45,12051},{0,52,3713},{17,63,9881},{17,63,9881},{17,63,9881},{13,63,5169},{12,63,8644},{3,63,649},{3,63,649},{0,45,569},{0,50,9245},{0,42,3905},{29,63,1280},{29,63,1280},{29,63,1280},{25,60,0},{55,0,4418},{9,63,233},{9,63,233},{0,45,569},{62,24,4418}, +{0,45,569},{63,41,1800},{46,63,725},{41,63,0},{19,63,0},{63,41,1800},{63,52,1800},{19,63,0},{0,55,1808},{63,52,1800},{0,55,1808},{13,0,5105},{13,0,5105},{13,0,5105},{13,0,5105},{2,63,185},{2,63,185},{2,63,185},{0,37,1},{0,31,2005},{0,31,2005},{26,63,23345},{20,63,14805},{20,63,11441},{14,63,6170},{23,63,24893},{9,63,7066},{4,63,1236},{0,53,2900},{0,63,19260},{0,52,7861},{40,63,6753}, +{34,63,3038},{32,63,1465},{27,63,9},{62,16,10952},{21,63,4298},{12,63,353},{0,53,2900},{62,39,10952},{0,53,2900},{20,63,11441},{20,63,11441},{20,63,11441},{14,63,6170},{12,63,9764},{4,63,1236},{4,63,1236},{0,47,458},{0,50,9789},{0,45,4185},{32,63,1465},{32,63,1465},{32,63,1465},{27,62,0},{58,0,4418},{12,63,353},{12,63,353},{0,47,458},{62,27,4418},{0,47,458},{63,44,1352},{48,63,544},{44,63,0}, +{25,63,0},{63,44,1352},{62,54,1352},{25,63,0},{0,56,1360},{62,54,1352},{0,56,1360},{14,0,5945},{14,0,5945},{14,0,5945},{14,0,5945},{3,63,400},{3,63,400},{3,63,400},{0,40,1},{0,33,2336},{0,33,2336},{26,63,24443},{23,63,16415},{20,63,13259},{15,63,7448},{23,63,25379},{9,63,7606},{6,63,2021},{0,55,2045},{0,63,18918},{0,53,7275},{40,63,6141},{37,63,2978},{34,63,1625},{29,63,10},{63,19,9818}, +{24,63,3870},{17,63,530},{0,55,2045},{63,41,9818},{0,55,2045},{20,63,13259},{20,63,13259},{20,63,13259},{15,63,7448},{15,63,11218},{6,63,2021},{6,63,2021},{0,49,365},{0,53,10427},{0,45,4509},{34,63,1625},{34,63,1625},{34,63,1625},{29,63,10},{53,16,4418},{17,63,530},{17,63,530},{0,49,365},{63,30,4418},{0,49,365},{63,47,925},{51,63,377},{47,63,1},{31,63,1},{63,47,925},{63,55,925},{31,63,1}, +{0,58,929},{63,55,925},{0,58,929},{15,0,6964},{15,0,6964},{15,0,6964},{15,0,6964},{3,63,769},{3,63,769},{3,63,769},{0,44,0},{0,36,2745},{0,36,2745},{29,63,25483},{23,63,17983},{22,63,15066},{17,63,8739},{23,63,26083},{12,63,8302},{6,63,2965},{0,56,1458},{0,63,18886},{0,53,6955},{43,63,5581},{40,63,2986},{37,63,1801},{32,63,65},{58,32,8901},{27,63,3558},{20,63,698},{0,56,1458},{52,48,8901}, +{0,56,1458},{22,63,15066},{22,63,15066},{22,63,15066},{17,63,8739},{15,63,12626},{6,63,2965},{6,63,2965},{0,52,277},{0,56,11011},{0,49,4833},{37,63,1801},{37,63,1801},{37,63,1801},{32,63,65},{56,16,4418},{20,63,698},{20,63,698},{0,52,277},{62,33,4418},{0,52,277},{63,50,613},{52,63,250},{50,63,0},{37,63,0},{63,50,613},{62,57,613},{37,63,0},{0,59,617},{62,57,613},{0,59,617},{16,0,7946}, +{16,0,7946},{16,0,7946},{16,0,7946},{5,63,1184},{5,63,1184},{5,63,1184},{0,47,0},{0,36,3145},{0,36,3145},{29,63,26667},{26,63,19695},{23,63,16891},{18,63,10206},{26,63,26795},{12,63,9118},{9,63,4037},{0,58,933},{0,63,19110},{0,56,6699},{46,63,5181},{40,63,2970},{40,63,2009},{34,63,160},{63,27,8069},{30,63,3310},{23,63,898},{0,58,933},{63,45,8069},{0,58,933},{23,63,16891},{23,63,16891},{23,63,16891}, +{18,63,10206},{17,63,14179},{9,63,4037},{9,63,4037},{0,55,221},{0,59,11627},{0,50,5115},{40,63,2009},{40,63,2009},{40,63,2009},{34,63,160},{59,16,4418},{23,63,898},{23,63,898},{0,55,221},{62,36,4418},{0,55,221},{63,53,365},{55,63,146},{53,63,0},{43,63,0},{63,53,365},{63,58,365},{43,63,0},{0,60,369},{63,58,365},{0,60,369},{16,0,8986},{16,0,8986},{16,0,8986},{16,0,8986},{6,63,1665}, +{6,63,1665},{6,63,1665},{0,50,1},{0,39,3545},{0,39,3545},{31,63,26643},{26,63,20231},{26,63,17731},{20,63,10867},{26,63,26531},{15,63,9546},{12,63,4889},{0,59,590},{0,63,18606},{0,56,5707},{46,63,4781},{43,63,2978},{42,63,2228},{37,63,320},{63,31,7322},{32,63,3134},{27,63,1125},{0,59,554},{63,47,7322},{0,59,554},{26,63,17731},{26,63,17731},{26,63,17731},{20,63,10867},{20,63,15043},{12,63,4889},{12,63,4889}, +{1,56,185},{0,62,11315},{0,53,4667},{42,63,2228},{42,63,2228},{42,63,2228},{37,63,320},{62,16,4418},{27,63,1125},{27,63,1125},{0,56,162},{62,39,4418},{0,56,162},{63,56,181},{57,63,73},{56,63,0},{49,63,0},{63,56,181},{62,60,181},{49,63,0},{0,61,185},{62,60,181},{0,61,185},{18,0,9250},{18,0,9250},{18,0,9250},{18,0,9250},{8,63,1972},{8,63,1972},{8,63,1972},{1,52,4},{0,42,3341}, +{0,42,3341},{34,63,26006},{29,63,20400},{28,63,18273},{23,63,11384},{29,63,25736},{17,63,9864},{12,63,5726},{2,60,366},{0,63,18111},{0,59,4452},{48,63,4436},{46,63,3050},{43,63,2465},{40,63,562},{63,35,6584},{37,63,3006},{30,63,1421},{0,61,237},{63,49,6584},{0,61,237},{28,63,18273},{28,63,18273},{28,63,18273},{23,63,11384},{23,63,15704},{12,63,5726},{12,63,5726},{3,59,189},{0,63,10886},{0,56,3924},{43,63,2465}, +{43,63,2465},{43,63,2465},{40,63,562},{63,21,4418},{30,63,1421},{30,63,1421},{0,59,100},{63,42,4418},{0,59,100},{63,59,52},{60,63,20},{59,63,1},{56,63,0},{63,59,52},{63,61,52},{56,63,0},{0,62,52},{63,61,52},{0,62,52},{20,0,9256},{20,0,9256},{20,0,9256},{20,0,9256},{9,63,2205},{9,63,2205},{9,63,2205},{4,54,1},{0,45,2925},{0,45,2925},{34,63,25526},{31,63,20721},{29,63,18700}, +{24,63,11921},{31,63,25279},{20,63,10264},{15,63,6494},{4,62,238},{4,63,17924},{0,59,3588},{51,63,4228},{48,63,3140},{46,63,2665},{41,63,833},{63,39,6019},{40,63,2958},{34,63,1693},{0,62,84},{47,59,6019},{0,62,84},{29,63,18700},{29,63,18700},{29,63,18700},{24,63,11921},{23,63,16280},{15,63,6494},{15,63,6494},{5,61,189},{0,63,10854},{0,59,3332},{46,63,2665},{46,63,2665},{46,63,2665},{41,63,833},{63,27,4418}, +{34,63,1693},{34,63,1693},{0,61,61},{63,45,4418},{0,61,61},{63,62,4},{63,63,4},{62,63,1},{62,63,0},{63,62,4},{62,63,4},{62,63,0},{0,63,4},{62,63,4},{0,63,4},{22,0,9256},{22,0,9256},{22,0,9256},{22,0,9256},{12,63,2389},{12,63,2389},{12,63,2389},{6,56,1},{0,50,2512},{0,50,2512},{37,63,24250},{34,63,19895},{31,63,18169},{26,63,11820},{34,63,23717},{20,63,10012},{17,63,6584}, +{7,62,122},{6,63,16879},{0,62,2736},{51,63,3648},{48,63,2784},{48,63,2384},{43,63,778},{63,42,5163},{41,63,2584},{37,63,1549},{0,63,9},{46,61,5163},{0,63,9},{31,63,18169},{31,63,18169},{31,63,18169},{26,63,11820},{26,63,15620},{17,63,6584},{17,63,6584},{7,62,106},{0,63,10150},{0,59,2624},{48,63,2384},{48,63,2384},{48,63,2384},{43,63,778},{63,31,3872},{37,63,1549},{37,63,1549},{0,63,9},{63,47,3872}, +{0,63,9},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{24,0,9256},{24,0,9256},{24,0,9256},{24,0,9256},{15,63,2605},{15,63,2605},{15,63,2605},{8,58,1},{0,53,2176},{0,53,2176},{37,63,22746},{34,63,18775},{34,63,17254},{29,63,11564},{34,63,21973},{23,63,9532},{20,63,6424},{9,62,57},{9,63,15607},{0,62,2032},{53,63,3058}, +{51,63,2304},{48,63,2000},{46,63,650},{63,43,4267},{43,63,2134},{40,63,1285},{4,63,0},{63,53,4267},{4,63,0},{34,63,17254},{34,63,17254},{34,63,17254},{29,63,11564},{29,63,14692},{20,63,6424},{20,63,6424},{9,62,41},{0,63,9366},{0,62,2016},{48,63,2000},{48,63,2000},{48,63,2000},{46,63,650},{55,49,3200},{40,63,1285},{40,63,1285},{4,63,0},{63,48,3200},{4,63,0},{63,63,0},{63,63,0},{63,63,0}, +{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{26,0,9256},{26,0,9256},{26,0,9256},{26,0,9256},{17,63,2836},{17,63,2836},{17,63,2836},{10,60,1},{0,59,1856},{0,59,1856},{40,63,21168},{37,63,17685},{34,63,16300},{30,63,11323},{37,63,20205},{26,63,9090},{23,63,6310},{12,63,4},{12,63,14287},{0,62,1546},{54,63,2377},{51,63,1809},{51,63,1553},{47,63,520},{61,49,3361}, +{46,63,1683},{43,63,1018},{11,63,0},{63,54,3361},{11,63,0},{34,63,16300},{34,63,16300},{34,63,16300},{30,63,11323},{29,63,13666},{23,63,6310},{23,63,6310},{12,63,4},{3,63,8686},{0,62,1530},{51,63,1553},{51,63,1553},{51,63,1553},{47,63,520},{63,37,2521},{43,63,1018},{43,63,1018},{11,63,0},{62,50,2521},{11,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0}, +{0,63,0},{63,63,0},{0,63,0},{29,0,9250},{29,0,9250},{29,0,9250},{29,0,9250},{20,63,3114},{20,63,3114},{20,63,3114},{12,62,1},{0,62,1514},{0,62,1514},{40,63,19824},{37,63,16725},{37,63,15500},{32,63,11084},{37,63,18685},{26,63,8770},{26,63,6270},{14,63,16},{15,63,13215},{0,63,1325},{54,63,1881},{54,63,1449},{51,63,1249},{48,63,409},{63,47,2649},{47,63,1329},{44,63,797},{16,63,1},{63,55,2649}, +{16,63,1},{37,63,15500},{37,63,15500},{37,63,15500},{32,63,11084},{31,63,12906},{26,63,6270},{26,63,6270},{14,63,16},{6,63,8150},{0,63,1325},{51,63,1249},{51,63,1249},{51,63,1249},{48,63,409},{63,40,1985},{44,63,797},{44,63,797},{16,63,1},{63,51,1985},{16,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{31,0,9250}, +{31,0,9250},{31,0,9250},{31,0,9250},{22,63,3393},{22,63,3393},{22,63,3393},{14,63,16},{0,63,1325},{0,63,1325},{43,63,18608},{40,63,15853},{37,63,14796},{34,63,10841},{40,63,17341},{29,63,8410},{26,63,6206},{17,63,74},{17,63,12226},{0,63,1341},{56,63,1451},{54,63,1081},{54,63,937},{51,63,305},{63,50,2017},{49,63,1011},{47,63,605},{22,63,1},{62,57,2017},{22,63,1},{37,63,14796},{37,63,14796},{37,63,14796}, +{34,63,10841},{34,63,12089},{26,63,6206},{26,63,6206},{17,63,74},{9,63,7678},{0,63,1341},{54,63,937},{54,63,937},{54,63,937},{51,63,305},{63,43,1513},{47,63,605},{47,63,605},{22,63,1},{62,53,1513},{22,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{32,0,9256},{32,0,9256},{32,0,9256},{32,0,9256},{23,63,3650}, +{23,63,3650},{23,63,3650},{17,63,74},{0,63,1341},{0,63,1341},{43,63,17392},{40,63,15021},{40,63,14060},{37,63,10673},{40,63,16013},{32,63,8261},{29,63,6166},{19,63,194},{20,63,11338},{1,63,1594},{57,63,1041},{56,63,822},{54,63,697},{52,63,234},{63,51,1473},{51,63,737},{49,63,442},{28,63,1},{63,57,1473},{28,63,1},{40,63,14060},{40,63,14060},{40,63,14060},{37,63,10673},{34,63,11401},{29,63,6166},{29,63,6166}, +{19,63,194},{12,63,7270},{1,63,1594},{54,63,697},{54,63,697},{54,63,697},{52,63,234},{63,46,1105},{49,63,442},{49,63,442},{28,63,1},{63,54,1105},{28,63,1},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{63,63,0},{0,63,0},{63,63,0},{0,63,0},{34,0,9256},{34,0,9256},{34,0,9256},{34,0,9256},{26,63,3898},{26,63,3898},{26,63,3898},{19,63,194},{1,63,1594}, +{1,63,1594}, diff --git a/ext/basis_universal/basisu_transcoder_tables_pvrtc2_45.inc b/ext/basis_universal/basisu_transcoder_tables_pvrtc2_45.inc new file mode 100644 index 0000000000..fbaf988d78 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_pvrtc2_45.inc @@ -0,0 +1,481 @@ +{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{0,1,52},{0,0,68},{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,1,35},{0,1,27},{0,1,18},{0,1,61},{0,1,43},{0,1,61},{0,1,1},{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1}, +{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,2,20},{0,1,10},{0,1,1},{0,1,9},{0,2,20},{0,1,18},{0,1,9},{0,1,36},{0,1,18},{0,1,36},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,4,56},{0,3,38},{0,2,52}, +{0,2,36},{0,4,56},{0,3,35},{0,2,0},{0,2,52},{0,2,88},{0,1,78},{0,4,56},{0,3,38},{0,2,52},{0,2,36},{1,0,52},{0,3,35},{0,2,0},{0,2,52},{1,1,51},{0,2,52},{0,3,37},{0,3,37},{0,3,37},{0,2,36},{0,3,10},{0,2,0},{0,2,0},{0,1,5},{0,1,35},{0,1,14},{0,3,37},{0,3,37},{0,3,37},{0,2,36},{0,3,10}, +{0,2,0},{0,2,0},{0,1,5},{1,0,16},{0,1,5},{1,1,18},{0,3,2},{0,2,16},{0,2,0},{1,1,18},{2,0,20},{0,2,0},{0,2,36},{2,0,20},{0,2,36},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{1,4,88},{1,3,78},{1,3,69},{1,3,77},{1,3,115},{0,4,88},{0,3,98}, +{0,3,101},{0,4,72},{0,3,38},{1,4,24},{1,3,14},{1,3,5},{1,3,13},{1,3,51},{0,4,24},{0,3,34},{0,3,37},{3,0,52},{0,3,37},{1,3,69},{1,3,69},{1,3,69},{1,2,72},{1,2,72},{1,2,72},{1,2,72},{1,2,72},{0,3,11},{0,2,24},{1,3,5},{1,3,5},{1,3,5},{1,2,8},{1,2,8},{1,2,8},{1,2,8},{1,2,8},{1,2,8}, +{1,2,8},{0,7,18},{1,3,10},{1,3,1},{0,3,9},{0,7,18},{1,3,18},{0,3,9},{0,3,36},{1,3,18},{0,3,36},{1,0,68},{1,0,68},{1,0,68},{1,0,68},{1,1,65},{1,1,65},{1,1,65},{0,3,65},{0,3,2},{0,3,2},{1,6,56},{1,5,38},{1,4,53},{1,4,37},{1,6,56},{1,5,35},{1,4,1},{1,4,66},{0,5,60},{0,4,70},{1,6,56}, +{1,5,38},{1,4,53},{1,4,37},{0,9,51},{1,5,35},{1,4,1},{0,4,54},{2,3,51},{0,4,54},{1,5,37},{1,5,37},{1,5,37},{1,4,36},{1,5,10},{1,4,0},{1,4,0},{1,3,5},{0,5,11},{1,3,14},{1,5,37},{1,5,37},{1,5,37},{1,4,36},{0,8,8},{1,4,0},{1,4,0},{1,3,5},{4,0,8},{1,3,5},{2,3,18},{1,5,2},{1,4,17}, +{1,4,1},{2,3,18},{4,1,18},{1,4,1},{0,4,50},{4,1,18},{0,4,50},{1,0,36},{1,0,36},{1,0,36},{1,0,36},{1,4,0},{1,4,0},{1,4,0},{1,3,1},{1,3,10},{1,3,10},{2,6,88},{2,5,78},{2,5,69},{2,5,77},{2,5,115},{2,5,107},{2,5,98},{1,5,117},{1,6,60},{1,5,36},{2,6,24},{2,5,14},{2,5,5},{2,5,13},{3,2,51}, +{1,6,35},{2,5,34},{1,5,36},{1,6,51},{1,5,36},{2,5,69},{2,5,69},{2,5,69},{2,4,72},{2,4,72},{2,4,72},{2,4,72},{2,4,72},{1,5,16},{1,5,36},{2,5,5},{2,5,5},{2,5,5},{2,4,8},{3,1,8},{2,4,8},{2,4,8},{2,4,8},{3,3,8},{2,4,8},{3,3,20},{2,5,10},{2,5,1},{2,5,9},{3,3,20},{2,5,18},{2,5,9}, +{0,5,36},{2,5,18},{0,5,36},{2,0,68},{2,0,68},{2,0,68},{2,0,68},{2,3,68},{2,3,68},{2,3,68},{2,4,68},{1,5,0},{1,5,0},{2,8,56},{2,7,38},{2,6,52},{2,6,36},{2,8,56},{2,7,35},{2,6,0},{2,6,52},{1,7,76},{1,6,70},{2,8,56},{2,7,38},{2,6,52},{2,6,36},{4,1,51},{2,7,35},{2,6,0},{1,6,45},{3,5,51}, +{1,6,45},{2,7,37},{2,7,37},{2,7,37},{2,6,36},{2,7,10},{2,6,0},{2,6,0},{2,5,5},{1,7,12},{2,5,14},{2,7,37},{2,7,37},{2,7,37},{2,6,36},{4,0,8},{2,6,0},{2,6,0},{2,5,5},{1,7,8},{2,5,5},{3,5,18},{2,7,2},{2,6,16},{2,6,0},{3,5,18},{0,9,18},{2,6,0},{0,6,36},{0,9,18},{0,6,36},{2,0,36}, +{2,0,36},{2,0,36},{2,0,36},{2,6,0},{2,6,0},{2,6,0},{2,5,1},{1,7,8},{1,7,8},{3,8,88},{3,7,78},{3,7,69},{3,7,77},{3,7,115},{2,8,88},{2,7,98},{2,7,101},{1,9,67},{2,7,38},{3,8,24},{3,7,14},{3,7,5},{3,7,13},{3,7,51},{2,8,24},{2,7,34},{2,7,37},{8,0,51},{2,7,37},{3,7,69},{3,7,69},{3,7,69}, +{3,6,72},{3,6,72},{3,6,72},{3,6,72},{3,6,72},{2,7,11},{2,6,24},{3,7,5},{3,7,5},{3,7,5},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{3,6,8},{5,1,18},{3,7,10},{3,7,1},{2,7,9},{5,1,18},{3,7,18},{2,7,9},{0,7,36},{3,7,18},{0,7,36},{3,0,68},{3,0,68},{3,0,68},{3,0,68},{3,5,65}, +{3,5,65},{3,5,65},{2,7,65},{2,7,2},{2,7,2},{3,10,56},{3,9,38},{3,8,53},{3,8,37},{3,10,56},{3,9,35},{3,8,1},{3,8,66},{2,9,60},{2,8,70},{3,10,56},{3,9,38},{3,8,53},{3,8,37},{5,3,51},{3,9,35},{3,8,1},{2,8,54},{4,7,51},{2,8,54},{3,9,37},{3,9,37},{3,9,37},{3,8,36},{3,9,10},{3,8,0},{3,8,0}, +{3,7,5},{2,9,11},{3,7,14},{3,9,37},{3,9,37},{3,9,37},{3,8,36},{5,2,8},{3,8,0},{3,8,0},{3,7,5},{8,1,8},{3,7,5},{4,7,18},{3,9,2},{3,8,17},{3,8,1},{4,7,18},{8,2,18},{3,8,1},{0,8,50},{8,2,18},{0,8,50},{3,0,36},{3,0,36},{3,0,36},{3,0,36},{3,8,0},{3,8,0},{3,8,0},{3,7,1},{3,7,10}, +{3,7,10},{4,10,88},{4,9,78},{4,9,69},{4,9,77},{4,9,115},{4,9,107},{4,9,98},{3,9,117},{3,10,60},{3,9,36},{4,10,24},{4,9,14},{4,9,5},{4,9,13},{5,6,51},{3,10,35},{4,9,34},{3,9,36},{10,1,51},{3,9,36},{4,9,69},{4,9,69},{4,9,69},{4,8,72},{4,8,72},{4,8,72},{4,8,72},{4,8,72},{3,9,16},{3,9,36},{4,9,5}, +{4,9,5},{4,9,5},{4,8,8},{5,5,8},{4,8,8},{4,8,8},{4,8,8},{5,7,8},{4,8,8},{7,0,18},{4,9,10},{4,9,1},{4,9,9},{7,0,18},{4,9,18},{4,9,9},{0,9,36},{4,9,18},{0,9,36},{4,0,68},{4,0,68},{4,0,68},{4,0,68},{4,7,68},{4,7,68},{4,7,68},{4,8,68},{3,9,0},{3,9,0},{4,12,56},{4,11,38},{4,10,52}, +{4,10,36},{4,12,56},{4,11,35},{4,10,0},{4,10,52},{3,11,76},{3,10,70},{4,12,56},{4,11,38},{4,10,52},{4,10,36},{7,2,51},{4,11,35},{4,10,0},{3,10,45},{12,0,51},{3,10,45},{4,11,37},{4,11,37},{4,11,37},{4,10,36},{4,11,10},{4,10,0},{4,10,0},{4,9,5},{3,11,12},{4,9,14},{4,11,37},{4,11,37},{4,11,37},{4,10,36},{7,1,8}, +{4,10,0},{4,10,0},{4,9,5},{10,2,8},{4,9,5},{5,9,18},{4,11,2},{4,10,16},{4,10,0},{5,9,18},{10,3,18},{4,10,0},{0,10,36},{10,3,18},{0,10,36},{4,0,36},{4,0,36},{4,0,36},{4,0,36},{4,10,0},{4,10,0},{4,10,0},{4,9,1},{3,11,8},{3,11,8},{5,12,88},{5,11,78},{5,11,69},{5,11,77},{5,11,115},{4,12,88},{4,11,98}, +{4,11,101},{3,13,67},{4,11,38},{5,12,24},{5,11,14},{5,11,5},{5,11,13},{5,11,51},{4,12,24},{4,11,34},{4,11,37},{11,3,51},{4,11,37},{5,11,69},{5,11,69},{5,11,69},{5,10,72},{5,10,72},{5,10,72},{5,10,72},{5,10,72},{4,11,11},{4,10,24},{5,11,5},{5,11,5},{5,11,5},{5,10,8},{5,10,8},{5,10,8},{5,10,8},{5,10,8},{12,1,8}, +{5,10,8},{8,0,18},{5,11,10},{5,11,1},{4,11,9},{8,0,18},{12,2,18},{4,11,9},{0,11,36},{12,2,18},{0,11,36},{5,0,68},{5,0,68},{5,0,68},{5,0,68},{5,9,65},{5,9,65},{5,9,65},{4,11,65},{4,11,2},{4,11,2},{5,14,56},{5,13,38},{5,12,53},{5,12,37},{5,14,56},{5,13,35},{5,12,1},{5,12,66},{4,13,60},{4,12,70},{5,14,56}, +{5,13,38},{5,12,53},{5,12,37},{8,2,51},{5,13,35},{5,12,1},{4,12,54},{13,2,51},{4,12,54},{5,13,37},{5,13,37},{5,13,37},{5,12,36},{5,13,10},{5,12,0},{5,12,0},{5,11,5},{4,13,11},{5,11,14},{5,13,37},{5,13,37},{5,13,37},{5,12,36},{8,1,8},{5,12,0},{5,12,0},{5,11,5},{10,5,8},{5,11,5},{6,11,18},{5,13,2},{5,12,17}, +{5,12,1},{6,11,18},{15,0,18},{5,12,1},{0,12,50},{15,0,18},{0,12,50},{5,0,36},{5,0,36},{5,0,36},{5,0,36},{5,12,0},{5,12,0},{5,12,0},{5,11,1},{5,11,10},{5,11,10},{6,14,88},{6,13,78},{6,13,69},{6,13,77},{6,13,115},{6,13,107},{6,13,98},{5,13,117},{5,14,60},{5,13,36},{6,14,24},{6,13,14},{6,13,5},{6,13,13},{8,5,51}, +{5,14,35},{6,13,34},{5,13,36},{12,5,51},{5,13,36},{6,13,69},{6,13,69},{6,13,69},{6,12,72},{6,12,72},{6,12,72},{6,12,72},{6,12,72},{5,13,16},{5,13,36},{6,13,5},{6,13,5},{6,13,5},{6,12,8},{8,4,8},{6,12,8},{6,12,8},{6,12,8},{14,2,8},{6,12,8},{3,24,18},{6,13,10},{6,13,1},{6,13,9},{3,24,18},{14,3,18},{6,13,9}, +{0,13,36},{14,3,18},{0,13,36},{6,0,68},{6,0,68},{6,0,68},{6,0,68},{6,11,68},{6,11,68},{6,11,68},{6,12,68},{5,13,0},{5,13,0},{6,16,56},{6,15,38},{6,14,52},{6,14,36},{6,16,56},{6,15,35},{6,14,0},{6,14,52},{5,15,76},{5,14,70},{6,16,56},{6,15,38},{6,14,52},{6,14,36},{3,26,51},{6,15,35},{6,14,0},{5,14,45},{15,3,51}, +{5,14,45},{6,15,37},{6,15,37},{6,15,37},{6,14,36},{6,15,10},{6,14,0},{6,14,0},{6,13,5},{5,15,12},{6,13,14},{6,15,37},{6,15,37},{6,15,37},{6,14,36},{3,25,8},{6,14,0},{6,14,0},{6,13,5},{12,6,8},{6,13,5},{9,5,18},{6,15,2},{6,14,16},{6,14,0},{9,5,18},{12,7,18},{6,14,0},{0,14,36},{12,7,18},{0,14,36},{6,0,36}, +{6,0,36},{6,0,36},{6,0,36},{6,14,0},{6,14,0},{6,14,0},{6,13,1},{5,15,8},{5,15,8},{7,16,88},{7,15,78},{7,15,69},{7,15,77},{7,15,115},{6,16,88},{6,15,98},{6,15,101},{5,17,67},{6,15,38},{7,16,24},{7,15,14},{7,15,5},{7,15,13},{11,0,51},{6,16,24},{6,15,34},{6,15,37},{13,7,51},{6,15,37},{7,15,69},{7,15,69},{7,15,69}, +{7,14,72},{7,14,72},{7,14,72},{7,14,72},{7,14,72},{6,15,11},{6,14,24},{7,15,5},{7,15,5},{7,15,5},{7,14,8},{9,6,8},{7,14,8},{7,14,8},{7,14,8},{14,5,8},{7,14,8},{10,4,18},{7,15,10},{7,15,1},{6,15,9},{10,4,18},{14,6,18},{6,15,9},{0,15,36},{14,6,18},{0,15,36},{7,0,68},{7,0,68},{7,0,68},{7,0,68},{7,13,65}, +{7,13,65},{7,13,65},{6,15,65},{6,15,2},{6,15,2},{7,18,56},{7,17,38},{7,16,53},{7,16,37},{7,18,56},{7,17,35},{7,16,1},{7,16,66},{6,17,60},{6,16,70},{7,18,56},{7,17,38},{7,16,53},{7,16,37},{10,6,51},{7,17,35},{7,16,1},{6,16,54},{15,6,51},{6,16,54},{7,17,37},{7,17,37},{7,17,37},{7,16,36},{7,17,10},{7,16,0},{7,16,0}, +{7,15,5},{6,17,11},{7,15,14},{7,17,37},{7,17,37},{7,17,37},{7,16,36},{10,5,8},{7,16,0},{7,16,0},{7,15,5},{12,9,8},{7,15,5},{12,0,18},{7,17,2},{7,16,17},{7,16,1},{12,0,18},{12,10,18},{7,16,1},{0,16,50},{12,10,18},{0,16,50},{7,0,36},{7,0,36},{7,0,36},{7,0,36},{7,16,0},{7,16,0},{7,16,0},{7,15,1},{7,15,10}, +{7,15,10},{7,21,326},{7,19,322},{8,17,392},{7,17,322},{7,21,137},{7,18,116},{7,17,133},{7,17,117},{7,18,60},{7,17,36},{8,16,118},{8,16,134},{8,17,136},{8,17,136},{10,9,51},{7,18,35},{7,17,52},{7,17,36},{14,9,51},{7,17,36},{7,20,307},{7,20,307},{7,20,307},{7,18,307},{7,20,91},{7,18,91},{7,18,91},{7,16,110},{7,17,16},{7,17,36},{8,15,101}, +{8,15,101},{8,15,101},{8,16,101},{10,8,8},{7,18,10},{7,18,10},{7,16,29},{11,12,8},{7,16,29},{12,3,18},{7,19,16},{8,17,36},{7,17,16},{12,3,18},{11,13,18},{7,17,16},{0,17,36},{11,13,18},{0,17,36},{7,0,306},{7,0,306},{7,0,306},{7,0,306},{7,19,81},{7,19,81},{7,19,81},{7,17,81},{7,17,0},{7,17,0},{8,19,88},{8,18,78},{8,18,69}, +{8,18,77},{8,18,115},{8,18,107},{8,18,98},{8,17,136},{7,19,76},{7,18,70},{8,19,24},{8,18,14},{8,18,5},{8,18,13},{9,15,51},{8,18,43},{8,18,34},{7,18,45},{5,22,51},{7,18,45},{8,18,69},{8,18,69},{8,18,69},{8,17,72},{8,17,72},{8,17,72},{8,17,72},{8,17,72},{7,19,12},{7,18,70},{8,18,5},{8,18,5},{8,18,5},{8,17,8},{9,14,8}, +{8,17,8},{8,17,8},{8,17,8},{14,10,8},{8,17,8},{11,9,18},{8,18,10},{8,18,1},{8,18,9},{11,9,18},{14,11,18},{8,18,9},{0,18,36},{14,11,18},{0,18,36},{8,0,68},{8,0,68},{8,0,68},{8,0,68},{8,16,65},{8,16,65},{8,16,65},{8,17,68},{7,19,8},{7,19,8},{8,21,56},{8,20,38},{8,19,52},{8,19,36},{8,21,56},{8,20,35},{8,19,0}, +{8,19,52},{7,21,67},{8,18,78},{8,21,56},{8,20,38},{8,19,52},{8,19,36},{13,4,51},{8,20,35},{8,19,0},{8,19,52},{15,11,51},{8,19,52},{8,20,37},{8,20,37},{8,20,37},{8,19,36},{8,20,10},{8,19,0},{8,19,0},{8,18,5},{8,18,35},{8,18,14},{8,20,37},{8,20,37},{8,20,37},{8,19,36},{11,10,8},{8,19,0},{8,19,0},{8,18,5},{5,23,8}, +{8,18,5},{12,8,18},{8,20,2},{8,19,16},{8,19,0},{12,8,18},{11,16,18},{8,19,0},{0,19,36},{11,16,18},{0,19,36},{8,0,36},{8,0,36},{8,0,36},{8,0,36},{8,19,0},{8,19,0},{8,19,0},{8,18,1},{8,18,10},{8,18,10},{9,21,88},{9,20,78},{9,20,70},{9,20,78},{9,20,115},{8,21,88},{8,20,99},{8,20,115},{8,21,72},{8,20,52},{9,21,24}, +{9,20,14},{9,20,6},{9,20,14},{15,0,51},{8,21,24},{8,20,35},{8,20,51},{12,16,51},{8,20,51},{9,20,69},{9,20,69},{9,20,69},{9,19,72},{9,19,72},{9,19,72},{9,19,72},{9,19,72},{8,20,11},{8,19,24},{9,20,5},{9,20,5},{9,20,5},{9,19,8},{12,9,8},{9,19,8},{9,19,8},{9,19,8},{14,13,8},{9,19,8},{14,4,18},{9,20,10},{9,20,2}, +{8,20,10},{14,4,18},{14,14,18},{8,20,10},{0,20,50},{14,14,18},{0,20,50},{9,0,68},{9,0,68},{9,0,68},{9,0,68},{9,18,65},{9,18,65},{9,18,65},{8,20,65},{8,20,2},{8,20,2},{9,24,70},{9,22,58},{9,21,75},{9,21,51},{9,23,52},{9,22,25},{9,21,3},{9,21,46},{8,23,68},{8,21,70},{9,24,69},{9,22,57},{9,21,74},{9,21,50},{15,3,51}, +{9,22,24},{9,21,2},{8,21,45},{11,19,51},{8,21,45},{9,23,51},{9,23,51},{9,23,51},{9,21,51},{9,22,9},{9,21,3},{9,21,3},{9,20,9},{8,22,12},{9,20,12},{9,23,50},{9,23,50},{9,23,50},{9,21,50},{15,2,8},{9,21,2},{9,21,2},{9,20,8},{13,16,8},{9,20,8},{14,7,18},{9,22,8},{9,21,25},{9,21,1},{14,7,18},{13,17,18},{9,21,1}, +{0,21,36},{13,17,18},{0,21,36},{9,0,50},{9,0,50},{9,0,50},{9,0,50},{9,21,2},{9,21,2},{9,21,2},{9,20,5},{9,20,8},{9,20,8},{10,23,88},{10,22,78},{10,22,69},{10,22,77},{10,22,115},{10,22,107},{10,22,98},{9,22,117},{9,23,60},{9,22,36},{10,23,24},{10,22,14},{10,22,5},{10,22,13},{11,19,51},{9,23,35},{10,22,34},{9,22,36},{9,23,51}, +{9,22,36},{10,22,69},{10,22,69},{10,22,69},{10,21,72},{10,21,72},{10,21,72},{10,21,72},{10,21,72},{9,22,16},{9,22,36},{10,22,5},{10,22,5},{10,22,5},{10,21,8},{11,18,8},{10,21,8},{10,21,8},{10,21,8},{10,21,8},{10,21,8},{13,13,18},{10,22,10},{10,22,1},{10,22,9},{13,13,18},{15,16,18},{10,22,9},{0,22,36},{15,16,18},{0,22,36},{10,0,68}, +{10,0,68},{10,0,68},{10,0,68},{10,20,65},{10,20,65},{10,20,65},{10,21,68},{9,22,0},{9,22,0},{10,25,56},{10,24,38},{10,23,52},{10,23,36},{10,25,56},{10,24,35},{10,23,0},{10,23,52},{9,24,63},{9,23,70},{10,25,56},{10,24,38},{10,23,52},{10,23,36},{15,8,51},{10,24,35},{10,23,0},{9,23,45},{11,22,51},{9,23,45},{10,24,37},{10,24,37},{10,24,37}, +{10,23,36},{10,24,10},{10,23,0},{10,23,0},{10,22,5},{9,24,14},{10,22,14},{10,24,37},{10,24,37},{10,24,37},{10,23,36},{13,14,8},{10,23,0},{10,23,0},{10,22,5},{8,25,8},{10,22,5},{14,12,18},{10,24,2},{10,23,16},{10,23,0},{14,12,18},{13,20,18},{10,23,0},{0,23,36},{13,20,18},{0,23,36},{10,0,36},{10,0,36},{10,0,36},{10,0,36},{10,23,0}, +{10,23,0},{10,23,0},{10,22,1},{10,22,10},{10,22,10},{11,25,88},{11,24,78},{11,24,70},{11,24,78},{11,24,115},{10,25,88},{10,24,99},{10,24,115},{9,26,67},{10,24,52},{11,25,24},{11,24,14},{11,24,6},{11,24,14},{14,14,51},{10,25,24},{10,24,35},{10,24,51},{14,20,51},{10,24,51},{11,24,69},{11,24,69},{11,24,69},{11,23,72},{11,23,72},{11,23,72},{11,23,72}, +{11,23,72},{10,24,11},{10,23,24},{11,24,5},{11,24,5},{11,24,5},{11,23,8},{14,13,8},{11,23,8},{11,23,8},{11,23,8},{11,23,8},{11,23,8},{13,18,18},{11,24,10},{11,24,2},{10,24,10},{13,18,18},{11,24,18},{10,24,10},{0,24,50},{11,24,18},{0,24,50},{11,0,68},{11,0,68},{11,0,68},{11,0,68},{11,22,65},{11,22,65},{11,22,65},{10,24,65},{10,24,2}, +{10,24,2},{11,28,70},{11,26,58},{11,25,75},{11,25,51},{11,27,52},{11,26,25},{11,25,3},{11,25,46},{10,27,68},{10,25,70},{11,28,69},{11,26,57},{11,25,74},{11,25,50},{14,17,51},{11,26,24},{11,25,2},{10,25,45},{13,23,51},{10,25,45},{11,27,51},{11,27,51},{11,27,51},{11,25,51},{11,26,9},{11,25,3},{11,25,3},{11,24,9},{10,26,12},{11,24,12},{11,27,50}, +{11,27,50},{11,27,50},{11,25,50},{14,16,8},{11,25,2},{11,25,2},{11,24,8},{15,20,8},{11,24,8},{13,21,18},{11,26,8},{11,25,25},{11,25,1},{13,21,18},{15,21,18},{11,25,1},{0,25,36},{15,21,18},{0,25,36},{11,0,50},{11,0,50},{11,0,50},{11,0,50},{11,25,2},{11,25,2},{11,25,2},{11,24,5},{11,24,8},{11,24,8},{12,27,88},{12,26,78},{12,26,69}, +{12,26,77},{12,26,115},{12,26,107},{12,26,98},{11,26,117},{11,27,60},{11,26,36},{12,27,24},{12,26,14},{12,26,5},{12,26,13},{13,23,51},{11,27,35},{12,26,34},{11,26,36},{11,27,51},{11,26,36},{12,26,69},{12,26,69},{12,26,69},{12,25,72},{12,25,72},{12,25,72},{12,25,72},{12,25,72},{11,26,16},{11,26,36},{12,26,5},{12,26,5},{12,26,5},{12,25,8},{13,22,8}, +{12,25,8},{12,25,8},{12,25,8},{12,25,8},{12,25,8},{15,17,18},{12,26,10},{12,26,1},{12,26,9},{15,17,18},{12,26,18},{12,26,9},{0,26,36},{12,26,18},{0,26,36},{12,0,68},{12,0,68},{12,0,68},{12,0,68},{12,24,65},{12,24,65},{12,24,65},{12,25,68},{11,26,0},{11,26,0},{12,29,56},{12,28,38},{12,27,52},{12,27,36},{12,29,56},{12,28,35},{12,27,0}, +{12,27,52},{11,28,63},{11,27,70},{12,29,56},{12,28,38},{12,27,52},{12,27,36},{15,19,51},{12,28,35},{12,27,0},{11,27,45},{13,26,51},{11,27,45},{12,28,37},{12,28,37},{12,28,37},{12,27,36},{12,28,10},{12,27,0},{12,27,0},{12,26,5},{11,28,14},{12,26,14},{12,28,37},{12,28,37},{12,28,37},{12,27,36},{15,18,8},{12,27,0},{12,27,0},{12,26,5},{10,29,8}, +{12,26,5},{13,26,18},{12,28,2},{12,27,16},{12,27,0},{13,26,18},{15,24,18},{12,27,0},{0,27,36},{15,24,18},{0,27,36},{12,0,36},{12,0,36},{12,0,36},{12,0,36},{12,27,0},{12,27,0},{12,27,0},{12,26,1},{12,26,10},{12,26,10},{13,29,88},{13,28,78},{13,28,70},{13,28,78},{13,28,115},{12,29,88},{12,28,99},{12,28,115},{11,30,67},{12,28,52},{13,29,24}, +{13,28,14},{13,28,6},{13,28,14},{13,28,51},{12,29,24},{12,28,35},{12,28,51},{11,30,51},{12,28,51},{13,28,69},{13,28,69},{13,28,69},{13,27,72},{13,27,72},{13,27,72},{13,27,72},{13,27,72},{12,28,11},{12,27,24},{13,28,5},{13,28,5},{13,28,5},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{13,27,8},{15,22,18},{13,28,10},{13,28,2}, +{12,28,10},{15,22,18},{13,28,18},{12,28,10},{0,28,50},{13,28,18},{0,28,50},{13,0,68},{13,0,68},{13,0,68},{13,0,68},{13,26,65},{13,26,65},{13,26,65},{12,28,65},{12,28,2},{12,28,2},{13,31,76},{13,30,58},{13,29,75},{13,29,51},{13,31,52},{13,30,25},{13,29,3},{13,29,46},{12,31,68},{12,29,70},{13,31,75},{13,30,57},{13,29,74},{13,29,50},{13,31,51}, +{13,30,24},{13,29,2},{12,29,45},{15,27,51},{12,29,45},{13,31,51},{13,31,51},{13,31,51},{13,29,51},{13,30,9},{13,29,3},{13,29,3},{13,28,9},{12,30,12},{13,28,12},{13,31,50},{13,31,50},{13,31,50},{13,29,50},{13,30,8},{13,29,2},{13,29,2},{13,28,8},{12,30,8},{13,28,8},{15,25,18},{13,30,8},{13,29,25},{13,29,1},{15,25,18},{12,31,18},{13,29,1}, +{0,29,36},{12,31,18},{0,29,36},{13,0,50},{13,0,50},{13,0,50},{13,0,50},{13,29,2},{13,29,2},{13,29,2},{13,28,5},{13,28,8},{13,28,8},{14,31,88},{14,30,78},{14,30,69},{14,30,77},{14,30,115},{14,30,107},{14,30,98},{13,30,117},{13,31,60},{13,30,36},{14,31,24},{14,30,14},{14,30,5},{14,30,13},{15,27,51},{13,31,35},{14,30,34},{13,30,36},{13,31,51}, +{13,30,36},{14,30,69},{14,30,69},{14,30,69},{14,29,72},{14,29,72},{14,29,72},{14,29,72},{14,29,72},{13,30,16},{13,30,36},{14,30,5},{14,30,5},{14,30,5},{14,29,8},{15,26,8},{14,29,8},{14,29,8},{14,29,8},{14,29,8},{14,29,8},{14,31,20},{14,30,10},{14,30,1},{14,30,9},{14,31,20},{14,30,18},{14,30,9},{0,30,36},{14,30,18},{0,30,36},{14,0,68}, +{14,0,68},{14,0,68},{14,0,68},{14,28,65},{14,28,65},{14,28,65},{14,29,68},{13,30,0},{13,30,0},{14,31,152},{14,31,88},{14,31,52},{14,31,36},{14,31,116},{14,31,36},{14,31,0},{14,31,52},{14,31,88},{13,31,70},{15,30,118},{14,31,88},{14,31,52},{14,31,36},{15,29,52},{14,31,36},{14,31,0},{13,31,45},{15,30,51},{13,31,45},{14,31,52},{14,31,52},{14,31,52}, +{14,31,36},{14,31,16},{14,31,0},{14,31,0},{14,30,5},{14,30,35},{14,30,14},{14,31,52},{14,31,52},{14,31,52},{14,31,36},{15,28,10},{14,31,0},{14,31,0},{14,30,5},{15,29,16},{14,30,5},{15,30,18},{15,30,34},{14,31,16},{14,31,0},{15,30,18},{15,30,26},{14,31,0},{0,31,36},{15,30,26},{0,31,36},{14,0,36},{14,0,36},{14,0,36},{14,0,36},{14,31,0}, +{14,31,0},{14,31,0},{14,30,1},{14,30,10},{14,30,10},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{14,31,20},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68},{15,31,68}, +{15,31,68},{14,31,56},{14,31,20},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{15,0,68},{15,0,68},{15,0,68},{15,0,68},{15,30,65},{15,30,65},{15,30,65},{15,31,68},{14,31,20}, +{14,31,20},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{0,2,158},{0,2,110},{0,2,62},{0,1,115},{0,1,178},{0,1,124},{0,4,74},{0,3,20},{0,2,2},{0,2,26},{0,2,158},{0,2,110},{0,2,62},{0,1,115},{1,0,158},{0,1,115},{0,2,1},{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{0,0,25},{0,0,25},{0,2,1}, +{0,2,1},{0,2,1},{0,1,0},{0,1,13},{0,1,9},{0,1,9},{0,0,25},{0,0,25},{0,0,25},{1,0,74},{0,3,20},{0,2,2},{0,2,26},{1,0,74},{1,1,72},{0,2,26},{0,1,90},{1,1,72},{0,1,90},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,6,83},{0,5,13},{0,3,26}, +{0,3,14},{0,5,248},{0,3,140},{0,3,41},{0,2,139},{0,2,319},{0,2,175},{0,6,83},{0,5,13},{0,3,26},{0,3,14},{1,1,244},{0,3,140},{0,3,41},{0,2,139},{0,3,248},{0,2,139},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{0,3,52},{0,2,18},{0,2,18},{0,1,29},{0,1,77},{0,1,38},{0,4,10},{0,4,10},{0,4,10},{0,3,13},{0,3,52}, +{0,2,18},{0,2,18},{0,1,29},{1,0,58},{0,1,29},{1,3,72},{0,5,4},{0,3,17},{0,3,5},{1,3,72},{3,0,74},{0,3,5},{0,2,90},{3,0,74},{0,2,90},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{0,9,193},{0,7,125},{0,4,202},{0,4,122},{0,7,244},{0,5,96},{0,4,2}, +{0,3,106},{0,4,395},{0,3,187},{1,6,99},{1,5,45},{1,4,26},{1,4,50},{1,4,243},{0,5,96},{0,4,2},{0,3,106},{2,2,243},{0,3,106},{0,7,121},{0,7,121},{0,7,121},{0,4,122},{0,5,52},{0,4,2},{0,4,2},{0,3,25},{0,3,133},{0,2,62},{1,4,26},{1,4,26},{1,4,26},{1,3,25},{1,2,50},{0,4,2},{0,4,2},{0,3,25},{1,2,50}, +{0,3,25},{0,9,72},{0,7,4},{1,4,1},{0,4,1},{0,9,72},{2,3,72},{0,4,1},{0,3,90},{2,3,72},{0,3,90},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{1,8,164},{1,7,94},{1,5,106},{1,5,94},{0,10,292},{0,7,125},{0,5,81},{0,4,130},{0,6,364},{0,4,106},{1,8,83}, +{1,7,13},{1,5,25},{1,5,13},{3,0,243},{0,7,76},{0,5,32},{0,4,81},{5,0,243},{0,4,81},{1,6,91},{1,6,91},{1,6,91},{1,5,94},{0,8,99},{0,6,51},{0,6,51},{0,4,66},{0,4,107},{0,4,42},{1,6,10},{1,6,10},{1,6,10},{1,5,13},{0,8,50},{0,6,2},{0,6,2},{0,4,17},{4,0,50},{0,4,17},{3,2,74},{1,7,4},{1,5,16}, +{1,5,4},{3,2,74},{5,1,72},{1,5,4},{0,4,80},{5,1,72},{0,4,80},{1,0,90},{1,0,90},{1,0,90},{1,0,90},{0,6,50},{0,6,50},{0,6,50},{0,4,50},{0,3,20},{0,3,20},{1,11,218},{1,9,149},{1,7,242},{1,6,149},{1,10,248},{1,7,99},{1,6,5},{1,5,99},{0,7,308},{0,5,100},{2,8,99},{2,7,45},{2,6,27},{2,6,51},{3,3,243}, +{0,9,81},{1,6,5},{0,5,99},{4,3,243},{0,5,99},{1,9,145},{1,9,145},{1,9,145},{1,6,148},{1,8,52},{1,6,4},{1,6,4},{1,5,18},{0,6,72},{0,5,19},{2,6,26},{2,6,26},{2,6,26},{2,5,25},{3,1,50},{1,6,4},{1,6,4},{0,5,18},{3,3,50},{0,5,18},{4,1,72},{1,9,5},{2,6,2},{1,6,5},{4,1,72},{3,5,72},{1,6,5}, +{0,5,90},{3,5,72},{0,5,90},{1,0,144},{1,0,144},{1,0,144},{1,0,144},{1,6,0},{1,6,0},{1,6,0},{1,4,4},{0,6,8},{0,6,8},{2,10,164},{2,9,94},{2,7,107},{2,7,95},{1,12,307},{1,9,137},{1,7,115},{1,6,154},{0,9,253},{1,6,106},{2,10,83},{2,9,13},{2,7,26},{2,7,14},{4,2,243},{1,9,73},{2,7,41},{1,6,90},{6,2,243}, +{1,6,90},{2,8,91},{2,8,91},{2,8,91},{2,7,94},{1,10,116},{1,8,69},{1,8,69},{1,6,73},{0,8,50},{1,6,25},{2,8,10},{2,8,10},{2,8,10},{2,7,13},{4,0,50},{1,8,5},{1,8,5},{1,6,9},{1,7,50},{1,6,9},{3,7,72},{2,9,4},{2,7,17},{2,7,5},{3,7,72},{8,0,72},{2,7,5},{0,6,90},{8,0,72},{0,6,90},{2,0,90}, +{2,0,90},{2,0,90},{2,0,90},{1,9,65},{1,9,65},{1,9,65},{1,6,64},{0,7,10},{0,7,10},{2,13,194},{2,11,126},{2,8,203},{2,8,123},{2,11,245},{2,9,97},{2,8,3},{2,7,107},{0,11,249},{1,7,100},{3,10,99},{3,9,45},{3,8,26},{3,8,50},{3,8,243},{1,11,81},{2,8,2},{1,7,99},{4,6,243},{1,7,99},{2,11,122},{2,11,122},{2,11,122}, +{2,8,123},{2,9,53},{2,8,3},{2,8,3},{2,7,26},{1,8,62},{1,7,19},{3,8,26},{3,8,26},{3,8,26},{3,7,25},{3,6,50},{2,8,2},{2,8,2},{1,7,18},{3,6,50},{1,7,18},{5,3,72},{2,11,4},{3,8,1},{2,8,1},{5,3,72},{4,7,72},{2,8,1},{0,7,90},{4,7,72},{0,7,90},{2,0,122},{2,0,122},{2,0,122},{2,0,122},{2,8,2}, +{2,8,2},{2,8,2},{2,6,2},{1,7,10},{1,7,10},{3,12,164},{3,11,94},{3,9,106},{3,9,94},{2,14,292},{2,11,125},{2,9,81},{2,8,130},{1,11,253},{2,8,106},{3,12,83},{3,11,13},{3,9,25},{3,9,13},{5,4,243},{2,11,76},{2,9,32},{2,8,81},{9,1,243},{2,8,81},{3,10,91},{3,10,91},{3,10,91},{3,9,94},{2,12,99},{2,10,51},{2,10,51}, +{2,8,66},{1,10,50},{2,8,42},{3,10,10},{3,10,10},{3,10,10},{3,9,13},{5,2,50},{2,10,2},{2,10,2},{2,8,17},{8,1,50},{2,8,17},{1,19,72},{3,11,4},{3,9,16},{3,9,4},{1,19,72},{9,2,72},{3,9,4},{0,8,80},{9,2,72},{0,8,80},{3,0,90},{3,0,90},{3,0,90},{3,0,90},{2,10,50},{2,10,50},{2,10,50},{2,8,50},{1,9,9}, +{1,9,9},{3,15,218},{3,13,149},{3,11,242},{3,10,149},{3,14,248},{3,11,99},{3,10,5},{3,9,99},{1,13,244},{2,9,100},{4,12,99},{4,11,45},{4,10,27},{4,10,51},{5,7,243},{2,13,81},{3,10,5},{2,9,99},{6,7,243},{2,9,99},{3,13,145},{3,13,145},{3,13,145},{3,10,148},{3,12,52},{3,10,4},{3,10,4},{3,9,18},{1,12,56},{2,9,19},{4,10,26}, +{4,10,26},{4,10,26},{4,9,25},{5,5,50},{3,10,4},{3,10,4},{2,9,18},{5,7,50},{2,9,18},{7,2,72},{3,13,5},{4,10,2},{3,10,5},{7,2,72},{12,0,72},{3,10,5},{0,9,90},{12,0,72},{0,9,90},{3,0,144},{3,0,144},{3,0,144},{3,0,144},{3,10,0},{3,10,0},{3,10,0},{3,8,4},{2,10,8},{2,10,8},{4,14,164},{4,13,94},{4,11,107}, +{4,11,95},{3,16,307},{3,13,137},{3,11,115},{3,10,154},{2,13,253},{3,10,106},{4,14,83},{4,13,13},{4,11,26},{4,11,14},{7,3,243},{3,13,73},{4,11,41},{3,10,90},{11,2,243},{3,10,90},{4,12,91},{4,12,91},{4,12,91},{4,11,94},{3,14,116},{3,12,69},{3,12,69},{3,10,73},{2,12,50},{3,10,25},{4,12,10},{4,12,10},{4,12,10},{4,11,13},{7,1,50}, +{3,12,5},{3,12,5},{3,10,9},{10,2,50},{3,10,9},{5,11,72},{4,13,4},{4,11,17},{4,11,5},{5,11,72},{11,3,72},{4,11,5},{0,10,90},{11,3,72},{0,10,90},{4,0,90},{4,0,90},{4,0,90},{4,0,90},{3,13,65},{3,13,65},{3,13,65},{3,10,64},{2,11,10},{2,11,10},{4,17,194},{4,15,126},{4,12,203},{4,12,123},{4,15,245},{4,13,97},{4,12,3}, +{4,11,107},{2,15,249},{3,11,100},{5,14,99},{5,13,45},{5,12,26},{5,12,50},{5,12,243},{3,15,81},{4,12,2},{3,11,99},{13,1,243},{3,11,99},{4,15,122},{4,15,122},{4,15,122},{4,12,123},{4,13,53},{4,12,3},{4,12,3},{4,11,26},{3,12,62},{3,11,19},{5,12,26},{5,12,26},{5,12,26},{5,11,25},{5,10,50},{4,12,2},{4,12,2},{3,11,18},{12,1,50}, +{3,11,18},{8,2,72},{4,15,4},{5,12,1},{4,12,1},{8,2,72},{13,2,72},{4,12,1},{0,11,90},{13,2,72},{0,11,90},{4,0,122},{4,0,122},{4,0,122},{4,0,122},{4,12,2},{4,12,2},{4,12,2},{4,10,2},{3,11,10},{3,11,10},{5,16,164},{5,15,94},{5,13,106},{5,13,94},{4,18,292},{4,15,125},{4,13,81},{4,12,130},{3,15,253},{4,12,106},{5,16,83}, +{5,15,13},{5,13,25},{5,13,13},{8,3,243},{4,15,76},{4,13,32},{4,12,81},{11,5,243},{4,12,81},{5,14,91},{5,14,91},{5,14,91},{5,13,94},{4,16,99},{4,14,51},{4,14,51},{4,12,66},{3,14,50},{4,12,42},{5,14,10},{5,14,10},{5,14,10},{5,13,13},{8,1,50},{4,14,2},{4,14,2},{4,12,17},{10,5,50},{4,12,17},{3,23,72},{5,15,4},{5,13,16}, +{5,13,4},{3,23,72},{11,6,72},{5,13,4},{0,12,80},{11,6,72},{0,12,80},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{4,14,50},{4,14,50},{4,14,50},{4,12,50},{3,13,9},{3,13,9},{5,19,218},{5,17,149},{5,15,242},{5,14,149},{5,18,248},{5,15,99},{5,14,5},{5,13,99},{3,17,244},{4,13,100},{6,16,99},{6,15,45},{6,14,27},{6,14,51},{8,6,243}, +{4,17,81},{5,14,5},{4,13,99},{15,2,243},{4,13,99},{5,17,145},{5,17,145},{5,17,145},{5,14,148},{5,16,52},{5,14,4},{5,14,4},{5,13,18},{3,16,56},{4,13,19},{6,14,26},{6,14,26},{6,14,26},{6,13,25},{8,4,50},{5,14,4},{5,14,4},{4,13,18},{14,2,50},{4,13,18},{3,26,72},{5,17,5},{6,14,2},{5,14,5},{3,26,72},{15,3,72},{5,14,5}, +{0,13,90},{15,3,72},{0,13,90},{5,0,144},{5,0,144},{5,0,144},{5,0,144},{5,14,0},{5,14,0},{5,14,0},{5,12,4},{4,14,8},{4,14,8},{6,18,164},{6,17,94},{6,15,107},{6,15,95},{5,20,307},{5,17,137},{5,15,115},{5,14,154},{4,17,253},{5,14,106},{6,18,83},{6,17,13},{6,15,26},{6,15,14},{5,20,243},{5,17,73},{6,15,41},{5,14,90},{13,6,243}, +{5,14,90},{6,16,91},{6,16,91},{6,16,91},{6,15,94},{5,18,116},{5,16,69},{5,16,69},{5,14,73},{4,16,50},{5,14,25},{6,16,10},{6,16,10},{6,16,10},{6,15,13},{3,25,50},{5,16,5},{5,16,5},{5,14,9},{12,6,50},{5,14,9},{11,0,72},{6,17,4},{6,15,17},{6,15,5},{11,0,72},{13,7,72},{6,15,5},{0,14,90},{13,7,72},{0,14,90},{6,0,90}, +{6,0,90},{6,0,90},{6,0,90},{5,17,65},{5,17,65},{5,17,65},{5,14,64},{4,15,10},{4,15,10},{6,21,194},{6,19,126},{6,16,203},{6,16,123},{6,19,245},{6,17,97},{6,16,3},{6,15,107},{4,19,249},{5,15,100},{7,18,99},{7,17,45},{7,16,26},{7,16,50},{11,1,243},{5,19,81},{6,16,2},{5,15,99},{15,5,243},{5,15,99},{6,19,122},{6,19,122},{6,19,122}, +{6,16,123},{6,17,53},{6,16,3},{6,16,3},{6,15,26},{5,16,62},{5,15,19},{7,16,26},{7,16,26},{7,16,26},{7,15,25},{9,6,50},{6,16,2},{6,16,2},{5,15,18},{14,5,50},{5,15,18},{10,6,72},{6,19,4},{7,16,1},{6,16,1},{10,6,72},{15,6,72},{6,16,1},{0,15,90},{15,6,72},{0,15,90},{6,0,122},{6,0,122},{6,0,122},{6,0,122},{6,16,2}, +{6,16,2},{6,16,2},{6,14,2},{5,15,10},{5,15,10},{7,20,164},{7,19,94},{7,17,106},{7,17,94},{6,22,292},{6,19,125},{6,17,81},{6,16,130},{5,19,253},{6,16,106},{7,20,83},{7,19,13},{7,17,25},{7,17,13},{10,7,243},{6,19,76},{6,17,32},{6,16,81},{13,9,243},{6,16,81},{7,18,91},{7,18,91},{7,18,91},{7,17,94},{6,20,99},{6,18,51},{6,18,51}, +{6,16,66},{5,18,50},{6,16,42},{7,18,10},{7,18,10},{7,18,10},{7,17,13},{10,5,50},{6,18,2},{6,18,2},{6,16,17},{12,9,50},{6,16,17},{12,2,72},{7,19,4},{7,17,16},{7,17,4},{12,2,72},{13,10,72},{7,17,4},{0,16,80},{13,10,72},{0,16,80},{7,0,90},{7,0,90},{7,0,90},{7,0,90},{6,18,50},{6,18,50},{6,18,50},{6,16,50},{5,17,9}, +{5,17,9},{7,23,218},{7,21,149},{7,19,242},{7,18,149},{7,22,248},{7,19,99},{7,18,5},{7,17,99},{5,21,244},{6,17,100},{7,23,218},{7,21,149},{8,18,206},{7,18,149},{13,0,243},{6,21,81},{7,18,5},{6,17,99},{5,21,243},{6,17,99},{7,21,145},{7,21,145},{7,21,145},{7,18,148},{7,20,52},{7,18,4},{7,18,4},{7,17,18},{5,20,56},{6,17,19},{7,21,145}, +{7,21,145},{7,21,145},{7,18,148},{10,8,50},{7,18,4},{7,18,4},{6,17,18},{11,12,50},{6,17,18},{9,15,72},{7,21,5},{8,18,37},{7,18,5},{9,15,72},{5,22,72},{7,18,5},{0,17,90},{5,22,72},{0,17,90},{7,0,144},{7,0,144},{7,0,144},{7,0,144},{7,18,0},{7,18,0},{7,18,0},{7,16,4},{6,18,8},{6,18,8},{8,21,388},{8,20,334},{8,19,316}, +{8,19,340},{7,24,307},{7,21,137},{7,19,115},{7,18,154},{6,21,253},{7,18,106},{8,21,99},{8,20,45},{8,19,27},{8,19,51},{8,19,243},{7,21,73},{7,19,51},{7,18,90},{15,10,243},{7,18,90},{8,19,315},{8,19,315},{8,19,315},{8,18,314},{7,22,116},{7,20,69},{7,20,69},{7,18,73},{6,20,50},{7,18,25},{8,19,26},{8,19,26},{8,19,26},{8,18,25},{9,14,50}, +{7,20,5},{7,20,5},{7,18,9},{14,10,50},{7,18,9},{13,4,72},{8,20,20},{8,19,2},{7,19,26},{13,4,72},{15,11,72},{7,19,26},{0,18,90},{15,11,72},{0,18,90},{8,0,314},{8,0,314},{8,0,314},{8,0,314},{7,21,65},{7,21,65},{7,21,65},{7,18,64},{6,19,10},{6,19,10},{8,23,164},{8,22,94},{8,20,106},{8,20,94},{8,22,329},{8,20,221},{8,20,121}, +{8,19,220},{6,23,249},{7,19,100},{8,23,83},{8,22,13},{8,20,25},{8,20,13},{13,5,243},{7,23,81},{8,20,40},{7,19,99},{12,15,243},{7,19,99},{8,21,91},{8,21,91},{8,21,91},{8,20,94},{8,20,133},{8,19,99},{8,19,99},{8,18,110},{7,20,62},{7,19,19},{8,21,10},{8,21,10},{8,21,10},{8,20,13},{11,10,50},{8,19,18},{8,19,18},{7,19,18},{5,23,50}, +{7,19,18},{15,0,72},{8,22,4},{8,20,16},{8,20,4},{15,0,72},{12,16,72},{8,20,4},{0,19,90},{12,16,72},{0,19,90},{8,0,90},{8,0,90},{8,0,90},{8,0,90},{8,18,81},{8,18,81},{8,18,81},{8,18,85},{7,19,10},{7,19,10},{8,26,194},{8,24,131},{8,21,203},{8,21,123},{8,24,245},{8,22,97},{8,21,3},{8,20,97},{7,23,253},{7,20,141},{9,23,99}, +{9,22,45},{9,21,26},{9,21,50},{15,1,243},{8,22,96},{8,21,2},{8,20,96},{15,13,243},{8,20,96},{8,24,122},{8,24,122},{8,24,122},{8,21,123},{8,22,53},{8,21,3},{8,21,3},{8,19,27},{7,22,50},{8,19,75},{9,21,26},{9,21,26},{9,21,26},{9,20,25},{12,9,50},{8,21,2},{8,21,2},{8,19,26},{14,13,50},{8,19,26},{14,6,72},{8,24,9},{9,21,1}, +{8,21,1},{14,6,72},{15,14,72},{8,21,1},{0,20,80},{15,14,72},{0,20,80},{8,0,122},{8,0,122},{8,0,122},{8,0,122},{8,21,2},{8,21,2},{8,21,2},{8,19,2},{7,21,9},{7,21,9},{9,26,154},{9,24,81},{9,22,106},{9,22,82},{9,24,307},{8,24,137},{9,22,91},{8,21,154},{7,25,244},{8,21,106},{9,26,90},{9,24,17},{9,22,42},{9,22,18},{15,4,243}, +{8,24,73},{9,22,27},{8,21,90},{9,22,243},{8,21,90},{9,24,81},{9,24,81},{9,24,81},{9,22,81},{9,22,114},{8,23,68},{8,23,68},{8,21,73},{7,24,56},{8,21,25},{9,24,17},{9,24,17},{9,24,17},{9,22,17},{15,2,50},{8,23,4},{8,23,4},{8,21,9},{13,16,50},{8,21,9},{11,19,72},{9,24,1},{9,22,26},{9,22,2},{11,19,72},{9,23,72},{9,22,2}, +{0,21,90},{9,23,72},{0,21,90},{9,0,80},{9,0,80},{9,0,80},{9,0,80},{9,20,65},{9,20,65},{9,20,65},{8,21,64},{8,21,16},{8,21,16},{9,28,216},{9,26,149},{9,23,245},{9,23,149},{9,27,248},{9,24,89},{9,23,5},{9,22,99},{7,27,260},{8,22,100},{10,25,99},{10,24,45},{10,23,27},{10,23,51},{10,23,243},{8,26,81},{9,23,5},{8,22,99},{11,21,243}, +{8,22,99},{9,26,145},{9,26,145},{9,26,145},{9,23,148},{9,25,52},{9,23,4},{9,23,4},{9,22,18},{8,23,72},{8,22,19},{10,23,26},{10,23,26},{10,23,26},{10,22,25},{11,18,50},{9,23,4},{9,23,4},{8,22,18},{10,21,50},{8,22,18},{15,8,72},{9,26,5},{10,23,2},{9,23,5},{15,8,72},{11,22,72},{9,23,5},{0,22,90},{11,22,72},{0,22,90},{9,0,144}, +{9,0,144},{9,0,144},{9,0,144},{9,23,0},{9,23,0},{9,23,0},{9,21,4},{8,23,8},{8,23,8},{10,27,164},{10,26,94},{10,24,106},{10,24,94},{9,29,307},{9,26,137},{9,24,105},{9,23,154},{8,26,253},{9,23,106},{10,27,83},{10,26,13},{10,24,25},{10,24,13},{15,9,243},{9,26,73},{10,24,40},{9,23,90},{14,19,243},{9,23,90},{10,25,91},{10,25,91},{10,25,91}, +{10,24,94},{9,27,116},{9,25,69},{9,25,69},{9,23,73},{8,25,50},{9,23,25},{10,25,10},{10,25,10},{10,25,10},{10,24,13},{13,14,50},{9,25,5},{9,25,5},{9,23,9},{8,25,50},{9,23,9},{14,14,72},{10,26,4},{10,24,16},{10,24,4},{14,14,72},{14,20,72},{10,24,4},{0,23,90},{14,20,72},{0,23,90},{10,0,90},{10,0,90},{10,0,90},{10,0,90},{9,26,65}, +{9,26,65},{9,26,65},{9,23,64},{8,24,9},{8,24,9},{10,30,194},{10,28,131},{10,25,203},{10,25,123},{10,28,245},{10,26,97},{10,25,3},{10,24,97},{8,28,252},{9,24,85},{11,27,99},{11,26,45},{11,25,26},{11,25,50},{14,15,243},{9,28,80},{10,25,2},{9,24,84},{12,23,243},{9,24,84},{10,28,122},{10,28,122},{10,28,122},{10,25,123},{10,26,53},{10,25,3},{10,25,3}, +{10,23,27},{9,25,62},{9,24,21},{11,25,26},{11,25,26},{11,25,26},{11,24,25},{14,13,50},{10,25,2},{10,25,2},{9,24,20},{11,23,50},{9,24,20},{13,20,72},{10,28,9},{11,25,1},{10,25,1},{13,20,72},{13,23,74},{10,25,1},{0,24,80},{13,23,74},{0,24,80},{10,0,122},{10,0,122},{10,0,122},{10,0,122},{10,25,2},{10,25,2},{10,25,2},{10,23,2},{9,24,5}, +{9,24,5},{11,30,154},{11,28,81},{11,26,106},{11,26,82},{11,28,307},{10,28,137},{11,26,91},{10,25,154},{9,28,260},{10,25,106},{11,30,90},{11,28,17},{11,26,42},{11,26,18},{14,18,243},{10,28,73},{11,26,27},{10,25,90},{11,26,243},{10,25,90},{11,28,81},{11,28,81},{11,28,81},{11,26,81},{11,26,114},{10,27,68},{10,27,68},{10,25,73},{9,27,53},{10,25,25},{11,28,17}, +{11,28,17},{11,28,17},{11,26,17},{14,16,50},{10,27,4},{10,27,4},{10,25,9},{15,20,50},{10,25,9},{13,23,72},{11,28,1},{11,26,26},{11,26,2},{13,23,72},{11,27,72},{11,26,2},{0,25,90},{11,27,72},{0,25,90},{11,0,80},{11,0,80},{11,0,80},{11,0,80},{11,24,65},{11,24,65},{11,24,65},{10,25,64},{10,25,16},{10,25,16},{11,31,248},{11,30,149},{11,27,245}, +{11,27,149},{11,31,248},{11,28,89},{11,27,5},{11,26,99},{9,30,244},{10,26,100},{12,29,99},{12,28,45},{12,27,27},{12,27,51},{12,27,243},{10,30,81},{11,27,5},{10,26,99},{13,25,243},{10,26,99},{11,30,145},{11,30,145},{11,30,145},{11,27,148},{11,29,52},{11,27,4},{11,27,4},{11,26,18},{9,29,56},{10,26,19},{12,27,26},{12,27,26},{12,27,26},{12,26,25},{13,22,50}, +{11,27,4},{11,27,4},{10,26,18},{12,25,50},{10,26,18},{15,19,72},{11,30,5},{12,27,2},{11,27,5},{15,19,72},{13,26,72},{11,27,5},{0,26,90},{13,26,72},{0,26,90},{11,0,144},{11,0,144},{11,0,144},{11,0,144},{11,27,0},{11,27,0},{11,27,0},{11,25,4},{10,27,8},{10,27,8},{12,31,164},{12,30,94},{12,28,106},{12,28,94},{12,30,329},{11,30,137},{11,28,105}, +{11,27,154},{10,30,253},{11,27,106},{12,31,83},{12,30,13},{12,28,25},{12,28,13},{14,23,243},{11,30,73},{12,28,40},{11,27,90},{11,29,243},{11,27,90},{12,29,91},{12,29,91},{12,29,91},{12,28,94},{11,31,116},{11,29,69},{11,29,69},{11,27,73},{10,29,50},{11,27,25},{12,29,10},{12,29,10},{12,29,10},{12,28,13},{15,18,50},{11,29,5},{11,29,5},{11,27,9},{10,29,50}, +{11,27,9},{13,28,72},{12,30,4},{12,28,16},{12,28,4},{13,28,72},{11,30,72},{12,28,4},{0,27,90},{11,30,72},{0,27,90},{12,0,90},{12,0,90},{12,0,90},{12,0,90},{11,30,65},{11,30,65},{11,30,65},{11,27,64},{10,28,9},{10,28,9},{12,31,356},{12,31,140},{12,29,203},{12,29,123},{12,31,284},{12,30,97},{12,29,3},{12,28,97},{10,31,287},{11,28,85},{13,31,99}, +{13,30,45},{13,29,26},{13,29,50},{13,29,243},{12,30,96},{12,29,2},{11,28,84},{14,27,243},{11,28,84},{12,31,131},{12,31,131},{12,31,131},{12,29,123},{12,30,53},{12,29,3},{12,29,3},{12,27,27},{11,29,62},{11,28,21},{13,29,26},{13,29,26},{13,29,26},{13,28,25},{13,27,50},{12,29,2},{12,29,2},{11,28,20},{13,27,50},{11,28,20},{15,24,72},{12,31,18},{13,29,1}, +{12,29,1},{15,24,72},{15,27,74},{12,29,1},{0,28,80},{15,27,74},{0,28,80},{12,0,122},{12,0,122},{12,0,122},{12,0,122},{12,29,2},{12,29,2},{12,29,2},{12,27,2},{11,28,5},{11,28,5},{13,31,280},{13,31,120},{13,30,106},{13,30,82},{13,31,328},{13,31,200},{13,30,91},{12,29,154},{12,31,344},{12,29,106},{13,31,216},{13,31,56},{13,30,42},{13,30,18},{15,25,244}, +{13,31,136},{13,30,27},{12,29,90},{13,30,243},{12,29,90},{13,31,84},{13,31,84},{13,31,84},{13,30,81},{13,30,114},{12,31,68},{12,31,68},{12,29,73},{11,31,53},{12,29,25},{13,31,20},{13,31,20},{13,31,20},{13,30,17},{13,30,50},{12,31,4},{12,31,4},{12,29,9},{12,30,50},{12,29,9},{15,27,72},{13,31,40},{13,30,26},{13,30,2},{15,27,72},{13,31,72},{13,30,2}, +{0,29,90},{13,31,72},{0,29,90},{13,0,80},{13,0,80},{13,0,80},{13,0,80},{13,28,65},{13,28,65},{13,28,65},{12,29,64},{12,29,16},{12,29,16},{14,31,415},{14,31,351},{13,31,244},{13,31,148},{14,31,511},{13,31,173},{13,31,4},{13,30,82},{13,31,381},{12,30,83},{14,31,126},{14,31,62},{14,31,26},{14,31,50},{14,31,222},{13,31,173},{13,31,4},{12,30,82},{14,30,221}, +{12,30,82},{13,31,244},{13,31,244},{13,31,244},{13,31,148},{13,31,100},{13,31,4},{13,31,4},{13,30,18},{12,31,72},{12,30,19},{14,31,26},{14,31,26},{14,31,26},{14,30,25},{15,26,50},{13,31,4},{13,31,4},{12,30,18},{14,29,50},{12,30,18},{15,29,61},{14,31,37},{14,31,1},{13,31,4},{15,29,61},{15,30,61},{13,31,4},{0,30,73},{15,30,61},{0,30,73},{13,0,144}, +{13,0,144},{13,0,144},{13,0,144},{13,31,0},{13,31,0},{13,31,0},{13,29,4},{12,31,8},{12,31,8},{14,31,239},{14,31,175},{14,31,139},{14,31,99},{14,31,239},{14,31,135},{14,31,99},{13,31,73},{13,31,285},{13,31,25},{14,31,158},{14,31,94},{14,31,58},{14,31,18},{15,29,94},{14,31,54},{14,31,18},{13,31,9},{15,30,93},{13,31,9},{14,31,139},{14,31,139},{14,31,139}, +{14,31,99},{14,31,139},{14,31,99},{14,31,99},{13,31,73},{13,31,116},{13,31,25},{14,31,58},{14,31,58},{14,31,58},{14,31,18},{15,28,52},{14,31,18},{14,31,18},{13,31,9},{15,29,58},{13,31,9},{15,30,9},{15,31,9},{15,31,9},{14,31,9},{15,30,9},{15,31,9},{14,31,9},{0,31,9},{15,31,9},{0,31,9},{14,0,90},{14,0,90},{14,0,90},{14,0,90},{14,30,81}, +{14,30,81},{14,30,81},{13,31,64},{13,31,16},{13,31,16},{15,31,314},{14,31,258},{14,31,222},{14,31,158},{14,31,226},{14,31,98},{14,31,62},{14,31,2},{14,31,122},{14,31,50},{15,31,25},{15,31,25},{15,31,25},{15,31,25},{15,30,22},{15,31,25},{15,31,25},{14,31,1},{15,31,25},{14,31,1},{14,31,222},{14,31,222},{14,31,222},{14,31,158},{14,31,126},{14,31,62},{14,31,62}, +{14,31,2},{14,31,86},{14,31,50},{15,31,25},{15,31,25},{15,31,25},{15,31,25},{15,30,13},{15,31,25},{15,31,25},{14,31,1},{15,30,25},{14,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{14,0,122},{14,0,122},{14,0,122},{14,0,122},{14,31,26},{14,31,26},{14,31,26},{14,31,2},{14,31,50}, +{14,31,50},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{0,4,442},{0,3,313},{0,3,142},{0,2,318},{0,2,498},{0,2,354},{0,6,202},{0,5,52},{0,3,25},{0,3,61},{1,1,441},{0,3,313},{0,3,142},{0,2,318},{2,0,442},{0,2,318},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,45},{0,1,25},{0,1,25},{0,1,26},{0,1,50},{0,1,35},{0,3,0}, +{0,3,0},{0,3,0},{0,2,1},{0,1,45},{0,1,25},{0,1,25},{0,1,26},{0,1,41},{0,1,26},{1,3,200},{0,5,52},{0,3,25},{0,3,61},{1,3,200},{3,0,202},{0,3,61},{0,2,218},{3,0,202},{0,2,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,9,200},{0,7,20},{0,5,20}, +{0,4,25},{0,6,686},{0,5,433},{0,4,169},{0,3,443},{0,3,794},{0,3,524},{0,9,200},{0,7,20},{0,5,20},{0,4,25},{0,6,686},{0,5,433},{0,4,169},{0,3,443},{3,0,686},{0,3,443},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,3,145},{0,2,85},{0,2,85},{0,2,101},{0,1,178},{0,1,115},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,3,145}, +{0,2,85},{0,2,85},{0,2,101},{0,2,149},{0,2,101},{0,9,200},{0,7,20},{0,5,20},{0,4,25},{0,9,200},{2,3,200},{0,4,25},{0,3,218},{2,3,200},{0,3,218},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,11,257},{0,9,54},{0,6,114},{0,5,65},{0,9,728},{0,6,371},{0,5,80}, +{0,4,377},{0,5,949},{0,4,521},{0,11,257},{0,9,54},{1,5,97},{0,5,65},{2,2,723},{0,6,371},{0,5,80},{0,4,377},{1,4,723},{0,4,377},{0,8,50},{0,8,50},{0,8,50},{0,5,49},{0,5,164},{0,4,50},{0,4,50},{0,3,65},{0,3,245},{0,2,126},{0,8,50},{0,8,50},{0,8,50},{0,5,49},{1,2,162},{0,4,50},{0,4,50},{0,3,65},{1,2,162}, +{0,3,65},{3,2,202},{0,9,5},{1,5,16},{0,5,16},{3,2,202},{5,1,200},{0,5,16},{0,4,208},{5,1,200},{0,4,208},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,2,1},{0,2,1},{0,2,1},{0,1,4},{0,1,13},{0,1,13},{0,14,425},{0,11,234},{1,7,277},{0,7,245},{0,11,724},{0,8,289},{0,6,34},{0,5,308},{0,6,1087},{0,5,533},{1,11,201}, +{1,9,18},{1,7,21},{1,6,26},{1,8,723},{0,8,289},{0,6,34},{0,5,308},{4,2,723},{0,5,308},{0,11,225},{0,11,225},{0,11,225},{0,7,229},{0,8,162},{0,6,18},{0,6,18},{0,4,25},{0,4,338},{0,3,162},{1,8,2},{1,8,2},{1,8,2},{1,5,5},{0,8,162},{0,6,18},{0,6,18},{0,4,25},{4,0,162},{0,4,25},{3,4,200},{0,11,9},{1,7,20}, +{0,7,20},{3,4,200},{7,0,200},{0,7,20},{0,5,208},{7,0,200},{0,5,208},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{1,14,410},{1,11,209},{1,8,288},{1,7,234},{0,14,739},{0,10,254},{0,8,33},{0,6,270},{0,8,1131},{0,6,450},{1,14,266},{1,11,65},{2,7,106},{1,7,90},{3,4,723}, +{0,10,238},{0,8,17},{0,6,254},{7,0,723},{0,6,254},{1,11,209},{1,11,209},{1,11,209},{1,7,209},{0,11,178},{0,8,17},{0,8,17},{0,5,18},{0,6,376},{0,5,123},{1,11,65},{1,11,65},{1,11,65},{1,7,65},{3,1,162},{0,8,1},{0,8,1},{0,5,2},{3,3,162},{0,5,2},{3,7,200},{1,11,1},{2,7,25},{0,8,17},{3,7,200},{8,0,200},{0,8,17}, +{0,6,218},{8,0,200},{0,6,218},{1,0,208},{1,0,208},{1,0,208},{1,0,208},{0,8,16},{0,8,16},{0,8,16},{0,5,17},{0,4,80},{0,4,80},{1,16,474},{1,13,276},{1,9,457},{1,9,292},{1,13,740},{1,10,298},{1,8,45},{1,7,315},{0,9,1013},{0,7,308},{2,13,201},{2,11,21},{2,9,21},{2,8,26},{5,0,723},{0,12,227},{1,8,29},{0,7,227},{5,4,723}, +{0,7,227},{1,13,272},{1,13,272},{1,13,272},{1,9,276},{1,10,180},{1,8,29},{1,8,29},{1,6,33},{0,8,306},{0,6,41},{2,10,2},{2,10,2},{2,10,2},{2,7,5},{4,0,162},{0,10,5},{0,10,5},{0,6,5},{1,7,162},{0,6,5},{5,3,200},{1,13,4},{2,9,20},{1,9,20},{5,3,200},{4,7,200},{1,9,20},{0,7,218},{4,7,200},{0,7,218},{1,0,272}, +{1,0,272},{1,0,272},{1,0,272},{1,7,17},{1,7,17},{1,7,17},{1,5,17},{0,6,40},{0,6,40},{2,15,426},{2,13,223},{2,10,283},{2,9,234},{1,16,739},{1,12,267},{1,10,33},{1,8,273},{0,11,913},{0,8,225},{2,15,257},{2,13,54},{3,9,97},{2,9,65},{4,6,723},{0,13,208},{1,10,17},{0,8,209},{3,8,723},{0,8,209},{2,12,219},{2,12,219},{2,12,219}, +{2,9,218},{1,13,180},{1,10,17},{1,10,17},{1,7,18},{0,9,229},{0,7,27},{2,12,50},{2,12,50},{2,12,50},{2,9,49},{3,6,162},{1,10,1},{1,10,1},{1,7,2},{3,6,162},{1,7,2},{1,19,200},{2,13,5},{3,9,16},{2,9,16},{1,19,200},{9,2,200},{2,9,16},{0,8,208},{9,2,200},{0,8,208},{2,0,218},{2,0,218},{2,0,218},{2,0,218},{1,10,16}, +{1,10,16},{1,10,16},{1,7,17},{0,8,17},{0,8,17},{2,18,450},{2,15,259},{2,11,410},{2,11,270},{2,15,749},{2,12,314},{2,10,59},{2,9,333},{0,13,868},{0,9,213},{3,15,201},{3,13,18},{3,11,21},{3,10,26},{6,2,723},{0,15,204},{2,10,34},{0,9,212},{8,3,723},{0,9,212},{2,15,250},{2,15,250},{2,15,250},{2,11,254},{2,12,187},{2,10,43},{2,10,43}, +{2,8,50},{0,11,189},{1,8,37},{3,12,2},{3,12,2},{3,12,2},{3,9,5},{5,2,162},{1,12,2},{1,12,2},{1,8,1},{8,1,162},{1,8,1},{5,8,200},{2,15,9},{3,11,20},{2,11,20},{5,8,200},{4,10,200},{2,11,20},{0,9,208},{4,10,200},{0,9,208},{2,0,250},{2,0,250},{2,0,250},{2,0,250},{2,9,25},{2,9,25},{2,9,25},{2,7,25},{0,9,5}, +{0,9,5},{3,18,410},{3,15,209},{3,12,288},{3,11,234},{2,18,739},{2,14,254},{2,12,33},{2,10,270},{0,15,804},{1,10,227},{3,18,266},{3,15,65},{4,11,106},{3,11,90},{5,8,723},{1,15,219},{2,12,17},{1,10,218},{4,10,723},{1,10,218},{3,15,209},{3,15,209},{3,15,209},{3,11,209},{2,15,178},{2,12,17},{2,12,17},{2,9,18},{0,13,171},{1,9,26},{3,15,65}, +{3,15,65},{3,15,65},{3,11,65},{5,5,162},{2,12,1},{2,12,1},{2,9,2},{5,7,162},{2,9,2},{5,11,200},{3,15,1},{4,11,25},{2,12,17},{5,11,200},{11,3,200},{2,12,17},{0,10,218},{11,3,200},{0,10,218},{3,0,208},{3,0,208},{3,0,208},{3,0,208},{2,12,16},{2,12,16},{2,12,16},{2,9,17},{1,10,9},{1,10,9},{3,20,474},{3,17,276},{3,13,457}, +{3,13,292},{3,17,740},{3,14,298},{3,12,45},{3,11,315},{0,16,747},{1,11,231},{4,17,201},{4,15,21},{4,13,21},{4,12,26},{7,4,723},{1,17,209},{3,12,29},{1,11,227},{9,5,723},{1,11,227},{3,17,272},{3,17,272},{3,17,272},{3,13,276},{3,14,180},{3,12,29},{3,12,29},{3,10,33},{0,15,171},{2,10,41},{4,14,2},{4,14,2},{4,14,2},{4,11,5},{7,1,162}, +{2,14,5},{2,14,5},{2,10,5},{10,2,162},{2,10,5},{8,2,200},{3,17,4},{4,13,20},{3,13,20},{8,2,200},{13,2,200},{3,13,20},{0,11,218},{13,2,200},{0,11,218},{3,0,272},{3,0,272},{3,0,272},{3,0,272},{3,11,17},{3,11,17},{3,11,17},{3,9,17},{1,12,8},{1,12,8},{4,19,426},{4,17,223},{4,14,283},{4,13,234},{3,20,739},{3,16,267},{3,14,33}, +{3,12,273},{0,18,727},{2,12,225},{4,19,257},{4,17,54},{5,13,97},{4,13,65},{6,10,723},{2,17,208},{3,14,17},{2,12,209},{12,3,723},{2,12,209},{4,16,219},{4,16,219},{4,16,219},{4,13,218},{3,17,180},{3,14,17},{3,14,17},{3,11,18},{1,15,171},{2,11,27},{4,16,50},{4,16,50},{4,16,50},{4,13,49},{5,10,162},{3,14,1},{3,14,1},{3,11,2},{12,1,162}, +{3,11,2},{3,23,200},{4,17,5},{5,13,16},{4,13,16},{3,23,200},{11,6,200},{4,13,16},{0,12,208},{11,6,200},{0,12,208},{4,0,218},{4,0,218},{4,0,218},{4,0,218},{3,14,16},{3,14,16},{3,14,16},{3,11,17},{1,13,10},{1,13,10},{4,22,450},{4,19,259},{4,15,410},{4,15,270},{4,19,749},{4,16,314},{4,14,59},{4,13,333},{1,18,747},{2,13,213},{5,19,201}, +{5,17,18},{5,15,21},{5,14,26},{9,1,723},{2,19,204},{4,14,34},{2,13,212},{15,1,723},{2,13,212},{4,19,250},{4,19,250},{4,19,250},{4,15,254},{4,16,187},{4,14,43},{4,14,43},{4,12,50},{1,16,174},{3,12,37},{5,16,2},{5,16,2},{5,16,2},{5,13,5},{8,1,162},{3,16,2},{3,16,2},{3,12,1},{10,5,162},{3,12,1},{9,4,200},{4,19,9},{5,15,20}, +{4,15,20},{9,4,200},{9,10,200},{4,15,20},{0,13,208},{9,10,200},{0,13,208},{4,0,250},{4,0,250},{4,0,250},{4,0,250},{4,13,25},{4,13,25},{4,13,25},{4,11,25},{2,13,5},{2,13,5},{5,22,410},{5,19,209},{5,16,288},{5,15,234},{4,22,739},{4,18,254},{4,16,33},{4,14,270},{1,20,724},{3,14,227},{5,22,266},{5,19,65},{6,15,106},{5,15,90},{9,4,723}, +{3,19,219},{4,16,17},{3,14,218},{9,10,723},{3,14,218},{5,19,209},{5,19,209},{5,19,209},{5,15,209},{4,19,178},{4,16,17},{4,16,17},{4,13,18},{2,17,171},{3,13,26},{5,19,65},{5,19,65},{5,19,65},{5,15,65},{8,4,162},{4,16,1},{4,16,1},{4,13,2},{14,2,162},{4,13,2},{11,0,200},{5,19,1},{6,15,25},{4,16,17},{11,0,200},{13,7,200},{4,16,17}, +{0,14,218},{13,7,200},{0,14,218},{5,0,208},{5,0,208},{5,0,208},{5,0,208},{4,16,16},{4,16,16},{4,16,16},{4,13,17},{3,14,9},{3,14,9},{5,24,474},{5,21,276},{5,17,457},{5,17,292},{5,21,740},{5,18,298},{5,16,45},{5,15,315},{1,22,740},{3,15,231},{6,21,201},{6,19,21},{6,17,21},{6,16,26},{10,3,723},{3,21,209},{5,16,29},{3,15,227},{11,9,723}, +{3,15,227},{5,21,272},{5,21,272},{5,21,272},{5,17,276},{5,18,180},{5,16,29},{5,16,29},{5,14,33},{2,19,171},{4,14,41},{6,18,2},{6,18,2},{6,18,2},{6,15,5},{3,25,162},{4,18,5},{4,18,5},{4,14,5},{12,6,162},{4,14,5},{10,6,200},{5,21,4},{6,17,20},{5,17,20},{10,6,200},{15,6,200},{5,17,20},{0,15,218},{15,6,200},{0,15,218},{5,0,272}, +{5,0,272},{5,0,272},{5,0,272},{5,15,17},{5,15,17},{5,15,17},{5,13,17},{3,16,8},{3,16,8},{6,23,426},{6,21,223},{6,18,283},{6,17,234},{5,24,739},{5,20,267},{5,18,33},{5,16,273},{2,22,727},{4,16,225},{6,23,257},{6,21,54},{7,17,97},{6,17,65},{9,9,723},{4,21,208},{5,18,17},{4,16,209},{14,7,723},{4,16,209},{6,20,219},{6,20,219},{6,20,219}, +{6,17,218},{5,21,180},{5,18,17},{5,18,17},{5,15,18},{3,19,171},{4,15,27},{6,20,50},{6,20,50},{6,20,50},{6,17,49},{9,6,162},{5,18,1},{5,18,1},{5,15,2},{14,5,162},{5,15,2},{12,2,200},{6,21,5},{7,17,16},{6,17,16},{12,2,200},{13,10,200},{6,17,16},{0,16,208},{13,10,200},{0,16,208},{6,0,218},{6,0,218},{6,0,218},{6,0,218},{5,18,16}, +{5,18,16},{5,18,16},{5,15,17},{3,17,10},{3,17,10},{6,26,450},{6,23,259},{6,19,410},{6,19,270},{6,23,749},{6,20,314},{6,18,59},{6,17,333},{3,22,747},{4,17,213},{7,23,201},{7,21,18},{7,19,21},{7,18,26},{11,5,723},{4,23,204},{6,18,34},{4,17,212},{12,11,723},{4,17,212},{6,23,250},{6,23,250},{6,23,250},{6,19,254},{6,20,187},{6,18,43},{6,18,43}, +{6,16,50},{3,20,174},{5,16,37},{7,20,2},{7,20,2},{7,20,2},{7,17,5},{10,5,162},{5,20,2},{5,20,2},{5,16,1},{12,9,162},{5,16,1},{11,8,200},{6,23,9},{7,19,20},{6,19,20},{11,8,200},{11,14,200},{6,19,20},{0,17,208},{11,14,200},{0,17,208},{6,0,250},{6,0,250},{6,0,250},{6,0,250},{6,17,25},{6,17,25},{6,17,25},{6,15,25},{4,17,5}, +{4,17,5},{7,26,410},{7,23,209},{7,20,288},{7,19,234},{6,26,739},{6,22,254},{6,20,33},{6,18,270},{3,24,724},{5,18,227},{7,26,266},{7,23,65},{7,20,144},{7,19,90},{11,8,723},{5,23,219},{6,20,17},{5,18,218},{11,14,723},{5,18,218},{7,23,209},{7,23,209},{7,23,209},{7,19,209},{6,23,178},{6,20,17},{6,20,17},{6,17,18},{4,21,171},{5,17,26},{7,23,65}, +{7,23,65},{7,23,65},{7,19,65},{10,8,162},{6,20,1},{6,20,1},{6,17,2},{11,12,162},{6,17,2},{13,4,200},{7,23,1},{8,19,50},{6,20,17},{13,4,200},{15,11,200},{6,20,17},{0,18,218},{15,11,200},{0,18,218},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{6,20,16},{6,20,16},{6,20,16},{6,17,17},{5,18,9},{5,18,9},{7,28,474},{7,25,276},{7,21,457}, +{7,21,292},{7,25,740},{7,22,298},{7,20,45},{7,19,315},{3,26,740},{5,19,231},{8,23,283},{8,22,133},{8,20,97},{8,20,133},{12,7,723},{5,25,209},{7,20,29},{5,19,227},{13,13,723},{5,19,227},{7,25,272},{7,25,272},{7,25,272},{7,21,276},{7,22,180},{7,20,29},{7,20,29},{7,18,33},{4,23,171},{6,18,41},{8,20,81},{8,20,81},{8,20,81},{8,19,82},{9,14,162}, +{6,22,5},{6,22,5},{6,18,5},{14,10,162},{6,18,5},{15,0,200},{7,25,4},{8,20,16},{7,21,20},{15,0,200},{12,16,200},{7,21,20},{0,19,218},{12,16,200},{0,19,218},{7,0,272},{7,0,272},{7,0,272},{7,0,272},{7,19,17},{7,19,17},{7,19,17},{7,17,17},{5,20,8},{5,20,8},{8,26,642},{8,24,459},{8,22,462},{8,21,467},{7,28,739},{7,24,267},{7,22,33}, +{7,20,273},{4,26,727},{6,20,225},{8,26,201},{8,24,18},{8,22,21},{8,21,26},{14,3,723},{6,25,208},{7,22,17},{6,20,209},{11,17,723},{6,20,209},{8,23,443},{8,23,443},{8,23,443},{8,20,446},{7,25,180},{7,22,17},{7,22,17},{7,19,18},{5,23,171},{6,19,27},{8,23,2},{8,23,2},{8,23,2},{8,20,5},{11,10,162},{7,22,1},{7,22,1},{7,19,2},{5,23,162}, +{7,19,2},{14,6,200},{8,24,17},{8,22,20},{7,22,17},{14,6,200},{15,14,200},{7,22,17},{0,20,208},{15,14,200},{0,20,208},{8,0,442},{8,0,442},{8,0,442},{8,0,442},{7,22,16},{7,22,16},{7,22,16},{7,19,17},{5,21,10},{5,21,10},{8,28,420},{8,26,223},{8,23,283},{8,22,234},{7,31,872},{7,26,371},{7,23,201},{7,21,368},{5,26,747},{6,21,213},{8,28,251}, +{8,26,54},{9,22,97},{8,22,65},{13,9,723},{6,27,204},{7,23,57},{6,21,212},{14,15,723},{6,21,212},{8,25,219},{8,25,219},{8,25,219},{8,22,218},{7,27,308},{7,24,146},{7,24,146},{7,20,145},{5,24,174},{7,20,37},{8,25,50},{8,25,50},{8,25,50},{8,22,49},{12,9,162},{7,24,2},{7,24,2},{7,20,1},{14,13,162},{7,20,1},{13,12,200},{8,26,5},{9,22,16}, +{8,22,16},{13,12,200},{13,18,200},{8,22,16},{0,21,208},{13,18,200},{0,21,208},{8,0,218},{8,0,218},{8,0,218},{8,0,218},{7,24,145},{7,24,145},{7,24,145},{7,20,145},{6,21,5},{6,21,5},{8,31,474},{8,28,276},{9,24,425},{8,24,292},{8,28,740},{8,25,298},{8,23,61},{8,22,315},{5,28,724},{7,22,227},{9,28,200},{9,26,13},{9,24,25},{9,23,29},{13,12,723}, +{7,27,219},{8,23,45},{7,22,218},{13,18,723},{7,22,218},{8,28,272},{8,28,272},{8,28,272},{8,24,276},{8,25,180},{8,23,36},{8,23,36},{8,21,33},{6,25,171},{7,21,26},{9,25,0},{9,25,0},{9,25,0},{9,23,4},{15,2,162},{8,23,20},{8,23,20},{8,21,17},{13,16,162},{8,21,17},{15,8,200},{8,28,4},{9,24,25},{8,24,20},{15,8,200},{11,22,200},{8,24,20}, +{0,22,218},{11,22,200},{0,22,218},{8,0,272},{8,0,272},{8,0,272},{8,0,272},{8,22,17},{8,22,17},{8,22,17},{8,20,17},{7,22,9},{7,22,9},{9,31,410},{9,28,212},{9,25,288},{9,24,224},{8,31,739},{8,27,254},{8,25,33},{8,23,270},{5,30,740},{7,23,231},{9,31,266},{9,28,68},{10,24,97},{9,24,80},{14,11,723},{7,29,209},{8,25,17},{7,23,227},{15,17,723}, +{7,23,227},{9,27,212},{9,27,212},{9,27,212},{9,24,208},{8,28,180},{8,25,17},{8,25,17},{8,22,18},{6,27,171},{7,23,62},{9,27,68},{9,27,68},{9,27,68},{9,24,64},{11,18,162},{8,25,1},{8,25,1},{8,22,2},{10,21,162},{8,22,2},{14,14,200},{9,28,4},{10,24,16},{9,24,16},{14,14,200},{14,20,200},{9,24,16},{0,23,218},{14,20,200},{0,23,218},{9,0,208}, +{9,0,208},{9,0,208},{9,0,208},{8,25,16},{8,25,16},{8,25,16},{8,22,17},{7,24,8},{7,24,8},{9,31,570},{9,30,276},{9,26,457},{9,26,292},{9,30,740},{9,27,298},{9,25,45},{9,24,324},{6,30,727},{7,24,280},{10,30,201},{10,28,18},{10,26,21},{10,25,26},{13,17,723},{8,29,227},{9,25,29},{8,24,224},{13,21,723},{8,24,224},{9,30,272},{9,30,272},{9,30,272}, +{9,26,276},{9,27,180},{9,25,29},{9,25,29},{9,23,33},{7,27,171},{8,23,41},{10,27,2},{10,27,2},{10,27,2},{10,24,5},{13,14,162},{8,27,5},{8,27,5},{8,23,5},{8,25,162},{8,23,5},{13,20,200},{9,30,4},{10,26,20},{9,26,20},{13,20,200},{13,23,202},{9,26,20},{0,24,208},{13,23,202},{0,24,208},{9,0,272},{9,0,272},{9,0,272},{9,0,272},{9,24,17}, +{9,24,17},{9,24,17},{9,22,17},{7,25,10},{7,25,10},{10,31,468},{10,30,223},{10,27,283},{10,26,234},{9,31,835},{9,29,267},{9,27,33},{9,25,273},{7,30,747},{8,25,225},{11,29,283},{10,30,54},{11,26,97},{10,26,65},{15,13,723},{8,30,208},{9,27,17},{8,25,209},{11,25,723},{8,25,209},{10,29,219},{10,29,219},{10,29,219},{10,26,218},{9,30,180},{9,27,17},{9,27,17}, +{9,24,20},{7,28,174},{8,24,17},{10,29,50},{10,29,50},{10,29,50},{10,26,49},{14,13,162},{9,27,1},{9,27,1},{9,24,4},{11,23,162},{9,24,4},{15,16,200},{10,30,5},{11,26,16},{10,26,16},{15,16,200},{15,22,200},{10,26,16},{0,25,208},{15,22,200},{0,25,208},{10,0,218},{10,0,218},{10,0,218},{10,0,218},{9,27,16},{9,27,16},{9,27,16},{9,24,20},{8,24,17}, +{8,24,17},{11,31,632},{10,31,297},{11,28,425},{10,28,292},{10,31,804},{10,29,298},{10,27,61},{10,26,315},{7,31,823},{8,26,231},{11,31,232},{11,30,13},{11,28,25},{11,27,29},{15,16,723},{9,31,216},{10,27,45},{8,26,227},{15,22,723},{8,26,227},{10,31,288},{10,31,288},{10,31,288},{10,28,276},{10,29,180},{10,27,36},{10,27,36},{10,25,33},{7,30,189},{9,25,30},{11,29,0}, +{11,29,0},{11,29,0},{11,27,4},{14,16,162},{9,29,4},{9,29,4},{9,25,5},{15,20,162},{9,25,5},{15,19,200},{11,30,13},{11,28,25},{10,28,20},{15,19,200},{13,26,200},{10,28,20},{0,26,218},{13,26,200},{0,26,218},{10,0,272},{10,0,272},{10,0,272},{10,0,272},{10,26,17},{10,26,17},{10,26,17},{10,24,17},{8,27,5},{8,27,5},{11,31,696},{11,31,237},{11,29,288}, +{11,28,224},{11,31,888},{10,31,254},{10,29,33},{10,27,270},{8,31,824},{9,27,227},{12,31,283},{11,31,93},{12,28,97},{11,28,80},{13,25,723},{10,31,238},{10,29,17},{9,27,218},{12,27,723},{9,27,218},{11,31,212},{11,31,212},{11,31,212},{11,28,208},{10,31,196},{10,29,17},{10,29,17},{10,26,18},{8,30,171},{9,26,26},{11,31,68},{11,31,68},{11,31,68},{11,28,64},{13,22,162}, +{10,29,1},{10,29,1},{10,26,2},{12,25,162},{10,26,2},{13,28,200},{11,31,29},{12,28,16},{11,28,16},{13,28,200},{11,30,200},{11,28,16},{0,27,218},{11,30,200},{0,27,218},{11,0,208},{11,0,208},{11,0,208},{11,0,208},{10,29,16},{10,29,16},{10,29,16},{10,26,17},{9,27,9},{9,27,9},{12,31,804},{12,31,492},{11,30,457},{11,30,292},{11,31,1080},{11,31,298},{11,29,45}, +{11,28,324},{9,31,920},{9,28,218},{12,31,363},{12,31,51},{12,30,21},{12,29,26},{15,21,723},{11,31,282},{11,29,29},{9,28,217},{15,25,723},{9,28,217},{11,31,372},{11,31,372},{11,31,372},{11,30,276},{11,31,180},{11,29,29},{11,29,29},{11,27,33},{8,31,184},{10,27,41},{12,31,2},{12,31,2},{12,31,2},{12,28,5},{15,18,162},{10,31,5},{10,31,5},{10,27,5},{10,29,162}, +{10,27,5},{15,24,200},{12,31,50},{12,30,20},{11,30,20},{15,24,200},{15,27,202},{11,30,20},{0,28,208},{15,27,202},{0,28,208},{11,0,272},{11,0,272},{11,0,272},{11,0,272},{11,28,17},{11,28,17},{11,28,17},{11,26,17},{9,29,8},{9,29,8},{12,31,996},{12,31,492},{12,31,283},{12,30,234},{12,31,1068},{11,31,458},{11,31,33},{11,29,273},{10,31,999},{10,29,225},{13,31,379}, +{13,31,171},{13,30,97},{12,30,65},{14,27,723},{12,31,371},{11,31,17},{10,29,209},{13,29,723},{10,29,209},{12,31,267},{12,31,267},{12,31,267},{12,30,218},{12,30,333},{11,31,17},{11,31,17},{11,28,20},{9,31,212},{10,28,17},{13,30,81},{13,30,81},{13,30,81},{12,30,49},{13,27,162},{11,31,1},{11,31,1},{11,28,4},{13,27,162},{11,28,4},{15,27,202},{13,31,90},{13,30,16}, +{12,30,16},{15,27,202},{15,28,202},{12,30,16},{0,29,208},{15,28,202},{0,29,208},{12,0,218},{12,0,218},{12,0,218},{12,0,218},{11,31,16},{11,31,16},{11,31,16},{11,28,20},{9,30,10},{9,30,10},{13,31,877},{13,31,605},{13,31,436},{12,31,288},{13,31,1021},{12,31,397},{12,31,36},{12,30,210},{11,31,910},{10,30,126},{14,31,414},{13,31,205},{13,31,36},{13,31,4},{15,26,546}, +{13,31,317},{12,31,20},{10,30,122},{14,29,546},{10,30,122},{13,31,436},{13,31,436},{13,31,436},{12,31,288},{12,31,276},{12,31,36},{12,31,36},{12,29,33},{10,31,261},{11,29,30},{13,31,36},{13,31,36},{13,31,36},{13,31,4},{13,30,162},{12,31,20},{12,31,20},{11,29,5},{12,30,162},{11,29,5},{15,28,117},{14,31,61},{14,31,25},{13,31,4},{15,28,117},{14,31,117},{13,31,4}, +{0,30,113},{14,31,117},{0,30,113},{12,0,272},{12,0,272},{12,0,272},{12,0,272},{12,30,17},{12,30,17},{12,30,17},{12,28,17},{10,31,5},{10,31,5},{13,31,845},{13,31,573},{13,31,404},{13,31,244},{13,31,797},{13,31,365},{12,31,196},{12,30,82},{12,31,737},{11,31,58},{14,31,190},{14,31,126},{14,31,90},{14,31,82},{14,31,334},{13,31,221},{13,31,52},{11,31,49},{14,30,333}, +{11,31,49},{13,31,404},{13,31,404},{13,31,404},{13,31,244},{13,31,356},{12,31,196},{12,31,196},{12,30,18},{11,31,333},{11,30,26},{14,31,90},{14,31,90},{14,31,90},{14,31,82},{15,26,162},{13,31,52},{13,31,52},{12,30,2},{14,29,162},{12,30,2},{15,30,25},{15,30,41},{14,31,9},{14,31,1},{15,30,25},{15,30,29},{14,31,1},{0,31,49},{15,30,29},{0,31,49},{13,0,208}, +{13,0,208},{13,0,208},{13,0,208},{12,31,52},{12,31,52},{12,31,52},{12,30,17},{11,31,9},{11,31,9},{14,31,642},{14,31,578},{14,31,542},{13,31,441},{14,31,690},{13,31,370},{13,31,201},{13,31,32},{13,31,610},{12,31,40},{14,31,201},{14,31,137},{14,31,101},{14,31,37},{15,29,193},{14,31,121},{14,31,85},{12,31,4},{14,31,193},{12,31,4},{14,31,542},{14,31,542},{14,31,542}, +{13,31,441},{13,31,473},{13,31,201},{13,31,201},{13,31,32},{12,31,401},{12,31,40},{14,31,101},{14,31,101},{14,31,101},{14,31,37},{15,28,145},{14,31,85},{14,31,85},{12,31,4},{15,29,149},{12,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,272},{13,0,272},{13,0,272},{13,0,272},{13,31,32}, +{13,31,32},{13,31,32},{13,30,17},{12,31,40},{12,31,40},{14,31,418},{14,31,354},{14,31,318},{14,31,254},{14,31,370},{14,31,242},{14,31,206},{13,31,32},{13,31,418},{13,31,80},{15,31,81},{15,31,81},{15,31,81},{15,31,81},{15,30,54},{14,31,73},{14,31,37},{14,31,9},{15,30,66},{14,31,9},{14,31,318},{14,31,318},{14,31,318},{14,31,254},{14,31,270},{14,31,206},{14,31,206}, +{13,31,32},{13,31,249},{13,31,80},{15,31,81},{15,31,81},{15,31,81},{15,31,81},{15,29,45},{14,31,37},{14,31,37},{14,31,9},{15,30,41},{14,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{14,0,218},{14,0,218},{14,0,218},{14,0,218},{13,31,160},{13,31,160},{13,31,160},{13,31,32},{13,31,80}, +{13,31,80},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{0,6,925},{0,5,658},{0,4,274},{0,3,670},{0,3,1039},{0,3,751},{0,9,421},{0,7,113},{0,5,5},{0,4,130},{0,6,925},{0,5,658},{0,4,274},{0,3,670},{3,0,925},{0,3,670},{0,4,1},{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{0,1,98},{0,1,59},{0,4,1}, +{0,4,1},{0,4,1},{0,3,4},{0,2,85},{0,2,45},{0,2,45},{0,1,50},{1,0,85},{0,1,50},{1,6,421},{0,7,113},{0,5,5},{0,4,130},{1,6,421},{3,2,421},{0,4,130},{0,3,445},{3,2,421},{0,3,445},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,12,425},{0,9,52},{0,6,10}, +{0,6,82},{0,8,1261},{0,6,805},{0,5,322},{0,4,833},{0,4,1445},{0,4,977},{0,12,425},{0,9,52},{0,6,10},{0,6,82},{0,8,1261},{0,6,805},{0,5,322},{0,4,833},{4,0,1261},{0,4,833},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{0,3,225},{0,3,117},{0,3,117},{0,2,125},{0,2,257},{0,2,161},{0,7,0},{0,7,0},{0,7,0},{0,4,1},{1,0,221}, +{0,3,117},{0,3,117},{0,2,125},{1,1,221},{0,2,125},{3,2,421},{0,9,52},{0,6,10},{0,6,82},{3,2,421},{5,1,421},{0,6,82},{0,4,433},{5,1,421},{0,4,433},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,14,430},{0,11,29},{0,7,74},{0,7,46},{0,10,1514},{0,8,874},{0,6,307}, +{0,5,917},{0,5,1814},{0,4,1074},{0,14,430},{0,11,29},{0,7,74},{0,7,46},{3,0,1514},{0,8,874},{0,6,307},{0,5,917},{5,0,1514},{0,5,917},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{0,5,340},{0,5,160},{0,5,160},{0,3,169},{0,3,421},{0,3,250},{0,10,10},{0,10,10},{0,10,10},{0,6,10},{1,2,338},{0,5,160},{0,5,160},{0,3,169},{1,2,338}, +{0,3,169},{4,1,421},{0,11,20},{1,7,5},{0,7,37},{4,1,421},{7,0,421},{0,7,37},{0,5,433},{7,0,421},{0,5,433},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,1,0},{0,1,0},{0,1,0},{0,1,4},{0,0,9},{0,0,9},{0,17,542},{0,13,130},{0,9,285},{0,8,137},{0,12,1517},{0,9,737},{0,7,185},{0,6,794},{0,7,1982},{0,5,1062},{1,13,450}, +{1,11,77},{1,8,34},{1,7,122},{3,3,1517},{0,9,737},{0,7,185},{0,6,794},{2,5,1514},{0,6,794},{0,12,121},{0,12,121},{0,12,121},{0,7,125},{0,8,338},{0,6,98},{0,6,98},{0,4,97},{0,4,514},{0,4,241},{1,9,25},{1,9,25},{1,9,25},{1,6,26},{0,8,338},{0,6,98},{0,6,98},{0,4,97},{4,0,338},{0,4,97},{5,0,421},{0,13,9},{1,8,9}, +{0,8,16},{5,0,421},{8,0,421},{0,8,16},{0,6,433},{8,0,421},{0,6,433},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,4,1},{0,4,1},{0,4,1},{0,2,1},{0,2,37},{0,2,37},{1,16,697},{1,13,297},{1,9,354},{1,9,309},{0,15,1517},{0,11,630},{0,9,50},{0,7,670},{0,8,2198},{0,6,1109},{1,16,441},{1,13,41},{1,9,98},{1,9,53},{4,2,1514}, +{0,11,630},{0,9,50},{0,7,670},{6,2,1514},{0,7,670},{1,12,273},{1,12,273},{1,12,273},{1,8,273},{0,11,338},{0,8,41},{0,8,41},{0,5,50},{0,6,680},{0,5,275},{1,12,17},{1,12,17},{1,12,17},{1,8,17},{3,1,338},{0,8,41},{0,8,41},{0,5,50},{3,3,338},{0,5,50},{6,0,421},{0,15,1},{2,9,5},{0,9,1},{6,0,421},{5,6,421},{0,9,1}, +{0,7,445},{5,6,421},{0,7,445},{1,0,272},{1,0,272},{1,0,272},{1,0,272},{0,7,1},{0,7,1},{0,7,1},{0,4,0},{0,3,106},{0,3,106},{1,19,821},{1,15,405},{1,11,570},{1,10,410},{0,18,1514},{0,13,577},{0,10,14},{0,8,602},{0,10,2462},{0,7,1175},{2,16,450},{2,13,77},{2,10,35},{2,10,107},{3,8,1514},{0,13,577},{0,10,14},{0,8,602},{4,6,1514}, +{0,8,602},{1,14,401},{1,14,401},{1,14,401},{1,9,404},{0,13,340},{0,10,13},{0,10,13},{0,6,29},{0,7,851},{0,6,353},{2,11,25},{2,11,25},{2,11,25},{2,8,26},{4,0,338},{0,10,13},{0,10,13},{0,6,29},{1,7,338},{0,6,29},{5,6,421},{1,15,5},{2,10,10},{0,10,10},{5,6,421},{10,1,421},{0,10,10},{0,8,433},{10,1,421},{0,8,433},{1,0,400}, +{1,0,400},{1,0,400},{1,0,400},{0,9,1},{0,9,1},{0,9,1},{0,6,4},{0,4,208},{0,4,208},{1,22,902},{1,17,485},{2,11,750},{1,11,482},{0,21,1566},{0,15,570},{0,11,95},{0,9,582},{0,11,2337},{0,9,933},{2,18,430},{2,15,29},{2,11,74},{2,11,46},{5,4,1514},{0,15,521},{0,11,46},{0,9,533},{9,1,1514},{0,9,533},{1,17,481},{1,17,481},{1,17,481}, +{1,11,481},{0,16,387},{0,12,51},{0,12,51},{0,7,75},{0,8,755},{0,7,222},{2,14,10},{2,14,10},{2,14,10},{2,10,10},{3,6,338},{0,12,2},{0,12,2},{0,7,26},{3,6,338},{0,7,26},{7,2,421},{1,17,4},{3,11,5},{1,11,1},{7,2,421},{12,0,421},{1,11,1},{0,9,433},{12,0,421},{0,9,433},{1,0,481},{1,0,481},{1,0,481},{1,0,481},{0,12,50}, +{0,12,50},{0,12,50},{0,7,50},{0,6,157},{0,6,157},{2,21,866},{2,17,454},{2,13,609},{2,12,461},{1,20,1515},{1,15,578},{1,12,19},{1,10,603},{0,13,2214},{0,10,707},{3,17,450},{3,15,77},{3,12,34},{3,11,122},{7,0,1514},{0,16,458},{1,12,18},{0,10,482},{4,9,1514},{0,10,482},{2,16,445},{2,16,445},{2,16,445},{2,11,449},{1,15,341},{1,12,19},{1,12,19}, +{1,8,26},{0,10,635},{0,8,106},{3,13,25},{3,13,25},{3,13,25},{3,10,26},{5,2,338},{0,14,2},{0,14,2},{0,9,20},{8,1,338},{0,9,20},{7,4,421},{2,17,9},{3,12,9},{1,12,9},{7,4,421},{11,3,421},{1,12,9},{0,10,433},{11,3,421},{0,10,433},{2,0,445},{2,0,445},{2,0,445},{2,0,445},{1,11,2},{1,11,2},{1,11,2},{1,7,10},{0,8,90}, +{0,8,90},{2,24,902},{2,19,482},{3,13,723},{2,13,482},{1,23,1578},{1,17,566},{1,14,117},{1,11,590},{0,15,2046},{0,11,535},{3,20,441},{3,17,41},{3,13,98},{3,13,53},{7,3,1514},{0,18,429},{2,13,50},{0,11,454},{11,2,1514},{0,11,454},{2,19,481},{2,19,481},{2,19,481},{2,13,481},{1,18,404},{1,14,68},{1,14,68},{1,10,89},{0,12,557},{0,10,49},{3,16,17}, +{3,16,17},{3,16,17},{3,12,17},{5,5,338},{1,14,4},{1,14,4},{0,10,13},{5,7,338},{0,10,13},{8,2,421},{2,19,1},{4,13,5},{2,13,1},{8,2,421},{14,1,421},{2,13,1},{0,11,445},{14,1,421},{0,11,445},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{1,14,64},{1,14,64},{1,14,64},{1,9,65},{0,10,40},{0,10,40},{3,23,854},{3,19,438},{3,15,603}, +{3,14,443},{2,22,1515},{2,17,578},{2,14,15},{2,12,603},{0,16,1911},{0,12,458},{4,20,450},{4,17,77},{4,14,35},{4,14,107},{5,12,1514},{0,20,425},{2,14,14},{0,12,433},{13,1,1514},{0,12,433},{3,18,434},{3,18,434},{3,18,434},{3,13,437},{2,17,341},{2,14,14},{2,14,14},{2,10,30},{0,14,477},{0,11,35},{4,15,25},{4,15,25},{4,15,25},{4,12,26},{7,1,338}, +{1,16,5},{1,16,5},{1,11,10},{10,2,338},{1,11,10},{8,5,421},{3,19,5},{4,14,10},{2,14,10},{8,5,421},{12,5,421},{2,14,10},{0,12,433},{12,5,421},{0,12,433},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{2,13,2},{2,13,2},{2,13,2},{2,10,5},{0,12,25},{0,12,25},{3,26,902},{3,21,485},{4,15,750},{3,15,482},{2,25,1566},{2,19,570},{2,15,95}, +{2,13,582},{0,18,1787},{0,13,442},{4,22,430},{4,19,29},{4,15,74},{4,15,46},{8,3,1514},{1,20,425},{2,15,46},{0,13,442},{11,5,1514},{0,13,442},{3,21,481},{3,21,481},{3,21,481},{3,15,481},{2,20,387},{2,16,51},{2,16,51},{2,11,75},{0,16,419},{1,12,69},{4,18,10},{4,18,10},{4,18,10},{4,14,10},{5,10,338},{2,16,2},{2,16,2},{1,12,20},{12,1,338}, +{1,12,20},{9,4,421},{3,21,4},{5,15,5},{3,15,1},{9,4,421},{15,3,421},{3,15,1},{0,13,433},{15,3,421},{0,13,433},{3,0,481},{3,0,481},{3,0,481},{3,0,481},{2,16,50},{2,16,50},{2,16,50},{2,11,50},{0,13,9},{0,13,9},{4,25,866},{4,21,454},{4,17,609},{4,16,461},{3,24,1515},{3,19,578},{3,16,19},{3,14,603},{0,20,1686},{1,14,458},{5,21,450}, +{5,19,77},{5,16,34},{5,15,122},{3,24,1514},{1,22,425},{3,16,18},{1,14,433},{14,3,1514},{1,14,433},{4,20,445},{4,20,445},{4,20,445},{4,15,449},{3,19,341},{3,16,19},{3,16,19},{3,12,26},{0,17,372},{1,13,45},{5,17,25},{5,17,25},{5,17,25},{5,14,26},{8,1,338},{2,18,2},{2,18,2},{2,13,20},{10,5,338},{2,13,20},{11,0,421},{4,21,9},{5,16,9}, +{3,16,9},{11,0,421},{13,7,421},{3,16,9},{0,14,433},{13,7,421},{0,14,433},{4,0,445},{4,0,445},{4,0,445},{4,0,445},{3,15,2},{3,15,2},{3,15,2},{3,11,10},{0,15,5},{0,15,5},{4,28,902},{4,23,482},{5,17,723},{4,17,482},{3,27,1578},{3,21,566},{3,18,117},{3,15,590},{0,22,1614},{1,15,462},{5,24,441},{5,21,41},{5,17,98},{5,17,53},{5,20,1514}, +{2,22,429},{4,17,50},{2,15,454},{13,6,1514},{2,15,454},{4,23,481},{4,23,481},{4,23,481},{4,17,481},{3,22,404},{3,18,68},{3,18,68},{3,14,89},{0,19,347},{2,14,49},{5,20,17},{5,20,17},{5,20,17},{5,16,17},{8,4,338},{3,18,4},{3,18,4},{2,14,13},{14,2,338},{2,14,13},{11,3,421},{4,23,1},{6,17,5},{4,17,1},{11,3,421},{15,6,421},{4,17,1}, +{0,15,445},{15,6,421},{0,15,445},{4,0,481},{4,0,481},{4,0,481},{4,0,481},{3,18,64},{3,18,64},{3,18,64},{3,13,65},{1,16,8},{1,16,8},{5,27,854},{5,23,438},{5,19,603},{5,18,443},{4,26,1515},{4,21,578},{4,18,15},{4,16,603},{0,23,1566},{2,16,458},{6,24,450},{6,21,77},{6,18,35},{6,18,107},{11,1,1514},{2,24,425},{4,18,14},{2,16,433},{15,5,1514}, +{2,16,433},{5,22,434},{5,22,434},{5,22,434},{5,17,437},{4,21,341},{4,18,14},{4,18,14},{4,14,30},{0,21,341},{2,15,35},{6,19,25},{6,19,25},{6,19,25},{6,16,26},{3,25,338},{3,20,5},{3,20,5},{3,15,10},{12,6,338},{3,15,10},{12,2,421},{5,23,5},{6,18,10},{4,18,10},{12,2,421},{14,9,421},{4,18,10},{0,16,433},{14,9,421},{0,16,433},{5,0,433}, +{5,0,433},{5,0,433},{5,0,433},{4,17,2},{4,17,2},{4,17,2},{4,14,5},{1,17,10},{1,17,10},{5,30,902},{5,25,485},{6,19,750},{5,19,482},{4,29,1566},{4,23,570},{4,19,95},{4,17,582},{0,25,1533},{2,17,442},{6,26,430},{6,23,29},{6,19,74},{6,19,46},{10,7,1514},{3,24,425},{4,19,46},{2,17,442},{13,9,1514},{2,17,442},{5,25,481},{5,25,481},{5,25,481}, +{5,19,481},{4,24,387},{4,20,51},{4,20,51},{4,15,75},{1,21,341},{3,16,69},{6,22,10},{6,22,10},{6,22,10},{6,18,10},{9,6,338},{4,20,2},{4,20,2},{3,16,20},{14,5,338},{3,16,20},{11,8,421},{5,25,4},{7,19,5},{5,19,1},{11,8,421},{11,14,421},{5,19,1},{0,17,433},{11,14,421},{0,17,433},{5,0,481},{5,0,481},{5,0,481},{5,0,481},{4,20,50}, +{4,20,50},{4,20,50},{4,15,50},{2,17,9},{2,17,9},{6,29,866},{6,25,454},{6,21,609},{6,20,461},{5,28,1515},{5,23,578},{5,20,19},{5,18,603},{0,27,1521},{3,18,458},{7,25,450},{7,23,77},{7,20,34},{7,19,122},{12,3,1514},{3,26,425},{5,20,18},{3,18,433},{11,13,1514},{3,18,433},{6,24,445},{6,24,445},{6,24,445},{6,19,449},{5,23,341},{5,20,19},{5,20,19}, +{5,16,26},{1,23,341},{3,17,45},{7,21,25},{7,21,25},{7,21,25},{7,18,26},{10,5,338},{4,22,2},{4,22,2},{4,17,20},{12,9,338},{4,17,20},{13,4,421},{6,25,9},{7,20,9},{5,20,9},{13,4,421},{15,11,421},{5,20,9},{0,18,433},{15,11,421},{0,18,433},{6,0,445},{6,0,445},{6,0,445},{6,0,445},{5,19,2},{5,19,2},{5,19,2},{5,15,10},{2,19,5}, +{2,19,5},{6,31,914},{6,27,482},{7,21,723},{6,21,482},{5,31,1578},{5,25,566},{5,22,117},{5,19,590},{1,27,1535},{3,19,462},{7,28,441},{7,25,41},{7,21,98},{7,21,53},{8,19,1514},{4,26,429},{6,21,50},{4,19,454},{15,10,1514},{4,19,454},{6,27,481},{6,27,481},{6,27,481},{6,21,481},{5,26,404},{5,22,68},{5,22,68},{5,18,89},{2,23,347},{4,18,49},{7,24,17}, +{7,24,17},{7,24,17},{7,20,17},{10,8,338},{5,22,4},{5,22,4},{4,18,13},{11,12,338},{4,18,13},{15,0,421},{6,27,1},{8,21,50},{6,21,1},{15,0,421},{13,15,421},{6,21,1},{0,19,445},{13,15,421},{0,19,445},{6,0,481},{6,0,481},{6,0,481},{6,0,481},{5,22,64},{5,22,64},{5,22,64},{5,17,65},{3,20,8},{3,20,8},{7,31,854},{7,27,438},{7,23,603}, +{7,22,443},{6,30,1515},{6,25,578},{6,22,15},{6,20,603},{1,29,1518},{4,20,458},{7,31,565},{7,27,149},{8,22,174},{7,22,154},{13,5,1514},{4,28,425},{6,22,14},{4,20,433},{12,15,1514},{4,20,433},{7,26,434},{7,26,434},{7,26,434},{7,21,437},{6,25,341},{6,22,14},{6,22,14},{6,18,30},{2,25,341},{4,19,35},{7,26,145},{7,26,145},{7,26,145},{7,21,148},{9,14,338}, +{5,24,5},{5,24,5},{5,19,10},{14,10,338},{5,19,10},{15,3,421},{7,27,5},{8,22,5},{6,22,10},{15,3,421},{15,14,421},{6,22,10},{0,20,433},{15,14,421},{0,20,433},{7,0,433},{7,0,433},{7,0,433},{7,0,433},{6,21,2},{6,21,2},{6,21,2},{6,18,5},{3,21,10},{3,21,10},{7,31,1046},{7,29,485},{7,24,770},{7,23,482},{7,29,1598},{6,27,570},{6,23,95}, +{6,21,582},{2,29,1533},{4,21,442},{8,28,450},{8,26,77},{8,23,35},{8,23,107},{15,1,1514},{5,28,425},{6,23,46},{4,21,442},{15,13,1514},{4,21,442},{7,29,481},{7,29,481},{7,29,481},{7,23,481},{6,28,387},{6,24,51},{6,24,51},{6,19,75},{3,25,341},{5,20,69},{8,24,25},{8,24,25},{8,24,25},{8,21,26},{11,10,338},{6,24,2},{6,24,2},{5,20,20},{5,23,338}, +{5,20,20},{13,12,421},{7,29,4},{8,23,10},{7,23,1},{13,12,421},{13,18,421},{7,23,1},{0,21,433},{13,18,421},{0,21,433},{7,0,481},{7,0,481},{7,0,481},{7,0,481},{6,24,50},{6,24,50},{6,24,50},{6,19,50},{4,21,9},{4,21,9},{8,31,1106},{8,28,714},{8,24,749},{8,24,734},{7,31,1542},{7,27,578},{7,24,19},{7,22,603},{2,31,1521},{5,22,458},{8,31,430}, +{8,28,38},{8,24,73},{8,24,58},{14,7,1514},{5,30,425},{7,24,18},{5,22,433},{13,17,1514},{5,22,433},{8,27,686},{8,27,686},{8,27,686},{8,23,686},{7,27,341},{7,24,19},{7,24,19},{7,20,26},{3,27,341},{5,21,45},{8,27,10},{8,27,10},{8,27,10},{8,23,10},{12,9,338},{6,26,2},{6,26,2},{6,21,20},{14,13,338},{6,21,20},{15,8,421},{7,31,20},{9,24,4}, +{7,24,9},{15,8,421},{15,17,421},{7,24,9},{0,22,433},{15,17,421},{0,22,433},{8,0,685},{8,0,685},{8,0,685},{8,0,685},{7,23,2},{7,23,2},{7,23,2},{7,19,10},{4,23,5},{4,23,5},{8,31,1034},{8,30,438},{8,26,603},{8,25,443},{8,30,1806},{7,29,566},{7,26,117},{7,23,590},{3,31,1535},{5,23,462},{9,31,437},{9,28,77},{9,25,33},{9,25,98},{10,23,1514}, +{6,30,429},{7,26,53},{6,23,454},{11,21,1514},{6,23,454},{8,29,434},{8,29,434},{8,29,434},{8,24,437},{7,30,404},{7,26,68},{7,26,68},{7,22,89},{4,27,347},{6,22,49},{9,26,17},{9,26,17},{9,26,17},{9,23,20},{15,2,338},{7,26,4},{7,26,4},{6,22,13},{13,16,338},{6,22,13},{15,11,421},{8,30,5},{9,25,17},{8,25,10},{15,11,421},{15,19,421},{8,25,10}, +{0,23,445},{15,19,421},{0,23,445},{8,0,433},{8,0,433},{8,0,433},{8,0,433},{7,26,64},{7,26,64},{7,26,64},{7,21,65},{5,24,8},{5,24,8},{9,31,1174},{8,31,506},{9,26,723},{8,26,482},{8,31,1643},{7,30,717},{8,26,131},{7,24,725},{4,31,1566},{6,24,458},{9,31,549},{9,30,41},{9,26,98},{9,26,53},{15,9,1514},{7,30,461},{8,26,50},{6,24,433},{14,19,1514}, +{6,24,433},{8,31,490},{8,31,490},{8,31,490},{8,26,481},{8,28,421},{8,25,122},{8,25,122},{8,22,131},{4,29,341},{6,23,35},{9,29,17},{9,29,17},{9,29,17},{9,25,17},{11,18,338},{7,28,5},{7,28,5},{7,23,10},{10,21,338},{7,23,10},{14,17,421},{9,30,25},{10,26,5},{8,26,1},{14,17,421},{13,23,421},{8,26,1},{0,24,433},{13,23,421},{0,24,433},{8,0,481}, +{8,0,481},{8,0,481},{8,0,481},{8,24,82},{8,24,82},{8,24,82},{8,21,81},{5,25,10},{5,25,10},{9,31,1334},{9,31,470},{9,28,597},{9,27,443},{9,31,1815},{8,30,578},{8,27,15},{8,25,603},{5,31,1638},{6,25,442},{10,31,506},{10,30,77},{10,27,35},{10,27,107},{14,15,1514},{7,31,506},{8,27,14},{6,25,442},{12,23,1514},{6,25,442},{9,31,434},{9,31,434},{9,31,434}, +{9,26,437},{8,30,341},{8,27,14},{8,27,14},{8,23,30},{5,29,341},{7,24,69},{10,28,25},{10,28,25},{10,28,25},{10,25,26},{13,14,338},{8,27,13},{8,27,13},{7,24,20},{8,25,338},{7,24,20},{15,16,421},{9,31,37},{10,27,10},{8,27,10},{15,16,421},{15,22,421},{8,27,10},{0,25,433},{15,22,421},{0,25,433},{9,0,433},{9,0,433},{9,0,433},{9,0,433},{8,26,2}, +{8,26,2},{8,26,2},{8,23,5},{6,25,9},{6,25,9},{10,31,1470},{10,31,735},{10,28,749},{9,28,481},{9,31,1895},{8,31,579},{8,28,89},{8,26,582},{6,31,1761},{7,26,458},{11,31,614},{10,31,59},{10,28,73},{10,28,58},{13,21,1514},{8,31,530},{8,28,40},{7,26,433},{15,21,1514},{7,26,433},{9,31,562},{9,31,562},{9,31,562},{9,28,481},{9,30,421},{8,29,51},{8,29,51}, +{8,24,65},{5,31,341},{7,25,45},{10,31,10},{10,31,10},{10,31,10},{10,27,10},{14,13,338},{8,29,2},{8,29,2},{8,24,16},{11,23,338},{8,24,16},{15,19,421},{10,31,50},{11,28,4},{9,28,0},{15,19,421},{13,26,421},{9,28,0},{0,26,433},{13,26,421},{0,26,433},{9,0,481},{9,0,481},{9,0,481},{9,0,481},{8,29,50},{8,29,50},{8,29,50},{8,24,49},{6,27,5}, +{6,27,5},{11,31,1838},{10,31,753},{10,30,603},{10,29,443},{10,31,2046},{9,31,629},{9,29,21},{9,27,589},{7,31,1935},{7,27,462},{11,31,749},{11,31,120},{11,29,33},{11,29,98},{12,27,1514},{9,31,629},{9,29,21},{7,27,461},{13,25,1514},{7,27,461},{10,31,497},{10,31,497},{10,31,497},{10,28,437},{9,31,388},{9,29,20},{9,29,20},{9,25,29},{6,31,347},{8,25,105},{11,30,17}, +{11,30,17},{11,30,17},{11,27,20},{14,16,338},{8,31,4},{8,31,4},{8,26,10},{15,20,338},{8,26,10},{14,25,421},{11,31,104},{11,29,17},{10,29,10},{14,25,421},{12,29,421},{10,29,10},{0,27,445},{12,29,421},{0,27,445},{10,0,433},{10,0,433},{10,0,433},{10,0,433},{9,28,1},{9,28,1},{9,28,1},{9,25,4},{7,28,8},{7,28,8},{11,31,1902},{11,31,1001},{11,30,723}, +{10,30,482},{11,31,2286},{10,31,782},{9,31,117},{9,28,578},{8,31,2118},{7,29,491},{12,31,770},{12,31,338},{11,30,98},{11,30,53},{14,23,1514},{10,31,701},{10,30,50},{8,28,442},{11,29,1514},{8,28,442},{11,31,677},{11,31,677},{11,31,677},{10,30,481},{10,31,437},{9,31,68},{9,31,68},{9,27,89},{7,31,379},{8,27,49},{11,31,52},{11,31,52},{11,31,52},{11,29,17},{13,22,338}, +{9,31,4},{9,31,4},{8,27,13},{12,25,338},{8,27,13},{15,24,421},{12,31,169},{12,30,5},{10,30,1},{15,24,421},{15,27,421},{10,30,1},{0,28,433},{15,27,421},{0,28,433},{10,0,481},{10,0,481},{10,0,481},{10,0,481},{9,31,64},{9,31,64},{9,31,64},{9,26,65},{7,29,10},{7,29,10},{12,31,2151},{11,31,1254},{11,31,629},{11,31,442},{11,31,2393},{10,31,975},{10,31,14}, +{10,29,570},{9,31,2241},{8,29,425},{13,31,931},{12,31,395},{12,31,34},{12,30,105},{13,29,1459},{11,31,778},{10,31,13},{8,29,400},{14,27,1459},{8,29,400},{11,31,629},{11,31,629},{11,31,629},{11,30,437},{10,31,581},{10,31,14},{10,31,14},{10,27,30},{8,31,477},{8,28,45},{12,31,34},{12,31,34},{12,31,34},{12,29,26},{15,18,338},{10,31,13},{10,31,13},{9,28,17},{10,29,338}, +{9,28,17},{15,27,394},{13,31,218},{12,31,9},{10,31,9},{15,27,394},{15,28,394},{10,31,9},{0,29,400},{15,28,394},{0,29,400},{11,0,433},{11,0,433},{11,0,433},{11,0,433},{10,30,2},{10,30,2},{10,30,2},{10,27,5},{8,29,25},{8,29,25},{12,31,1767},{12,31,1167},{12,31,806},{11,31,506},{12,31,1983},{11,31,747},{11,31,122},{10,29,346},{10,31,1836},{8,30,217},{13,31,611}, +{13,31,339},{12,31,130},{12,31,10},{15,24,1064},{12,31,587},{11,31,41},{8,30,217},{15,27,1067},{8,30,217},{12,31,806},{12,31,806},{12,31,806},{11,31,506},{11,31,581},{11,31,122},{11,31,122},{10,28,65},{9,31,557},{9,29,69},{12,31,130},{12,31,130},{12,31,130},{12,31,10},{13,27,338},{11,31,41},{11,31,41},{10,28,16},{13,27,338},{10,28,16},{14,31,200},{14,31,136},{13,31,1}, +{12,31,1},{14,31,200},{15,29,200},{12,31,1},{0,30,208},{15,29,200},{0,30,208},{11,0,481},{11,0,481},{11,0,481},{11,0,481},{11,30,82},{11,30,82},{11,30,82},{10,28,49},{8,30,9},{8,30,9},{13,31,1646},{12,31,1194},{12,31,833},{12,31,497},{12,31,1686},{12,31,750},{11,31,221},{11,30,122},{11,31,1541},{9,30,110},{14,31,542},{13,31,285},{13,31,116},{13,31,20},{15,26,722}, +{13,31,429},{12,31,100},{10,30,74},{14,29,722},{10,30,74},{12,31,833},{12,31,833},{12,31,833},{12,31,497},{12,31,725},{11,31,221},{11,31,221},{11,29,29},{10,31,632},{9,30,46},{13,31,116},{13,31,116},{13,31,116},{13,31,20},{13,30,338},{12,31,100},{12,31,100},{10,30,10},{12,30,338},{10,30,10},{15,29,61},{14,31,37},{14,31,1},{13,31,4},{15,29,61},{15,30,61},{13,31,4}, +{0,30,73},{15,30,61},{0,30,73},{12,0,433},{12,0,433},{12,0,433},{12,0,433},{11,31,25},{11,31,25},{11,31,25},{11,29,4},{9,31,17},{9,31,17},{13,31,1406},{13,31,1134},{13,31,965},{12,31,737},{13,31,1454},{12,31,702},{12,31,341},{11,31,89},{11,31,1381},{10,31,49},{14,31,318},{14,31,254},{14,31,218},{13,31,116},{14,31,510},{13,31,333},{13,31,164},{10,31,13},{14,30,509}, +{10,31,13},{13,31,965},{13,31,965},{13,31,965},{12,31,737},{12,31,869},{12,31,341},{12,31,341},{11,31,89},{11,31,756},{10,31,49},{14,31,218},{14,31,218},{14,31,218},{13,31,116},{15,26,338},{13,31,164},{13,31,164},{10,31,13},{14,29,338},{10,31,13},{15,30,9},{15,31,9},{15,31,9},{14,31,9},{15,30,9},{15,31,9},{14,31,9},{0,31,9},{15,31,9},{0,31,9},{12,0,481}, +{12,0,481},{12,0,481},{12,0,481},{12,31,85},{12,31,85},{12,31,85},{11,30,65},{10,31,40},{10,31,40},{13,31,1315},{13,31,1043},{13,31,874},{13,31,602},{13,31,1171},{13,31,627},{13,31,458},{12,31,5},{12,31,1087},{11,31,80},{14,31,225},{14,31,161},{14,31,125},{14,31,61},{15,29,297},{14,31,193},{14,31,157},{12,31,4},{14,31,297},{12,31,4},{13,31,874},{13,31,874},{13,31,874}, +{13,31,602},{13,31,730},{13,31,458},{13,31,458},{12,31,5},{11,31,705},{11,31,80},{14,31,125},{14,31,125},{14,31,125},{14,31,61},{14,31,221},{14,31,157},{14,31,157},{12,31,4},{15,29,221},{12,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,433},{13,0,433},{13,0,433},{13,0,433},{12,31,101}, +{12,31,101},{12,31,101},{12,31,5},{11,31,80},{11,31,80},{14,31,885},{14,31,821},{14,31,785},{13,31,650},{14,31,885},{13,31,483},{13,31,314},{13,31,81},{13,31,779},{11,31,144},{15,31,169},{14,31,145},{14,31,109},{14,31,45},{15,30,118},{14,31,81},{14,31,45},{13,31,0},{15,30,114},{13,31,0},{14,31,785},{14,31,785},{14,31,785},{13,31,650},{13,31,586},{13,31,314},{13,31,314}, +{13,31,81},{12,31,518},{11,31,144},{14,31,109},{14,31,109},{14,31,109},{14,31,45},{15,29,85},{14,31,45},{14,31,45},{13,31,0},{14,31,85},{13,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,481},{13,0,481},{13,0,481},{13,0,481},{13,31,145},{13,31,145},{13,31,145},{13,31,81},{11,31,144}, +{11,31,144},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{0,9,1899},{0,7,1355},{0,6,589},{0,4,1354},{0,5,2124},{0,4,1498},{0,13,884},{0,10,225},{0,7,18},{0,6,265},{2,2,1896},{0,7,1355},{0,6,589},{0,4,1354},{1,4,1896},{0,4,1354},{0,6,0},{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{0,2,200},{0,1,134},{0,6,0}, +{0,6,0},{0,6,0},{0,4,4},{0,3,162},{0,3,90},{0,3,90},{0,2,104},{0,2,164},{0,2,104},{3,3,882},{0,10,225},{0,7,18},{0,6,265},{3,3,882},{4,3,882},{0,6,265},{0,5,890},{4,3,882},{0,5,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,15,884},{0,12,170},{0,8,8}, +{0,7,202},{0,10,2360},{0,8,1530},{0,7,643},{0,5,1579},{0,6,2684},{0,5,1804},{0,15,884},{0,12,170},{0,8,8},{0,7,202},{1,7,2355},{0,8,1530},{0,7,643},{0,5,1579},{1,5,2355},{0,5,1579},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{0,4,340},{0,4,180},{0,4,180},{0,2,200},{0,2,392},{0,2,236},{0,9,1},{0,9,1},{0,9,1},{0,5,1},{1,1,338}, +{0,4,180},{0,4,180},{0,2,200},{2,0,340},{0,2,200},{4,2,882},{0,12,170},{0,8,8},{0,7,202},{4,2,882},{6,2,882},{0,7,202},{0,6,890},{6,2,882},{0,6,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{0,12,2899},{0,9,1773},{0,8,725}, +{0,6,1854},{0,7,3348},{0,5,2124},{0,18,882},{0,14,106},{0,10,52},{0,9,148},{1,9,2899},{0,9,1773},{0,8,725},{0,6,1854},{6,0,2899},{0,6,1854},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{0,6,580},{0,5,306},{0,5,306},{0,3,325},{0,3,667},{0,3,406},{0,11,1},{0,11,1},{0,11,1},{0,7,1},{1,2,580},{0,5,306},{0,5,306},{0,3,325},{2,1,578}, +{0,3,325},{3,8,882},{0,14,106},{1,9,13},{0,9,148},{3,8,882},{4,6,882},{0,9,148},{0,7,890},{4,6,882},{0,7,890},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,21,920},{0,16,89},{0,11,153},{0,10,121},{0,14,3051},{0,11,1709},{0,9,557},{0,7,1795},{0,8,3651},{0,6,2174},{0,21,920}, +{0,16,89},{1,10,108},{0,10,121},{4,1,3048},{0,11,1709},{0,9,557},{0,7,1795},{3,5,3048},{0,7,1795},{0,14,37},{0,14,37},{0,14,37},{0,8,37},{0,8,648},{0,7,274},{0,7,274},{0,4,277},{0,4,824},{0,4,421},{0,14,37},{0,14,37},{0,14,37},{0,8,37},{0,8,648},{0,7,274},{0,7,274},{0,4,277},{4,0,648},{0,4,277},{5,4,882},{0,16,53},{1,10,8}, +{0,10,85},{5,4,882},{9,1,882},{0,10,85},{0,8,900},{9,1,882},{0,8,900},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,2,0},{0,2,0},{0,2,0},{0,1,1},{0,1,10},{0,1,10},{0,23,1115},{0,18,242},{1,12,309},{0,11,259},{0,17,3051},{0,13,1579},{0,10,346},{0,8,1630},{0,9,3924},{0,7,2173},{1,20,885},{1,16,90},{1,12,53},{1,11,131},{4,4,3048}, +{0,13,1579},{0,10,346},{0,8,1630},{7,2,3048},{0,8,1630},{0,17,226},{0,17,226},{0,17,226},{0,10,225},{0,11,648},{0,9,169},{0,9,169},{0,5,200},{0,6,990},{0,5,425},{1,13,2},{1,13,2},{1,13,2},{1,9,2},{3,1,648},{0,9,169},{0,9,169},{0,5,200},{3,3,648},{0,5,200},{5,7,882},{0,18,17},{2,11,18},{0,11,34},{5,7,882},{6,7,882},{0,11,34}, +{0,9,890},{6,7,882},{0,9,890},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,5,0},{0,5,0},{0,5,0},{0,3,0},{0,2,61},{0,2,61},{1,23,1187},{1,18,350},{1,13,422},{1,12,373},{0,20,3048},{0,15,1443},{0,12,204},{0,9,1483},{0,11,4212},{0,8,2174},{1,23,931},{1,18,94},{2,12,108},{1,12,117},{6,0,3048},{0,15,1443},{0,12,204},{0,9,1483},{5,6,3048}, +{0,9,1483},{1,16,305},{1,16,305},{1,16,305},{1,10,309},{0,13,650},{0,11,109},{0,11,109},{0,7,148},{0,7,1161},{0,6,473},{1,16,49},{1,16,49},{1,16,49},{1,10,53},{4,0,648},{0,11,109},{0,11,109},{0,7,148},{1,7,648},{0,7,148},{7,3,882},{0,20,8},{2,12,8},{0,12,8},{7,3,882},{11,2,882},{0,12,8},{0,10,890},{11,2,882},{0,10,890},{1,0,305}, +{1,0,305},{1,0,305},{1,0,305},{0,8,1},{0,8,1},{0,8,1},{0,5,4},{0,3,145},{0,3,145},{1,25,1365},{1,20,497},{1,14,713},{1,13,510},{0,23,3051},{0,16,1278},{0,13,86},{0,10,1354},{0,12,4609},{0,9,2228},{2,22,886},{2,18,110},{2,14,56},{2,13,152},{5,6,3048},{0,16,1278},{0,13,86},{0,10,1354},{10,1,3048},{0,10,1354},{1,19,482},{1,19,482},{1,19,482}, +{1,12,481},{0,16,648},{0,12,72},{0,12,72},{0,8,101},{0,8,1352},{0,7,557},{2,15,5},{2,15,5},{2,15,5},{2,11,5},{3,6,648},{0,12,72},{0,12,72},{0,8,101},{3,6,648},{0,8,101},{5,12,882},{0,21,10},{3,13,13},{0,13,5},{5,12,882},{13,1,882},{0,13,5},{0,11,890},{13,1,882},{0,11,890},{1,0,481},{1,0,481},{1,0,481},{1,0,481},{0,10,1}, +{0,10,1},{0,10,1},{0,6,1},{0,5,261},{0,5,261},{1,28,1667},{1,22,793},{1,15,1182},{1,14,793},{0,25,3048},{0,18,1170},{0,14,36},{0,11,1243},{0,14,5005},{0,10,2318},{2,25,920},{2,20,89},{3,14,108},{2,14,121},{7,2,3048},{0,18,1170},{0,14,36},{0,11,1243},{12,0,3048},{0,11,1243},{1,21,786},{1,21,786},{1,21,786},{1,14,789},{0,19,650},{0,14,32},{0,14,32}, +{0,9,50},{0,9,1619},{0,8,661},{2,18,37},{2,18,37},{2,18,37},{2,12,37},{5,2,648},{0,14,32},{0,14,32},{0,9,50},{8,1,648},{0,9,50},{8,3,882},{1,22,8},{3,14,8},{1,14,8},{8,3,882},{11,5,882},{1,14,8},{0,12,900},{11,5,882},{0,12,900},{1,0,785},{1,0,785},{1,0,785},{1,0,785},{0,13,1},{0,13,1},{0,13,1},{0,8,4},{0,6,405}, +{0,6,405},{2,27,1844},{2,22,971},{2,16,1186},{2,15,988},{0,28,3084},{0,20,1095},{0,16,77},{0,12,1159},{0,16,4945},{0,12,2084},{3,24,885},{3,20,90},{3,16,53},{3,15,131},{6,8,3048},{0,20,1059},{0,16,41},{0,12,1123},{4,12,3048},{0,12,1123},{2,21,955},{2,21,955},{2,21,955},{2,14,954},{0,22,686},{0,16,41},{0,16,41},{0,10,49},{0,11,1577},{0,9,545},{3,17,2}, +{3,17,2},{3,17,2},{3,13,2},{5,5,648},{0,16,5},{0,16,5},{0,10,13},{5,7,648},{0,10,13},{8,6,882},{1,24,9},{4,15,18},{1,15,13},{8,6,882},{15,2,882},{1,15,13},{0,13,890},{15,2,882},{0,13,890},{2,0,954},{2,0,954},{2,0,954},{2,0,954},{0,16,37},{0,16,37},{0,16,37},{0,9,40},{0,8,373},{0,8,373},{2,30,1772},{2,24,898},{2,17,1287}, +{2,16,898},{1,27,3055},{1,20,1143},{1,16,33},{1,13,1214},{0,17,4639},{0,13,1730},{3,27,931},{3,22,94},{4,16,108},{3,16,117},{5,14,3048},{0,21,996},{1,16,29},{0,13,1054},{14,1,3048},{0,13,1054},{2,23,891},{2,23,891},{2,23,891},{2,16,894},{1,21,652},{1,16,29},{1,16,29},{1,11,44},{0,13,1452},{0,11,365},{3,20,49},{3,20,49},{3,20,49},{3,14,53},{7,1,648}, +{0,18,1},{0,18,1},{0,11,4},{10,2,648},{0,11,4},{5,20,882},{2,24,8},{4,16,8},{2,16,8},{5,20,882},{13,6,882},{2,16,8},{0,14,890},{13,6,882},{0,14,890},{2,0,890},{2,0,890},{2,0,890},{2,0,890},{1,15,4},{1,15,4},{1,15,4},{1,10,5},{0,9,269},{0,9,269},{3,29,1838},{3,24,970},{3,18,1186},{3,17,983},{1,30,3084},{1,22,1095},{1,18,77}, +{1,14,1159},{0,19,4419},{0,14,1444},{4,26,886},{4,22,110},{4,18,56},{4,17,152},{8,5,3048},{0,23,936},{1,18,41},{0,14,1003},{12,5,3048},{0,14,1003},{3,23,955},{3,23,955},{3,23,955},{3,16,954},{1,23,692},{1,18,41},{1,18,41},{1,12,46},{0,15,1296},{0,12,235},{4,19,5},{4,19,5},{4,19,5},{4,15,5},{5,10,648},{1,18,5},{1,18,5},{0,12,10},{12,1,648}, +{0,12,10},{11,1,882},{2,25,10},{5,17,13},{2,17,5},{11,1,882},{15,5,882},{2,17,5},{0,15,890},{15,5,882},{0,15,890},{3,0,954},{3,0,954},{3,0,954},{3,0,954},{1,18,37},{1,18,37},{1,18,37},{1,11,40},{0,11,185},{0,11,185},{3,31,1790},{3,26,898},{3,19,1287},{3,18,898},{2,29,3057},{2,22,1179},{2,18,45},{1,15,1250},{0,20,4156},{0,15,1226},{4,29,920}, +{4,24,89},{5,18,108},{4,18,121},{3,26,3048},{0,25,909},{2,18,36},{0,15,970},{15,3,3048},{0,15,970},{3,25,891},{3,25,891},{3,25,891},{3,18,894},{2,23,659},{2,18,41},{2,18,41},{2,13,59},{0,16,1137},{0,13,137},{4,22,37},{4,22,37},{4,22,37},{4,16,37},{8,1,648},{1,20,2},{1,20,2},{1,13,1},{10,5,648},{1,13,1},{10,7,882},{3,26,8},{5,18,8}, +{3,18,8},{10,7,882},{13,9,882},{3,18,8},{0,16,900},{13,9,882},{0,16,900},{3,0,890},{3,0,890},{3,0,890},{3,0,890},{2,17,10},{2,17,10},{2,17,10},{2,12,13},{0,13,136},{0,13,136},{4,31,1844},{4,26,971},{4,20,1186},{4,19,988},{2,31,3111},{2,24,1095},{2,20,77},{2,16,1159},{0,22,3940},{0,16,1055},{5,28,885},{5,24,90},{5,20,53},{5,19,131},{5,22,3048}, +{0,27,886},{2,20,41},{0,17,926},{8,13,3048},{0,17,926},{4,25,955},{4,25,955},{4,25,955},{4,18,954},{2,26,686},{2,20,41},{2,20,41},{2,14,49},{0,18,1002},{0,15,110},{5,21,2},{5,21,2},{5,21,2},{5,17,2},{8,4,648},{2,20,5},{2,20,5},{2,14,13},{14,2,648},{2,14,13},{13,0,882},{3,28,9},{6,19,18},{3,19,13},{13,0,882},{5,21,882},{3,19,13}, +{0,17,890},{5,21,882},{0,17,890},{4,0,954},{4,0,954},{4,0,954},{4,0,954},{2,20,37},{2,20,37},{2,20,37},{2,13,40},{0,15,74},{0,15,74},{4,31,1972},{4,28,898},{4,21,1287},{4,20,898},{3,31,3055},{3,24,1143},{3,20,33},{3,17,1214},{0,23,3820},{0,18,963},{5,31,931},{5,26,94},{6,20,108},{5,20,117},{11,3,3048},{0,28,899},{3,20,29},{0,18,899},{11,11,3048}, +{0,18,899},{4,27,891},{4,27,891},{4,27,891},{4,20,894},{3,25,652},{3,20,29},{3,20,29},{3,15,44},{0,20,876},{0,16,102},{5,24,49},{5,24,49},{5,24,49},{5,18,53},{3,25,648},{2,22,1},{2,22,1},{2,15,4},{12,6,648},{2,15,4},{8,19,882},{4,28,8},{6,20,8},{4,20,8},{8,19,882},{15,10,882},{4,20,8},{0,18,890},{15,10,882},{0,18,890},{4,0,890}, +{4,0,890},{4,0,890},{4,0,890},{3,19,4},{3,19,4},{3,19,4},{3,14,5},{0,17,29},{0,17,29},{5,31,1964},{5,28,970},{5,22,1186},{5,21,983},{4,31,3172},{3,26,1095},{3,22,77},{3,18,1159},{0,25,3679},{0,19,899},{6,30,886},{6,26,110},{6,22,56},{6,21,152},{10,9,3048},{1,29,888},{3,22,41},{0,19,890},{14,9,3048},{0,19,890},{5,27,955},{5,27,955},{5,27,955}, +{5,20,954},{3,27,692},{3,22,41},{3,22,41},{3,16,46},{0,22,800},{1,16,98},{6,23,5},{6,23,5},{6,23,5},{6,19,5},{9,6,648},{3,22,5},{3,22,5},{2,16,10},{14,5,648},{2,16,10},{13,5,882},{4,29,10},{7,21,13},{4,21,5},{13,5,882},{12,15,882},{4,21,5},{0,19,890},{12,15,882},{0,19,890},{5,0,954},{5,0,954},{5,0,954},{5,0,954},{3,22,37}, +{3,22,37},{3,22,37},{3,15,40},{0,19,9},{0,19,9},{6,31,2264},{5,30,898},{5,23,1287},{5,22,898},{4,31,3204},{4,26,1179},{4,22,45},{3,19,1250},{0,27,3523},{0,20,908},{6,31,968},{6,28,89},{7,22,108},{6,22,121},{9,15,3048},{1,30,899},{4,22,36},{0,20,904},{5,22,3048},{0,20,904},{5,29,891},{5,29,891},{5,29,891},{5,22,894},{4,27,659},{4,22,41},{4,22,41}, +{4,17,59},{0,23,747},{1,18,102},{6,26,37},{6,26,37},{6,26,37},{6,20,37},{10,5,648},{3,24,2},{3,24,2},{3,17,1},{12,9,648},{3,17,1},{15,1,882},{5,30,8},{7,22,8},{5,22,8},{15,1,882},{15,13,882},{5,22,8},{0,20,900},{15,13,882},{0,20,900},{5,0,890},{5,0,890},{5,0,890},{5,0,890},{4,21,10},{4,21,10},{4,21,10},{4,16,13},{0,20,8}, +{0,20,8},{6,31,2228},{6,30,971},{6,24,1186},{6,23,988},{5,31,3256},{4,28,1095},{4,24,77},{4,20,1159},{0,29,3364},{1,21,894},{7,31,915},{7,28,90},{7,24,53},{7,23,131},{14,1,3048},{2,31,886},{4,24,41},{1,21,890},{10,17,3048},{1,21,890},{6,29,955},{6,29,955},{6,29,955},{6,22,954},{4,30,686},{4,24,41},{4,24,41},{4,18,49},{0,25,705},{2,19,110},{7,25,2}, +{7,25,2},{7,25,2},{7,21,2},{10,8,648},{4,24,5},{4,24,5},{4,18,13},{11,12,648},{4,18,13},{15,4,882},{6,30,17},{7,24,52},{5,23,13},{15,4,882},{9,22,882},{5,23,13},{0,21,890},{9,22,882},{0,21,890},{6,0,954},{6,0,954},{6,0,954},{6,0,954},{4,24,37},{4,24,37},{4,24,37},{4,17,40},{1,21,4},{1,21,4},{7,31,2444},{6,31,907},{6,25,1287}, +{6,24,898},{6,31,3436},{5,28,1143},{5,24,33},{5,21,1214},{0,31,3276},{1,22,908},{8,30,1208},{7,30,94},{7,25,166},{7,24,117},{13,7,3048},{3,31,906},{5,24,29},{1,22,899},{13,15,3048},{1,22,899},{6,31,891},{6,31,891},{6,31,891},{6,24,894},{5,29,652},{5,24,29},{5,24,29},{5,19,44},{0,27,665},{2,20,102},{7,28,49},{7,28,49},{7,28,49},{7,22,53},{9,14,648}, +{4,26,1},{4,26,1},{4,19,4},{14,10,648},{4,19,4},{10,23,882},{6,31,17},{8,24,13},{6,24,8},{10,23,882},{11,21,882},{6,24,8},{0,22,890},{11,21,882},{0,22,890},{6,0,890},{6,0,890},{6,0,890},{6,0,890},{5,23,4},{5,23,4},{5,23,4},{5,18,5},{1,23,4},{1,23,4},{7,31,2636},{7,31,991},{7,26,1186},{7,25,983},{6,31,3532},{5,30,1095},{5,26,77}, +{5,22,1159},{0,31,3340},{2,23,899},{8,31,1014},{7,31,262},{8,25,108},{7,25,254},{15,3,3048},{4,31,936},{5,26,41},{2,23,890},{11,19,3048},{2,23,890},{7,31,955},{7,31,955},{7,31,955},{7,24,954},{5,31,692},{5,26,41},{5,26,41},{5,20,46},{0,29,651},{3,20,98},{8,26,101},{8,26,101},{8,26,101},{8,22,101},{11,10,648},{5,26,5},{5,26,5},{4,20,10},{5,23,648}, +{4,20,10},{15,9,882},{7,31,37},{8,25,8},{6,25,5},{15,9,882},{14,19,882},{6,25,5},{0,23,890},{14,19,882},{0,23,890},{7,0,954},{7,0,954},{7,0,954},{7,0,954},{5,26,37},{5,26,37},{5,26,37},{5,19,40},{2,23,9},{2,23,9},{8,31,3110},{7,31,1135},{7,27,1287},{7,26,898},{7,31,3652},{6,30,1179},{6,26,45},{5,23,1250},{1,31,3492},{2,24,908},{8,31,1174}, +{8,31,110},{8,27,56},{8,26,152},{11,19,3048},{5,31,996},{6,26,36},{2,24,904},{9,23,3048},{2,24,904},{7,31,939},{7,31,939},{7,31,939},{7,26,894},{6,31,659},{6,26,41},{6,26,41},{6,21,59},{1,29,659},{3,22,102},{8,28,4},{8,28,4},{8,28,4},{8,24,8},{12,9,648},{5,28,2},{5,28,2},{5,21,1},{14,13,648},{5,21,1},{14,15,882},{8,31,106},{9,26,13}, +{7,26,8},{14,15,882},{12,23,882},{7,26,8},{0,24,900},{12,23,882},{0,24,900},{7,0,890},{7,0,890},{7,0,890},{7,0,890},{6,25,10},{6,25,10},{6,25,10},{6,20,13},{2,24,8},{2,24,8},{8,31,3038},{8,31,1470},{8,28,1391},{7,27,1137},{7,31,4120},{6,31,1146},{6,28,77},{6,24,1159},{3,31,3681},{3,25,894},{9,31,1205},{8,31,245},{9,27,99},{8,27,122},{10,25,3048}, +{6,31,1110},{6,28,41},{3,25,890},{12,21,3048},{3,25,890},{8,31,1274},{8,31,1274},{8,31,1274},{7,27,1128},{7,30,750},{6,28,41},{6,28,41},{6,22,49},{1,31,648},{4,23,110},{8,31,49},{8,31,49},{8,31,49},{8,25,53},{15,2,648},{6,28,5},{6,28,5},{6,22,13},{13,16,648},{6,22,13},{14,18,882},{9,31,164},{9,27,18},{7,27,13},{14,18,882},{11,26,882},{7,27,13}, +{0,25,890},{11,26,882},{0,25,890},{7,0,1124},{7,0,1124},{7,0,1124},{7,0,1124},{6,28,37},{6,28,37},{6,28,37},{6,21,40},{3,25,4},{3,25,4},{9,31,3454},{8,31,1502},{8,29,1186},{8,28,983},{8,31,4077},{7,31,1230},{7,28,33},{7,25,1214},{4,31,3820},{3,26,908},{10,31,1368},{9,31,261},{9,29,53},{9,28,126},{15,11,3048},{7,31,1226},{7,28,29},{3,26,899},{15,19,3048}, +{3,26,899},{8,31,1018},{8,31,1018},{8,31,1018},{8,27,954},{7,31,724},{7,28,29},{7,28,29},{7,23,44},{2,31,665},{4,24,102},{9,30,2},{9,30,2},{9,30,2},{9,26,2},{11,18,648},{6,30,1},{6,30,1},{6,23,4},{10,21,648},{6,23,4},{12,27,882},{10,31,225},{10,28,13},{7,28,20},{12,27,882},{13,25,882},{7,28,20},{0,26,890},{13,25,882},{0,26,890},{8,0,954}, +{8,0,954},{8,0,954},{8,0,954},{7,27,4},{7,27,4},{7,27,4},{7,22,5},{3,27,4},{3,27,4},{9,31,3614},{9,31,1886},{8,30,1287},{8,29,898},{8,31,4381},{7,31,1582},{7,30,77},{7,26,1159},{5,31,4036},{4,27,899},{10,31,1560},{10,31,405},{10,29,108},{9,29,117},{14,17,3048},{8,31,1444},{7,30,41},{4,27,890},{13,23,3048},{4,27,890},{8,31,1146},{8,31,1146},{8,31,1146}, +{8,29,894},{8,30,1011},{7,30,41},{7,30,41},{7,24,46},{3,31,705},{5,24,98},{9,31,85},{9,31,85},{9,31,85},{9,27,53},{13,14,648},{7,30,5},{7,30,5},{6,24,10},{8,25,648},{6,24,10},{14,23,882},{10,31,305},{10,29,8},{8,29,8},{14,23,882},{11,29,882},{8,29,8},{0,27,890},{11,29,882},{0,27,890},{8,0,890},{8,0,890},{8,0,890},{8,0,890},{7,30,37}, +{7,30,37},{7,30,37},{7,23,40},{4,27,9},{4,27,9},{10,31,4072},{9,31,2174},{9,31,1186},{9,30,983},{9,31,4545},{8,31,1725},{8,30,207},{7,27,1250},{6,31,4339},{4,28,908},{11,31,1656},{10,31,645},{10,31,56},{10,30,152},{13,23,3048},{8,31,1604},{7,31,77},{4,28,904},{11,27,3048},{4,28,904},{9,31,1150},{9,31,1150},{9,31,1150},{9,29,954},{8,31,841},{8,29,193},{8,29,193}, +{7,25,197},{4,31,747},{5,26,102},{10,31,20},{10,31,20},{10,31,20},{10,28,8},{14,13,648},{7,31,41},{7,31,41},{7,25,1},{11,23,648},{7,25,1},{13,29,882},{11,31,397},{11,30,13},{8,30,5},{13,29,882},{14,27,882},{8,30,5},{0,28,900},{14,27,882},{0,28,900},{9,0,954},{9,0,954},{9,0,954},{9,0,954},{8,27,122},{8,27,122},{8,27,122},{8,23,122},{4,28,8}, +{4,28,8},{10,31,4147},{10,31,2404},{9,31,1429},{9,31,901},{10,31,4627},{9,31,1938},{8,31,38},{8,28,1061},{7,31,4330},{5,29,789},{12,31,1701},{11,31,715},{11,31,90},{10,31,113},{15,19,2814},{10,31,1554},{8,31,34},{5,29,785},{13,26,2814},{5,29,785},{9,31,1429},{9,31,1429},{9,31,1429},{9,31,901},{9,31,1022},{8,31,38},{8,31,38},{8,26,44},{5,31,840},{6,27,110},{11,31,90}, +{11,31,90},{11,31,90},{10,29,53},{14,16,648},{8,31,34},{8,31,34},{7,26,20},{15,20,648},{7,26,20},{15,25,761},{12,31,425},{11,31,9},{9,31,1},{15,25,761},{12,31,761},{9,31,1},{0,29,785},{12,31,761},{0,29,785},{9,0,900},{9,0,900},{9,0,900},{9,0,900},{8,30,4},{8,30,4},{8,30,4},{8,25,5},{5,29,4},{5,29,4},{11,31,3735},{10,31,2356},{10,31,1395}, +{10,31,954},{10,31,4099},{9,31,1618},{9,31,174},{8,29,686},{7,31,3930},{6,29,510},{12,31,1285},{12,31,685},{11,31,122},{11,31,37},{13,27,2249},{10,31,1186},{9,31,74},{6,29,485},{13,27,2249},{6,29,485},{10,31,1395},{10,31,1395},{10,31,1395},{10,31,954},{9,31,1086},{9,31,174},{9,31,174},{8,27,49},{6,31,969},{6,28,102},{11,31,122},{11,31,122},{11,31,122},{11,30,2},{13,22,648}, +{9,31,74},{9,31,74},{8,27,13},{12,25,648},{8,27,13},{15,26,481},{13,31,269},{12,31,0},{10,31,0},{15,26,481},{15,28,481},{10,31,0},{0,29,481},{15,28,481},{0,29,481},{10,0,954},{10,0,954},{10,0,954},{10,0,954},{8,31,61},{8,31,61},{8,31,61},{8,26,40},{5,31,4},{5,31,4},{11,31,3399},{11,31,2260},{11,31,1635},{10,31,954},{11,31,3639},{10,31,1435},{9,31,238}, +{9,29,430},{8,31,3443},{6,30,314},{13,31,1121},{12,31,525},{12,31,164},{11,31,53},{13,29,1769},{11,31,918},{10,31,113},{7,30,290},{14,27,1769},{7,30,290},{11,31,1635},{11,31,1635},{11,31,1635},{10,31,954},{10,31,1251},{9,31,238},{9,31,238},{9,28,41},{7,31,1105},{7,28,98},{12,31,164},{12,31,164},{12,31,164},{11,31,53},{15,18,648},{10,31,113},{10,31,113},{8,28,1},{10,29,648}, +{8,28,1},{15,27,269},{13,31,173},{13,31,4},{11,31,4},{15,27,269},{14,30,265},{11,31,4},{0,30,289},{14,30,265},{0,30,289},{10,0,890},{10,0,890},{10,0,890},{10,0,890},{9,31,13},{9,31,13},{9,31,13},{9,27,5},{6,31,9},{6,31,9},{12,31,3157},{11,31,2308},{11,31,1683},{11,31,1054},{11,31,3303},{10,31,1339},{10,31,378},{9,30,213},{9,31,3103},{7,30,166},{13,31,801}, +{13,31,529},{12,31,260},{12,31,20},{15,24,1374},{12,31,777},{11,31,181},{8,30,117},{15,27,1377},{8,30,117},{11,31,1683},{11,31,1683},{11,31,1683},{11,31,1054},{10,31,1491},{10,31,378},{10,31,378},{9,29,46},{8,31,1331},{7,30,102},{12,31,260},{12,31,260},{12,31,260},{12,31,20},{13,27,648},{11,31,181},{11,31,181},{8,29,10},{13,27,648},{8,29,10},{15,28,117},{14,31,61},{14,31,25}, +{13,31,4},{15,28,117},{14,31,117},{13,31,4},{0,30,113},{14,31,117},{0,30,113},{11,0,954},{11,0,954},{11,0,954},{11,0,954},{10,31,122},{10,31,122},{10,31,122},{9,28,40},{7,31,29},{7,31,29},{12,31,2860},{12,31,2260},{12,31,1899},{11,31,1261},{12,31,2932},{11,31,1310},{11,31,685},{10,30,108},{10,31,2731},{7,31,173},{13,31,747},{13,31,475},{13,31,306},{13,31,130},{15,26,1032}, +{12,31,651},{12,31,290},{8,31,40},{14,29,1032},{8,31,40},{12,31,1899},{12,31,1899},{12,31,1899},{11,31,1261},{11,31,1620},{11,31,685},{11,31,685},{10,30,44},{9,31,1524},{8,30,134},{13,31,306},{13,31,306},{13,31,306},{13,31,130},{13,30,648},{12,31,290},{12,31,290},{9,30,5},{12,30,648},{9,30,5},{15,30,18},{15,30,34},{14,31,16},{14,31,0},{15,30,18},{15,30,26},{14,31,0}, +{0,31,36},{15,30,26},{0,31,36},{11,0,900},{11,0,900},{11,0,900},{11,0,900},{10,31,104},{10,31,104},{10,31,104},{10,29,5},{8,30,130},{8,30,130},{13,31,2732},{12,31,2276},{12,31,1915},{12,31,1315},{12,31,2660},{11,31,1414},{11,31,789},{10,31,45},{11,31,2487},{8,31,116},{14,31,524},{14,31,460},{14,31,424},{13,31,170},{14,31,776},{13,31,507},{13,31,338},{10,31,9},{14,30,771}, +{10,31,9},{12,31,1915},{12,31,1915},{12,31,1915},{12,31,1315},{12,31,1699},{11,31,789},{11,31,789},{10,31,45},{10,31,1546},{8,31,116},{14,31,424},{14,31,424},{14,31,424},{13,31,170},{15,26,580},{13,31,338},{13,31,338},{10,31,9},{14,29,580},{10,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{12,0,954}, +{12,0,954},{12,0,954},{12,0,954},{11,31,164},{11,31,164},{11,31,164},{10,30,40},{8,31,116},{8,31,116},{13,31,2156},{13,31,1884},{13,31,1715},{12,31,1251},{13,31,2132},{12,31,1108},{12,31,747},{11,31,5},{11,31,1927},{9,31,180},{14,31,300},{14,31,236},{14,31,200},{14,31,136},{15,28,451},{14,31,328},{13,31,194},{11,31,1},{15,29,456},{11,31,1},{13,31,1715},{13,31,1715},{13,31,1715}, +{12,31,1251},{12,31,1347},{12,31,747},{12,31,747},{11,31,5},{10,31,1242},{9,31,180},{14,31,200},{14,31,200},{14,31,200},{14,31,136},{15,27,338},{13,31,194},{13,31,194},{11,31,1},{13,31,338},{11,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{12,0,890},{12,0,890},{12,0,890},{12,0,890},{11,31,260}, +{11,31,260},{11,31,260},{11,31,5},{9,31,180},{9,31,180},{13,31,1836},{13,31,1564},{13,31,1395},{13,31,1123},{13,31,1620},{12,31,1012},{12,31,651},{11,31,85},{12,31,1564},{10,31,233},{14,31,204},{14,31,140},{14,31,104},{14,31,40},{15,29,216},{14,31,136},{14,31,100},{12,31,1},{14,31,216},{12,31,1},{13,31,1395},{13,31,1395},{13,31,1395},{13,31,1123},{13,31,1179},{12,31,651},{12,31,651}, +{11,31,85},{11,31,998},{10,31,233},{14,31,104},{14,31,104},{14,31,104},{14,31,40},{15,28,162},{14,31,100},{14,31,100},{12,31,1},{15,29,164},{12,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{13,0,954},{13,0,954},{13,0,954},{13,0,954},{12,31,290},{12,31,290},{12,31,290},{11,31,85},{10,31,233}, +{10,31,233},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{0,11,3379},{0,9,2369},{0,8,1061},{0,5,2435},{0,6,3760},{0,5,2660},{0,17,1568},{0,14,442},{0,10,40},{0,8,485},{1,8,3372},{0,9,2369},{0,8,1061},{0,5,2435},{5,1,3371},{0,5,2435},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{0,2,332},{0,2,200},{0,8,0}, +{0,8,0},{0,8,0},{0,5,1},{0,4,288},{0,4,160},{0,4,160},{0,2,164},{2,0,288},{0,2,164},{3,7,1568},{0,14,442},{0,10,40},{0,8,485},{3,7,1568},{8,0,1568},{0,8,485},{0,6,1586},{8,0,1568},{0,6,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,20,1570},{0,16,325},{0,11,5}, +{0,9,392},{0,13,3968},{0,10,2630},{0,9,1121},{0,6,2710},{0,7,4484},{0,6,3034},{0,20,1570},{0,16,325},{0,11,5},{0,9,392},{1,10,3968},{0,10,2630},{0,9,1121},{0,6,2710},{5,2,3968},{0,6,2710},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{0,5,514},{0,5,274},{0,5,274},{0,3,289},{0,3,595},{0,3,370},{0,11,1},{0,11,1},{0,11,1},{0,6,4},{1,2,512}, +{0,5,274},{0,5,274},{0,3,289},{1,2,512},{0,3,289},{5,3,1568},{0,16,325},{0,11,5},{0,9,392},{5,3,1568},{4,7,1568},{0,9,392},{0,7,1586},{4,7,1568},{0,7,1586},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{0,15,4652},{0,11,2945},{0,10,1217}, +{0,7,3035},{0,8,5283},{0,7,3476},{0,22,1570},{0,17,225},{0,12,18},{0,11,292},{2,8,4651},{0,11,2945},{0,10,1217},{0,7,3035},{5,3,4651},{0,7,3035},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{0,7,802},{0,6,424},{0,6,424},{0,4,449},{0,3,931},{0,3,562},{0,13,0},{0,13,0},{0,13,0},{0,8,1},{2,0,800},{0,6,424},{0,6,424},{0,4,449},{0,4,800}, +{0,4,449},{1,19,1568},{0,17,225},{0,12,18},{0,11,292},{1,19,1568},{9,2,1568},{0,11,292},{0,8,1576},{9,2,1568},{0,8,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,1570},{0,19,149},{0,13,73},{0,12,194},{0,17,5424},{0,13,3368},{0,11,1349},{0,8,3449},{0,9,6213},{0,7,3956},{0,25,1570}, +{0,19,149},{0,13,73},{0,12,194},{5,0,5419},{0,13,3368},{0,11,1349},{0,8,3449},{5,4,5419},{0,8,3449},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{0,8,1152},{0,7,610},{0,7,610},{0,4,625},{0,4,1328},{0,4,769},{0,16,1},{0,16,1},{0,16,1},{0,9,4},{0,8,1152},{0,7,610},{0,7,610},{0,4,625},{4,0,1152},{0,4,625},{5,8,1568},{0,19,149},{1,13,13}, +{0,12,194},{5,8,1568},{4,10,1568},{0,12,194},{0,9,1576},{4,10,1568},{0,9,1576},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,1651},{0,21,155},{0,14,281},{0,13,198},{0,20,5424},{0,15,3099},{0,12,996},{0,9,3179},{0,10,6544},{0,8,3890},{1,24,1619},{0,21,155},{1,14,69},{0,13,198},{5,3,5419}, +{0,15,3099},{0,12,996},{0,9,3179},{4,7,5419},{0,9,3179},{0,19,82},{0,19,82},{0,19,82},{0,11,82},{0,11,1152},{0,9,445},{0,9,445},{0,6,505},{0,6,1494},{0,5,737},{1,15,50},{1,15,50},{1,15,50},{1,10,49},{3,1,1152},{0,9,445},{0,9,445},{0,6,505},{3,3,1152},{0,6,505},{5,11,1568},{0,21,74},{1,14,20},{0,13,117},{5,11,1568},{11,3,1568},{0,13,117}, +{0,10,1586},{11,3,1568},{0,10,1586},{0,0,81},{0,0,81},{0,0,81},{0,0,81},{0,3,0},{0,3,0},{0,3,0},{0,2,1},{0,1,25},{0,1,25},{1,27,1825},{0,23,323},{1,15,342},{0,14,361},{0,22,5420},{0,16,2834},{0,13,726},{0,10,2966},{0,11,6916},{0,9,3860},{1,27,1569},{1,21,131},{1,15,86},{1,14,181},{1,19,5419},{0,16,2834},{0,13,726},{0,10,2966},{9,2,5419}, +{0,10,2966},{1,18,257},{1,18,257},{1,18,257},{1,12,261},{0,13,1154},{0,11,337},{0,11,337},{0,7,388},{0,7,1665},{0,6,749},{1,18,1},{1,18,1},{1,18,1},{1,12,5},{4,0,1152},{0,11,337},{0,11,337},{0,7,388},{1,7,1152},{0,7,388},{8,2,1568},{0,23,34},{2,15,5},{0,14,72},{8,2,1568},{13,2,1568},{0,14,72},{0,11,1586},{13,2,1568},{0,11,1586},{1,0,257}, +{1,0,257},{1,0,257},{1,0,257},{0,6,1},{0,6,1},{0,6,1},{0,3,4},{0,2,85},{0,2,85},{1,30,1907},{1,23,411},{1,16,542},{1,15,454},{0,25,5424},{0,18,2630},{0,15,486},{0,11,2771},{0,13,7299},{0,11,3860},{2,26,1634},{1,23,155},{2,16,82},{1,15,198},{5,8,5419},{0,18,2630},{0,15,486},{0,11,2771},{4,10,5419},{0,11,2771},{1,21,338},{1,21,338},{1,21,338}, +{1,13,338},{0,16,1152},{0,13,274},{0,13,274},{0,8,305},{0,8,1856},{0,7,797},{2,17,64},{2,17,64},{2,17,64},{2,12,65},{3,6,1152},{0,13,274},{0,13,274},{0,8,305},{3,6,1152},{0,8,305},{3,23,1568},{0,25,17},{2,16,18},{0,15,45},{3,23,1568},{11,6,1568},{0,15,45},{0,12,1576},{11,6,1568},{0,12,1576},{1,0,337},{1,0,337},{1,0,337},{1,0,337},{0,8,1}, +{0,8,1},{0,8,1},{0,5,0},{0,4,169},{0,4,169},{1,31,2145},{1,25,590},{1,17,915},{1,16,619},{0,27,5420},{0,20,2424},{0,16,282},{0,12,2552},{0,15,7711},{0,11,3908},{2,29,1570},{2,23,149},{2,17,73},{2,16,194},{7,4,5419},{0,20,2424},{0,16,282},{0,12,2552},{9,5,5419},{0,12,2552},{1,23,546},{1,23,546},{1,23,546},{1,15,546},{0,19,1154},{0,15,194},{0,15,194}, +{0,9,218},{0,9,2123},{0,8,865},{2,20,1},{2,20,1},{2,20,1},{2,13,4},{5,2,1152},{0,15,194},{0,15,194},{0,9,218},{8,1,1152},{0,9,218},{9,4,1568},{0,27,5},{3,17,13},{0,16,26},{9,4,1568},{9,10,1568},{0,16,26},{0,13,1576},{9,10,1568},{0,13,1576},{1,0,545},{1,0,545},{1,0,545},{1,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289}, +{0,5,289},{2,31,2746},{1,27,945},{2,18,1370},{1,17,977},{0,30,5420},{0,22,2243},{0,17,145},{0,13,2386},{0,16,8161},{0,13,3986},{3,28,1619},{2,25,155},{3,18,69},{2,17,198},{8,2,5419},{0,22,2243},{0,17,145},{0,13,2386},{13,2,5419},{0,13,2386},{1,26,932},{1,26,932},{1,26,932},{1,16,936},{0,22,1154},{0,17,109},{0,17,109},{0,10,145},{0,11,2441},{0,9,1001},{3,19,50}, +{3,19,50},{3,19,50},{3,14,49},{5,5,1152},{0,17,109},{0,17,109},{0,10,145},{5,7,1152},{0,10,145},{11,0,1568},{0,29,10},{3,18,20},{0,18,8},{11,0,1568},{13,7,1568},{0,18,8},{0,14,1586},{13,7,1568},{0,14,1586},{1,0,932},{1,0,932},{1,0,932},{1,0,932},{0,14,1},{0,14,1},{0,14,1},{0,8,1},{0,6,468},{0,6,468},{2,31,3146},{2,27,1412},{2,19,1743}, +{1,19,1441},{0,31,5515},{0,23,2096},{0,19,69},{0,14,2251},{0,18,8669},{0,14,4100},{3,31,1569},{3,25,131},{3,19,86},{3,18,181},{3,23,5419},{0,23,2096},{0,19,69},{0,14,2251},{11,6,5419},{0,14,2251},{2,25,1379},{2,25,1379},{2,25,1379},{2,17,1379},{0,24,1152},{0,18,61},{0,18,61},{0,11,100},{0,12,2859},{0,10,1157},{3,22,1},{3,22,1},{3,22,1},{3,16,5},{7,1,1152}, +{0,18,61},{0,18,61},{0,11,100},{10,2,1152},{0,11,100},{10,6,1568},{1,29,2},{4,19,5},{0,19,5},{10,6,1568},{15,6,1568},{0,19,5},{0,15,1586},{15,6,1568},{0,15,1586},{2,0,1378},{2,0,1378},{2,0,1378},{2,0,1378},{0,16,1},{0,16,1},{0,16,1},{0,10,1},{0,8,657},{0,8,657},{2,31,3802},{2,29,1603},{2,21,2148},{2,19,1631},{1,31,5655},{0,25,2005},{0,20,31}, +{0,15,2138},{0,19,8963},{0,15,4070},{4,30,1634},{3,27,155},{4,20,82},{3,19,198},{9,4,5419},{0,25,2001},{0,20,27},{0,15,2134},{9,10,5419},{0,15,2134},{2,28,1587},{2,28,1587},{2,28,1587},{2,18,1590},{0,27,1158},{0,20,22},{0,20,22},{0,12,62},{0,14,3075},{0,11,1221},{4,21,64},{4,21,64},{4,21,64},{4,16,65},{5,10,1152},{0,20,18},{0,20,18},{0,12,58},{12,1,1152}, +{0,12,58},{12,2,1568},{1,31,10},{4,20,18},{0,20,18},{12,2,1568},{13,10,1568},{0,20,18},{0,16,1576},{13,10,1568},{0,16,1576},{2,0,1586},{2,0,1586},{2,0,1586},{2,0,1586},{0,19,4},{0,19,4},{0,19,4},{0,11,8},{0,9,769},{0,9,769},{3,31,3890},{2,31,1623},{3,21,2180},{2,20,1644},{1,31,5863},{0,27,1989},{1,21,109},{0,17,2117},{0,21,8560},{0,16,3545},{4,31,1640}, +{4,27,149},{4,21,73},{4,20,194},{10,3,5419},{0,27,1889},{0,21,49},{0,17,2017},{11,9,5419},{0,17,2017},{2,30,1619},{2,30,1619},{2,30,1619},{2,20,1619},{1,26,1188},{1,20,86},{1,20,86},{1,13,121},{0,16,2801},{0,13,949},{4,24,1},{4,24,1},{4,24,1},{4,17,4},{8,1,1152},{0,22,2},{0,22,2},{0,14,26},{10,5,1152},{0,14,26},{11,8,1568},{2,31,5},{5,21,13}, +{1,21,9},{11,8,1568},{11,14,1568},{1,21,9},{0,17,1576},{11,14,1568},{0,17,1576},{2,0,1618},{2,0,1618},{2,0,1618},{2,0,1618},{1,18,37},{1,18,37},{1,18,37},{1,12,37},{0,10,625},{0,10,625},{4,31,4308},{3,31,1589},{3,23,2160},{3,21,1621},{2,31,5895},{1,27,1999},{1,22,33},{1,18,2124},{0,23,8196},{0,17,3043},{5,31,1667},{4,29,155},{5,22,69},{4,21,198},{10,6,5419}, +{0,29,1772},{1,22,24},{0,18,1875},{15,6,5419},{0,18,1875},{3,30,1576},{3,30,1576},{3,30,1576},{3,20,1580},{1,29,1161},{1,22,29},{1,22,29},{1,15,58},{0,17,2529},{0,14,656},{5,23,50},{5,23,50},{5,23,50},{5,18,49},{8,4,1152},{0,24,1},{0,24,1},{0,15,1},{14,2,1152},{0,15,1},{13,4,1568},{3,31,13},{5,22,20},{2,22,8},{13,4,1568},{15,11,1568},{2,22,8}, +{0,18,1586},{15,11,1568},{0,18,1586},{3,0,1576},{3,0,1576},{3,0,1576},{3,0,1576},{1,21,10},{1,21,10},{1,21,10},{1,14,13},{0,12,520},{0,12,520},{4,31,4436},{3,31,1765},{4,23,2175},{3,23,1669},{3,31,6079},{1,29,1977},{2,23,105},{1,19,2107},{0,24,7969},{0,18,2675},{6,31,1832},{5,29,131},{5,23,86},{5,22,181},{12,2,5419},{0,30,1699},{1,23,62},{0,19,1782},{13,10,5419}, +{0,19,1782},{3,31,1665},{3,31,1665},{3,31,1665},{3,22,1640},{2,28,1188},{2,22,97},{2,22,97},{2,15,136},{0,19,2313},{0,15,474},{5,26,1},{5,26,1},{5,26,1},{5,20,5},{3,25,1152},{1,24,5},{1,24,5},{0,16,2},{12,6,1152},{0,16,2},{15,0,1568},{4,31,34},{6,23,5},{2,23,5},{15,0,1568},{12,16,1568},{2,23,5},{0,19,1586},{12,16,1568},{0,19,1586},{3,0,1640}, +{3,0,1640},{3,0,1640},{3,0,1640},{2,20,37},{2,20,37},{2,20,37},{2,14,37},{0,14,400},{0,14,400},{5,31,4740},{4,31,1716},{4,25,2148},{4,23,1631},{3,31,6351},{2,29,2005},{2,24,31},{2,19,2138},{0,26,7669},{0,19,2375},{6,31,1832},{5,31,155},{6,24,82},{5,23,198},{11,8,5419},{0,31,1712},{2,24,27},{0,20,1720},{11,14,5419},{0,20,1720},{4,31,1595},{4,31,1595},{4,31,1595}, +{4,22,1590},{2,31,1158},{2,24,22},{2,24,22},{2,16,62},{0,21,2091},{0,17,306},{6,25,64},{6,25,64},{6,25,64},{6,20,65},{9,6,1152},{1,26,1},{1,26,1},{1,17,5},{14,5,1152},{1,17,5},{14,6,1568},{5,31,74},{6,24,18},{2,24,18},{14,6,1568},{15,14,1568},{2,24,18},{0,20,1576},{15,14,1568},{0,20,1576},{4,0,1586},{4,0,1586},{4,0,1586},{4,0,1586},{2,23,4}, +{2,23,4},{2,23,4},{2,15,8},{0,16,277},{0,16,277},{5,31,5060},{5,31,1980},{5,25,2180},{4,24,1644},{4,31,6508},{2,31,1989},{3,25,109},{2,21,2117},{0,28,7364},{0,21,2098},{7,31,1952},{6,31,149},{6,25,73},{6,24,194},{12,7,5419},{1,31,1804},{2,25,49},{0,21,1657},{13,13,5419},{0,21,1657},{4,31,1739},{4,31,1739},{4,31,1739},{4,24,1619},{3,30,1188},{3,24,86},{3,24,86}, +{3,17,121},{0,22,1928},{0,18,194},{6,28,1},{6,28,1},{6,28,1},{6,21,4},{10,5,1152},{2,26,2},{2,26,2},{1,18,2},{12,9,1152},{1,18,2},{13,12,1568},{6,31,149},{7,25,13},{3,25,9},{13,12,1568},{13,18,1568},{3,25,9},{0,21,1576},{13,18,1568},{0,21,1576},{4,0,1618},{4,0,1618},{4,0,1618},{4,0,1618},{3,22,37},{3,22,37},{3,22,37},{3,16,37},{0,18,193}, +{0,18,193},{6,31,5316},{5,31,2160},{5,27,2160},{5,25,1621},{5,31,6800},{3,31,1999},{3,26,33},{3,22,2124},{0,29,7068},{0,22,1836},{7,31,2195},{7,31,270},{7,26,69},{6,25,198},{15,0,5419},{2,31,1970},{3,26,24},{0,22,1611},{12,16,5419},{0,22,1611},{5,31,1676},{5,31,1676},{5,31,1676},{5,24,1580},{3,31,1233},{3,26,29},{3,26,29},{3,19,58},{0,24,1798},{0,19,157},{7,27,50}, +{7,27,50},{7,27,50},{7,22,49},{10,8,1152},{2,28,1},{2,28,1},{2,19,1},{11,12,1152},{2,19,1},{15,8,1568},{7,31,221},{7,26,20},{4,26,8},{15,8,1568},{11,22,1568},{4,26,8},{0,22,1586},{11,22,1568},{0,22,1586},{5,0,1576},{5,0,1576},{5,0,1576},{5,0,1576},{3,25,10},{3,25,10},{3,25,10},{3,18,13},{0,20,106},{0,20,106},{6,31,5828},{6,31,2435},{6,27,2175}, +{5,27,1669},{5,31,7184},{4,31,2132},{4,27,105},{3,23,2107},{0,31,6820},{0,23,1690},{8,31,2306},{7,31,334},{7,27,86},{7,26,181},{14,6,5419},{4,31,2096},{3,27,62},{0,23,1590},{15,14,5419},{0,23,1590},{6,31,1859},{6,31,1859},{6,31,1859},{5,26,1640},{4,31,1220},{4,26,97},{4,26,97},{4,19,136},{0,26,1650},{0,21,161},{7,30,1},{7,30,1},{7,30,1},{7,24,5},{9,14,1152}, +{3,28,5},{3,28,5},{2,20,2},{14,10,1152},{2,20,2},{14,14,1568},{7,31,333},{8,27,40},{4,27,5},{14,14,1568},{14,20,1568},{4,27,5},{0,23,1586},{14,20,1568},{0,23,1586},{5,0,1640},{5,0,1640},{5,0,1640},{5,0,1640},{4,24,37},{4,24,37},{4,24,37},{4,18,37},{0,22,58},{0,22,58},{7,31,6036},{6,31,2835},{6,29,2148},{6,27,1631},{6,31,7316},{4,31,2228},{4,28,31}, +{4,23,2138},{0,31,6884},{0,24,1613},{8,31,2402},{8,31,666},{8,28,269},{7,27,198},{13,12,5419},{4,31,2224},{4,28,27},{0,24,1577},{13,18,5419},{0,24,1577},{6,31,1811},{6,31,1811},{6,31,1811},{6,26,1590},{5,31,1356},{4,28,22},{4,28,22},{4,20,62},{0,28,1508},{1,21,137},{7,31,106},{7,31,106},{7,31,106},{7,25,82},{11,10,1152},{3,30,1},{3,30,1},{3,21,5},{5,23,1152}, +{3,21,5},{13,20,1568},{8,31,410},{8,28,13},{4,28,18},{13,20,1568},{13,23,1570},{4,28,18},{0,24,1576},{13,23,1570},{0,24,1576},{6,0,1586},{6,0,1586},{6,0,1586},{6,0,1586},{4,27,4},{4,27,4},{4,27,4},{4,19,8},{0,24,37},{0,24,37},{7,31,6740},{7,31,3135},{7,29,2180},{6,28,1644},{7,31,7676},{5,31,2448},{5,29,109},{4,25,2117},{1,31,7196},{0,25,1593},{9,31,2594}, +{8,31,698},{8,29,82},{8,28,345},{14,11,5419},{5,31,2412},{4,29,49},{1,25,1580},{15,17,5419},{1,25,1580},{7,31,1979},{7,31,1979},{7,31,1979},{6,28,1619},{5,31,1388},{5,28,86},{5,28,86},{5,21,121},{0,30,1416},{1,23,161},{8,30,64},{8,30,64},{8,30,64},{8,25,65},{12,9,1152},{4,30,2},{4,30,2},{3,22,2},{14,13,1152},{3,22,2},{15,16,1568},{9,31,530},{8,29,18}, +{5,29,9},{15,16,1568},{15,22,1568},{5,29,9},{0,25,1576},{15,22,1568},{0,25,1576},{6,0,1618},{6,0,1618},{6,0,1618},{6,0,1618},{5,26,37},{5,26,37},{5,26,37},{5,20,37},{0,25,17},{0,25,17},{8,31,6906},{7,31,3909},{7,31,2160},{7,29,1621},{7,31,8144},{6,31,2902},{5,30,33},{5,26,2124},{2,31,7661},{1,26,1615},{9,31,2945},{9,31,1025},{8,30,86},{8,29,181},{14,14,5419}, +{7,31,2694},{5,30,24},{1,26,1590},{14,20,5419},{1,26,1590},{7,31,2060},{7,31,2060},{7,31,2060},{7,28,1580},{6,31,1476},{5,30,29},{5,30,29},{5,23,58},{0,31,1324},{2,23,157},{8,31,37},{8,31,37},{8,31,37},{8,27,5},{15,2,1152},{5,30,20},{5,30,20},{4,23,1},{13,16,1152},{4,23,1},{15,19,1568},{10,31,637},{9,30,5},{6,30,8},{15,19,1568},{13,26,1568},{6,30,8}, +{0,26,1586},{13,26,1568},{0,26,1586},{7,0,1576},{7,0,1576},{7,0,1576},{7,0,1576},{5,29,10},{5,29,10},{5,29,10},{5,22,13},{0,28,10},{0,28,10},{8,31,7386},{8,31,4250},{8,31,2490},{7,31,1669},{8,31,8461},{6,31,3350},{6,31,105},{5,27,2107},{4,31,8004},{1,27,1611},{10,31,3112},{9,31,1361},{9,31,69},{8,30,198},{13,20,5419},{7,31,2950},{5,31,62},{2,27,1590},{11,25,5420}, +{2,27,1590},{8,31,2486},{8,31,2486},{8,31,2486},{7,30,1640},{6,31,1700},{6,30,97},{6,30,97},{6,23,136},{1,31,1424},{2,25,161},{9,31,65},{9,31,65},{9,31,65},{9,27,49},{11,18,1152},{5,31,58},{5,31,58},{4,24,2},{10,21,1152},{4,24,2},{13,28,1568},{11,31,785},{9,31,20},{6,31,5},{13,28,1568},{11,30,1568},{6,31,5},{0,27,1586},{11,30,1568},{0,27,1586},{7,0,1640}, +{7,0,1640},{7,0,1640},{7,0,1640},{6,28,37},{6,28,37},{6,28,37},{6,22,37},{1,28,10},{1,28,10},{9,31,7014},{8,31,4230},{8,31,2294},{8,31,1846},{8,31,7865},{7,31,3114},{6,31,85},{6,27,1706},{4,31,7436},{2,28,1289},{11,31,2852},{10,31,1221},{9,31,145},{9,30,114},{13,22,4803},{8,31,2648},{6,31,81},{2,28,1253},{12,25,4803},{2,28,1253},{8,31,2294},{8,31,2294},{8,31,2294}, +{8,30,1811},{7,31,1740},{6,31,85},{6,31,85},{6,24,62},{2,31,1577},{3,25,137},{9,31,145},{9,31,145},{9,31,145},{9,29,5},{13,14,1152},{6,31,81},{6,31,81},{5,25,5},{8,25,1152},{5,25,5},{15,23,1250},{11,31,689},{10,31,4},{7,31,9},{15,23,1250},{11,31,1250},{7,31,9},{0,28,1252},{11,31,1250},{0,28,1252},{8,0,1810},{8,0,1810},{8,0,1810},{8,0,1810},{6,31,4}, +{6,31,4},{6,31,4},{6,23,8},{1,29,8},{1,29,8},{9,31,6534},{9,31,4134},{8,31,2486},{8,31,1590},{9,31,7237},{7,31,2970},{7,31,161},{6,28,1256},{5,31,6748},{2,29,949},{11,31,2340},{10,31,1125},{10,31,164},{9,31,97},{15,17,4056},{9,31,2244},{7,31,125},{3,28,909},{12,26,4056},{3,28,909},{8,31,2486},{8,31,2486},{8,31,2486},{8,31,1590},{7,31,2156},{7,31,161},{7,31,161}, +{7,25,121},{3,31,1729},{3,27,161},{10,31,164},{10,31,164},{10,31,164},{10,29,65},{14,13,1152},{7,31,125},{7,31,125},{5,26,2},{11,23,1152},{5,26,2},{13,31,882},{12,31,482},{11,31,0},{8,31,4},{13,31,882},{15,27,882},{8,31,4},{0,28,900},{15,27,882},{0,28,900},{8,0,1586},{8,0,1586},{8,0,1586},{8,0,1586},{7,30,37},{7,30,37},{7,30,37},{7,24,37},{1,31,16}, +{1,31,16},{10,31,6091},{9,31,4053},{9,31,2609},{8,31,1761},{9,31,6490},{8,31,2622},{7,31,458},{7,28,835},{6,31,6162},{3,29,598},{12,31,1989},{11,31,931},{11,31,306},{10,31,5},{15,19,3318},{10,31,1806},{8,31,202},{4,29,545},{13,26,3318},{4,29,545},{9,31,2609},{9,31,2609},{9,31,2609},{8,31,1761},{8,31,2086},{7,31,458},{7,31,458},{7,27,58},{4,31,1868},{4,27,157},{11,31,306}, +{11,31,306},{11,31,306},{10,31,5},{14,16,1152},{8,31,202},{8,31,202},{6,27,1},{15,20,1152},{6,27,1},{15,26,545},{13,31,313},{12,31,4},{10,31,4},{15,26,545},{14,29,545},{10,31,4},{0,29,545},{14,29,545},{0,29,545},{8,0,1640},{8,0,1640},{8,0,1640},{8,0,1640},{7,31,58},{7,31,58},{7,31,58},{7,26,13},{2,31,13},{2,31,13},{10,31,5723},{10,31,3980},{9,31,2945}, +{9,31,1745},{10,31,6083},{8,31,2494},{8,31,558},{7,29,558},{7,31,5674},{4,30,411},{12,31,1573},{11,31,963},{11,31,338},{11,31,49},{13,27,2753},{10,31,1438},{9,31,290},{5,29,341},{13,27,2753},{5,29,341},{9,31,2945},{9,31,2945},{9,31,2945},{9,31,1745},{9,31,2390},{8,31,558},{8,31,558},{7,28,147},{5,31,2064},{4,29,161},{11,31,338},{11,31,338},{11,31,338},{11,31,49},{13,22,1152}, +{9,31,290},{9,31,290},{6,28,2},{12,25,1152},{6,28,2},{15,27,313},{13,31,185},{13,31,16},{11,31,0},{15,27,313},{13,31,313},{11,31,0},{0,29,337},{13,31,313},{0,29,337},{9,0,1576},{9,0,1576},{9,0,1576},{9,0,1576},{8,31,197},{8,31,197},{8,31,197},{7,27,122},{3,31,25},{3,31,25},{11,31,5415},{10,31,3996},{10,31,3035},{10,31,2006},{10,31,5619},{9,31,2378},{8,31,814}, +{8,29,414},{7,31,5338},{5,30,251},{12,31,1413},{12,31,813},{12,31,452},{11,31,65},{13,29,2273},{11,31,1218},{10,31,365},{6,30,146},{14,27,2273},{6,30,146},{10,31,3035},{10,31,3035},{10,31,3035},{10,31,2006},{9,31,2518},{8,31,814},{8,31,814},{8,28,121},{6,31,2329},{5,29,137},{12,31,452},{12,31,452},{12,31,452},{11,31,65},{15,18,1152},{10,31,365},{10,31,365},{7,29,5},{10,29,1152}, +{7,29,5},{15,28,145},{14,31,85},{13,31,16},{12,31,4},{15,28,145},{15,29,149},{12,31,4},{0,30,145},{15,29,149},{0,30,145},{9,0,1640},{9,0,1640},{9,0,1640},{9,0,1640},{8,31,85},{8,31,85},{8,31,85},{8,27,37},{4,31,40},{4,31,40},{11,31,5143},{11,31,4004},{11,31,3379},{10,31,2070},{11,31,5287},{10,31,2431},{9,31,1062},{8,30,133},{8,31,5011},{5,31,161},{13,31,1161}, +{13,31,889},{12,31,548},{12,31,164},{15,24,1878},{11,31,1106},{11,31,481},{7,30,66},{15,27,1881},{7,30,66},{11,31,3379},{11,31,3379},{11,31,3379},{10,31,2070},{10,31,2835},{9,31,1062},{9,31,1062},{8,29,62},{7,31,2577},{5,31,161},{12,31,548},{12,31,548},{12,31,548},{12,31,164},{13,27,1152},{11,31,481},{11,31,481},{7,30,2},{13,27,1152},{7,30,2},{15,29,45},{14,31,37},{14,31,1}, +{14,31,9},{15,29,45},{15,30,41},{14,31,9},{0,30,65},{15,30,41},{0,30,65},{10,0,1586},{10,0,1586},{10,0,1586},{10,0,1586},{9,31,221},{9,31,221},{9,31,221},{8,28,8},{5,31,80},{5,31,80},{12,31,4948},{11,31,4157},{11,31,3532},{11,31,2393},{11,31,5008},{10,31,2422},{10,31,1461},{9,31,125},{9,31,4752},{6,31,157},{13,31,1107},{13,31,835},{13,31,666},{12,31,362},{15,26,1536}, +{12,31,1011},{12,31,650},{8,31,16},{14,29,1536},{8,31,16},{11,31,3532},{11,31,3532},{11,31,3532},{11,31,2393},{10,31,3204},{10,31,1461},{10,31,1461},{9,30,114},{8,31,2976},{6,31,157},{13,31,666},{13,31,666},{13,31,666},{12,31,362},{13,30,1152},{12,31,650},{12,31,650},{8,31,16},{12,30,1152},{8,31,16},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0}, +{0,31,0},{15,31,0},{0,31,0},{10,0,1640},{10,0,1640},{10,0,1640},{10,0,1640},{9,31,221},{9,31,221},{9,31,221},{9,29,25},{6,31,157},{6,31,157},{12,31,4212},{12,31,3612},{12,31,3251},{11,31,2201},{12,31,4212},{11,31,2154},{10,31,1301},{9,31,13},{10,31,3939},{7,31,233},{14,31,776},{13,31,659},{13,31,490},{13,31,218},{15,27,1067},{13,31,699},{12,31,442},{9,31,4},{13,31,1067}, +{9,31,4},{12,31,3251},{12,31,3251},{12,31,3251},{11,31,2201},{11,31,2668},{10,31,1301},{10,31,1301},{9,31,13},{8,31,2528},{7,31,233},{13,31,490},{13,31,490},{13,31,490},{13,31,218},{15,25,802},{12,31,442},{12,31,442},{9,31,4},{15,27,802},{9,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{11,0,1576}, +{11,0,1576},{11,0,1576},{11,0,1576},{10,31,340},{10,31,340},{10,31,340},{9,31,13},{7,31,233},{7,31,233},{12,31,3732},{12,31,3132},{12,31,2771},{12,31,2171},{12,31,3444},{11,31,1834},{11,31,1209},{10,31,37},{10,31,3219},{8,31,400},{14,31,456},{14,31,392},{14,31,356},{13,31,170},{14,31,684},{13,31,459},{13,31,290},{10,31,1},{14,30,683},{10,31,1},{12,31,2771},{12,31,2771},{12,31,2771}, +{12,31,2171},{11,31,2348},{11,31,1209},{11,31,1209},{10,31,37},{9,31,2156},{8,31,400},{14,31,356},{14,31,356},{14,31,356},{13,31,170},{15,26,512},{13,31,290},{13,31,290},{10,31,1},{14,29,512},{10,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{11,0,1640},{11,0,1640},{11,0,1640},{11,0,1640},{10,31,436}, +{10,31,436},{10,31,436},{10,31,37},{8,31,400},{8,31,400},{13,31,3172},{13,31,2900},{12,31,2547},{12,31,1947},{12,31,2932},{12,31,1732},{11,31,1145},{10,31,53},{11,31,2695},{8,31,464},{14,31,264},{14,31,200},{14,31,164},{14,31,100},{15,28,387},{14,31,268},{13,31,178},{11,31,1},{15,29,396},{11,31,1},{12,31,2547},{12,31,2547},{12,31,2547},{12,31,1947},{12,31,1971},{11,31,1145},{11,31,1145}, +{10,31,53},{10,31,1794},{8,31,464},{14,31,164},{14,31,164},{14,31,164},{14,31,100},{15,27,290},{13,31,178},{13,31,178},{11,31,1},{14,30,290},{11,31,1},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{12,0,1586},{12,0,1586},{12,0,1586},{12,0,1586},{11,31,520},{11,31,520},{11,31,520},{10,31,53},{8,31,464}, +{8,31,464},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{0,15,5885},{0,11,4118},{0,10,1800},{0,7,4202},{0,8,6546},{0,7,4643},{0,23,2665},{0,18,680},{0,13,50},{0,11,785},{3,5,5885},{0,11,4118},{0,10,1800},{0,7,4202},{0,9,5885},{0,7,4202},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,549},{0,5,289},{0,5,289},{0,3,306},{0,3,630},{0,3,387},{0,11,0}, +{0,11,0},{0,11,0},{0,7,4},{1,2,545},{0,5,289},{0,5,289},{0,3,306},{2,1,545},{0,3,306},{6,3,2665},{0,18,680},{0,13,50},{0,11,785},{6,3,2665},{11,0,2665},{0,11,785},{0,8,2689},{11,0,2665},{0,8,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,25,2665},{0,20,521},{0,14,5}, +{0,12,625},{0,17,6669},{0,13,4529},{0,11,1890},{0,8,4610},{0,9,7494},{0,7,5171},{0,25,2665},{0,20,521},{0,14,5},{0,12,625},{3,7,6669},{0,13,4529},{0,11,1890},{0,8,4610},{8,0,6669},{0,8,4610},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,7,841},{0,6,445},{0,6,445},{0,4,464},{0,3,982},{0,3,595},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{2,0,841}, +{0,6,445},{0,6,445},{0,4,464},{1,3,841},{0,4,464},{7,2,2665},{0,20,521},{0,14,5},{0,12,625},{7,2,2665},{12,0,2665},{0,12,625},{0,9,2689},{12,0,2665},{0,9,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{0,19,7541},{0,14,4934},{0,12,2042}, +{0,9,5045},{0,10,8546},{0,8,5682},{0,28,2665},{0,22,405},{0,15,10},{0,13,514},{5,2,7538},{0,14,4934},{0,12,2042},{0,9,5045},{8,1,7538},{0,9,5045},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,8,1201},{0,7,637},{0,7,637},{0,4,656},{0,4,1385},{0,4,800},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{1,5,1201},{0,7,637},{0,7,637},{0,4,656},{4,0,1201}, +{0,4,656},{6,8,2665},{0,22,405},{0,15,10},{0,13,514},{6,8,2665},{11,3,2665},{0,13,514},{0,10,2689},{11,3,2665},{0,10,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,30,2669},{0,23,313},{0,16,68},{0,15,410},{0,20,8498},{0,16,5330},{0,13,2210},{0,10,5530},{0,11,9702},{0,9,6270},{0,30,2669}, +{0,23,313},{0,16,68},{0,15,410},{4,7,8493},{0,16,5330},{0,13,2210},{0,10,5530},{8,2,8493},{0,10,5530},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,9,1629},{0,8,832},{0,8,832},{0,5,881},{0,5,1874},{0,5,1106},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{2,3,1625},{0,8,832},{0,8,832},{0,5,881},{4,1,1625},{0,5,881},{8,2,2665},{0,23,313},{1,16,8}, +{0,15,410},{8,2,2665},{14,1,2665},{0,15,410},{0,11,2689},{14,1,2665},{0,11,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,31,2777},{0,26,232},{0,17,197},{0,16,305},{0,22,9674},{0,17,5849},{0,14,2450},{0,10,6106},{0,12,11199},{0,10,7006},{0,31,2777},{0,26,232},{0,17,197},{0,16,305},{1,19,9669}, +{0,17,5849},{0,14,2450},{0,10,6106},{9,2,9669},{0,10,6106},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,11,2178},{0,10,1125},{0,10,1125},{0,6,1189},{0,6,2520},{0,5,1475},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{3,1,2178},{0,10,1125},{0,10,1125},{0,6,1189},{3,3,2178},{0,6,1189},{9,2,2665},{0,26,232},{1,17,17},{0,16,305},{9,2,2665},{13,4,2665},{0,16,305}, +{0,12,2689},{13,4,2665},{0,12,2689},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{1,31,3045},{0,28,217},{0,19,401},{0,17,282},{0,25,9670},{0,19,5529},{0,16,1970},{0,12,5738},{0,13,11589},{0,11,6898},{1,31,2789},{0,28,217},{1,18,146},{0,17,282},{5,8,9669},{0,19,5529},{0,16,1970},{0,12,5738},{4,10,9669}, +{0,12,5738},{0,24,64},{0,24,64},{0,24,64},{0,15,68},{0,13,2180},{0,11,949},{0,11,949},{0,7,1018},{0,7,2691},{0,6,1433},{1,21,64},{1,21,64},{1,21,64},{1,13,68},{4,0,2178},{0,11,949},{0,11,949},{0,7,1018},{1,7,2178},{0,7,1018},{10,1,2665},{0,28,153},{2,18,5},{0,17,218},{10,1,2665},{15,3,2665},{0,17,218},{0,13,2689},{15,3,2665},{0,13,2689},{0,0,64}, +{0,0,64},{0,0,64},{0,0,64},{0,3,1},{0,3,1},{0,3,1},{0,2,4},{0,1,18},{0,1,18},{1,31,3285},{0,29,341},{1,19,453},{0,18,405},{0,27,9674},{0,20,5170},{0,17,1546},{0,13,5429},{0,15,11993},{0,12,6819},{2,31,2966},{1,28,221},{1,19,197},{1,18,305},{7,4,9669},{0,20,5170},{0,17,1546},{0,13,5429},{9,5,9669},{0,13,5429},{0,27,257},{0,27,257},{0,27,257}, +{1,15,256},{0,16,2178},{0,13,832},{0,13,832},{0,8,881},{0,8,2882},{0,7,1427},{1,23,4},{1,23,4},{1,23,4},{1,15,0},{3,6,2178},{0,13,832},{0,13,832},{0,8,881},{3,6,2178},{0,8,881},{11,0,2665},{0,29,85},{2,19,10},{0,18,149},{11,0,2665},{13,7,2665},{0,18,149},{0,14,2689},{13,7,2665},{0,14,2689},{0,0,256},{0,0,256},{0,0,256},{0,0,256},{0,5,1}, +{0,5,1},{0,5,1},{0,3,1},{0,2,72},{0,2,72},{1,31,3909},{1,29,465},{1,21,676},{1,19,538},{0,30,9669},{0,22,4878},{0,18,1190},{0,14,5138},{0,16,12390},{0,13,6789},{2,31,2966},{1,29,209},{2,20,149},{1,19,282},{6,10,9669},{0,22,4878},{0,18,1190},{0,14,5138},{12,3,9669},{0,14,5138},{1,26,320},{1,26,320},{1,26,320},{1,16,324},{0,19,2180},{0,15,680},{0,15,680}, +{0,9,740},{0,9,3149},{0,8,1441},{1,26,64},{1,26,64},{1,26,64},{1,16,68},{5,2,2178},{0,15,680},{0,15,680},{0,9,740},{8,1,2178},{0,9,740},{11,3,2665},{0,31,41},{3,20,8},{0,19,98},{11,3,2665},{15,6,2665},{0,19,98},{0,15,2689},{15,6,2665},{0,15,2689},{1,0,320},{1,0,320},{1,0,320},{1,0,320},{0,8,0},{0,8,0},{0,8,0},{0,5,1},{0,4,160}, +{0,4,160},{2,31,4514},{1,31,630},{1,22,1110},{1,20,694},{0,31,9789},{0,23,4646},{0,20,849},{0,15,4826},{0,18,12955},{0,14,6798},{3,31,3101},{2,30,232},{2,21,197},{2,20,305},{3,23,9669},{0,23,4646},{0,20,849},{0,15,4826},{11,6,9669},{0,15,4826},{1,29,545},{1,29,545},{1,29,545},{1,18,546},{0,22,2180},{0,17,505},{0,17,505},{0,11,610},{0,11,3467},{0,10,1513},{2,26,1}, +{2,26,1},{2,26,1},{2,17,0},{5,5,2178},{0,17,505},{0,17,505},{0,11,610},{5,7,2178},{0,11,610},{11,6,2665},{1,31,85},{3,21,17},{0,20,65},{11,6,2665},{15,8,2665},{0,20,65},{0,16,2689},{15,8,2665},{0,16,2689},{1,0,545},{1,0,545},{1,0,545},{1,0,545},{0,11,0},{0,11,0},{0,11,0},{0,7,4},{0,5,289},{0,5,289},{2,31,5330},{1,31,1110},{2,23,1490}, +{1,21,979},{1,31,9981},{0,26,4406},{0,21,579},{0,16,4610},{0,19,13489},{0,15,6846},{3,31,3341},{2,31,226},{3,22,146},{2,21,282},{9,4,9669},{0,26,4406},{0,21,579},{0,16,4610},{9,10,9669},{0,16,4610},{1,31,885},{1,31,885},{1,31,885},{1,20,885},{0,24,2178},{0,19,389},{0,19,389},{0,12,464},{0,12,3885},{0,11,1603},{3,25,64},{3,25,64},{3,25,64},{3,17,68},{7,1,2178}, +{0,19,389},{0,19,389},{0,12,464},{10,2,2178},{0,12,464},{13,2,2665},{2,31,162},{4,22,5},{0,22,37},{13,2,2665},{12,13,2665},{0,22,37},{0,17,2689},{12,13,2665},{0,17,2689},{1,0,881},{1,0,881},{1,0,881},{1,0,881},{0,13,1},{0,13,1},{0,13,1},{0,8,0},{0,6,445},{0,6,445},{3,31,6366},{2,31,1635},{2,24,1886},{1,22,1410},{1,31,10381},{0,28,4146},{0,22,377}, +{0,17,4373},{0,20,14006},{0,16,6915},{4,31,3434},{3,31,242},{3,23,197},{3,22,305},{10,3,9669},{0,28,4146},{0,22,377},{0,17,4373},{11,9,9669},{0,17,4373},{2,31,1346},{2,31,1346},{2,31,1346},{2,20,1345},{0,27,2180},{0,21,274},{0,21,274},{0,13,353},{0,14,4269},{0,11,1763},{3,27,4},{3,27,4},{3,27,4},{3,19,0},{5,10,2178},{0,21,274},{0,21,274},{0,13,353},{12,1,2178}, +{0,13,353},{14,1,2665},{3,31,242},{4,23,10},{0,23,10},{14,1,2665},{15,11,2665},{0,23,10},{0,18,2689},{15,11,2665},{0,18,2689},{1,0,1345},{1,0,1345},{1,0,1345},{1,0,1345},{0,16,0},{0,16,0},{0,16,0},{0,10,4},{0,7,637},{0,7,637},{3,31,7374},{2,31,2339},{2,25,2441},{2,23,1763},{2,31,11019},{0,29,3909},{0,23,243},{0,18,4154},{0,22,14614},{0,17,7029},{5,31,3654}, +{4,31,394},{4,24,149},{3,23,282},{9,9,9669},{0,29,3909},{0,23,243},{0,18,4154},{14,7,9669},{0,18,4154},{2,31,1714},{2,31,1714},{2,31,1714},{2,22,1669},{0,29,2180},{0,23,194},{0,23,194},{0,14,260},{0,15,4686},{0,13,1937},{3,30,64},{3,30,64},{3,30,64},{3,20,68},{8,1,2178},{0,23,194},{0,23,194},{0,14,260},{10,5,2178},{0,14,260},{15,0,2665},{4,31,313},{5,24,8}, +{0,24,4},{15,0,2665},{13,15,2665},{0,24,4},{0,19,2689},{13,15,2665},{0,19,2689},{2,0,1665},{2,0,1665},{2,0,1665},{2,0,1665},{0,19,1},{0,19,1},{0,19,1},{0,11,1},{0,8,832},{0,8,832},{3,31,8967},{3,31,3510},{3,26,3255},{2,24,2243},{2,31,11766},{0,31,3686},{0,25,138},{0,19,3938},{0,23,15369},{0,18,7206},{5,31,3933},{4,31,457},{4,25,197},{4,24,305},{12,2,9669}, +{0,31,3686},{0,25,138},{0,19,3938},{13,10,9669},{0,19,3938},{2,31,2434},{2,31,2434},{2,31,2434},{2,23,2182},{0,31,2210},{0,25,137},{0,25,137},{0,15,181},{0,16,5157},{0,14,2163},{4,30,1},{4,30,1},{4,30,1},{4,21,0},{8,4,2178},{0,25,137},{0,25,137},{0,15,181},{14,2,2178},{0,15,181},{15,3,2665},{5,31,421},{5,25,17},{1,25,5},{15,3,2665},{12,18,2665},{1,25,5}, +{0,20,2689},{12,18,2665},{0,20,2689},{2,0,2178},{2,0,2178},{2,0,2178},{2,0,2178},{0,22,1},{0,22,1},{0,22,1},{0,13,0},{0,10,1125},{0,10,1125},{4,31,10234},{3,31,4421},{3,27,3739},{2,26,2742},{2,31,12773},{0,31,3719},{0,26,87},{0,20,3771},{0,25,16061},{0,19,7283},{6,31,4050},{5,31,629},{5,26,146},{4,25,282},{11,8,9669},{0,31,3718},{0,26,86},{0,20,3770},{11,14,9669}, +{0,20,3770},{3,31,3125},{3,31,3125},{3,31,3125},{2,25,2706},{1,31,2411},{0,26,86},{0,26,86},{0,16,129},{0,18,5544},{0,15,2318},{5,29,64},{5,29,64},{5,29,64},{5,21,68},{3,25,2178},{0,26,85},{0,26,85},{0,16,128},{12,6,2178},{0,16,128},{15,6,2665},{5,31,565},{6,26,5},{1,26,2},{15,6,2665},{14,17,2665},{1,26,2},{0,21,2689},{14,17,2665},{0,21,2689},{2,0,2705}, +{2,0,2705},{2,0,2705},{2,0,2705},{0,24,1},{0,24,1},{0,24,1},{0,15,5},{0,11,1348},{0,11,1348},{4,31,10874},{4,31,5018},{3,28,3750},{3,26,2754},{3,31,13045},{1,31,4003},{0,27,183},{0,21,3686},{0,27,15601},{0,20,6570},{7,31,4366},{5,31,965},{5,27,197},{5,26,305},{12,7,9669},{1,31,3954},{0,27,102},{0,21,3605},{13,13,9669},{0,21,3605},{3,31,3173},{3,31,3173},{3,31,3173}, +{3,25,2690},{1,31,2427},{0,28,113},{0,28,113},{0,17,170},{0,20,5170},{0,16,1856},{5,31,4},{5,31,4},{5,31,4},{5,23,0},{9,6,2178},{0,28,32},{0,28,32},{0,17,89},{14,5,2178},{0,17,89},{15,8,2665},{6,31,706},{6,27,10},{2,27,10},{15,8,2665},{12,21,2665},{2,27,10},{0,22,2689},{12,21,2665},{0,22,2689},{3,0,2689},{3,0,2689},{3,0,2689},{3,0,2689},{1,23,53}, +{1,23,53},{1,23,53},{1,15,49},{0,13,1217},{0,13,1217},{5,31,11278},{4,31,5402},{4,29,3753},{3,28,2745},{4,31,13566},{1,31,4403},{1,28,77},{0,22,3747},{0,28,15046},{0,21,5958},{7,31,4590},{6,31,1171},{6,28,149},{5,27,282},{14,3,9669},{2,31,4265},{1,28,76},{0,22,3458},{11,17,9669},{0,22,3458},{4,31,3377},{4,31,3377},{4,31,3377},{3,27,2706},{2,31,2532},{1,28,73},{1,28,73}, +{1,18,129},{0,21,4837},{0,17,1490},{6,31,82},{6,31,82},{6,31,82},{5,24,68},{10,5,2178},{0,30,8},{0,30,8},{0,19,49},{12,9,2178},{0,19,49},{15,11,2665},{7,31,850},{7,28,8},{2,28,4},{15,11,2665},{15,19,2665},{2,28,4},{0,23,2689},{15,19,2665},{0,23,2689},{3,0,2705},{3,0,2705},{3,0,2705},{3,0,2705},{1,26,1},{1,26,1},{1,26,1},{1,16,5},{0,14,1037}, +{0,14,1037},{6,31,11954},{5,31,6090},{4,30,3794},{4,28,2754},{5,31,14170},{2,31,4863},{2,29,187},{1,24,3689},{0,30,14558},{0,23,5274},{8,31,5030},{7,31,1556},{6,29,197},{6,28,305},{14,6,9669},{3,31,4594},{1,29,101},{0,24,3265},{15,14,9669},{0,24,3265},{4,31,3530},{4,31,3530},{4,31,3530},{4,27,2693},{2,31,2739},{1,30,134},{1,30,134},{1,19,197},{0,23,4506},{0,19,1109},{6,31,64}, +{6,31,64},{6,31,64},{6,25,0},{10,8,2178},{1,30,34},{1,30,34},{0,20,16},{11,12,2178},{0,20,16},{15,14,2665},{8,31,1053},{7,29,17},{3,29,5},{15,14,2665},{14,22,2665},{3,29,5},{0,24,2689},{14,22,2665},{0,24,2689},{4,0,2689},{4,0,2689},{4,0,2689},{4,0,2689},{2,26,50},{2,26,50},{2,26,50},{2,17,49},{0,16,818},{0,16,818},{6,31,12466},{5,31,6794},{5,31,3739}, +{4,30,2742},{5,31,14554},{3,31,5363},{2,30,87},{1,24,3737},{0,31,14190},{0,24,4785},{8,31,5158},{7,31,2036},{7,30,146},{6,29,282},{13,12,9669},{4,31,4806},{2,30,86},{0,25,3130},{13,18,9669},{0,25,3130},{5,31,3658},{5,31,3658},{5,31,3658},{4,29,2706},{3,31,2795},{2,30,86},{2,30,86},{2,20,129},{0,25,4315},{0,20,809},{7,31,100},{7,31,100},{7,31,100},{7,25,68},{9,14,2178}, +{1,31,68},{1,31,68},{0,21,1},{14,10,2178},{0,21,1},{13,23,2665},{9,31,1241},{8,30,50},{3,30,2},{13,23,2665},{11,27,2665},{3,30,2},{0,25,2689},{11,27,2665},{0,25,2689},{4,0,2705},{4,0,2705},{4,0,2705},{4,0,2705},{2,28,1},{2,28,1},{2,28,1},{2,19,5},{0,18,666},{0,18,666},{7,31,13094},{6,31,7445},{5,31,3915},{5,30,2754},{6,31,14998},{4,31,5926},{2,31,183}, +{2,25,3686},{0,31,14254},{0,25,4323},{9,31,5546},{8,31,2478},{7,31,197},{7,30,305},{14,11,9669},{5,31,5138},{2,31,102},{0,26,3013},{15,17,9669},{0,26,3013},{5,31,3914},{5,31,3914},{5,31,3914},{5,29,2690},{4,31,3042},{2,31,182},{2,31,182},{2,21,170},{0,27,4059},{0,21,597},{7,31,196},{7,31,196},{7,31,196},{7,27,0},{11,10,2178},{2,31,101},{2,31,101},{0,22,4},{5,23,2178}, +{0,22,4},{15,19,2665},{10,31,1384},{8,31,5},{4,31,10},{15,19,2665},{14,25,2665},{4,31,10},{0,26,2689},{14,25,2665},{0,26,2689},{5,0,2689},{5,0,2689},{5,0,2689},{5,0,2689},{3,27,53},{3,27,53},{3,27,53},{3,19,49},{0,20,505},{0,20,505},{7,31,12517},{6,31,7482},{6,31,4001},{5,31,2706},{6,31,14185},{4,31,5491},{3,31,154},{2,26,3124},{0,31,13437},{0,26,3306},{9,31,4949}, +{8,31,2261},{8,31,325},{7,30,192},{14,13,8712},{6,31,4686},{3,31,153},{0,27,2403},{11,23,8712},{0,27,2403},{6,31,4001},{6,31,4001},{6,31,4001},{5,31,2706},{4,31,3234},{3,31,154},{3,31,154},{3,22,129},{0,28,3762},{0,23,425},{8,31,325},{8,31,325},{8,31,325},{7,28,68},{12,9,2178},{3,31,153},{3,31,153},{1,23,1},{14,13,2178},{1,23,1},{13,27,2178},{10,31,1157},{9,31,16}, +{5,31,1},{13,27,2178},{13,27,2178},{5,31,1},{0,27,2178},{13,27,2178},{0,27,2178},{5,0,2705},{5,0,2705},{5,0,2705},{5,0,2705},{3,30,1},{3,30,1},{3,30,1},{3,20,5},{0,22,389},{0,22,389},{8,31,12034},{7,31,7195},{6,31,4370},{6,31,2693},{7,31,13066},{5,31,5014},{4,31,261},{3,27,2390},{1,31,12394},{0,27,2277},{10,31,4410},{9,31,2045},{8,31,289},{8,30,192},{14,15,7578}, +{7,31,4050},{4,31,212},{0,27,1701},{12,23,7578},{0,27,1701},{6,31,4370},{6,31,4370},{6,31,4370},{6,31,2693},{5,31,3429},{4,31,261},{4,31,261},{3,23,197},{0,30,3509},{0,24,306},{8,31,289},{8,31,289},{8,31,289},{8,28,68},{15,2,2178},{4,31,212},{4,31,212},{1,24,9},{13,16,2178},{1,24,9},{15,22,1625},{11,31,850},{9,31,25},{6,31,4},{15,22,1625},{13,28,1625},{6,31,4}, +{0,27,1665},{13,28,1625},{0,27,1665},{6,0,2689},{6,0,2689},{6,0,2689},{6,0,2689},{4,30,50},{4,30,50},{4,30,50},{4,21,49},{0,24,306},{0,24,306},{8,31,11042},{7,31,7259},{7,31,4450},{6,31,2805},{7,31,12298},{5,31,4742},{4,31,501},{4,27,1875},{2,31,11643},{0,28,1578},{10,31,3802},{9,31,1869},{9,31,425},{8,31,25},{13,20,6661},{7,31,3554},{5,31,292},{0,28,1217},{13,23,6662}, +{0,28,1217},{7,31,4450},{7,31,4450},{7,31,4450},{6,31,2805},{6,31,3714},{4,31,501},{4,31,501},{4,24,129},{0,31,3354},{0,25,244},{9,31,425},{9,31,425},{9,31,425},{8,30,0},{11,18,2178},{5,31,292},{5,31,292},{2,25,1},{10,21,2178},{2,25,1},{15,23,1201},{11,31,674},{10,31,9},{7,31,16},{15,23,1201},{12,30,1201},{7,31,16},{0,28,1201},{12,30,1201},{0,28,1201},{6,0,2705}, +{6,0,2705},{6,0,2705},{6,0,2705},{4,31,17},{4,31,17},{4,31,17},{4,23,5},{0,26,218},{0,26,218},{8,31,10434},{8,31,7186},{7,31,4898},{7,31,2833},{8,31,11595},{6,31,4462},{5,31,629},{4,28,1387},{3,31,10895},{0,28,1002},{11,31,3446},{10,31,1707},{9,31,505},{8,31,73},{13,22,5829},{8,31,3170},{6,31,405},{1,28,869},{12,25,5829},{1,28,869},{7,31,4898},{7,31,4898},{7,31,4898}, +{7,31,2833},{6,31,3906},{5,31,629},{5,31,629},{4,25,170},{0,31,3546},{0,27,228},{9,31,505},{9,31,505},{9,31,505},{9,30,68},{13,14,2178},{6,31,405},{6,31,405},{2,26,4},{8,25,2178},{2,26,4},{13,31,841},{12,31,461},{11,31,1},{8,31,9},{13,31,841},{15,27,841},{8,31,9},{0,28,865},{15,27,841},{0,28,865},{7,0,2689},{7,0,2689},{7,0,2689},{7,0,2689},{5,31,53}, +{5,31,53},{5,31,53},{5,23,49},{0,28,137},{0,28,137},{9,31,10014},{8,31,6962},{8,31,5026},{7,31,3105},{8,31,10683},{7,31,4354},{6,31,933},{5,28,1019},{4,31,10078},{0,29,630},{11,31,2934},{10,31,1611},{10,31,650},{9,31,25},{15,17,5082},{8,31,2786},{7,31,521},{1,29,546},{12,26,5082},{1,29,546},{8,31,5026},{8,31,5026},{8,31,5026},{7,31,3105},{7,31,4170},{6,31,933},{6,31,933}, +{5,26,129},{1,31,3814},{0,28,234},{10,31,650},{10,31,650},{10,31,650},{9,31,25},{14,13,2178},{7,31,521},{7,31,521},{3,27,1},{11,23,2178},{3,27,1},{15,26,545},{13,31,313},{12,31,4},{10,31,4},{15,26,545},{14,29,545},{10,31,4},{0,29,545},{14,29,545},{0,29,545},{7,0,2705},{7,0,2705},{7,0,2705},{7,0,2705},{5,31,101},{5,31,101},{5,31,101},{5,24,5},{0,29,85}, +{0,29,85},{9,31,9465},{9,31,7065},{8,31,5233},{8,31,3329},{8,31,10116},{7,31,4183},{6,31,1338},{5,29,645},{5,31,9447},{0,30,441},{11,31,2664},{11,31,1525},{10,31,848},{10,31,113},{15,19,4344},{9,31,2424},{8,31,724},{2,30,321},{13,26,4344},{2,30,321},{8,31,5233},{8,31,5233},{8,31,5233},{8,31,3329},{7,31,4629},{6,31,1338},{6,31,1338},{5,27,197},{2,31,4212},{1,29,213},{10,31,848}, +{10,31,848},{10,31,848},{10,31,113},{14,16,2178},{8,31,724},{8,31,724},{3,28,9},{15,20,2178},{3,28,9},{15,27,290},{13,31,178},{13,31,9},{11,31,1},{15,27,290},{14,30,290},{11,31,1},{0,29,320},{14,30,290},{0,29,320},{8,0,2929},{8,0,2929},{8,0,2929},{8,0,2929},{6,31,113},{6,31,113},{6,31,113},{6,25,49},{0,31,45},{0,31,45},{10,31,9329},{9,31,6985},{9,31,5541}, +{8,31,3473},{9,31,9496},{8,31,4420},{7,31,1630},{6,29,426},{5,31,9031},{1,30,301},{12,31,2275},{11,31,1557},{11,31,932},{10,31,225},{13,27,3779},{10,31,2086},{8,31,884},{3,30,129},{13,27,3779},{3,30,129},{9,31,5541},{9,31,5541},{9,31,5541},{8,31,3473},{8,31,4836},{7,31,1630},{7,31,1630},{6,28,129},{4,31,4442},{1,30,237},{11,31,932},{11,31,932},{11,31,932},{10,31,225},{13,22,2178}, +{8,31,884},{8,31,884},{4,29,1},{12,25,2178},{4,29,1},{15,28,130},{14,31,72},{13,31,25},{12,31,9},{15,28,130},{15,29,136},{12,31,9},{0,30,128},{15,29,136},{0,30,128},{8,0,2689},{8,0,2689},{8,0,2689},{8,0,2689},{6,31,257},{6,31,257},{6,31,257},{6,27,5},{1,31,89},{1,31,89},{10,31,8929},{10,31,7186},{9,31,5845},{9,31,3829},{9,31,9208},{8,31,4260},{7,31,2270}, +{6,30,245},{6,31,8708},{2,31,228},{12,31,2115},{12,31,1515},{12,31,1154},{11,31,353},{13,29,3299},{11,31,1938},{10,31,1013},{4,30,68},{14,27,3299},{4,30,68},{9,31,5845},{9,31,5845},{9,31,5845},{9,31,3829},{8,31,5124},{7,31,2270},{7,31,2270},{6,29,170},{4,31,4762},{2,31,228},{12,31,1154},{12,31,1154},{12,31,1154},{11,31,353},{15,18,2178},{10,31,1013},{10,31,1013},{4,30,4},{10,29,2178}, +{4,30,4},{15,30,34},{14,31,40},{14,31,4},{14,31,4},{15,30,34},{15,30,34},{14,31,4},{0,30,64},{15,30,34},{0,30,64},{8,0,2705},{8,0,2705},{8,0,2705},{8,0,2705},{7,31,245},{7,31,245},{7,31,245},{7,27,49},{2,31,164},{2,31,164},{11,31,8857},{10,31,7170},{10,31,6209},{9,31,4133},{10,31,8853},{8,31,4484},{8,31,2548},{7,31,170},{7,31,8388},{3,31,244},{13,31,1971}, +{12,31,1611},{12,31,1250},{11,31,625},{15,24,2904},{11,31,1826},{10,31,1157},{5,31,1},{15,27,2907},{5,31,1},{10,31,6209},{10,31,6209},{10,31,6209},{9,31,4133},{9,31,5460},{8,31,2548},{8,31,2548},{7,30,129},{5,31,5126},{3,31,244},{12,31,1250},{12,31,1250},{12,31,1250},{11,31,625},{13,27,2178},{10,31,1157},{10,31,1157},{5,31,1},{13,27,2178},{5,31,1},{15,31,0},{15,31,0},{15,31,0}, +{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{9,0,2689},{9,0,2689},{9,0,2689},{9,0,2689},{7,31,485},{7,31,485},{7,31,485},{7,28,5},{3,31,244},{3,31,244},{11,31,7705},{11,31,6566},{10,31,5633},{10,31,3890},{10,31,7737},{9,31,3874},{8,31,2386},{7,31,116},{7,31,7398},{4,31,317},{13,31,1458},{13,31,1186},{13,31,1017},{12,31,425},{15,25,2166}, +{12,31,1398},{11,31,850},{6,31,4},{12,31,2166},{6,31,4},{10,31,5633},{10,31,5633},{10,31,5633},{10,31,3890},{9,31,4830},{8,31,2386},{8,31,2386},{7,31,116},{6,31,4509},{4,31,317},{13,31,1017},{13,31,1017},{13,31,1017},{12,31,425},{15,22,1625},{11,31,850},{11,31,850},{6,31,4},{13,28,1625},{6,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0}, +{0,31,0},{15,31,0},{0,31,0},{9,0,2725},{9,0,2725},{9,0,2725},{9,0,2725},{8,31,450},{8,31,450},{8,31,450},{7,30,101},{4,31,317},{4,31,317},{11,31,6953},{11,31,5814},{11,31,5189},{10,31,3650},{11,31,6713},{10,31,3531},{9,31,2142},{8,31,74},{8,31,6397},{5,31,425},{13,31,1138},{13,31,866},{13,31,697},{12,31,361},{15,26,1601},{12,31,1046},{11,31,674},{7,31,16},{14,29,1601}, +{7,31,16},{11,31,5189},{11,31,5189},{11,31,5189},{10,31,3650},{10,31,4313},{9,31,2142},{9,31,2142},{8,31,74},{7,31,3981},{5,31,425},{13,31,697},{13,31,697},{13,31,697},{12,31,361},{15,23,1201},{11,31,674},{11,31,674},{7,31,16},{12,30,1201},{7,31,16},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{10,0,2689}, +{10,0,2689},{10,0,2689},{10,0,2689},{8,31,578},{8,31,578},{8,31,578},{8,30,49},{5,31,425},{5,31,425},{12,31,6211},{11,31,5318},{11,31,4693},{11,31,3554},{11,31,5833},{10,31,3067},{10,31,2106},{8,31,10},{9,31,5601},{6,31,580},{14,31,825},{13,31,674},{13,31,505},{13,31,233},{15,27,1122},{13,31,738},{12,31,461},{8,31,9},{13,31,1122},{8,31,9},{11,31,4693},{11,31,4693},{11,31,4693}, +{11,31,3554},{10,31,3849},{10,31,2106},{10,31,2106},{8,31,10},{7,31,3629},{6,31,580},{13,31,505},{13,31,505},{13,31,505},{13,31,233},{13,31,841},{12,31,461},{12,31,461},{8,31,9},{15,27,841},{8,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{10,0,2705},{10,0,2705},{10,0,2705},{10,0,2705},{9,31,666}, +{9,31,666},{9,31,666},{8,31,10},{6,31,580},{6,31,580},{12,31,5427},{12,31,4827},{11,31,4453},{11,31,3314},{12,31,5175},{10,31,2859},{10,31,1898},{9,31,74},{10,31,4842},{7,31,724},{14,31,489},{14,31,425},{14,31,389},{13,31,169},{14,31,729},{13,31,482},{13,31,313},{10,31,4},{14,30,726},{10,31,4},{11,31,4453},{11,31,4453},{11,31,4453},{11,31,3314},{11,31,3445},{10,31,1898},{10,31,1898}, +{9,31,74},{8,31,3213},{7,31,724},{14,31,389},{14,31,389},{14,31,389},{13,31,169},{15,26,545},{13,31,313},{13,31,313},{10,31,4},{14,29,545},{10,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{11,0,2689},{11,0,2689},{11,0,2689},{11,0,2689},{9,31,890},{9,31,890},{9,31,890},{9,31,74},{7,31,724}, +{7,31,724},{2,31,33740},{0,31,5184},{0,22,420},{0,21,4221},{1,31,46089},{0,29,24105},{0,21,8317},{0,18,24790},{0,21,63990},{0,16,38959},{1,31,9704},{0,30,2866},{0,21,389},{0,19,3229},{7,2,18065},{0,20,13257},{0,17,6153},{0,12,13481},{12,0,18065},{0,12,13481},{0,15,1},{0,15,1},{0,15,1},{0,9,1},{0,8,1105},{0,7,585},{0,7,585},{0,4,596},{0,4,1273},{0,4,740},{0,15,1}, +{0,15,1},{0,15,1},{0,9,1},{2,1,1105},{0,7,585},{0,7,585},{0,4,596},{4,0,1105},{0,4,596},{9,6,9248},{0,30,2866},{0,21,389},{0,19,3229},{9,6,9248},{14,5,9248},{0,19,3229},{0,14,9248},{14,5,9248},{0,14,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,38380},{0,31,6720},{0,23,245}, +{0,22,3864},{2,31,50747},{0,31,24961},{0,22,8353},{0,19,25735},{0,22,65535},{0,17,41319},{1,31,10152},{0,31,2624},{0,23,229},{0,20,2980},{5,10,19334},{0,20,13769},{0,18,6243},{0,13,14116},{12,1,19334},{0,13,14116},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{0,9,1513},{0,8,772},{0,8,772},{0,5,821},{0,5,1750},{0,4,1028},{0,18,0},{0,18,0},{0,18,0},{0,11,1},{1,6,1513}, +{0,8,772},{0,8,772},{0,5,821},{3,2,1513},{0,5,821},{10,5,9248},{0,31,2624},{0,23,229},{0,20,2980},{10,5,9248},{12,9,9248},{0,20,2980},{0,15,9248},{12,9,9248},{0,15,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,43788},{0,31,9024},{0,24,126},{0,23,3525},{2,31,56155},{0,31,26241},{0,23,8425}, +{0,20,26793},{0,23,65535},{0,18,43819},{2,31,10787},{0,31,2624},{0,24,122},{0,21,2701},{8,0,20689},{0,22,14385},{0,19,6369},{0,13,14756},{12,2,20689},{0,13,14756},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{0,10,1989},{0,9,1018},{0,9,1018},{0,6,1096},{0,5,2294},{0,5,1334},{0,21,1},{0,21,1},{0,21,1},{0,12,4},{1,7,1985},{0,9,1018},{0,9,1018},{0,6,1096},{1,5,1985}, +{0,6,1096},{12,1,9248},{0,31,2624},{0,24,122},{0,21,2701},{12,1,9248},{15,7,9248},{0,21,2701},{0,16,9250},{15,7,9248},{0,16,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{2,31,49964},{1,31,11512},{0,25,41},{0,24,3109},{2,31,62331},{0,31,28289},{0,24,8585},{0,21,27848},{0,23,65535},{0,19,46459},{2,31,11395}, +{0,31,2880},{0,25,37},{0,22,2440},{8,2,22129},{0,23,15030},{0,20,6509},{0,14,15441},{13,2,22129},{0,14,15441},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{0,12,2525},{0,10,1300},{0,10,1300},{0,6,1384},{0,6,2905},{0,6,1708},{0,23,1},{0,23,1},{0,23,1},{0,14,0},{3,2,2521},{0,10,1300},{0,10,1300},{0,6,1384},{5,1,2521},{0,6,1384},{11,7,9248},{0,31,2880},{0,25,37}, +{0,22,2440},{11,7,9248},{13,11,9248},{0,22,2440},{0,17,9250},{13,11,9248},{0,17,9250},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,57022},{1,31,15166},{0,26,20},{0,25,2804},{2,31,65535},{0,31,31511},{0,25,8733},{0,22,29095},{0,26,65535},{0,20,49444},{2,31,12385},{0,31,3474},{0,26,4},{0,23,2173},{8,4,23851}, +{0,23,15948},{0,21,6729},{0,15,16274},{14,2,23851},{0,15,16274},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{0,13,3200},{0,11,1665},{0,11,1665},{0,7,1754},{0,7,3691},{0,6,2185},{0,26,0},{0,26,0},{0,26,0},{0,16,4},{1,10,3200},{0,11,1665},{0,11,1665},{0,7,1754},{5,2,3200},{0,7,1754},{11,10,9248},{1,31,3226},{0,26,4},{0,23,2173},{11,10,9248},{5,23,9248},{0,23,2173}, +{0,18,9248},{5,23,9248},{0,18,9248},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,63870},{1,31,19230},{0,27,45},{0,27,2520},{3,31,65535},{0,31,35191},{0,26,8925},{0,23,30250},{0,28,65535},{0,21,52374},{3,31,13449},{1,31,4026},{0,27,29},{0,24,1901},{3,24,25472},{0,26,16706},{0,22,6963},{0,16,17124},{14,3,25472}, +{0,16,17124},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{0,14,3874},{0,13,2084},{0,13,2084},{0,8,2165},{0,8,4466},{0,7,2627},{0,29,1},{0,29,1},{0,29,1},{0,17,1},{4,1,3872},{0,13,2084},{0,13,2084},{0,8,2165},{3,5,3872},{0,8,2165},{12,9,9248},{2,31,3593},{0,27,29},{0,24,1901},{12,9,9248},{14,13,9248},{0,24,1901},{0,19,9248},{14,13,9248},{0,19,9248},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{3,31,65535},{1,31,24002},{0,28,109},{0,27,2268},{3,31,65535},{1,31,39095},{0,27,8825},{0,24,30825},{0,28,65535},{0,22,54996},{3,31,14345},{1,31,4766},{0,29,102},{0,26,1697},{3,26,26744},{0,28,17104},{0,23,6957},{0,17,17625},{15,3,26744},{0,17,17625},{0,31,5},{0,31,5},{0,31,5}, +{0,19,5},{0,16,4418},{0,14,2306},{0,14,2306},{0,9,2420},{0,8,5122},{0,8,2997},{0,31,5},{0,31,5},{0,31,5},{0,19,5},{3,6,4418},{0,14,2306},{0,14,2306},{0,9,2420},{3,6,4418},{0,9,2420},{14,5,9248},{4,31,3904},{1,28,1},{0,26,1693},{14,5,9248},{12,17,9248},{0,26,1693},{0,20,9250},{12,17,9248},{0,20,9250},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,1,1}, +{0,1,1},{0,1,1},{0,0,4},{0,0,4},{0,0,4},{3,31,65535},{1,31,29442},{0,29,330},{0,28,2105},{3,31,65535},{1,31,42151},{0,28,7781},{0,25,30108},{0,29,65535},{0,22,56388},{4,31,14976},{2,31,5434},{1,29,62},{0,27,1580},{11,0,26744},{0,29,16547},{0,24,6221},{0,18,17124},{13,7,26744},{0,18,17124},{0,31,181},{0,31,181},{0,31,181},{0,20,101},{0,19,4420},{0,16,2005},{0,16,2005}, +{0,10,2165},{0,9,5389},{0,9,2925},{1,31,37},{1,31,37},{1,31,37},{1,19,37},{5,2,4418},{0,16,2005},{0,16,2005},{0,10,2165},{8,1,4418},{0,10,2165},{13,11,9248},{4,31,4160},{1,29,26},{0,27,1480},{13,11,9248},{15,15,9248},{0,27,1480},{0,21,9250},{15,15,9248},{0,21,9250},{0,0,100},{0,0,100},{0,0,100},{0,0,100},{0,3,1},{0,3,1},{0,3,1},{0,2,0},{0,1,34}, +{0,1,34},{4,31,65535},{2,31,36070},{0,30,822},{0,30,2062},{3,31,65535},{1,31,46660},{0,29,6696},{0,26,29322},{0,31,65535},{0,23,58077},{4,31,15507},{3,31,6253},{1,31,109},{0,28,1646},{11,3,26744},{0,31,15992},{0,26,5346},{0,19,16582},{11,11,26744},{0,19,16582},{1,31,329},{1,31,329},{1,31,329},{1,21,266},{0,22,4420},{0,18,1737},{0,18,1737},{0,11,1898},{0,11,5707},{0,10,2885},{1,31,73}, +{1,31,73},{1,31,73},{1,21,10},{5,5,4418},{0,18,1737},{0,18,1737},{0,11,1898},{5,7,4418},{0,11,1898},{13,14,9248},{5,31,4570},{2,30,4},{0,28,1285},{13,14,9248},{8,25,9248},{0,28,1285},{0,22,9248},{8,25,9248},{0,22,9248},{1,0,265},{1,0,265},{1,0,265},{1,0,265},{0,6,1},{0,6,1},{0,6,1},{0,4,1},{0,3,97},{0,3,97},{4,31,65535},{2,31,40786},{0,31,1405}, +{0,30,2138},{4,31,65535},{1,31,49800},{0,30,5634},{0,27,27967},{0,31,65535},{0,24,58770},{5,31,15531},{3,31,6593},{2,31,61},{1,29,1533},{12,2,26259},{0,31,15284},{0,27,4514},{0,20,15812},{13,10,26259},{0,20,15812},{1,31,633},{1,31,633},{1,31,633},{1,22,381},{0,24,4418},{0,20,1480},{0,20,1480},{0,12,1640},{0,12,6125},{0,11,2891},{2,31,61},{2,31,61},{2,31,61},{2,21,37},{7,1,4418}, +{0,20,1480},{0,20,1480},{0,12,1640},{10,2,4418},{0,12,1640},{13,16,8978},{6,31,4777},{2,31,25},{0,29,1040},{13,16,8978},{15,18,8978},{0,29,1040},{0,23,8980},{15,18,8978},{0,23,8980},{1,0,377},{1,0,377},{1,0,377},{1,0,377},{0,9,0},{0,9,0},{0,9,0},{0,5,4},{0,4,193},{0,4,193},{4,31,65535},{2,31,40898},{1,31,2217},{0,31,2125},{4,31,65535},{1,31,47976},{0,30,4194}, +{0,27,24703},{0,31,65535},{0,24,56130},{5,31,14379},{4,31,6051},{2,31,173},{2,29,1284},{9,14,24371},{0,31,13716},{0,28,3402},{0,21,13989},{14,10,24371},{0,21,13989},{1,31,1193},{1,31,1193},{1,31,1193},{1,24,617},{0,27,4420},{0,22,1280},{0,22,1280},{0,13,1445},{0,14,6509},{0,12,2945},{2,31,173},{2,31,173},{2,31,173},{2,23,5},{5,10,4418},{0,22,1280},{0,22,1280},{0,13,1445},{12,1,4418}, +{0,13,1445},{14,14,7938},{7,31,4253},{3,31,9},{0,29,656},{14,14,7938},{14,20,7938},{0,29,656},{0,23,7956},{14,20,7938},{0,23,7956},{1,0,617},{1,0,617},{1,0,617},{1,0,617},{0,11,4},{0,11,4},{0,11,4},{0,7,0},{0,5,325},{0,5,325},{4,31,65535},{2,31,41266},{1,31,3033},{0,31,2333},{4,31,65535},{1,31,46408},{0,30,3010},{0,27,21695},{0,31,65535},{0,25,53636},{6,31,13140}, +{4,31,5571},{3,31,157},{2,29,932},{11,9,22568},{0,31,12404},{0,28,2474},{0,21,12245},{14,11,22568},{0,21,12245},{2,31,1630},{2,31,1630},{2,31,1630},{1,26,989},{0,29,4420},{0,23,1090},{0,23,1090},{0,14,1268},{0,15,6926},{0,13,3029},{3,31,157},{3,31,157},{3,31,157},{3,23,37},{8,1,4418},{0,23,1090},{0,23,1090},{0,14,1268},{10,5,4418},{0,14,1268},{15,12,6962},{7,31,3709},{4,31,1}, +{0,30,353},{15,12,6962},{13,22,6962},{0,30,353},{0,24,6970},{13,22,6962},{0,24,6970},{1,0,985},{1,0,985},{1,0,985},{1,0,985},{0,14,0},{0,14,0},{0,14,0},{0,8,4},{0,6,493},{0,6,493},{4,31,65535},{2,31,41986},{1,31,4257},{0,31,2873},{4,31,65535},{1,31,44950},{0,30,1984},{0,28,18569},{0,31,65535},{0,25,51026},{6,31,11934},{5,31,5125},{4,31,296},{3,29,706},{13,4,20642}, +{0,31,11234},{0,29,1634},{0,22,10422},{15,11,20642},{0,22,10422},{2,31,2350},{2,31,2350},{2,31,2350},{2,26,1450},{0,31,4450},{0,25,949},{0,25,949},{0,16,1096},{0,16,7397},{0,14,3171},{4,31,296},{4,31,296},{4,31,296},{3,25,10},{8,4,4418},{0,25,949},{0,25,949},{0,16,1096},{14,2,4418},{0,16,1096},{14,17,5941},{7,31,3250},{5,31,0},{0,30,128},{14,17,5941},{13,23,5941},{0,30,128}, +{0,24,5953},{13,23,5941},{0,24,5953},{2,0,1450},{2,0,1450},{2,0,1450},{2,0,1450},{0,17,0},{0,17,0},{0,17,0},{0,10,1},{0,8,697},{0,8,697},{4,31,65535},{2,31,42898},{1,31,5617},{1,31,3337},{4,31,65535},{1,31,43926},{0,31,1250},{0,28,15865},{0,31,65535},{0,25,48978},{7,31,10938},{5,31,4773},{4,31,360},{3,30,509},{12,9,19021},{1,31,10246},{0,30,1088},{0,23,8945},{14,13,19021}, +{0,23,8945},{2,31,3262},{2,31,3262},{2,31,3262},{2,28,1822},{1,31,4682},{0,28,776},{0,28,776},{0,17,925},{0,18,7893},{0,15,3333},{4,31,360},{4,31,360},{4,31,360},{4,25,37},{3,25,4418},{0,28,776},{0,28,776},{0,17,925},{12,6,4418},{0,17,925},{15,15,5101},{8,31,2777},{6,31,9},{0,31,25},{15,15,5101},{11,26,5101},{0,31,25},{0,25,5105},{11,26,5101},{0,25,5105},{2,0,1818}, +{2,0,1818},{2,0,1818},{2,0,1818},{0,20,1},{0,20,1},{0,20,1},{0,12,1},{0,9,925},{0,9,925},{4,31,65535},{2,31,44066},{1,31,7233},{1,31,3993},{4,31,65535},{2,31,43110},{0,31,738},{0,28,13417},{0,31,65535},{0,25,47186},{7,31,9978},{6,31,4467},{5,31,452},{4,30,357},{15,1,17485},{2,31,9441},{0,30,704},{0,24,7570},{15,13,17485},{0,24,7570},{3,31,4058},{3,31,4058},{3,31,4058}, +{2,29,2315},{1,31,4874},{0,29,610},{0,29,610},{0,18,772},{0,20,8427},{0,16,3497},{5,31,452},{5,31,452},{5,31,452},{4,27,5},{9,6,4418},{0,29,610},{0,29,610},{0,18,772},{14,5,4418},{0,18,772},{15,16,4325},{8,31,2377},{6,31,25},{0,31,9},{15,16,4325},{15,22,4325},{0,31,9},{0,25,4337},{15,22,4325},{0,25,4337},{2,0,2314},{2,0,2314},{2,0,2314},{2,0,2314},{0,22,1}, +{0,22,1},{0,22,1},{0,13,4},{0,10,1189},{0,10,1189},{5,31,65535},{3,31,45090},{1,31,9105},{1,31,4905},{4,31,65535},{2,31,42326},{0,31,482},{0,28,11225},{0,31,65535},{0,26,45590},{7,31,9274},{6,31,4179},{5,31,612},{4,30,245},{14,6,16034},{3,31,8633},{0,31,482},{0,24,6242},{15,14,16034},{0,24,6242},{3,31,5066},{3,31,5066},{3,31,5066},{2,31,2939},{1,31,5322},{0,31,482},{0,31,482}, +{0,19,637},{0,20,8939},{0,17,3725},{5,31,612},{5,31,612},{5,31,612},{5,27,37},{10,5,4418},{0,31,482},{0,31,482},{0,19,637},{12,9,4418},{0,19,637},{13,24,3613},{9,31,1973},{7,31,9},{2,31,1},{13,24,3613},{15,23,3613},{2,31,1},{0,26,3617},{15,23,3613},{0,26,3617},{2,0,2938},{2,0,2938},{2,0,2938},{2,0,2938},{0,25,1},{0,25,1},{0,25,1},{0,15,0},{0,11,1489}, +{0,11,1489},{5,31,65535},{3,31,46530},{1,31,11517},{1,31,6237},{4,31,65535},{2,31,41750},{0,31,500},{0,29,8976},{0,31,65535},{0,26,43934},{8,31,8225},{7,31,3853},{6,31,680},{5,30,109},{11,18,14504},{4,31,7667},{0,31,500},{0,25,4979},{10,21,14504},{0,25,4979},{3,31,6506},{3,31,6506},{3,31,6506},{3,31,3701},{2,31,6019},{0,31,500},{0,31,500},{0,20,520},{0,22,9629},{0,18,4035},{6,31,680}, +{6,31,680},{6,31,680},{5,29,10},{10,8,4418},{0,31,500},{0,31,500},{0,20,520},{11,12,4418},{0,20,520},{15,19,2888},{10,31,1537},{8,31,16},{3,31,4},{15,19,2888},{13,26,2888},{3,31,4},{0,26,2906},{13,26,2888},{0,26,2906},{3,0,3697},{3,0,3697},{3,0,3697},{3,0,3697},{0,28,1},{0,28,1},{0,28,1},{0,17,4},{0,11,1930},{0,11,1930},{5,31,65535},{3,31,48082},{1,31,13933}, +{1,31,7693},{4,31,65535},{2,31,41510},{0,31,788},{0,29,7120},{0,31,65535},{0,26,42734},{8,31,7409},{7,31,3693},{7,31,884},{6,30,116},{13,13,13235},{4,31,6899},{1,31,628},{0,25,3987},{15,16,13235},{0,25,3987},{4,31,7686},{4,31,7686},{4,31,7686},{3,31,4437},{2,31,6659},{0,31,788},{0,31,788},{0,21,421},{0,23,10286},{0,20,4305},{7,31,884},{7,31,884},{7,31,884},{6,29,37},{9,14,4418}, +{1,31,628},{1,31,628},{0,21,421},{14,10,4418},{0,21,421},{15,20,2312},{10,31,1217},{8,31,16},{4,31,9},{15,20,2312},{12,28,2312},{4,31,9},{0,27,2314},{12,28,2312},{0,27,2314},{3,0,4337},{3,0,4337},{3,0,4337},{3,0,4337},{0,30,1},{0,30,1},{0,30,1},{0,18,1},{0,13,2329},{0,13,2329},{5,31,65535},{3,31,49890},{2,31,16310},{1,31,9405},{4,31,65535},{2,31,41526},{0,31,1332}, +{0,29,5520},{0,31,65535},{0,26,41790},{8,31,6849},{8,31,3601},{7,31,980},{6,31,5},{15,8,12051},{5,31,6275},{2,31,801},{0,26,3066},{11,22,12051},{0,26,3066},{4,31,9062},{4,31,9062},{4,31,9062},{3,31,5429},{2,31,7555},{1,31,1172},{1,31,1172},{0,23,325},{0,23,11118},{0,20,4625},{7,31,980},{7,31,980},{7,31,980},{6,31,5},{11,10,4418},{2,31,801},{2,31,801},{0,23,325},{5,23,4418}, +{0,23,325},{13,28,1800},{11,31,949},{9,31,4},{6,31,1},{13,28,1800},{11,30,1800},{6,31,1},{0,27,1818},{11,30,1800},{0,27,1818},{3,0,5105},{3,0,5105},{3,0,5105},{3,0,5105},{0,31,36},{0,31,36},{0,31,36},{0,20,4},{0,15,2741},{0,15,2741},{5,31,65535},{3,31,51954},{2,31,18790},{1,31,11373},{5,31,65535},{2,31,41798},{0,31,2132},{0,29,4176},{0,31,65535},{0,27,41092},{9,31,6153}, +{8,31,3297},{7,31,1332},{7,31,37},{14,13,10952},{5,31,5763},{3,31,965},{0,27,2291},{11,23,10952},{0,27,2291},{4,31,10694},{4,31,10694},{4,31,10694},{4,31,6566},{3,31,8619},{1,31,1716},{1,31,1716},{0,24,221},{0,26,11876},{0,22,4989},{7,31,1332},{7,31,1332},{7,31,1332},{7,31,37},{12,9,4418},{3,31,965},{3,31,965},{0,24,221},{14,13,4418},{0,24,221},{14,26,1352},{11,31,725},{10,31,0}, +{7,31,1},{14,26,1352},{15,26,1352},{7,31,1},{0,28,1360},{15,26,1352},{0,28,1360},{3,0,6001},{3,0,6001},{3,0,6001},{3,0,6001},{0,31,196},{0,31,196},{0,31,196},{0,21,1},{0,16,3130},{0,16,3130},{5,31,65535},{3,31,54582},{2,31,21886},{1,31,13893},{5,31,65535},{2,31,42410},{0,31,3338},{0,30,2841},{0,31,65535},{0,27,40390},{9,31,5649},{9,31,3249},{8,31,1325},{7,31,109},{14,15,9818}, +{6,31,5258},{4,31,1108},{0,27,1589},{12,23,9818},{0,27,1589},{5,31,12376},{5,31,12376},{5,31,12376},{4,31,7844},{3,31,9861},{1,31,2634},{1,31,2634},{0,25,136},{0,28,12696},{0,23,5429},{8,31,1325},{8,31,1325},{8,31,1325},{7,31,109},{15,2,4418},{4,31,1108},{4,31,1108},{0,25,136},{13,16,4418},{0,25,136},{15,24,925},{12,31,505},{11,31,1},{8,31,1},{15,24,925},{15,27,925},{8,31,1}, +{0,28,937},{15,27,925},{0,28,937},{4,0,7060},{4,0,7060},{4,0,7060},{4,0,7060},{1,31,425},{1,31,425},{1,31,425},{0,23,0},{0,17,3665},{0,17,3665},{5,31,65535},{3,31,57190},{2,31,24910},{1,31,16405},{5,31,65535},{2,31,43226},{0,31,4682},{0,30,1833},{0,31,65535},{0,27,40038},{10,31,5202},{9,31,3073},{8,31,1565},{8,31,277},{13,20,8901},{7,31,4814},{5,31,1300},{0,28,1021},{13,23,8902}, +{0,28,1021},{5,31,14136},{5,31,14136},{5,31,14136},{4,31,9252},{3,31,11237},{2,31,3590},{2,31,3590},{0,26,85},{0,29,13491},{0,23,5925},{8,31,1565},{8,31,1565},{8,31,1565},{8,31,277},{11,18,4418},{5,31,1300},{5,31,1300},{0,26,85},{10,21,4418},{0,26,85},{15,25,617},{13,31,365},{12,31,16},{9,31,9},{15,25,617},{13,30,613},{9,31,9},{0,29,617},{13,30,613},{0,29,617},{4,0,7956}, +{4,0,7956},{4,0,7956},{4,0,7956},{1,31,697},{1,31,697},{1,31,697},{0,25,4},{0,18,4181},{0,18,4181},{5,31,65535},{3,31,60054},{2,31,28190},{2,31,18895},{5,31,65535},{2,31,44298},{1,31,6090},{0,30,1081},{0,31,65535},{0,27,39942},{10,31,4850},{10,31,3107},{9,31,1709},{8,31,325},{13,22,8069},{7,31,4574},{6,31,1553},{0,29,602},{12,25,8069},{0,29,602},{6,31,16067},{6,31,16067},{6,31,16067}, +{5,31,10872},{4,31,12824},{2,31,4662},{2,31,4662},{0,27,52},{0,30,14340},{0,25,6449},{9,31,1709},{9,31,1709},{9,31,1709},{8,31,325},{13,14,4418},{6,31,1553},{6,31,1553},{0,27,52},{8,25,4418},{0,27,52},{15,27,365},{13,31,205},{12,31,16},{11,31,4},{15,27,365},{13,31,365},{11,31,4},{0,29,377},{13,31,365},{0,29,377},{4,0,8980},{4,0,8980},{4,0,8980},{4,0,8980},{1,31,1097}, +{1,31,1097},{1,31,1097},{0,26,1},{0,20,4682},{0,20,4682},{6,31,65535},{4,31,58981},{2,31,29926},{2,31,19751},{5,31,65535},{3,31,43402},{1,31,6910},{0,30,765},{0,31,65535},{0,28,34909},{11,31,4502},{10,31,3011},{9,31,2045},{9,31,557},{15,17,7322},{8,31,4242},{7,31,1781},{0,29,314},{12,26,7322},{0,29,314},{6,31,16739},{6,31,16739},{6,31,16739},{5,31,11492},{4,31,13636},{3,31,5586},{3,31,5586}, +{0,28,65},{0,31,14139},{0,26,6041},{9,31,2045},{9,31,2045},{9,31,2045},{9,31,557},{14,13,4418},{7,31,1781},{7,31,1781},{0,28,29},{11,23,4418},{0,28,29},{15,28,181},{14,31,117},{13,31,4},{12,31,0},{15,28,181},{15,29,181},{12,31,0},{0,30,185},{15,29,181},{0,30,185},{4,0,9376},{4,0,9376},{4,0,9376},{4,0,9376},{2,31,1405},{2,31,1405},{2,31,1405},{0,28,40},{0,21,4520}, +{0,21,4520},{6,31,65535},{4,31,57316},{3,31,30345},{3,31,20808},{6,31,65535},{3,31,41449},{2,31,8321},{1,31,301},{0,31,65535},{0,28,28330},{11,31,4232},{11,31,3093},{10,31,2248},{9,31,809},{15,19,6584},{9,31,3992},{7,31,2105},{0,30,77},{13,26,6584},{0,30,77},{7,31,17380},{7,31,17380},{7,31,17380},{6,31,12161},{5,31,14315},{3,31,6405},{3,31,6405},{1,29,53},{0,31,13860},{0,28,5286},{10,31,2248}, +{10,31,2248},{10,31,2248},{9,31,809},{14,16,4418},{7,31,2105},{7,31,2105},{0,30,13},{15,20,4418},{0,30,13},{15,29,52},{14,31,36},{14,31,0},{13,31,9},{15,29,52},{15,30,50},{13,31,9},{0,30,68},{15,30,50},{0,30,68},{5,0,9250},{5,0,9250},{5,0,9250},{5,0,9250},{2,31,1549},{2,31,1549},{2,31,1549},{1,28,2},{0,23,4114},{0,23,4114},{6,31,65535},{5,31,55908},{4,31,31583}, +{3,31,21256},{6,31,65535},{4,31,39740},{2,31,9073},{1,31,285},{0,31,65535},{0,29,23356},{12,31,4011},{11,31,3125},{11,31,2500},{10,31,1037},{13,27,6019},{10,31,3738},{8,31,2340},{0,31,4},{13,27,6019},{0,31,4},{7,31,17796},{7,31,17796},{7,31,17796},{6,31,12625},{6,31,14996},{4,31,7139},{4,31,7139},{1,30,86},{0,31,14020},{0,29,4652},{11,31,2500},{11,31,2500},{11,31,2500},{10,31,1037},{13,22,4418}, +{8,31,2340},{8,31,2340},{0,31,4},{12,25,4418},{0,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{15,31,4},{0,31,4},{15,31,4},{0,31,4},{6,0,9376},{6,0,9376},{6,0,9376},{6,0,9376},{3,31,1765},{3,31,1765},{3,31,1765},{1,30,50},{0,25,3877},{0,25,3877},{7,31,65535},{5,31,53236},{4,31,30487},{4,31,21367},{6,31,65535},{4,31,37332},{3,31,9385}, +{2,31,36},{0,31,65535},{0,29,18680},{12,31,3443},{12,31,2843},{11,31,2248},{10,31,997},{14,25,5163},{10,31,3218},{9,31,2120},{1,31,4},{12,29,5163},{1,31,4},{7,31,17504},{7,31,17504},{7,31,17504},{7,31,12569},{6,31,14328},{4,31,7227},{4,31,7227},{2,31,20},{0,31,13376},{0,29,3944},{11,31,2248},{11,31,2248},{11,31,2248},{10,31,997},{15,17,3872},{9,31,2120},{9,31,2120},{1,31,4},{12,26,3872}, +{1,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{6,0,9248},{6,0,9248},{6,0,9248},{6,0,9248},{3,31,2005},{3,31,2005},{3,31,2005},{2,30,5},{0,27,3545},{0,27,3545},{7,31,65535},{6,31,50785},{4,31,29687},{4,31,20567},{7,31,65535},{4,31,35412},{3,31,8985},{2,31,196},{1,31,65535},{0,29,14712},{12,31,2883}, +{12,31,2283},{12,31,1922},{11,31,821},{13,29,4267},{11,31,2694},{10,31,1745},{3,31,4},{14,27,4267},{3,31,4},{8,31,16610},{8,31,16610},{8,31,16610},{7,31,12185},{6,31,13528},{5,31,6915},{5,31,6915},{2,31,52},{1,31,12556},{0,30,3314},{12,31,1922},{12,31,1922},{12,31,1922},{11,31,821},{12,28,3200},{10,31,1745},{10,31,1745},{3,31,4},{11,28,3200},{3,31,4},{15,31,0},{15,31,0},{15,31,0}, +{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{6,0,9376},{6,0,9376},{6,0,9376},{6,0,9376},{4,31,2250},{4,31,2250},{4,31,2250},{2,31,52},{0,28,3170},{0,28,3170},{7,31,65535},{6,31,47239},{5,31,28065},{5,31,20409},{7,31,65535},{5,31,32574},{4,31,8965},{3,31,54},{1,31,65206},{0,30,10964},{13,31,2326},{12,31,1806},{12,31,1445},{11,31,650},{13,30,3361}, +{11,31,2091},{10,31,1322},{4,31,0},{12,30,3361},{4,31,0},{8,31,15584},{8,31,15584},{8,31,15584},{7,31,12059},{7,31,12522},{6,31,6811},{6,31,6811},{3,31,50},{1,31,11710},{0,31,2834},{12,31,1445},{12,31,1445},{12,31,1445},{11,31,650},{14,23,2521},{10,31,1322},{10,31,1322},{4,31,0},{15,24,2521},{4,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0}, +{0,31,0},{15,31,0},{0,31,0},{7,0,9250},{7,0,9250},{7,0,9250},{7,0,9250},{5,31,2600},{5,31,2600},{5,31,2600},{3,31,50},{0,31,2834},{0,31,2834},{8,31,65535},{6,31,44903},{5,31,27361},{5,31,19705},{7,31,64494},{5,31,30846},{4,31,8677},{3,31,470},{2,31,60777},{0,30,8308},{13,31,1782},{13,31,1510},{12,31,1157},{12,31,557},{13,31,2646},{11,31,1691},{11,31,1066},{5,31,4},{15,27,2646}, +{5,31,4},{8,31,14944},{8,31,14944},{8,31,14944},{8,31,11696},{7,31,11850},{6,31,6555},{6,31,6555},{4,31,164},{2,31,11097},{0,31,2610},{12,31,1157},{12,31,1157},{12,31,1157},{12,31,557},{15,21,1985},{11,31,1066},{11,31,1066},{5,31,4},{15,25,1985},{5,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{7,0,9410}, +{7,0,9410},{7,0,9410},{7,0,9410},{5,31,2792},{5,31,2792},{5,31,2792},{4,31,164},{0,31,2610},{0,31,2610},{8,31,63584},{7,31,42019},{6,31,25930},{5,31,19769},{8,31,60273},{6,31,28860},{5,31,8761},{4,31,276},{3,31,56253},{0,30,6420},{13,31,1366},{13,31,1094},{13,31,925},{12,31,397},{15,25,2018},{12,31,1298},{11,31,794},{7,31,4},{13,30,2017},{7,31,4},{9,31,14244},{9,31,14244},{9,31,14244}, +{8,31,11312},{8,31,11249},{7,31,6499},{7,31,6499},{4,31,260},{3,31,10457},{0,31,2642},{13,31,925},{13,31,925},{13,31,925},{12,31,397},{15,22,1513},{11,31,794},{11,31,794},{7,31,4},{14,27,1513},{7,31,4},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{8,0,9376},{8,0,9376},{8,0,9376},{8,0,9376},{6,31,3074}, +{6,31,3074},{6,31,3074},{4,31,260},{0,31,2642},{0,31,2642},{8,31,58848},{7,31,39683},{6,31,25130},{6,31,19007},{8,31,54849},{6,31,27132},{5,31,8569},{4,31,756},{4,31,51302},{0,31,5046},{13,31,1078},{13,31,806},{13,31,637},{12,31,365},{15,26,1473},{12,31,978},{12,31,617},{8,31,9},{14,29,1473},{8,31,9},{9,31,13604},{9,31,13604},{9,31,13604},{8,31,11184},{8,31,10433},{7,31,6339},{7,31,6339}, +{5,31,424},{4,31,9713},{0,31,2930},{13,31,637},{13,31,637},{13,31,637},{12,31,365},{14,27,1105},{12,31,617},{12,31,617},{8,31,9},{13,29,1105},{8,31,9},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{15,31,0},{0,31,0},{15,31,0},{0,31,0},{8,0,9248},{8,0,9248},{8,0,9248},{8,0,9248},{6,31,3330},{6,31,3330},{6,31,3330},{5,31,424},{0,31,2930}, +{0,31,2930}, diff --git a/ext/basis_universal/basisu_transcoder_tables_pvrtc2_alpha_33.inc b/ext/basis_universal/basisu_transcoder_tables_pvrtc2_alpha_33.inc new file mode 100644 index 0000000000..3b9d7022e7 --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_tables_pvrtc2_alpha_33.inc @@ -0,0 +1,481 @@ +{0,0,20},{0,0,20},{0,0,97},{0,0,145},{0,0,56},{0,0,104},{0,0,181},{0,0,406},{0,0,204},{0,0,442},{0,0,20},{0,0,20},{0,0,97},{0,0,145},{0,0,56},{0,0,104},{0,0,181},{0,0,406},{0,0,168},{0,0,406},{0,0,16},{0,0,16},{0,0,16},{0,0,64},{0,0,52},{0,0,100},{0,0,100},{0,0,325},{0,0,200},{0,0,361},{0,0,16}, +{0,0,16},{0,0,16},{0,0,64},{0,0,52},{0,0,100},{0,0,100},{0,0,325},{0,0,164},{0,0,325},{0,0,20},{0,0,20},{0,0,97},{0,0,145},{0,0,20},{0,0,68},{0,0,145},{0,0,306},{0,0,68},{0,0,306},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,1,126},{0,0,88},{0,0,53}, +{0,0,37},{0,0,116},{0,0,36},{0,0,1},{0,0,66},{0,0,88},{0,0,102},{0,1,126},{0,0,88},{0,0,53},{0,0,37},{0,0,116},{0,0,36},{0,0,1},{0,0,66},{0,0,52},{0,0,66},{0,0,52},{0,0,52},{0,0,52},{0,0,36},{0,0,16},{0,0,0},{0,0,0},{0,0,65},{0,0,52},{0,0,101},{0,0,52},{0,0,52},{0,0,52},{0,0,36},{0,0,16}, +{0,0,0},{0,0,0},{0,0,65},{0,0,16},{0,0,65},{0,1,90},{0,0,52},{0,0,17},{0,0,1},{0,1,90},{0,0,36},{0,0,1},{0,0,50},{0,0,36},{0,0,50},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,0,0},{0,0,0},{0,0,0},{0,0,16},{0,0,52},{0,0,52},{0,1,286},{0,1,310},{0,0,453},{0,0,373},{0,1,115},{0,1,307},{0,0,241}, +{0,0,130},{0,0,280},{0,0,70},{0,1,222},{0,1,246},{0,0,389},{0,0,309},{0,1,51},{1,0,195},{0,0,177},{0,0,66},{1,0,107},{0,0,66},{0,1,261},{0,1,261},{0,1,261},{0,0,324},{0,1,90},{0,0,192},{0,0,192},{0,0,81},{0,0,84},{0,0,21},{0,1,197},{0,1,197},{0,1,197},{0,0,260},{0,1,26},{0,0,128},{0,0,128},{0,0,17},{0,0,80}, +{0,0,17},{0,1,26},{0,1,50},{1,0,130},{1,0,74},{0,1,26},{1,0,26},{1,0,74},{0,0,50},{1,0,26},{0,0,50},{0,0,260},{0,0,260},{0,0,260},{0,0,260},{0,1,89},{0,1,89},{0,1,89},{0,0,80},{0,0,20},{0,0,20},{1,0,494},{1,0,550},{1,0,694},{1,0,702},{0,2,363},{0,1,291},{1,0,583},{1,0,631},{0,1,116},{1,0,428},{1,0,170}, +{1,0,226},{1,0,370},{1,0,378},{1,0,51},{0,1,35},{1,0,259},{1,0,307},{1,0,91},{1,0,307},{1,0,469},{1,0,469},{1,0,469},{1,0,477},{0,1,314},{0,1,290},{0,1,290},{1,0,406},{0,1,115},{1,0,203},{1,0,145},{1,0,145},{1,0,145},{1,0,153},{1,0,26},{1,0,34},{1,0,34},{1,0,82},{1,0,10},{1,0,82},{1,0,26},{0,1,50},{1,0,226}, +{1,0,234},{1,0,26},{0,1,26},{1,0,234},{0,0,306},{0,1,26},{0,0,306},{1,0,468},{1,0,468},{1,0,468},{1,0,468},{0,1,265},{0,1,265},{0,1,265},{1,0,325},{0,1,90},{0,1,90},{1,1,116},{1,1,124},{1,1,215},{1,1,271},{1,1,188},{1,1,252},{1,1,343},{1,1,606},{0,1,152},{0,1,392},{1,1,35},{1,1,43},{1,1,134},{1,1,190},{1,1,107}, +{1,1,171},{0,1,260},{0,1,356},{2,0,51},{0,1,356},{1,1,115},{1,1,115},{1,1,115},{1,1,171},{1,0,161},{1,0,241},{1,0,241},{1,0,469},{0,1,52},{0,1,292},{1,1,34},{1,1,34},{1,1,34},{1,1,90},{0,2,16},{1,0,160},{1,0,160},{0,1,256},{0,1,16},{0,1,256},{1,1,26},{1,1,34},{1,1,125},{0,1,116},{1,1,26},{2,0,26},{0,1,116}, +{0,1,356},{2,0,26},{0,1,356},{1,0,90},{1,0,90},{1,0,90},{1,0,90},{1,0,97},{1,0,97},{1,0,97},{1,0,145},{0,1,36},{0,1,36},{1,1,116},{1,1,60},{1,1,39},{1,1,31},{1,1,92},{1,1,28},{1,1,7},{1,1,94},{1,1,100},{1,1,142},{1,1,115},{1,1,59},{1,1,38},{1,1,30},{0,3,51},{1,1,27},{1,1,6},{1,1,93},{1,1,51}, +{1,1,93},{1,1,35},{1,1,35},{1,1,35},{1,1,27},{1,1,11},{1,1,3},{1,1,3},{1,1,90},{1,1,75},{1,1,138},{1,1,34},{1,1,34},{1,1,34},{1,1,26},{1,1,10},{1,1,2},{1,1,2},{1,1,89},{1,1,26},{1,1,89},{2,0,26},{1,1,34},{1,1,13},{1,1,5},{2,0,26},{3,0,26},{1,1,5},{0,1,68},{3,0,26},{0,1,68},{1,0,26}, +{1,0,26},{1,0,26},{1,0,26},{1,1,2},{1,1,2},{1,1,2},{1,1,26},{1,1,74},{1,1,74},{1,2,238},{1,2,286},{1,1,375},{1,1,303},{1,2,105},{1,1,316},{1,1,183},{1,1,94},{0,2,156},{1,1,46},{1,2,189},{1,2,237},{1,1,326},{1,1,254},{1,2,56},{2,1,232},{1,1,134},{1,1,45},{0,2,56},{1,1,45},{1,2,222},{1,2,222},{1,2,222}, +{1,1,267},{1,2,89},{1,1,147},{1,1,147},{1,1,58},{1,1,59},{1,1,10},{1,2,173},{1,2,173},{1,2,173},{1,1,218},{2,0,10},{1,1,98},{1,1,98},{1,1,9},{3,0,10},{1,1,9},{1,2,20},{1,2,68},{2,1,136},{2,1,72},{1,2,20},{0,2,20},{2,1,72},{0,1,36},{0,2,20},{0,1,36},{1,0,218},{1,0,218},{1,0,218},{1,0,218},{1,2,85}, +{1,2,85},{1,2,85},{1,1,58},{1,1,10},{1,1,10},{2,1,550},{2,1,598},{2,1,730},{2,1,730},{1,3,361},{1,2,265},{2,1,597},{1,1,606},{1,2,152},{2,1,408},{2,1,189},{2,1,237},{2,1,369},{2,1,369},{2,1,56},{1,2,40},{2,1,236},{2,1,264},{4,0,56},{2,1,264},{2,1,534},{2,1,534},{2,1,534},{2,1,534},{1,2,265},{1,2,265},{1,2,265}, +{1,1,410},{2,1,152},{2,1,212},{2,1,173},{2,1,173},{2,1,173},{2,1,173},{0,4,8},{2,1,40},{2,1,40},{2,1,68},{2,1,8},{2,1,68},{2,1,20},{1,2,36},{2,1,200},{2,1,200},{2,1,20},{4,0,20},{2,1,200},{0,1,260},{4,0,20},{0,1,260},{2,0,530},{2,0,530},{2,0,530},{2,0,530},{1,2,229},{1,2,229},{1,2,229},{1,2,325},{1,2,116}, +{1,2,116},{2,2,152},{2,2,168},{2,2,273},{2,2,337},{2,2,236},{2,2,316},{2,2,421},{2,2,706},{1,2,116},{1,2,436},{2,2,52},{2,2,68},{2,2,173},{2,2,237},{3,0,56},{1,2,211},{1,2,251},{1,2,411},{3,1,56},{1,2,411},{2,2,152},{2,2,152},{2,2,152},{2,2,216},{2,1,158},{2,1,230},{2,1,230},{2,1,438},{1,2,35},{1,2,315},{2,2,52}, +{2,2,52},{2,2,52},{2,2,116},{1,3,10},{2,1,130},{2,1,130},{1,2,290},{1,2,10},{1,2,290},{3,0,20},{2,2,52},{2,2,157},{1,2,130},{3,0,20},{3,1,20},{1,2,130},{0,2,410},{3,1,20},{0,2,410},{2,0,116},{2,0,116},{2,0,116},{2,0,116},{2,1,109},{2,1,109},{2,1,109},{2,1,149},{1,2,26},{1,2,26},{2,2,88},{2,2,40},{2,2,33}, +{2,2,33},{2,2,76},{2,2,28},{2,2,21},{2,2,130},{2,2,120},{2,2,190},{2,2,84},{2,2,36},{2,2,29},{2,2,29},{1,4,56},{2,2,24},{2,2,17},{2,2,126},{2,2,56},{2,2,126},{2,2,24},{2,2,24},{2,2,24},{2,2,24},{2,2,12},{2,2,12},{2,2,12},{2,2,121},{2,2,104},{2,2,181},{2,2,20},{2,2,20},{2,2,20},{2,2,20},{2,2,8}, +{2,2,8},{2,2,8},{2,2,117},{5,0,8},{2,2,117},{1,4,20},{2,2,20},{2,2,13},{2,2,13},{1,4,20},{2,2,20},{2,2,13},{0,2,90},{2,2,20},{0,2,90},{2,0,20},{2,0,20},{2,0,20},{2,0,20},{2,2,8},{2,2,8},{2,2,8},{2,2,40},{2,2,100},{2,2,100},{2,3,198},{2,3,270},{2,2,305},{2,2,241},{2,3,103},{2,2,252},{2,2,133}, +{2,2,66},{1,3,148},{2,2,30},{2,3,162},{2,3,234},{2,2,269},{2,2,205},{2,3,67},{2,2,216},{2,2,97},{2,2,30},{6,0,67},{2,2,30},{2,3,189},{2,3,189},{2,3,189},{2,2,216},{2,3,94},{2,2,108},{2,2,108},{2,2,41},{2,2,40},{2,2,5},{2,3,153},{2,3,153},{2,3,153},{2,2,180},{3,1,8},{2,2,72},{2,2,72},{2,2,5},{4,1,8}, +{2,2,5},{2,3,18},{2,3,90},{2,2,125},{2,2,61},{2,3,18},{6,0,18},{2,2,61},{0,2,26},{6,0,18},{0,2,26},{2,0,180},{2,0,180},{2,0,180},{2,0,180},{2,2,72},{2,2,72},{2,2,72},{2,2,40},{2,2,4},{2,2,4},{3,2,614},{2,3,622},{3,2,774},{3,2,766},{2,3,343},{2,3,247},{3,2,619},{2,2,514},{2,3,196},{2,2,382},{3,2,214}, +{3,2,254},{3,2,374},{3,2,366},{4,0,59},{2,3,51},{3,2,219},{3,2,227},{3,2,59},{3,2,227},{3,2,605},{3,2,605},{3,2,605},{3,2,597},{2,3,222},{2,3,246},{2,3,246},{2,2,345},{3,2,179},{2,2,213},{3,2,205},{3,2,205},{3,2,205},{3,2,197},{4,0,10},{3,2,50},{3,2,50},{3,2,58},{3,2,10},{3,2,58},{3,2,18},{2,3,26},{3,2,178}, +{3,2,170},{3,2,18},{5,1,18},{3,2,170},{0,2,218},{5,1,18},{0,2,218},{2,0,596},{2,0,596},{2,0,596},{2,0,596},{2,3,197},{2,3,197},{2,3,197},{2,2,296},{2,3,146},{2,3,146},{3,3,196},{3,3,220},{3,3,339},{3,3,411},{3,3,292},{3,3,388},{3,3,507},{3,3,814},{2,3,88},{2,3,488},{3,3,75},{3,3,99},{3,3,218},{3,3,290},{4,1,67}, +{2,3,168},{2,3,248},{2,3,472},{4,2,67},{2,3,472},{3,2,182},{3,2,182},{3,2,182},{3,2,246},{3,2,161},{3,2,225},{3,2,225},{3,2,413},{2,3,24},{3,2,308},{3,2,61},{3,2,61},{3,2,61},{3,2,125},{2,4,8},{3,2,104},{3,2,104},{3,2,292},{7,0,8},{3,2,292},{4,1,18},{3,3,74},{3,3,193},{2,3,148},{4,1,18},{4,2,18},{2,3,148}, +{0,3,468},{4,2,18},{0,3,468},{3,0,146},{3,0,146},{3,0,146},{3,0,146},{3,2,125},{3,2,125},{3,2,125},{3,2,157},{2,3,20},{2,3,20},{3,3,68},{3,3,28},{3,3,35},{3,3,43},{3,3,68},{3,3,36},{3,3,43},{3,3,174},{3,3,148},{3,3,246},{3,3,59},{3,3,19},{3,3,26},{3,3,34},{3,3,59},{3,3,27},{3,3,34},{2,3,152},{6,1,59}, +{2,3,152},{3,3,19},{3,3,19},{3,3,19},{3,3,27},{3,3,19},{3,3,27},{3,3,27},{3,3,158},{3,3,139},{3,3,230},{3,3,10},{3,3,10},{3,3,10},{3,3,18},{3,3,10},{3,3,18},{3,3,18},{2,3,136},{6,1,10},{2,3,136},{5,0,18},{3,3,10},{3,3,17},{3,3,25},{5,0,18},{3,3,18},{3,3,25},{0,3,116},{3,3,18},{0,3,116},{3,0,18}, +{3,0,18},{3,0,18},{3,0,18},{3,3,18},{3,3,18},{3,3,18},{3,3,58},{3,3,130},{3,3,130},{3,4,166},{3,4,262},{3,3,243},{3,3,187},{3,4,109},{3,3,196},{3,3,91},{3,3,46},{3,3,148},{3,3,22},{3,4,141},{3,4,237},{3,3,218},{3,3,162},{4,2,59},{3,3,171},{3,3,66},{3,3,21},{5,2,59},{3,3,21},{3,4,162},{3,4,162},{3,4,162}, +{3,3,171},{3,4,105},{3,3,75},{3,3,75},{3,3,30},{3,3,27},{3,3,6},{3,4,137},{3,4,137},{3,4,137},{3,3,146},{4,2,10},{3,3,50},{3,3,50},{3,3,5},{5,2,10},{3,3,5},{3,4,20},{3,4,116},{3,3,97},{3,3,41},{3,4,20},{7,1,20},{3,3,41},{0,3,20},{7,1,20},{0,3,20},{3,0,146},{3,0,146},{3,0,146},{3,0,146},{3,3,50}, +{3,3,50},{3,3,50},{3,3,26},{3,3,2},{3,3,2},{3,5,598},{3,4,550},{4,3,826},{4,3,810},{3,4,285},{3,4,237},{4,3,649},{3,3,430},{4,3,248},{3,3,310},{4,3,245},{4,3,277},{4,3,385},{4,3,369},{5,1,52},{3,4,68},{4,3,208},{4,3,196},{4,3,52},{4,3,196},{3,4,546},{3,4,546},{3,4,546},{3,4,594},{3,4,185},{3,4,233},{3,4,233}, +{3,3,286},{4,3,212},{3,3,166},{4,3,241},{4,3,241},{4,3,241},{4,3,225},{5,1,16},{4,3,64},{4,3,64},{4,3,52},{7,1,16},{4,3,52},{4,3,20},{3,4,20},{4,3,160},{4,3,144},{4,3,20},{6,2,20},{4,3,144},{0,3,180},{6,2,20},{0,3,180},{3,0,530},{3,0,530},{3,0,530},{3,0,530},{3,4,169},{3,4,169},{3,4,169},{3,3,250},{3,3,130}, +{3,3,130},{4,4,248},{4,4,280},{4,4,413},{4,4,493},{4,3,291},{4,3,451},{4,4,601},{4,3,835},{3,4,68},{3,4,548},{4,4,104},{4,4,136},{4,4,269},{4,4,349},{6,0,59},{3,4,131},{3,4,251},{3,4,539},{3,4,59},{3,4,539},{4,3,205},{4,3,205},{4,3,205},{4,3,261},{4,3,170},{4,3,226},{4,3,226},{4,3,394},{3,4,19},{4,3,275},{4,3,61}, +{4,3,61},{4,3,61},{4,3,117},{6,0,10},{4,3,82},{4,3,82},{4,3,250},{3,4,10},{4,3,250},{5,2,20},{4,4,100},{4,4,233},{3,4,170},{5,2,20},{5,3,20},{3,4,170},{0,4,530},{5,3,20},{0,4,530},{4,0,180},{4,0,180},{4,0,180},{4,0,180},{4,3,145},{4,3,145},{4,3,145},{4,3,169},{3,4,18},{3,4,18},{4,4,56},{4,4,24},{4,4,45}, +{4,4,61},{4,4,68},{4,4,52},{4,4,73},{4,4,226},{4,4,184},{3,4,292},{4,4,40},{4,4,8},{4,4,29},{4,4,45},{4,4,52},{4,4,36},{4,4,57},{3,4,171},{7,2,52},{3,4,171},{4,4,20},{4,4,20},{4,4,20},{4,4,36},{4,4,32},{4,4,48},{4,4,48},{4,4,201},{4,4,180},{3,4,267},{4,4,4},{4,4,4},{4,4,4},{4,4,20},{5,2,16}, +{4,4,32},{4,4,32},{3,4,146},{7,2,16},{3,4,146},{6,1,20},{4,4,4},{4,4,25},{4,4,41},{6,1,20},{4,4,20},{4,4,41},{0,4,146},{4,4,20},{0,4,146},{4,0,20},{4,0,20},{4,0,20},{4,0,20},{4,4,32},{4,4,32},{4,4,32},{4,4,80},{3,4,146},{3,4,146},{4,5,142},{4,5,262},{4,4,189},{4,4,141},{4,5,123},{4,4,148},{4,4,57}, +{4,4,34},{4,4,120},{4,4,22},{4,5,126},{4,5,246},{4,4,173},{4,4,125},{5,3,52},{4,4,132},{4,4,41},{4,4,18},{6,3,52},{4,4,18},{4,5,141},{4,5,141},{4,5,141},{4,4,132},{4,4,96},{4,4,48},{4,4,48},{4,4,25},{4,4,20},{4,4,13},{4,5,125},{4,5,125},{4,5,125},{4,4,116},{6,1,16},{4,4,32},{4,4,32},{4,4,9},{6,3,16}, +{4,4,9},{7,0,26},{4,5,146},{4,4,73},{4,4,25},{7,0,26},{3,5,26},{4,4,25},{0,4,18},{3,5,26},{0,4,18},{4,0,116},{4,0,116},{4,0,116},{4,0,116},{4,4,32},{4,4,32},{4,4,32},{4,4,16},{4,4,4},{4,4,4},{4,5,558},{4,5,486},{4,4,845},{4,4,733},{4,5,235},{4,5,235},{4,4,553},{4,4,354},{5,4,276},{4,4,246},{5,4,282}, +{5,4,306},{5,4,402},{5,4,378},{6,2,51},{4,5,91},{5,4,203},{5,4,171},{5,4,51},{5,4,171},{4,5,477},{4,5,477},{4,5,477},{4,5,549},{4,5,154},{4,5,226},{4,5,226},{4,4,233},{3,5,235},{4,4,125},{5,4,281},{5,4,281},{5,4,281},{5,4,257},{7,0,10},{5,4,82},{5,4,82},{5,4,50},{3,5,10},{5,4,50},{6,2,26},{4,5,18},{5,4,146}, +{5,4,122},{6,2,26},{7,3,26},{5,4,122},{0,4,146},{7,3,26},{0,4,146},{4,0,468},{4,0,468},{4,0,468},{4,0,468},{4,5,145},{4,5,145},{4,5,145},{4,4,208},{4,4,100},{4,4,100},{5,5,308},{5,5,348},{5,5,495},{5,5,583},{5,4,285},{5,4,429},{5,4,633},{5,4,781},{4,5,56},{4,5,616},{5,5,139},{5,5,179},{5,5,326},{5,5,414},{7,1,52}, +{4,5,100},{4,5,260},{5,4,612},{4,5,52},{5,4,612},{5,4,234},{5,4,234},{5,4,234},{5,4,282},{5,4,185},{5,4,233},{5,4,233},{5,4,381},{4,5,20},{5,4,248},{5,4,65},{5,4,65},{5,4,65},{5,4,113},{7,1,16},{5,4,64},{5,4,64},{5,4,212},{7,3,16},{5,4,212},{6,3,26},{5,5,130},{5,5,277},{4,5,196},{6,3,26},{6,4,26},{4,5,196}, +{0,4,596},{6,4,26},{0,4,596},{5,0,218},{5,0,218},{5,0,218},{5,0,218},{5,4,169},{5,4,169},{5,4,169},{5,4,185},{4,5,20},{4,5,20},{5,5,52},{5,5,28},{5,5,63},{5,5,87},{5,5,76},{5,5,76},{5,5,111},{5,5,286},{5,5,228},{4,5,296},{5,5,27},{5,5,3},{5,5,38},{5,5,62},{5,5,51},{5,5,51},{5,5,86},{4,5,196},{3,6,51}, +{4,5,196},{5,5,27},{5,5,27},{5,5,27},{5,5,51},{5,5,51},{5,5,75},{5,5,75},{5,5,250},{4,5,180},{4,5,260},{5,5,2},{5,5,2},{5,5,2},{5,5,26},{6,3,10},{5,5,50},{5,5,50},{4,5,160},{6,4,10},{4,5,160},{7,2,26},{5,5,2},{5,5,37},{5,5,61},{7,2,26},{5,5,26},{5,5,61},{0,5,180},{5,5,26},{0,5,180},{5,0,26}, +{5,0,26},{5,0,26},{5,0,26},{5,5,50},{5,5,50},{5,5,50},{5,5,106},{4,5,116},{4,5,116},{5,6,126},{5,5,220},{5,5,143},{5,5,103},{5,6,145},{5,5,108},{5,5,31},{5,5,30},{5,5,100},{5,5,30},{5,6,117},{5,5,211},{5,5,134},{5,5,94},{6,4,51},{5,5,99},{5,5,22},{5,5,21},{7,4,51},{5,5,21},{5,6,126},{5,6,126},{5,6,126}, +{5,5,99},{5,5,67},{5,5,27},{5,5,27},{5,5,26},{5,5,19},{5,5,26},{5,6,117},{5,6,117},{5,6,117},{5,5,90},{7,2,10},{5,5,18},{5,5,18},{5,5,17},{5,5,10},{5,5,17},{6,4,26},{5,5,130},{5,5,53},{5,5,13},{6,4,26},{7,4,26},{5,5,13},{0,5,20},{7,4,26},{0,5,20},{5,0,90},{5,0,90},{5,0,90},{5,0,90},{5,5,18}, +{5,5,18},{5,5,18},{5,5,10},{5,5,10},{5,5,10},{5,6,478},{5,6,430},{5,5,735},{5,5,631},{5,6,193},{5,6,241},{5,5,463},{5,5,286},{4,6,268},{5,5,190},{6,5,325},{5,6,309},{6,5,425},{6,5,393},{7,3,56},{6,5,120},{6,5,204},{6,5,152},{6,5,56},{6,5,152},{5,6,414},{5,6,414},{5,6,414},{5,6,510},{5,6,129},{5,6,225},{5,6,225}, +{5,5,186},{5,5,195},{5,5,90},{5,6,293},{5,6,293},{5,6,293},{6,5,293},{5,6,8},{6,5,104},{6,5,104},{6,5,52},{4,6,8},{6,5,52},{7,3,20},{5,6,20},{6,5,136},{6,5,104},{7,3,20},{6,5,20},{6,5,104},{0,5,116},{6,5,20},{0,5,116},{5,0,410},{5,0,410},{5,0,410},{5,0,410},{5,6,125},{5,6,125},{5,6,125},{5,5,170},{5,5,74}, +{5,5,74},{6,5,350},{6,6,424},{6,6,585},{6,5,670},{6,5,287},{6,5,415},{6,5,607},{6,5,735},{5,6,52},{6,5,588},{6,5,154},{6,6,228},{6,6,389},{6,5,474},{5,7,51},{5,6,75},{5,6,275},{6,5,539},{5,6,51},{6,5,539},{6,5,269},{6,5,269},{6,5,269},{6,5,309},{6,5,206},{6,5,246},{6,5,246},{6,5,374},{5,6,27},{6,5,227},{6,5,73}, +{6,5,73},{6,5,73},{6,5,113},{6,5,10},{6,5,50},{6,5,50},{6,5,178},{3,7,10},{6,5,178},{5,7,26},{5,6,146},{6,6,325},{5,6,226},{5,7,26},{5,6,26},{5,6,226},{0,5,530},{5,6,26},{0,5,530},{6,0,260},{6,0,260},{6,0,260},{6,0,260},{6,5,197},{6,5,197},{6,5,197},{6,5,205},{5,6,26},{5,6,26},{6,6,56},{6,6,40},{6,6,89}, +{6,6,121},{6,6,92},{6,6,108},{6,6,157},{6,6,354},{6,6,280},{5,6,308},{6,6,20},{6,6,4},{6,6,53},{6,6,85},{6,6,56},{6,6,72},{6,6,121},{5,6,227},{4,7,56},{5,6,227},{6,6,40},{6,6,40},{6,6,40},{6,6,72},{6,6,76},{6,6,108},{6,6,108},{6,6,305},{5,6,139},{5,6,259},{6,6,4},{6,6,4},{6,6,4},{6,6,36},{7,4,8}, +{6,6,72},{6,6,72},{5,6,178},{7,5,8},{5,6,178},{6,6,20},{6,6,4},{6,6,53},{6,6,85},{6,6,20},{4,7,20},{6,6,85},{0,6,218},{4,7,20},{0,6,218},{6,0,36},{6,0,36},{6,0,36},{6,0,36},{6,6,72},{6,6,72},{6,6,72},{6,6,136},{5,6,90},{5,6,90},{6,7,118},{6,6,168},{6,6,105},{6,6,73},{6,7,175},{6,6,76},{6,6,13}, +{6,6,34},{6,6,88},{6,6,46},{6,7,114},{6,6,164},{6,6,101},{6,6,69},{7,5,56},{6,6,72},{6,6,9},{6,6,30},{6,6,72},{6,6,30},{6,6,104},{6,6,104},{6,6,104},{6,6,72},{6,6,44},{6,6,12},{6,6,12},{6,6,33},{6,6,24},{6,6,45},{6,6,100},{6,6,100},{6,6,100},{6,6,68},{7,5,40},{6,6,8},{6,6,8},{6,6,29},{6,6,8}, +{6,6,29},{7,5,20},{6,6,100},{6,6,37},{6,6,5},{7,5,20},{5,7,50},{6,6,5},{0,6,26},{5,7,50},{0,6,26},{6,0,68},{6,0,68},{6,0,68},{6,0,68},{6,6,8},{6,6,8},{6,6,8},{6,6,8},{6,6,20},{6,6,20},{6,7,406},{6,7,382},{6,6,633},{6,6,537},{6,7,159},{6,7,255},{6,6,381},{6,6,226},{5,7,228},{6,6,142},{6,7,306}, +{6,7,282},{7,6,454},{7,6,414},{6,7,59},{7,6,139},{7,6,211},{6,6,126},{5,7,59},{6,6,126},{6,7,357},{6,7,357},{6,7,357},{6,6,456},{6,7,110},{6,7,230},{6,7,230},{6,6,145},{6,6,152},{6,6,61},{6,7,257},{6,7,257},{6,7,257},{7,6,333},{6,7,10},{7,6,130},{7,6,130},{6,6,45},{5,7,10},{6,6,45},{7,6,50},{6,7,26},{7,6,130}, +{7,6,90},{7,6,50},{7,6,18},{7,6,90},{0,6,90},{7,6,18},{0,6,90},{6,0,356},{6,0,356},{6,0,356},{6,0,356},{6,7,109},{6,7,109},{6,7,109},{6,6,136},{6,6,52},{6,6,52},{7,6,374},{7,6,454},{7,6,634},{7,6,666},{7,6,297},{7,6,409},{7,6,589},{7,6,697},{6,7,56},{7,6,536},{7,6,149},{7,6,229},{7,6,409},{7,6,441},{7,6,72}, +{6,7,56},{6,7,296},{7,6,472},{6,7,56},{7,6,472},{7,6,310},{7,6,310},{7,6,310},{7,6,342},{7,6,233},{7,6,265},{7,6,265},{7,6,373},{6,7,40},{7,6,212},{7,6,85},{7,6,85},{7,6,85},{7,6,117},{7,6,8},{7,6,40},{7,6,40},{7,6,148},{7,6,40},{7,6,148},{7,6,68},{6,7,116},{7,6,328},{6,7,260},{7,6,68},{6,7,20},{6,7,260}, +{0,6,468},{6,7,20},{0,6,468},{7,0,306},{7,0,306},{7,0,306},{7,0,306},{7,6,229},{7,6,229},{7,6,229},{7,6,229},{6,7,36},{6,7,36},{7,7,68},{7,7,60},{7,7,123},{7,7,163},{7,7,116},{7,7,148},{7,7,211},{7,7,430},{6,7,248},{6,7,328},{7,7,19},{7,7,11},{7,7,74},{7,7,114},{7,7,67},{7,7,99},{7,7,162},{6,7,264},{7,7,171}, +{6,7,264},{7,7,59},{7,7,59},{7,7,59},{7,7,99},{7,7,107},{7,7,147},{7,7,147},{7,7,366},{6,7,104},{6,7,264},{7,7,10},{7,7,10},{7,7,10},{7,7,50},{7,7,58},{7,7,98},{7,7,98},{6,7,200},{6,7,40},{6,7,200},{7,7,18},{7,7,10},{7,7,73},{6,7,100},{7,7,18},{7,7,50},{6,7,100},{0,7,260},{7,7,50},{0,7,260},{7,0,50}, +{7,0,50},{7,0,50},{7,0,50},{7,6,85},{7,6,85},{7,6,85},{7,6,149},{6,7,68},{6,7,68},{7,7,196},{7,7,124},{7,7,75},{7,7,51},{7,7,148},{7,7,52},{7,7,3},{7,7,46},{7,7,84},{7,7,70},{7,7,195},{7,7,123},{7,7,74},{7,7,50},{7,7,147},{7,7,51},{7,7,2},{7,7,45},{7,7,59},{7,7,45},{7,7,75},{7,7,75},{7,7,75}, +{7,7,51},{7,7,27},{7,7,3},{7,7,3},{7,7,46},{7,7,35},{7,7,70},{7,7,74},{7,7,74},{7,7,74},{7,7,50},{7,7,26},{7,7,2},{7,7,2},{7,7,45},{7,7,10},{7,7,45},{7,7,146},{7,7,74},{7,7,25},{7,7,1},{7,7,146},{7,7,50},{7,7,1},{0,7,36},{7,7,50},{0,7,36},{7,0,50},{7,0,50},{7,0,50},{7,0,50},{7,7,2}, +{7,7,2},{7,7,2},{7,7,10},{7,7,34},{7,7,34},{7,7,548},{7,7,476},{7,7,427},{7,7,355},{7,7,404},{7,7,260},{7,7,211},{7,7,106},{7,7,132},{7,7,34},{7,7,467},{7,7,395},{7,7,346},{7,7,274},{7,7,323},{7,7,179},{7,7,130},{7,7,25},{7,7,123},{7,7,25},{7,7,427},{7,7,427},{7,7,427},{7,7,355},{7,7,283},{7,7,211},{7,7,211}, +{7,7,106},{7,7,83},{7,7,34},{7,7,346},{7,7,346},{7,7,346},{7,7,274},{7,7,202},{7,7,130},{7,7,130},{7,7,25},{7,7,74},{7,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,306},{7,0,306},{7,0,306},{7,0,306},{7,7,162},{7,7,162},{7,7,162},{7,7,106},{7,7,34}, +{7,7,34},{0,0,122},{0,0,50},{0,0,1},{0,0,25},{0,0,158},{0,0,110},{0,0,61},{0,0,244},{0,0,210},{0,0,280},{0,0,122},{0,0,50},{0,0,1},{0,0,25},{0,0,158},{0,0,110},{0,0,61},{0,0,244},{0,0,174},{0,0,244},{0,0,1},{0,0,1},{0,0,1},{0,0,25},{0,0,37},{0,0,61},{0,0,61},{0,0,244},{0,0,161},{0,0,280},{0,0,1}, +{0,0,1},{0,0,1},{0,0,25},{0,0,37},{0,0,61},{0,0,61},{0,0,244},{0,0,125},{0,0,244},{0,0,122},{0,0,50},{0,0,1},{0,0,25},{0,0,122},{0,0,74},{0,0,25},{0,0,144},{0,0,74},{0,0,144},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,1,81},{0,1,81},{0,0,122}, +{0,0,82},{0,1,328},{0,0,243},{0,0,82},{0,0,129},{0,0,319},{0,0,165},{0,1,81},{0,1,81},{0,0,122},{0,0,82},{0,1,328},{0,0,243},{0,0,82},{0,0,129},{0,0,283},{0,0,129},{0,1,45},{0,1,45},{0,1,45},{0,0,18},{0,0,58},{0,0,18},{0,0,18},{0,0,65},{0,0,94},{0,0,101},{0,1,45},{0,1,45},{0,1,45},{0,0,18},{0,0,58}, +{0,0,18},{0,0,18},{0,0,65},{0,0,58},{0,0,65},{0,1,72},{0,1,72},{0,0,113},{0,0,73},{0,1,72},{1,0,104},{0,0,73},{0,0,80},{1,0,104},{0,0,80},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,49},{0,0,85},{0,0,85},{0,2,225},{0,1,129},{0,1,449},{0,0,498},{0,1,264},{0,1,168},{0,0,402}, +{0,0,273},{0,0,687},{0,0,309},{0,2,225},{0,1,129},{0,1,449},{0,0,498},{0,1,264},{0,1,168},{0,0,402},{0,0,273},{1,0,248},{0,0,273},{0,1,125},{0,1,125},{0,1,125},{0,1,221},{0,1,68},{0,0,146},{0,0,146},{0,0,17},{0,0,158},{0,0,53},{0,1,125},{0,1,125},{0,1,125},{0,1,221},{0,1,68},{0,0,146},{0,0,146},{0,0,17},{0,0,122}, +{0,0,17},{1,0,72},{0,1,8},{1,0,292},{1,0,260},{1,0,72},{1,0,104},{1,0,260},{0,0,272},{1,0,104},{0,0,272},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,0,25},{0,0,25},{0,0,25},{0,0,1},{0,0,37},{0,0,37},{0,2,514},{0,2,558},{0,1,610},{0,1,514},{0,2,297},{0,1,153},{0,1,153},{0,1,777},{0,1,392},{0,0,802},{1,1,347}, +{1,1,355},{1,1,446},{0,1,465},{0,2,248},{0,1,104},{0,1,104},{0,1,728},{0,1,248},{0,1,728},{0,2,414},{0,2,414},{0,2,414},{0,1,414},{0,1,149},{0,1,53},{0,1,53},{0,0,274},{0,1,292},{0,0,226},{1,0,229},{1,0,229},{1,0,229},{1,0,261},{1,0,68},{0,1,4},{0,1,4},{1,0,160},{1,0,52},{1,0,160},{0,2,104},{1,1,130},{0,1,200}, +{0,1,104},{0,2,104},{2,0,74},{0,1,104},{0,1,584},{2,0,74},{0,1,584},{0,0,410},{0,0,410},{0,0,410},{0,0,410},{0,1,49},{0,1,49},{0,1,49},{0,0,130},{0,0,82},{0,0,82},{1,1,464},{1,1,400},{1,1,365},{1,1,397},{1,1,572},{0,2,499},{0,1,387},{0,1,435},{0,1,428},{0,1,188},{1,1,140},{1,1,76},{1,1,41},{1,1,73},{1,1,248}, +{1,1,216},{0,1,131},{0,1,179},{2,0,264},{0,1,179},{1,1,364},{1,1,364},{1,1,364},{1,1,396},{0,2,314},{0,1,386},{0,1,386},{0,1,434},{0,1,67},{0,1,187},{1,1,40},{1,1,40},{1,1,40},{1,1,72},{0,2,58},{0,1,130},{0,1,130},{0,1,178},{0,1,58},{0,1,178},{0,3,72},{1,1,40},{1,1,5},{1,1,37},{0,3,72},{1,1,72},{1,1,37}, +{0,1,170},{1,1,72},{0,1,170},{1,0,360},{1,0,360},{1,0,360},{1,0,360},{0,2,265},{0,2,265},{0,2,265},{0,1,265},{0,1,18},{0,1,18},{1,2,178},{1,2,202},{1,1,189},{1,1,157},{1,2,463},{1,1,316},{1,1,169},{1,1,238},{0,2,412},{0,1,124},{1,2,78},{1,2,102},{1,1,89},{1,1,57},{2,0,248},{0,2,99},{1,1,69},{0,1,99},{3,0,248}, +{0,1,99},{1,1,140},{1,1,140},{1,1,140},{1,1,108},{1,1,152},{1,1,120},{1,1,120},{1,1,189},{0,1,275},{0,1,75},{1,1,40},{1,1,40},{1,1,40},{1,1,8},{1,1,52},{1,1,20},{1,1,20},{0,1,50},{1,1,68},{0,1,50},{1,2,74},{1,2,98},{1,1,85},{1,1,53},{1,2,74},{0,2,74},{1,1,53},{0,1,74},{0,2,74},{0,1,74},{1,0,104}, +{1,0,104},{1,0,104},{1,0,104},{1,1,116},{1,1,116},{1,1,116},{1,1,164},{0,1,50},{0,1,50},{1,3,226},{1,2,106},{1,2,466},{1,1,429},{1,2,255},{1,2,207},{1,1,345},{1,1,238},{0,2,252},{1,1,298},{1,3,222},{1,2,102},{1,2,462},{1,1,425},{1,2,251},{1,2,203},{1,1,341},{1,1,234},{0,2,251},{1,1,234},{1,2,105},{1,2,105},{1,2,105}, +{1,1,204},{1,2,86},{1,1,120},{1,1,120},{1,1,13},{0,2,83},{1,1,73},{1,2,101},{1,2,101},{1,2,101},{1,1,200},{2,0,52},{1,1,116},{1,1,116},{1,1,9},{3,0,52},{1,1,9},{2,1,74},{1,2,2},{2,1,274},{2,1,234},{2,1,74},{4,0,74},{2,1,234},{0,1,234},{4,0,74},{0,1,234},{1,0,104},{1,0,104},{1,0,104},{1,0,104},{1,1,20}, +{1,1,20},{1,1,20},{1,1,4},{1,1,64},{1,1,64},{1,3,450},{1,2,522},{1,2,562},{1,2,490},{1,3,295},{1,2,127},{1,2,167},{1,1,750},{1,2,428},{1,1,714},{2,2,400},{2,2,416},{2,2,521},{1,2,454},{2,1,251},{1,2,91},{1,2,131},{0,2,651},{4,0,251},{0,2,651},{1,3,369},{1,3,369},{1,3,369},{1,2,369},{1,2,118},{1,2,46},{1,2,46}, +{1,1,221},{0,2,163},{1,1,185},{2,1,257},{2,1,257},{2,1,257},{2,1,281},{0,4,50},{1,2,10},{1,2,10},{2,1,146},{2,1,50},{2,1,146},{3,0,80},{2,2,160},{1,2,202},{1,2,130},{3,0,80},{3,1,80},{1,2,130},{0,1,650},{3,1,80},{0,1,650},{1,0,360},{1,0,360},{1,0,360},{1,0,360},{1,2,37},{1,2,37},{1,2,37},{1,1,100},{1,1,64}, +{1,1,64},{2,2,500},{2,2,444},{2,2,423},{2,2,463},{1,4,588},{1,3,513},{1,2,329},{1,2,441},{0,3,284},{1,2,232},{2,2,139},{2,2,83},{2,2,62},{2,2,102},{3,0,251},{2,2,243},{1,2,104},{1,2,216},{3,1,251},{1,2,216},{2,2,419},{2,2,419},{2,2,419},{2,2,459},{1,3,277},{1,2,325},{1,2,325},{1,2,437},{1,2,68},{1,2,228},{2,2,58}, +{2,2,58},{2,2,58},{2,2,98},{1,3,52},{1,2,100},{1,2,100},{1,2,212},{1,2,52},{1,2,212},{1,4,74},{2,2,34},{2,2,13},{1,2,40},{1,4,74},{2,2,74},{1,2,40},{0,2,200},{2,2,74},{0,2,200},{2,0,410},{2,0,410},{2,0,410},{2,0,410},{1,3,241},{1,3,241},{1,3,241},{1,2,241},{1,2,32},{1,2,32},{2,3,202},{2,3,250},{2,2,183}, +{2,2,159},{2,2,460},{2,2,316},{2,2,183},{2,2,274},{1,3,468},{1,2,104},{2,3,81},{2,3,129},{2,2,62},{2,2,38},{1,4,251},{1,3,96},{2,2,62},{1,2,88},{2,2,251},{1,2,88},{2,2,147},{2,2,147},{2,2,147},{2,2,123},{2,2,171},{2,2,147},{2,2,147},{2,2,238},{0,3,219},{1,2,68},{2,2,26},{2,2,26},{2,2,26},{2,2,2},{2,2,50}, +{2,2,26},{2,2,26},{1,2,52},{5,0,50},{1,2,52},{2,3,80},{2,3,128},{2,2,61},{2,2,37},{2,3,80},{6,0,80},{2,2,37},{0,2,72},{6,0,80},{0,2,72},{2,0,122},{2,0,122},{2,0,122},{2,0,122},{2,2,146},{2,2,146},{2,2,146},{2,2,202},{1,2,32},{1,2,32},{2,3,234},{2,3,90},{2,2,455},{2,2,367},{2,3,253},{2,3,253},{2,2,295}, +{2,2,210},{1,3,244},{2,2,282},{2,3,225},{2,3,81},{2,2,446},{2,2,358},{2,3,244},{2,3,244},{2,2,286},{2,2,201},{6,0,244},{2,2,201},{2,3,90},{2,3,90},{2,3,90},{2,2,171},{2,3,109},{2,2,99},{2,2,99},{2,2,14},{1,3,100},{2,2,86},{2,3,81},{2,3,81},{2,3,81},{2,2,162},{3,1,50},{2,2,90},{2,2,90},{2,2,5},{4,1,50}, +{2,2,5},{4,0,80},{2,3,0},{3,2,260},{3,2,212},{4,0,80},{5,1,80},{3,2,212},{0,2,200},{5,1,80},{0,2,200},{2,0,90},{2,0,90},{2,0,90},{2,0,90},{2,2,18},{2,2,18},{2,2,18},{2,2,10},{2,2,82},{2,2,82},{2,4,394},{2,3,442},{2,3,522},{2,3,474},{2,4,301},{2,3,109},{2,3,189},{2,2,658},{2,3,472},{2,2,634},{2,4,369}, +{2,3,417},{2,3,497},{2,3,449},{3,2,244},{2,3,84},{2,3,164},{3,2,620},{5,1,244},{3,2,620},{2,4,330},{2,4,330},{2,4,330},{2,3,330},{2,3,93},{2,3,45},{2,3,45},{2,2,174},{1,3,132},{2,2,150},{3,2,289},{3,2,289},{3,2,289},{3,2,305},{4,0,52},{2,3,20},{2,3,20},{3,2,136},{3,2,52},{3,2,136},{2,4,80},{2,3,128},{2,3,208}, +{2,3,160},{2,4,80},{7,0,80},{2,3,160},{0,2,584},{7,0,80},{0,2,584},{2,0,314},{2,0,314},{2,0,314},{2,0,314},{2,3,29},{2,3,29},{2,3,29},{2,2,74},{2,2,50},{2,2,50},{3,3,544},{3,3,496},{3,3,489},{3,3,537},{2,4,535},{2,4,535},{2,3,279},{2,3,455},{1,4,292},{2,3,284},{3,3,144},{3,3,96},{3,3,89},{3,3,137},{4,1,244}, +{3,3,276},{2,3,83},{2,3,259},{4,2,244},{2,3,259},{3,3,480},{3,3,480},{3,3,480},{3,3,528},{2,4,246},{2,3,270},{2,3,270},{2,3,446},{2,3,75},{2,3,275},{3,3,80},{3,3,80},{3,3,80},{3,3,128},{2,4,50},{2,3,74},{2,3,74},{2,3,250},{7,0,50},{2,3,250},{5,0,80},{3,3,32},{3,3,25},{2,3,34},{5,0,80},{6,1,80},{2,3,34}, +{0,3,234},{6,1,80},{0,3,234},{3,0,464},{3,0,464},{3,0,464},{3,0,464},{2,4,221},{2,4,221},{2,4,221},{2,3,221},{2,3,50},{2,3,50},{3,4,234},{3,3,304},{3,3,185},{3,3,169},{3,3,452},{3,3,324},{3,3,205},{3,3,318},{1,4,452},{2,3,92},{3,4,90},{3,3,160},{3,3,41},{3,3,25},{5,0,244},{2,4,99},{3,3,61},{2,3,83},{3,3,244}, +{2,3,83},{3,3,160},{3,3,160},{3,3,160},{3,3,144},{3,3,196},{3,3,180},{3,3,180},{3,3,293},{2,3,187},{2,3,67},{3,3,16},{3,3,16},{3,3,16},{3,3,0},{3,3,52},{3,3,36},{3,3,36},{2,3,58},{6,1,52},{2,3,58},{4,2,80},{3,3,160},{3,3,41},{3,3,25},{4,2,80},{5,2,80},{3,3,25},{0,3,74},{5,2,80},{0,3,74},{3,0,144}, +{3,0,144},{3,0,144},{3,0,144},{3,3,180},{3,3,180},{3,3,180},{3,3,244},{2,3,18},{2,3,18},{3,4,202},{3,4,82},{3,3,393},{3,3,313},{3,4,259},{3,4,307},{3,3,253},{3,3,190},{2,4,244},{3,3,274},{3,4,186},{3,4,66},{3,3,377},{3,3,297},{3,4,243},{2,4,243},{3,3,237},{3,3,174},{7,1,243},{3,3,174},{3,4,81},{3,4,81},{3,4,81}, +{3,3,144},{3,4,138},{3,3,84},{3,3,84},{3,3,21},{2,4,123},{3,3,105},{3,4,65},{3,4,65},{3,4,65},{3,3,128},{4,2,52},{3,3,68},{3,3,68},{3,3,5},{5,2,52},{3,3,5},{5,1,74},{3,4,2},{4,3,250},{4,3,194},{5,1,74},{4,3,74},{4,3,194},{0,3,170},{4,3,74},{0,3,170},{3,0,80},{3,0,80},{3,0,80},{3,0,80},{3,3,20}, +{3,3,20},{3,3,20},{3,3,20},{3,3,104},{3,3,104},{3,5,346},{3,4,370},{3,4,490},{3,4,466},{3,5,315},{3,4,99},{3,4,219},{3,3,574},{2,4,468},{3,3,562},{3,5,330},{3,4,354},{3,4,474},{3,4,450},{4,3,243},{3,4,83},{3,4,203},{3,3,558},{6,2,243},{3,3,558},{3,5,297},{3,5,297},{3,5,297},{3,4,297},{3,4,74},{3,4,50},{3,4,50}, +{3,3,133},{2,4,107},{3,3,121},{3,5,281},{3,5,281},{3,5,281},{3,4,281},{5,1,58},{3,4,34},{3,4,34},{3,3,117},{7,1,58},{3,3,117},{6,0,74},{3,4,98},{3,4,218},{3,4,194},{6,0,74},{3,4,74},{3,4,194},{0,3,522},{3,4,74},{0,3,522},{3,0,272},{3,0,272},{3,0,272},{3,0,272},{3,4,25},{3,4,25},{3,4,25},{3,3,52},{3,3,40}, +{3,3,40},{4,4,596},{4,4,556},{4,4,563},{4,4,619},{3,5,477},{3,4,477},{3,4,237},{3,4,477},{2,5,308},{3,4,344},{4,4,155},{4,4,115},{4,4,122},{4,4,178},{5,2,243},{2,5,299},{3,4,68},{2,4,308},{5,3,243},{2,4,308},{4,4,547},{4,4,547},{4,4,547},{4,4,603},{3,5,221},{3,4,221},{3,4,221},{3,4,461},{3,4,88},{3,4,328},{4,4,106}, +{4,4,106},{4,4,106},{4,4,162},{6,0,52},{3,4,52},{3,4,52},{2,4,292},{3,4,52},{2,4,292},{4,4,74},{4,4,34},{4,4,41},{3,4,32},{4,4,74},{7,2,74},{3,4,32},{0,4,272},{7,2,74},{0,4,272},{4,0,522},{4,0,522},{4,0,522},{4,0,522},{3,4,205},{3,4,205},{3,4,205},{3,4,205},{3,4,72},{3,4,72},{4,5,274},{4,4,300},{4,4,195}, +{4,4,187},{4,4,452},{4,4,340},{4,4,235},{4,4,370},{2,5,404},{3,4,88},{4,5,105},{4,4,131},{4,4,26},{4,4,18},{6,1,243},{3,5,108},{4,4,66},{3,4,84},{4,4,243},{3,4,84},{4,4,179},{4,4,179},{4,4,179},{4,4,171},{4,4,227},{4,4,219},{4,4,219},{4,4,354},{3,4,152},{3,4,72},{4,4,10},{4,4,10},{4,4,10},{4,4,2},{5,2,58}, +{4,4,50},{4,4,50},{3,4,68},{7,2,58},{3,4,68},{5,3,74},{4,4,130},{4,4,25},{4,4,17},{5,3,74},{6,3,74},{4,4,17},{0,4,80},{6,3,74},{0,4,80},{4,0,170},{4,0,170},{4,0,170},{4,0,170},{4,3,205},{4,3,205},{4,3,205},{4,3,269},{3,4,8},{3,4,8},{4,5,178},{4,5,82},{4,4,339},{4,4,267},{4,5,273},{4,5,369},{4,4,219}, +{4,4,178},{3,5,252},{4,4,274},{4,5,153},{4,5,57},{4,4,314},{4,4,242},{7,0,248},{3,5,204},{4,4,194},{4,4,153},{3,5,248},{4,4,153},{4,5,78},{4,5,78},{4,5,78},{4,4,123},{4,4,147},{4,4,75},{4,4,75},{4,4,34},{3,5,152},{4,4,130},{4,5,53},{4,5,53},{4,5,53},{4,4,98},{6,1,58},{4,4,50},{4,4,50},{4,4,9},{6,3,58}, +{4,4,9},{6,2,72},{4,5,8},{5,4,244},{5,4,180},{6,2,72},{5,4,72},{5,4,180},{0,4,144},{5,4,72},{0,4,144},{4,0,74},{4,0,74},{4,0,74},{4,0,74},{4,4,26},{4,4,26},{4,4,26},{4,4,34},{4,4,130},{4,4,130},{4,6,306},{4,5,306},{4,5,466},{4,5,466},{4,6,337},{4,5,97},{4,5,257},{4,4,498},{3,5,412},{4,4,498},{4,6,297}, +{4,5,297},{4,5,457},{4,5,457},{5,4,248},{4,5,88},{4,5,248},{4,4,489},{7,3,248},{4,4,489},{4,5,270},{4,5,270},{4,5,270},{4,5,270},{4,5,61},{4,5,61},{4,5,61},{4,4,98},{3,5,88},{4,4,98},{4,5,261},{4,5,261},{4,5,261},{4,5,261},{7,0,52},{4,5,52},{4,5,52},{4,4,89},{3,5,52},{4,4,89},{7,1,72},{4,5,72},{4,5,232}, +{3,5,232},{7,1,72},{4,5,72},{3,5,232},{0,4,464},{4,5,72},{0,4,464},{4,0,234},{4,0,234},{4,0,234},{4,0,234},{4,5,25},{4,5,25},{4,5,25},{4,4,34},{4,4,34},{4,4,34},{5,5,656},{5,5,624},{5,5,645},{5,5,709},{4,6,427},{4,5,403},{4,5,203},{4,5,507},{4,5,332},{4,5,412},{5,5,172},{5,5,140},{5,5,161},{5,5,225},{6,3,248}, +{4,5,259},{4,5,59},{3,5,339},{6,4,248},{3,5,339},{5,5,620},{5,5,620},{5,5,620},{5,5,684},{4,6,202},{4,5,178},{4,5,178},{4,5,482},{4,5,107},{4,5,387},{5,5,136},{5,5,136},{5,5,136},{5,5,200},{7,1,58},{4,5,34},{4,5,34},{5,4,290},{7,3,58},{5,4,290},{5,5,72},{5,5,40},{5,5,61},{4,5,34},{5,5,72},{3,6,72},{4,5,34}, +{0,5,314},{3,6,72},{0,5,314},{5,0,584},{5,0,584},{5,0,584},{5,0,584},{4,5,169},{4,5,169},{4,5,169},{4,5,193},{4,5,98},{4,5,98},{5,6,322},{5,5,304},{5,5,213},{5,5,213},{5,5,460},{5,5,364},{5,5,273},{5,5,430},{3,6,364},{4,5,92},{5,6,126},{5,5,108},{5,5,17},{5,5,17},{7,2,248},{4,6,123},{5,5,77},{4,5,91},{5,5,248}, +{4,5,91},{5,5,204},{5,5,204},{5,5,204},{5,5,204},{5,5,264},{5,5,264},{5,5,264},{5,5,421},{4,5,123},{4,5,83},{5,5,8},{5,5,8},{5,5,8},{5,5,8},{6,3,52},{5,5,68},{5,5,68},{4,5,82},{6,4,52},{4,5,82},{6,4,72},{5,5,104},{5,5,13},{5,5,13},{6,4,72},{7,4,72},{5,5,13},{0,5,90},{7,4,72},{0,5,90},{5,0,200}, +{5,0,200},{5,0,200},{5,0,200},{5,4,221},{5,4,221},{5,4,221},{5,4,277},{4,5,2},{4,5,2},{5,6,162},{5,6,90},{5,5,293},{5,5,229},{5,6,295},{5,5,396},{5,5,193},{5,5,174},{4,6,268},{5,5,282},{5,6,126},{5,6,54},{5,5,257},{5,5,193},{5,6,259},{4,6,171},{5,5,157},{5,5,138},{4,6,259},{5,5,138},{5,6,81},{5,6,81},{5,6,81}, +{5,5,108},{5,5,136},{5,5,72},{5,5,72},{5,5,53},{4,6,187},{5,5,161},{5,6,45},{5,6,45},{5,6,45},{5,5,72},{7,2,52},{5,5,36},{5,5,36},{5,5,17},{5,5,52},{5,5,17},{7,3,74},{5,6,18},{5,5,221},{5,5,157},{7,3,74},{6,5,74},{5,5,157},{0,5,122},{6,5,74},{0,5,122},{5,0,72},{5,0,72},{5,0,72},{5,0,72},{5,5,36}, +{5,5,36},{5,5,36},{5,5,52},{5,5,160},{5,5,160},{5,7,274},{5,6,250},{5,6,450},{5,6,474},{5,6,343},{5,6,103},{5,6,303},{5,5,430},{4,6,364},{5,5,442},{5,7,270},{5,6,246},{5,6,446},{5,6,470},{7,3,251},{5,6,99},{5,6,299},{5,5,426},{6,5,251},{5,5,426},{5,6,225},{5,6,225},{5,6,225},{5,6,249},{5,6,54},{5,6,78},{5,6,78}, +{5,5,69},{4,6,75},{5,5,81},{5,6,221},{5,6,221},{5,6,221},{5,6,245},{5,6,50},{5,6,74},{5,6,74},{5,5,65},{4,6,50},{5,5,65},{5,7,74},{5,6,50},{5,6,250},{4,6,250},{5,7,74},{5,6,74},{4,6,250},{0,5,410},{5,6,74},{0,5,410},{5,0,200},{5,0,200},{5,0,200},{5,0,200},{5,6,29},{5,6,29},{5,6,29},{5,5,20},{5,5,32}, +{5,5,32},{6,6,724},{6,6,700},{6,6,735},{5,6,690},{5,7,385},{5,6,337},{5,6,177},{5,6,545},{5,6,328},{5,6,488},{6,6,195},{6,6,171},{6,6,206},{6,6,278},{7,4,259},{5,6,216},{5,6,56},{4,6,376},{7,5,259},{4,6,376},{5,7,654},{5,7,654},{5,7,654},{5,6,654},{5,7,189},{5,6,141},{5,6,141},{5,6,509},{5,6,132},{5,5,450},{6,5,157}, +{6,5,157},{6,5,157},{6,5,221},{6,5,52},{5,6,20},{5,6,20},{6,5,256},{3,7,52},{6,5,256},{6,6,74},{6,6,50},{6,6,85},{5,6,40},{6,6,74},{4,7,74},{5,6,40},{0,6,360},{4,7,74},{0,6,360},{5,0,650},{5,0,650},{5,0,650},{5,0,650},{5,6,137},{5,6,137},{5,6,137},{5,6,185},{5,6,128},{5,6,128},{6,7,378},{6,6,316},{6,6,239}, +{6,6,247},{6,6,476},{6,6,396},{6,6,319},{5,6,465},{4,7,332},{5,6,104},{6,7,153},{6,6,91},{6,6,14},{6,6,22},{6,6,251},{5,7,144},{6,6,94},{5,6,104},{4,7,251},{5,6,104},{6,6,235},{6,6,235},{6,6,235},{6,6,243},{6,6,307},{6,6,315},{6,6,315},{5,6,461},{5,6,100},{5,6,100},{6,6,10},{6,6,10},{6,6,10},{6,6,18},{7,4,50}, +{6,6,90},{6,6,90},{5,6,100},{7,5,50},{5,6,100},{7,5,74},{6,6,82},{6,6,5},{6,6,13},{7,5,74},{6,6,90},{6,6,13},{0,6,104},{6,6,90},{0,6,104},{6,0,234},{6,0,234},{6,0,234},{6,0,234},{6,5,241},{6,5,241},{6,5,241},{6,5,289},{5,6,0},{5,6,0},{6,7,154},{6,7,106},{6,6,255},{6,6,199},{6,7,325},{6,6,364},{6,6,175}, +{6,6,178},{5,7,292},{5,6,232},{6,7,105},{6,7,57},{6,6,206},{6,6,150},{7,5,251},{5,7,144},{6,6,126},{6,6,129},{5,7,276},{6,6,129},{6,7,90},{6,7,90},{6,7,90},{6,6,99},{6,6,131},{6,6,75},{6,6,75},{6,6,78},{6,6,219},{5,6,132},{6,7,41},{6,7,41},{6,7,41},{6,6,50},{7,5,82},{6,6,26},{6,6,26},{6,6,29},{6,6,50}, +{6,6,29},{6,7,80},{6,7,32},{6,6,181},{6,6,125},{6,7,80},{7,6,80},{6,6,125},{0,6,104},{7,6,80},{0,6,104},{6,0,74},{6,0,74},{6,0,74},{6,0,74},{6,6,50},{6,6,50},{6,6,50},{6,6,74},{5,6,128},{5,6,128},{6,7,442},{6,7,202},{6,7,442},{6,7,490},{6,7,309},{6,7,117},{6,7,357},{6,6,370},{5,7,324},{6,6,394},{6,7,441}, +{6,7,201},{6,7,441},{6,7,489},{7,6,276},{6,7,116},{6,7,356},{6,6,369},{7,6,244},{6,6,369},{6,7,186},{6,7,186},{6,7,186},{6,7,234},{6,7,53},{6,7,101},{6,7,101},{6,6,46},{5,7,68},{6,6,70},{6,7,185},{6,7,185},{6,7,185},{6,7,233},{6,7,52},{6,7,100},{6,7,100},{6,6,45},{5,7,52},{6,6,45},{7,6,80},{6,7,32},{6,7,272}, +{5,7,272},{7,6,80},{6,7,80},{5,7,272},{0,6,360},{6,7,80},{0,6,360},{6,0,170},{6,0,170},{6,0,170},{6,0,170},{6,7,37},{6,7,37},{6,7,37},{6,6,10},{6,6,34},{6,6,34},{7,7,800},{7,7,784},{6,7,802},{6,7,634},{6,7,903},{6,7,279},{6,7,159},{6,7,591},{6,7,332},{6,7,572},{7,7,224},{7,7,208},{7,7,257},{7,7,337},{7,6,339}, +{6,7,179},{6,7,59},{5,7,419},{6,7,251},{5,7,419},{7,6,745},{7,6,745},{7,6,745},{6,7,585},{6,7,278},{6,7,110},{6,7,110},{6,6,469},{6,7,163},{6,6,385},{7,6,169},{7,6,169},{7,6,169},{7,6,225},{7,6,50},{6,7,10},{6,7,10},{7,6,226},{7,6,82},{7,6,226},{7,7,80},{7,7,64},{7,7,113},{6,7,50},{7,7,80},{7,7,144},{6,7,50}, +{0,7,410},{7,7,144},{0,7,410},{6,0,584},{6,0,584},{6,0,584},{6,0,584},{6,7,109},{6,7,109},{6,7,109},{6,7,181},{6,6,160},{6,6,160},{7,7,393},{7,7,321},{7,7,272},{7,7,288},{7,7,477},{7,7,421},{7,7,372},{6,7,446},{6,7,483},{6,7,123},{7,7,137},{7,7,65},{7,7,16},{7,7,32},{7,7,221},{7,7,165},{7,7,116},{6,7,122},{7,7,261}, +{6,7,122},{7,7,272},{7,7,272},{7,7,272},{7,7,288},{7,7,356},{7,7,372},{7,7,372},{6,7,446},{6,7,83},{6,7,123},{7,7,16},{7,7,16},{7,7,16},{7,7,32},{7,7,100},{7,7,116},{7,7,116},{6,7,122},{6,7,82},{6,7,122},{7,7,121},{7,7,49},{7,7,0},{7,7,16},{7,7,121},{7,7,65},{7,7,16},{0,7,121},{7,7,65},{0,7,121},{7,0,272}, +{7,0,272},{7,0,272},{7,0,272},{7,6,265},{7,6,265},{7,6,265},{7,6,305},{6,7,2},{6,7,2},{7,7,265},{7,7,193},{7,7,144},{7,7,96},{7,7,253},{7,7,133},{7,7,84},{7,7,109},{7,7,297},{6,7,107},{7,7,201},{7,7,129},{7,7,80},{7,7,32},{7,7,189},{7,7,69},{7,7,20},{7,7,45},{7,7,101},{7,7,45},{7,7,144},{7,7,144},{7,7,144}, +{7,7,96},{7,7,132},{7,7,84},{7,7,84},{7,7,109},{7,7,248},{6,7,107},{7,7,80},{7,7,80},{7,7,80},{7,7,32},{7,7,68},{7,7,20},{7,7,20},{7,7,45},{7,7,52},{7,7,45},{7,7,185},{7,7,113},{7,7,64},{7,7,16},{7,7,185},{7,7,65},{7,7,16},{0,7,9},{7,7,65},{0,7,9},{7,0,80},{7,0,80},{7,0,80},{7,0,80},{7,7,68}, +{7,7,68},{7,7,68},{7,7,100},{6,7,98},{6,7,98},{7,7,386},{7,7,314},{7,7,265},{7,7,193},{7,7,278},{7,7,134},{7,7,85},{7,7,4},{7,7,138},{7,7,40},{7,7,386},{7,7,314},{7,7,265},{7,7,193},{7,7,278},{7,7,134},{7,7,85},{7,7,4},{7,7,102},{7,7,4},{7,7,265},{7,7,265},{7,7,265},{7,7,193},{7,7,157},{7,7,85},{7,7,85}, +{7,7,4},{7,7,89},{7,7,40},{7,7,265},{7,7,265},{7,7,265},{7,7,193},{7,7,157},{7,7,85},{7,7,85},{7,7,4},{7,7,53},{7,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,144},{7,0,144},{7,0,144},{7,0,144},{7,7,36},{7,7,36},{7,7,36},{7,7,4},{7,7,40}, +{7,7,40},{0,1,200},{0,1,104},{0,0,153},{0,0,145},{0,1,561},{0,0,398},{0,0,181},{0,0,308},{0,0,498},{0,0,344},{0,1,200},{0,1,104},{0,0,153},{0,0,145},{0,1,561},{0,0,398},{0,0,181},{0,0,308},{0,0,462},{0,0,308},{0,0,9},{0,0,9},{0,0,9},{0,0,1},{0,0,45},{0,0,37},{0,0,37},{0,0,164},{0,0,137},{0,0,200},{0,0,9}, +{0,0,9},{0,0,9},{0,0,1},{0,0,45},{0,0,37},{0,0,37},{0,0,164},{0,0,101},{0,0,164},{0,1,200},{0,1,104},{0,0,153},{0,0,145},{0,1,200},{1,0,232},{0,0,145},{0,0,208},{1,0,232},{0,0,208},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,2,232},{0,1,40},{0,1,200}, +{0,1,392},{0,1,689},{0,1,593},{0,0,485},{0,0,500},{0,0,914},{0,0,536},{0,2,232},{0,1,40},{0,1,200},{0,1,392},{0,1,689},{0,1,593},{0,0,485},{0,0,500},{1,0,761},{0,0,500},{0,1,4},{0,1,4},{0,1,4},{0,0,49},{0,0,157},{0,0,85},{0,0,85},{0,0,100},{0,0,185},{0,0,136},{0,1,4},{0,1,4},{0,1,4},{0,0,49},{0,0,157}, +{0,0,85},{0,0,85},{0,0,100},{0,0,149},{0,0,100},{1,0,200},{0,1,40},{0,1,200},{0,1,392},{1,0,200},{1,0,232},{0,1,392},{0,0,400},{1,0,232},{0,0,400},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,2,281},{0,2,149},{0,1,121},{0,1,121},{0,2,808},{0,1,376},{0,1,216}, +{0,0,857},{0,1,1169},{0,0,893},{0,2,281},{0,2,149},{0,1,121},{0,1,121},{1,0,728},{0,1,376},{0,1,216},{0,0,857},{1,0,744},{0,0,857},{0,1,85},{0,1,85},{0,1,85},{0,1,85},{0,1,180},{0,1,180},{0,1,180},{0,0,73},{0,0,270},{0,0,109},{0,1,85},{0,1,85},{0,1,85},{0,1,85},{0,1,180},{0,1,180},{0,1,180},{0,0,73},{0,0,234}, +{0,0,73},{0,2,232},{0,2,100},{0,1,72},{0,1,72},{0,2,232},{2,0,202},{0,1,72},{0,1,712},{2,0,202},{0,1,712},{0,0,49},{0,0,49},{0,0,49},{0,0,49},{0,0,1},{0,0,1},{0,0,1},{0,0,9},{0,0,45},{0,0,45},{0,3,427},{0,2,229},{0,1,425},{0,1,233},{0,2,744},{0,1,504},{0,1,24},{0,1,584},{0,1,1105},{0,1,945},{0,3,427}, +{0,2,229},{1,1,414},{0,1,233},{0,2,744},{0,1,504},{0,1,24},{0,1,584},{2,0,739},{0,1,584},{0,2,229},{0,2,229},{0,2,229},{0,1,229},{0,1,212},{0,1,20},{0,1,20},{0,0,281},{0,0,590},{0,0,317},{0,2,229},{0,2,229},{0,2,229},{0,1,229},{1,0,180},{0,1,20},{0,1,20},{0,0,281},{1,0,164},{0,0,281},{0,3,202},{0,2,4},{1,1,53}, +{0,1,8},{0,3,202},{1,1,202},{0,1,8},{0,1,328},{1,1,202},{0,1,328},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,1,16},{0,1,16},{0,1,16},{0,0,25},{0,0,61},{0,0,61},{0,4,842},{0,3,740},{1,1,1125},{0,1,834},{0,3,744},{0,2,267},{0,1,283},{0,1,267},{0,1,1356},{0,1,476},{1,2,302},{1,2,230},{1,1,225},{1,1,225},{0,3,728}, +{0,2,251},{0,1,267},{0,1,251},{1,1,728},{0,1,251},{0,3,596},{0,3,596},{0,3,596},{0,1,713},{0,2,186},{0,1,162},{0,1,162},{0,1,146},{0,1,395},{0,1,355},{1,1,104},{1,1,104},{1,1,104},{1,1,104},{0,2,170},{0,1,146},{0,1,146},{0,1,130},{0,1,170},{0,1,130},{1,2,202},{1,2,130},{1,1,125},{1,1,125},{1,2,202},{0,2,202},{1,1,125}, +{0,1,202},{0,2,202},{0,1,202},{0,0,592},{0,0,592},{0,0,592},{0,0,592},{0,1,41},{0,1,41},{0,1,41},{0,1,65},{0,0,200},{0,0,200},{1,3,738},{1,2,522},{1,2,722},{1,1,885},{0,4,987},{0,2,443},{0,2,379},{0,1,507},{0,2,1100},{0,1,412},{1,3,254},{1,2,38},{1,2,238},{1,1,401},{1,2,739},{0,2,299},{0,2,235},{0,1,363},{0,2,739}, +{0,1,363},{1,2,497},{1,2,497},{1,2,497},{1,1,524},{0,3,324},{0,2,154},{0,2,154},{0,1,146},{0,1,411},{0,1,51},{1,2,13},{1,2,13},{1,2,13},{1,1,40},{1,1,164},{0,2,10},{0,2,10},{0,1,2},{1,1,180},{0,1,2},{2,1,202},{1,2,34},{1,2,234},{0,2,234},{2,1,202},{4,0,202},{0,2,234},{0,1,362},{4,0,202},{0,1,362},{1,0,488}, +{1,0,488},{1,0,488},{1,0,488},{0,2,145},{0,2,145},{0,2,145},{0,1,145},{0,1,50},{0,1,50},{1,3,450},{1,3,362},{1,2,306},{1,2,330},{1,2,1015},{1,2,583},{1,2,463},{1,1,990},{0,2,940},{0,1,860},{1,3,254},{1,3,166},{1,2,110},{1,2,134},{0,4,731},{0,3,288},{0,2,155},{1,1,794},{2,1,731},{1,1,794},{1,2,257},{1,2,257},{1,2,257}, +{1,2,281},{1,2,390},{1,1,392},{1,1,392},{1,1,261},{0,2,315},{0,1,131},{1,2,61},{1,2,61},{1,2,61},{1,2,85},{2,0,164},{0,2,106},{0,2,106},{1,1,65},{3,0,164},{1,1,65},{3,0,208},{1,3,130},{1,2,74},{0,2,74},{3,0,208},{3,1,208},{0,2,74},{0,1,778},{3,1,208},{0,1,778},{1,0,232},{1,0,232},{1,0,232},{1,0,232},{1,1,196}, +{1,1,196},{1,1,196},{1,1,212},{0,1,82},{0,1,82},{1,4,440},{1,3,234},{1,2,402},{1,2,234},{1,3,767},{1,2,503},{1,2,63},{1,2,687},{0,3,1140},{0,2,396},{1,4,404},{1,3,198},{1,2,366},{1,2,198},{1,3,731},{0,3,224},{1,2,27},{0,2,387},{1,2,731},{0,2,387},{1,3,233},{1,3,233},{1,3,233},{1,2,233},{1,2,230},{1,2,62},{1,2,62}, +{1,1,277},{0,2,203},{1,1,385},{1,3,197},{1,3,197},{1,3,197},{1,2,197},{0,4,162},{1,2,26},{1,2,26},{1,1,241},{2,1,162},{1,1,241},{2,2,208},{1,3,2},{2,2,65},{1,2,2},{2,2,208},{5,0,208},{1,2,2},{0,2,362},{5,0,208},{0,2,362},{1,0,232},{1,0,232},{1,0,232},{1,0,232},{1,2,61},{1,2,61},{1,2,61},{1,1,52},{0,2,34}, +{0,2,34},{1,5,810},{1,3,702},{1,2,1122},{1,2,738},{1,4,748},{1,3,281},{1,2,225},{1,2,273},{0,3,780},{0,2,252},{2,3,329},{2,3,281},{2,2,222},{2,2,230},{2,2,731},{1,3,272},{1,2,216},{0,2,216},{5,0,731},{0,2,216},{1,4,547},{1,4,547},{1,4,547},{1,2,638},{1,3,173},{1,2,125},{1,2,125},{1,2,173},{0,3,339},{0,2,152},{2,2,122}, +{2,2,122},{2,2,122},{2,2,130},{1,3,164},{1,2,116},{1,2,116},{0,2,116},{1,2,164},{0,2,116},{2,3,208},{2,3,160},{2,2,101},{2,2,109},{2,3,208},{6,0,208},{2,2,109},{0,2,200},{6,0,208},{0,2,200},{1,0,538},{1,0,538},{1,0,538},{1,0,538},{1,2,25},{1,2,25},{1,2,25},{1,2,73},{0,2,52},{0,2,52},{2,3,810},{2,3,570},{2,3,810}, +{2,2,887},{1,4,940},{1,3,393},{1,3,393},{1,2,449},{0,3,1004},{1,2,392},{2,3,281},{2,3,41},{2,3,281},{2,2,358},{3,1,731},{1,3,272},{1,3,272},{1,2,328},{4,1,731},{1,2,328},{2,3,554},{2,3,554},{2,3,554},{2,2,563},{1,4,315},{1,3,137},{1,3,137},{1,2,125},{0,3,163},{1,2,68},{2,3,25},{2,3,25},{2,3,25},{2,2,34},{2,2,162}, +{1,3,16},{1,3,16},{1,2,4},{5,0,162},{1,2,4},{4,0,208},{2,3,32},{2,3,272},{1,3,272},{4,0,208},{5,1,208},{1,3,272},{0,2,328},{5,1,208},{0,2,328},{2,0,538},{2,0,538},{2,0,538},{2,0,538},{1,3,121},{1,3,121},{1,3,121},{1,2,121},{1,2,64},{1,2,64},{2,4,458},{2,3,410},{2,3,330},{2,3,378},{2,3,1013},{2,3,629},{1,3,505}, +{2,2,962},{0,4,772},{1,2,776},{2,4,233},{2,3,185},{2,3,105},{2,3,153},{4,0,724},{1,4,323},{1,3,144},{2,2,737},{3,2,724},{2,2,737},{2,3,266},{2,3,266},{2,3,266},{2,3,314},{2,3,437},{2,2,395},{2,2,395},{2,2,286},{1,3,356},{1,2,100},{2,3,41},{2,3,41},{2,3,41},{2,3,89},{3,1,162},{1,3,80},{1,3,80},{2,2,61},{4,1,162}, +{2,2,61},{2,4,208},{2,3,160},{2,3,80},{1,3,80},{2,4,208},{7,0,208},{1,3,80},{0,2,712},{7,0,208},{0,2,712},{2,0,250},{2,0,250},{2,0,250},{2,0,250},{2,2,226},{2,2,226},{2,2,226},{2,2,250},{1,2,64},{1,2,64},{2,5,436},{2,4,222},{2,3,362},{2,3,218},{2,4,773},{2,3,485},{2,3,85},{2,3,773},{0,4,804},{1,3,452},{2,5,387}, +{2,4,173},{2,3,313},{2,3,169},{2,4,724},{1,4,211},{2,3,36},{1,3,436},{7,0,724},{1,3,436},{2,4,218},{2,4,218},{2,4,218},{2,3,218},{2,3,229},{2,3,85},{2,3,85},{2,2,254},{1,3,196},{2,2,374},{2,4,169},{2,4,169},{2,4,169},{2,3,169},{4,0,164},{2,3,36},{2,3,36},{2,2,205},{3,2,164},{2,2,205},{3,3,202},{2,4,4},{3,3,81}, +{2,3,0},{3,3,202},{6,1,202},{2,3,0},{0,3,400},{6,1,202},{0,3,400},{2,0,218},{2,0,218},{2,0,218},{2,0,218},{2,3,85},{2,3,85},{2,3,85},{2,2,58},{1,3,52},{1,3,52},{2,5,760},{2,4,618},{2,3,1010},{2,3,650},{2,5,760},{2,4,303},{2,3,175},{2,3,287},{1,4,788},{1,3,236},{3,4,362},{3,4,338},{3,3,225},{3,3,241},{3,3,724}, +{2,4,299},{2,3,171},{1,3,211},{6,1,724},{1,3,211},{2,5,504},{2,5,504},{2,5,504},{2,3,569},{2,4,166},{2,3,94},{2,3,94},{2,3,206},{0,4,363},{1,3,155},{3,3,144},{3,3,144},{3,3,144},{3,3,160},{2,4,162},{2,3,90},{2,3,90},{1,3,130},{7,0,162},{1,3,130},{4,2,208},{2,4,130},{3,3,81},{3,3,97},{4,2,208},{5,2,208},{3,3,97}, +{0,3,202},{5,2,208},{0,3,202},{2,0,488},{2,0,488},{2,0,488},{2,0,488},{2,3,13},{2,3,13},{2,3,13},{2,3,85},{1,3,34},{1,3,34},{3,4,842},{3,4,626},{3,4,906},{3,3,897},{2,5,888},{2,4,351},{2,4,415},{2,3,399},{0,5,788},{2,3,380},{3,4,266},{3,4,50},{3,4,330},{3,3,321},{4,2,724},{2,4,251},{2,4,315},{2,3,299},{5,2,724}, +{2,3,299},{3,4,617},{3,4,617},{3,4,617},{3,3,608},{2,5,312},{2,4,126},{2,4,126},{2,3,110},{1,4,164},{2,3,91},{3,4,41},{3,4,41},{3,4,41},{3,3,32},{3,3,164},{2,4,26},{2,4,26},{2,3,10},{6,1,164},{2,3,10},{5,1,202},{3,4,34},{3,4,314},{3,3,305},{5,1,202},{4,3,202},{3,3,305},{0,3,298},{4,3,202},{0,3,298},{3,0,592}, +{3,0,592},{3,0,592},{3,0,592},{2,4,101},{2,4,101},{2,4,101},{2,3,101},{2,3,82},{2,3,82},{3,5,474},{3,4,402},{3,4,362},{3,4,434},{3,4,1019},{3,4,683},{2,4,463},{3,3,942},{1,5,804},{2,3,700},{3,5,218},{3,4,146},{3,4,106},{3,4,178},{5,1,723},{2,5,364},{2,4,139},{3,3,686},{4,3,723},{3,3,686},{3,4,281},{3,4,281},{3,4,281}, +{3,4,353},{3,4,490},{2,4,382},{2,4,382},{3,3,317},{1,4,324},{2,3,75},{3,4,25},{3,4,25},{3,4,25},{3,4,97},{4,2,164},{2,4,58},{2,4,58},{3,3,61},{5,2,164},{3,3,61},{6,0,202},{3,4,130},{3,4,90},{2,4,90},{6,0,202},{3,4,202},{2,4,90},{0,3,650},{3,4,202},{0,3,650},{3,0,272},{3,0,272},{3,0,272},{3,0,272},{3,3,260}, +{3,3,260},{3,3,260},{3,3,292},{2,3,50},{2,3,50},{3,6,440},{3,5,218},{3,4,330},{3,4,210},{3,5,787},{3,4,475},{3,4,115},{3,4,867},{1,5,772},{2,4,516},{3,6,376},{3,5,154},{3,4,266},{3,4,146},{6,0,723},{2,5,204},{3,4,51},{1,4,478},{3,4,723},{1,4,478},{3,5,209},{3,5,209},{3,5,209},{3,4,209},{3,4,234},{3,4,114},{3,4,114}, +{3,3,237},{2,4,195},{3,3,369},{3,5,145},{3,5,145},{3,5,145},{3,4,145},{5,1,170},{3,4,50},{3,4,50},{3,3,173},{7,1,170},{3,3,173},{4,4,200},{3,5,10},{4,4,101},{3,4,2},{4,4,200},{7,2,200},{3,4,2},{0,4,442},{7,2,200},{0,4,442},{3,0,208},{3,0,208},{3,0,208},{3,0,208},{3,3,100},{3,3,100},{3,3,100},{3,3,68},{2,4,74}, +{2,4,74},{3,6,692},{3,5,542},{3,4,906},{3,4,570},{3,6,780},{3,5,333},{3,4,133},{3,4,309},{2,5,804},{2,4,228},{4,5,401},{4,4,395},{4,4,234},{4,4,258},{4,4,723},{3,5,332},{3,4,132},{2,4,212},{7,2,723},{2,4,212},{3,6,467},{3,6,467},{3,6,467},{3,4,506},{3,5,165},{3,4,69},{3,4,69},{3,4,245},{1,5,324},{2,4,164},{4,4,170}, +{4,4,170},{4,4,170},{4,4,194},{6,0,164},{3,4,68},{3,4,68},{2,4,148},{3,4,164},{2,4,148},{5,3,202},{3,5,100},{4,4,65},{4,4,89},{5,3,202},{6,3,202},{4,4,89},{0,4,208},{6,3,202},{0,4,208},{3,0,442},{3,0,442},{3,0,442},{3,0,442},{3,4,5},{3,4,5},{3,4,5},{3,4,101},{2,4,20},{2,4,20},{4,5,882},{4,5,690},{4,4,955}, +{4,4,915},{3,6,844},{3,5,317},{3,5,445},{3,4,357},{1,6,772},{3,4,376},{4,5,257},{4,5,65},{4,4,330},{4,4,290},{5,3,723},{3,5,236},{3,5,364},{3,4,276},{6,3,723},{3,4,276},{4,5,686},{4,5,686},{4,5,686},{4,4,659},{3,6,315},{3,5,121},{3,5,121},{3,4,101},{2,5,171},{3,4,120},{4,5,61},{4,5,61},{4,5,61},{4,4,34},{5,2,170}, +{3,5,40},{3,5,40},{3,4,20},{7,2,170},{3,4,20},{6,2,200},{4,5,40},{4,4,305},{4,4,265},{6,2,200},{5,4,200},{4,4,265},{0,4,272},{5,4,200},{0,4,272},{4,0,650},{4,0,650},{4,0,650},{4,0,650},{3,5,85},{3,5,85},{3,5,85},{3,4,85},{3,4,104},{3,4,104},{4,6,498},{4,5,402},{4,5,402},{4,5,498},{3,7,1017},{3,6,700},{3,5,429}, +{3,4,917},{2,6,844},{3,4,632},{4,6,209},{4,5,113},{4,5,113},{4,5,209},{6,2,728},{3,6,411},{3,5,140},{3,4,628},{5,4,728},{3,4,628},{4,5,302},{4,5,302},{4,5,302},{4,5,398},{3,6,459},{3,5,329},{3,5,329},{3,4,341},{2,5,283},{3,4,56},{4,5,13},{4,5,13},{4,5,13},{4,5,109},{6,1,170},{3,5,40},{3,5,40},{3,4,52},{6,3,170}, +{3,4,52},{7,1,200},{4,5,104},{4,5,104},{3,5,104},{7,1,200},{4,5,200},{3,5,104},{0,4,592},{4,5,200},{0,4,592},{4,0,298},{4,0,298},{4,0,298},{4,0,298},{4,4,298},{4,4,298},{4,4,298},{3,4,325},{3,4,40},{3,4,40},{4,7,452},{4,6,222},{4,5,306},{4,5,210},{4,6,809},{4,5,473},{4,5,153},{4,5,969},{2,6,748},{3,5,588},{4,7,371}, +{4,6,141},{4,5,225},{4,5,129},{7,1,728},{3,6,203},{4,5,72},{2,5,513},{4,5,728},{2,5,513},{4,6,206},{4,6,206},{4,6,206},{4,5,206},{4,5,245},{4,5,149},{4,5,149},{4,4,226},{3,5,200},{4,4,370},{4,6,125},{4,6,125},{4,6,125},{4,5,125},{7,0,164},{4,5,68},{4,5,68},{4,4,145},{3,5,164},{4,4,145},{5,5,202},{4,6,20},{4,5,104}, +{4,5,8},{5,5,202},{3,6,202},{4,5,8},{0,5,488},{3,6,202},{0,5,488},{4,0,202},{4,0,202},{4,0,202},{4,0,202},{4,4,106},{4,4,106},{4,4,106},{4,4,82},{3,5,100},{3,5,100},{4,7,632},{4,6,474},{4,5,810},{4,5,498},{4,7,808},{4,6,371},{4,5,99},{4,5,339},{3,6,828},{3,5,228},{5,6,446},{5,5,396},{5,5,249},{5,5,281},{5,5,728}, +{4,6,371},{4,5,99},{3,5,219},{3,6,728},{3,5,219},{4,7,436},{4,7,436},{4,7,436},{4,5,449},{4,6,170},{4,5,50},{4,5,50},{4,5,290},{2,6,291},{3,5,179},{5,5,200},{5,5,200},{5,5,200},{5,5,232},{7,1,170},{4,5,50},{4,5,50},{3,5,170},{7,3,170},{3,5,170},{6,4,200},{4,6,74},{5,5,53},{5,5,85},{6,4,200},{7,4,200},{5,5,85}, +{0,5,218},{7,4,200},{0,5,218},{4,0,400},{4,0,400},{4,0,400},{4,0,400},{4,5,1},{4,5,1},{4,5,1},{4,4,100},{3,5,10},{3,5,10},{5,6,930},{5,6,762},{5,5,973},{5,5,941},{4,7,808},{4,6,291},{4,6,483},{4,5,323},{2,7,764},{4,5,380},{5,6,254},{5,6,86},{5,5,297},{5,5,265},{6,4,728},{4,6,227},{5,5,373},{4,5,259},{7,4,728}, +{4,5,259},{5,5,748},{5,5,748},{5,5,748},{5,5,716},{4,6,298},{4,6,122},{4,6,122},{4,5,98},{3,6,184},{4,5,155},{5,5,72},{5,5,72},{5,5,72},{5,5,40},{6,3,164},{4,6,58},{4,6,58},{4,5,34},{6,4,164},{4,5,34},{7,3,202},{5,6,50},{5,5,261},{5,5,229},{7,3,202},{6,5,202},{5,5,229},{0,5,250},{6,5,202},{0,5,250},{5,0,712}, +{5,0,712},{5,0,712},{5,0,712},{4,6,73},{4,6,73},{4,6,73},{4,5,73},{4,5,130},{4,5,130},{5,7,530},{5,6,410},{5,6,450},{5,6,570},{5,6,1055},{4,7,720},{4,6,403},{4,5,819},{3,7,892},{4,5,572},{5,7,206},{5,6,86},{5,6,126},{5,6,246},{5,6,731},{3,7,387},{4,6,147},{4,5,563},{4,6,731},{4,5,563},{5,6,329},{5,6,329},{5,6,329}, +{5,5,428},{4,7,420},{4,6,282},{4,6,282},{4,5,290},{3,6,248},{4,5,43},{5,6,5},{5,6,5},{5,6,5},{5,5,104},{7,2,164},{4,6,26},{4,6,26},{4,5,34},{5,5,164},{4,5,34},{5,7,202},{5,6,82},{5,6,122},{4,6,122},{5,7,202},{5,6,202},{4,6,122},{0,5,538},{5,6,202},{0,5,538},{5,0,328},{5,0,328},{5,0,328},{5,0,328},{4,6,281}, +{4,6,281},{4,6,281},{4,5,281},{4,5,34},{4,5,34},{5,7,498},{5,7,234},{5,6,290},{5,6,218},{5,7,839},{5,6,479},{5,6,199},{5,6,1079},{3,7,732},{4,6,668},{5,7,398},{5,7,134},{5,6,190},{5,6,118},{6,5,731},{4,7,208},{5,6,99},{3,6,554},{3,7,731},{3,6,554},{5,7,209},{5,7,209},{5,7,209},{5,6,209},{5,6,262},{5,6,190},{5,6,190}, +{5,5,221},{4,6,211},{4,5,315},{5,7,109},{5,7,109},{5,7,109},{5,6,109},{5,6,162},{5,6,90},{5,6,90},{5,5,121},{4,6,162},{5,5,121},{7,4,208},{5,7,34},{5,6,90},{5,6,18},{7,4,208},{7,5,208},{5,6,18},{0,6,538},{7,5,208},{0,6,538},{5,0,200},{5,0,200},{5,0,200},{5,0,200},{5,5,116},{5,5,116},{5,5,116},{5,5,100},{4,6,130}, +{4,6,130},{5,7,1074},{5,7,414},{5,6,722},{5,6,434},{5,7,857},{5,7,417},{5,6,73},{5,6,377},{4,7,860},{4,6,236},{6,7,497},{6,6,403},{6,6,270},{6,6,310},{7,4,731},{4,7,379},{5,6,72},{4,6,232},{7,5,731},{4,6,232},{5,7,398},{5,7,398},{5,7,398},{5,6,398},{5,7,181},{5,6,37},{5,6,37},{5,6,341},{3,7,264},{4,6,200},{6,6,234}, +{6,6,234},{6,6,234},{6,6,274},{6,5,164},{5,6,36},{5,6,36},{4,6,196},{3,7,164},{4,6,196},{7,5,202},{5,7,52},{6,6,45},{5,6,72},{7,5,202},{6,6,218},{5,6,72},{0,6,232},{6,6,218},{0,6,232},{5,0,362},{5,0,362},{5,0,362},{5,0,362},{5,6,1},{5,6,1},{5,6,1},{5,5,82},{4,6,4},{4,6,4},{6,7,986},{6,7,842},{6,6,999}, +{6,6,975},{5,7,1417},{5,7,273},{5,6,505},{5,6,297},{4,7,828},{5,6,392},{6,7,257},{6,7,113},{6,6,270},{6,6,246},{7,5,739},{5,7,224},{6,6,366},{5,6,248},{6,6,731},{5,6,248},{6,6,803},{6,6,803},{6,6,803},{6,6,779},{5,7,261},{5,7,129},{5,7,129},{5,6,101},{4,7,203},{5,6,196},{6,6,74},{6,6,74},{6,6,74},{6,6,50},{7,4,162}, +{5,7,80},{5,7,80},{5,6,52},{7,5,162},{5,6,52},{6,7,208},{6,7,64},{6,6,221},{6,6,197},{6,7,208},{7,6,208},{6,6,197},{0,6,232},{7,6,208},{0,6,232},{5,0,778},{5,0,778},{5,0,778},{5,0,778},{5,7,65},{5,7,65},{5,7,65},{5,6,65},{5,6,160},{5,6,160},{6,7,762},{6,7,426},{6,7,506},{6,7,650},{6,7,1085},{5,7,641},{5,7,385}, +{5,6,729},{5,7,980},{5,6,520},{6,7,401},{6,7,65},{6,7,145},{6,7,289},{6,7,724},{5,7,416},{5,7,160},{5,6,504},{5,7,724},{5,6,504},{6,7,362},{6,7,362},{6,7,362},{6,6,443},{6,6,555},{5,7,241},{5,7,241},{5,6,245},{4,7,219},{5,6,36},{6,7,1},{6,7,1},{6,7,1},{6,6,82},{7,5,194},{5,7,16},{5,7,16},{5,6,20},{6,6,162}, +{5,6,20},{7,6,208},{6,7,64},{6,7,144},{5,7,144},{7,6,208},{6,7,208},{5,7,144},{0,6,488},{6,7,208},{0,6,488},{6,0,362},{6,0,362},{6,0,362},{6,0,362},{5,7,241},{5,7,241},{5,7,241},{5,6,241},{5,6,32},{5,6,32},{6,7,1050},{6,7,522},{6,7,282},{6,7,234},{6,7,1069},{6,7,493},{6,7,253},{6,6,1122},{5,7,1012},{5,7,756},{7,7,843}, +{6,7,401},{6,7,161},{6,7,113},{7,6,724},{6,7,372},{6,7,132},{4,7,601},{6,7,756},{4,7,601},{6,7,266},{6,7,266},{6,7,266},{6,7,218},{6,7,285},{6,7,237},{6,7,237},{6,6,222},{5,7,228},{5,6,260},{6,7,145},{6,7,145},{6,7,145},{6,7,97},{6,7,164},{6,7,116},{6,7,116},{6,6,101},{5,7,164},{6,6,101},{7,7,218},{7,7,178},{6,7,80}, +{6,7,32},{7,7,218},{6,7,272},{6,7,32},{0,7,592},{6,7,272},{0,7,592},{6,0,202},{6,0,202},{6,0,202},{6,0,202},{6,6,130},{6,6,130},{6,6,130},{6,6,122},{5,6,160},{5,6,160},{6,7,1641},{6,7,1017},{6,7,617},{6,7,353},{6,7,1318},{6,7,430},{6,7,30},{6,7,398},{6,7,1035},{5,7,227},{7,7,393},{7,7,321},{7,7,272},{7,7,320},{7,7,621}, +{6,7,426},{6,7,26},{5,7,226},{6,7,594},{5,7,226},{6,7,617},{6,7,617},{6,7,617},{6,7,353},{6,7,294},{6,7,30},{6,7,30},{6,7,398},{5,7,291},{5,7,227},{7,7,272},{7,7,272},{7,7,272},{7,7,320},{7,6,162},{6,7,26},{6,7,26},{5,7,226},{7,6,194},{5,7,226},{7,7,137},{7,7,65},{7,7,16},{6,7,25},{7,7,137},{7,7,113},{6,7,25}, +{0,7,225},{7,7,113},{0,7,225},{6,0,328},{6,0,328},{6,0,328},{6,0,328},{6,7,5},{6,7,5},{6,7,5},{6,6,68},{5,7,2},{5,7,2},{7,7,985},{7,7,913},{7,7,864},{7,7,848},{7,7,1117},{6,7,654},{6,7,254},{6,7,110},{6,7,763},{5,7,179},{7,7,201},{7,7,129},{7,7,80},{7,7,64},{7,7,333},{7,7,245},{7,7,196},{6,7,74},{7,7,373}, +{6,7,74},{7,7,864},{7,7,864},{7,7,864},{7,7,848},{6,7,710},{6,7,254},{6,7,254},{6,7,110},{6,7,363},{5,7,179},{7,7,80},{7,7,80},{7,7,80},{7,7,64},{7,7,212},{7,7,196},{7,7,196},{6,7,74},{6,7,194},{6,7,74},{7,7,137},{7,7,65},{7,7,16},{7,7,0},{7,7,137},{7,7,49},{7,7,0},{0,7,49},{7,7,49},{0,7,49},{6,0,712}, +{6,0,712},{6,0,712},{6,0,712},{6,7,85},{6,7,85},{6,7,85},{6,7,61},{5,7,130},{5,7,130},{7,7,642},{7,7,570},{7,7,521},{7,7,449},{7,7,678},{7,7,534},{7,7,485},{6,7,205},{6,7,834},{6,7,34},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,278},{7,7,134},{7,7,85},{6,7,9},{7,7,198},{6,7,9},{7,7,521},{7,7,521},{7,7,521}, +{7,7,449},{7,7,557},{7,7,485},{7,7,485},{6,7,205},{6,7,434},{6,7,34},{7,7,121},{7,7,121},{7,7,121},{7,7,49},{7,7,157},{7,7,85},{7,7,85},{6,7,9},{7,7,149},{6,7,9},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,400},{7,0,400},{7,0,400},{7,0,400},{6,7,421}, +{6,7,421},{6,7,421},{6,7,205},{6,7,34},{6,7,34},{7,7,450},{7,7,378},{7,7,329},{7,7,257},{7,7,390},{7,7,246},{7,7,197},{7,7,148},{7,7,426},{6,7,130},{7,7,306},{7,7,234},{7,7,185},{7,7,113},{7,7,246},{7,7,102},{7,7,53},{7,7,4},{7,7,102},{7,7,4},{7,7,329},{7,7,329},{7,7,329},{7,7,257},{7,7,269},{7,7,197},{7,7,197}, +{7,7,148},{7,7,377},{6,7,130},{7,7,185},{7,7,185},{7,7,185},{7,7,113},{7,7,125},{7,7,53},{7,7,53},{7,7,4},{7,7,53},{7,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,208},{7,0,208},{7,0,208},{7,0,208},{7,7,148},{7,7,148},{7,7,148},{7,7,148},{6,7,130}, +{6,7,130},{0,2,445},{0,1,157},{0,1,117},{0,1,405},{0,1,926},{0,1,806},{0,0,670},{0,0,741},{0,0,1169},{0,0,777},{0,2,445},{0,1,157},{0,1,117},{0,1,405},{0,1,926},{0,1,806},{0,0,670},{0,0,741},{1,0,990},{0,0,741},{0,1,36},{0,1,36},{0,1,36},{0,0,9},{0,0,85},{0,0,45},{0,0,45},{0,0,116},{0,0,145},{0,0,152},{0,1,36}, +{0,1,36},{0,1,36},{0,0,9},{0,0,85},{0,0,45},{0,0,45},{0,0,116},{0,0,109},{0,0,116},{1,0,421},{0,1,157},{0,1,117},{0,1,405},{1,0,421},{0,1,445},{0,1,405},{0,0,641},{0,1,445},{0,0,641},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,2,461},{0,2,109},{0,1,5}, +{0,1,101},{0,1,1326},{0,1,822},{0,1,462},{0,0,1205},{0,1,1783},{0,0,1241},{0,2,461},{0,2,109},{0,1,5},{0,1,101},{1,0,1294},{0,1,822},{0,1,462},{0,0,1205},{1,0,1262},{0,0,1205},{0,1,4},{0,1,4},{0,1,4},{0,1,100},{0,0,261},{0,0,157},{0,0,157},{0,0,116},{0,0,257},{0,0,152},{0,1,4},{0,1,4},{0,1,4},{0,1,100},{0,0,261}, +{0,0,157},{0,0,157},{0,0,116},{0,0,221},{0,0,116},{1,1,461},{0,2,109},{0,1,5},{0,1,101},{1,1,461},{2,0,421},{0,1,101},{0,1,901},{2,0,421},{0,1,901},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,3,430},{0,2,38},{0,1,158},{0,1,62},{0,2,1517},{0,1,989},{0,1,309}, +{0,1,1317},{0,1,1878},{0,1,1678},{0,3,430},{0,2,38},{0,1,158},{0,1,62},{0,2,1517},{0,1,989},{0,1,309},{0,1,1317},{0,1,1517},{0,1,1317},{0,2,13},{0,2,13},{0,2,13},{0,1,13},{0,1,356},{0,1,260},{0,1,260},{0,0,193},{0,0,446},{0,0,229},{0,2,13},{0,2,13},{0,2,13},{0,1,13},{0,1,356},{0,1,260},{0,1,260},{0,0,193},{0,0,410}, +{0,0,193},{0,3,421},{0,2,29},{0,1,149},{0,1,53},{0,3,421},{1,1,421},{0,1,53},{0,1,533},{1,1,421},{0,1,533},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,9},{0,0,49},{0,0,85},{0,0,85},{0,4,602},{0,3,234},{0,2,518},{0,1,382},{0,3,1622},{0,2,825},{0,1,325},{0,1,821},{0,1,2022},{0,1,1182},{0,4,602}, +{0,3,234},{0,2,518},{0,1,382},{1,1,1526},{0,2,825},{0,1,325},{0,1,821},{2,0,1526},{0,1,821},{0,2,157},{0,2,157},{0,2,157},{0,1,157},{0,1,388},{0,1,100},{0,1,100},{0,0,401},{0,0,766},{0,0,437},{0,2,157},{0,2,157},{0,2,157},{0,1,157},{1,0,356},{0,1,100},{0,1,100},{0,0,401},{1,0,340},{0,0,401},{1,2,425},{0,3,113},{1,1,234}, +{0,1,261},{1,2,425},{0,2,425},{0,1,261},{0,1,421},{0,2,425},{0,1,421},{0,0,121},{0,0,121},{0,0,121},{0,0,121},{0,0,25},{0,0,25},{0,0,25},{0,0,1},{0,0,37},{0,0,37},{0,4,845},{0,3,405},{0,2,725},{0,2,549},{0,3,1541},{0,2,654},{0,2,270},{0,1,722},{0,2,2583},{0,1,1083},{1,3,657},{1,2,345},{1,2,345},{0,2,549},{2,0,1517}, +{0,2,654},{0,2,270},{0,1,722},{3,0,1517},{0,1,722},{0,3,404},{0,3,404},{0,3,404},{0,2,449},{0,2,346},{0,2,170},{0,2,170},{0,1,146},{0,1,707},{0,1,507},{1,1,232},{1,1,232},{1,1,232},{1,1,200},{0,2,346},{0,2,170},{0,2,170},{0,1,146},{0,1,346},{0,1,146},{2,1,421},{0,3,5},{1,2,149},{0,2,149},{2,1,421},{4,0,421},{0,2,149}, +{0,1,601},{4,0,421},{0,1,601},{0,0,400},{0,0,400},{0,0,400},{0,0,400},{0,1,1},{0,1,1},{0,1,1},{0,0,100},{0,0,136},{0,0,136},{0,5,1209},{0,4,937},{1,2,1197},{0,2,789},{0,4,1526},{0,3,737},{0,2,14},{0,1,1042},{0,2,2487},{0,1,1403},{1,3,481},{1,3,173},{1,2,41},{1,2,161},{1,2,1526},{0,3,737},{0,2,14},{0,1,1042},{2,1,1526}, +{0,1,1042},{0,4,793},{0,4,793},{0,4,793},{0,2,785},{0,3,356},{0,2,10},{0,2,10},{0,1,18},{0,1,899},{0,1,379},{1,2,37},{1,2,37},{1,2,37},{1,1,136},{1,1,340},{0,2,10},{0,2,10},{0,1,18},{1,1,356},{0,1,18},{3,0,425},{1,3,137},{1,2,5},{0,2,5},{3,0,425},{3,1,425},{0,2,5},{0,2,965},{3,1,425},{0,2,965},{0,0,784}, +{0,0,784},{0,0,784},{0,0,784},{0,2,9},{0,2,9},{0,2,9},{0,1,9},{0,0,360},{0,0,360},{1,4,1158},{1,3,758},{1,2,850},{1,2,778},{0,4,1671},{0,3,546},{0,2,191},{0,2,903},{0,2,2390},{0,2,1430},{1,4,429},{1,3,29},{1,2,121},{1,2,49},{2,1,1526},{0,3,497},{0,2,142},{0,2,854},{4,0,1526},{0,2,854},{1,3,742},{1,3,742},{1,3,742}, +{1,2,742},{0,3,437},{0,2,155},{0,2,155},{0,1,195},{0,2,946},{0,1,290},{1,3,13},{1,3,13},{1,3,13},{1,2,13},{2,0,340},{0,2,106},{0,2,106},{0,1,146},{3,0,340},{0,1,146},{1,4,425},{1,3,25},{1,2,117},{1,2,45},{1,4,425},{2,2,425},{1,2,45},{0,2,565},{2,2,425},{0,2,565},{1,0,733},{1,0,733},{1,0,733},{1,0,733},{0,2,74}, +{0,2,74},{0,2,74},{0,1,74},{0,1,169},{0,1,169},{1,4,966},{1,4,606},{1,3,886},{1,2,682},{0,5,1742},{0,3,866},{0,3,641},{0,2,727},{0,3,2382},{0,2,758},{1,4,605},{1,4,245},{1,3,525},{1,2,321},{3,0,1517},{0,3,641},{1,2,302},{0,2,502},{3,1,1517},{0,2,502},{1,3,486},{1,3,486},{1,3,486},{1,2,486},{0,4,563},{0,3,241},{0,3,241}, +{0,2,531},{0,2,626},{0,1,546},{1,3,125},{1,3,125},{1,3,125},{1,2,125},{0,4,338},{0,3,16},{0,3,16},{0,2,306},{2,1,338},{0,2,306},{3,1,433},{1,4,145},{2,2,212},{1,2,221},{3,1,433},{6,0,433},{1,2,221},{0,2,421},{6,0,433},{0,2,421},{1,0,461},{1,0,461},{1,0,461},{1,0,461},{0,3,225},{0,3,225},{0,3,225},{0,2,306},{0,1,185}, +{0,1,185},{1,5,894},{1,4,462},{1,3,778},{1,3,646},{1,4,1626},{1,3,749},{1,3,429},{1,2,809},{0,3,2022},{0,2,614},{2,4,706},{1,4,362},{2,3,410},{1,3,546},{3,1,1526},{0,4,441},{0,3,227},{0,2,565},{4,1,1526},{0,2,565},{1,4,462},{1,4,462},{1,4,462},{1,3,525},{1,3,440},{1,2,296},{1,2,296},{1,2,280},{0,2,725},{0,2,85},{2,2,250}, +{2,2,250},{2,2,250},{2,2,226},{1,3,340},{0,3,106},{0,3,106},{0,2,36},{1,2,340},{0,2,36},{3,2,425},{1,4,1},{2,3,185},{0,3,146},{3,2,425},{5,1,425},{0,3,146},{0,2,565},{5,1,425},{0,2,565},{1,0,461},{1,0,461},{1,0,461},{1,0,461},{1,2,100},{1,2,100},{1,2,100},{1,1,181},{0,2,49},{0,2,49},{1,6,1166},{1,4,878},{1,3,1226}, +{1,3,742},{1,5,1545},{1,4,798},{1,3,29},{1,2,985},{0,3,2246},{0,2,1030},{2,4,482},{2,4,218},{2,3,58},{2,3,202},{2,3,1517},{0,4,521},{1,3,25},{1,2,981},{6,0,1517},{1,2,981},{1,5,749},{1,5,749},{1,5,749},{1,3,733},{1,4,374},{1,3,20},{1,3,20},{1,2,24},{0,3,482},{0,2,69},{2,3,49},{2,3,49},{2,3,49},{2,2,130},{2,2,338}, +{1,3,16},{1,3,16},{1,2,20},{5,0,338},{1,2,20},{4,1,433},{1,4,145},{2,3,9},{1,3,9},{4,1,433},{7,0,433},{1,3,9},{0,2,965},{7,0,433},{0,2,965},{1,0,733},{1,0,733},{1,0,733},{1,0,733},{1,3,20},{1,3,20},{1,3,20},{1,2,20},{0,2,65},{0,2,65},{2,5,1218},{2,4,810},{2,3,874},{2,3,826},{1,5,1625},{1,4,542},{1,3,141}, +{1,3,961},{0,4,1806},{0,3,642},{2,5,434},{2,4,26},{2,3,90},{2,3,42},{3,2,1517},{1,4,506},{1,3,105},{0,3,626},{5,1,1517},{0,3,626},{2,4,801},{2,4,801},{2,4,801},{2,3,801},{1,4,406},{1,3,116},{1,3,116},{1,2,152},{0,3,482},{1,2,285},{2,4,17},{2,4,17},{2,4,17},{2,3,17},{3,1,338},{1,3,80},{1,3,80},{1,2,116},{4,1,338}, +{1,2,116},{3,3,425},{2,4,25},{2,3,89},{2,3,41},{3,3,425},{6,1,425},{2,3,41},{0,3,601},{6,1,425},{0,3,601},{2,0,785},{2,0,785},{2,0,785},{2,0,785},{1,3,52},{1,3,52},{1,3,52},{1,2,52},{0,3,41},{0,3,41},{2,5,962},{2,4,618},{2,3,906},{2,3,666},{1,6,1710},{1,4,798},{1,4,663},{1,3,721},{0,4,1838},{0,3,450},{2,5,562}, +{2,4,218},{2,3,506},{2,3,266},{4,1,1514},{0,5,474},{2,3,285},{0,3,434},{4,2,1514},{0,3,434},{2,4,497},{2,4,497},{2,4,497},{2,3,497},{1,5,536},{1,4,222},{1,4,222},{1,3,552},{0,4,469},{0,3,281},{2,4,97},{2,4,97},{2,4,97},{2,3,97},{4,0,340},{1,4,26},{1,4,26},{0,3,265},{3,2,340},{0,3,265},{4,2,425},{2,4,137},{3,3,194}, +{2,3,185},{4,2,425},{5,2,425},{2,3,185},{0,3,425},{5,2,425},{0,3,425},{2,0,481},{2,0,481},{2,0,481},{2,0,481},{1,4,197},{1,4,197},{1,4,197},{1,3,296},{0,3,25},{0,3,25},{2,6,870},{2,5,446},{2,4,758},{2,4,670},{2,5,1638},{2,4,771},{2,4,515},{2,3,823},{0,5,1710},{1,3,598},{3,4,737},{2,5,325},{3,4,481},{2,4,549},{5,0,1517}, +{1,5,458},{1,4,224},{1,3,534},{3,3,1517},{1,3,534},{2,5,445},{2,5,445},{2,5,445},{2,4,526},{2,4,459},{2,3,291},{2,3,291},{2,3,339},{0,4,370},{1,3,114},{3,3,272},{3,3,272},{3,3,272},{3,3,256},{2,4,338},{1,4,80},{1,4,80},{1,3,50},{7,0,338},{1,3,50},{5,1,425},{2,5,1},{3,4,225},{1,4,160},{5,1,425},{4,3,425},{1,4,160}, +{0,3,533},{4,3,425},{0,3,533},{2,0,445},{2,0,445},{2,0,445},{2,0,445},{2,3,122},{2,3,122},{2,3,122},{2,2,185},{1,3,65},{1,3,65},{2,7,1130},{2,5,798},{2,4,1142},{2,4,702},{2,6,1571},{2,4,819},{2,4,51},{2,3,935},{0,5,1614},{1,3,950},{3,5,489},{3,5,269},{3,4,81},{3,4,249},{3,4,1514},{1,5,490},{2,4,42},{2,3,926},{7,1,1514}, +{2,3,926},{2,6,710},{2,6,710},{2,6,710},{2,4,686},{2,5,397},{2,4,35},{2,4,35},{2,3,35},{1,4,509},{1,3,50},{3,4,65},{3,4,65},{3,4,65},{3,3,128},{3,3,340},{2,4,26},{2,4,26},{2,3,26},{6,1,340},{2,3,26},{6,0,425},{2,5,113},{3,4,17},{2,4,17},{6,0,425},{3,4,425},{2,4,17},{0,3,901},{3,4,425},{0,3,901},{2,0,685}, +{2,0,685},{2,0,685},{2,0,685},{2,4,34},{2,4,34},{2,4,34},{2,3,34},{1,3,49},{1,3,49},{3,6,1286},{3,5,870},{3,4,906},{3,4,882},{2,6,1587},{2,5,546},{2,4,99},{2,4,1027},{1,5,1838},{1,4,702},{3,6,445},{3,5,29},{3,4,65},{3,4,41},{4,3,1514},{2,5,521},{2,4,74},{1,4,677},{6,2,1514},{1,4,677},{3,5,866},{3,5,866},{3,5,866}, +{3,4,866},{2,5,381},{2,4,83},{2,4,83},{2,3,115},{0,5,349},{2,3,286},{3,5,25},{3,5,25},{3,5,25},{3,4,25},{4,2,340},{2,4,58},{2,4,58},{2,3,90},{5,2,340},{2,3,90},{4,4,421},{3,5,29},{3,4,65},{3,4,41},{4,4,421},{7,2,421},{3,4,41},{0,4,641},{7,2,421},{0,4,641},{3,0,841},{3,0,841},{3,0,841},{3,0,841},{2,4,34}, +{2,4,34},{2,4,34},{2,3,34},{1,4,61},{1,4,61},{3,6,966},{3,5,614},{3,4,874},{3,4,658},{2,7,1686},{2,5,738},{2,4,659},{2,4,723},{0,6,1518},{1,4,446},{3,6,525},{3,5,173},{3,4,433},{3,4,217},{5,2,1517},{1,6,457},{3,4,274},{1,4,437},{5,3,1517},{1,4,437},{3,5,514},{3,5,514},{3,5,514},{3,4,514},{2,6,515},{2,5,209},{2,5,209}, +{2,3,579},{1,5,510},{1,4,302},{3,5,73},{3,5,73},{3,5,73},{3,4,73},{5,1,346},{2,5,40},{2,5,40},{3,3,293},{7,1,346},{3,3,293},{5,3,421},{3,5,109},{4,4,180},{3,4,153},{5,3,421},{6,3,421},{3,4,153},{0,4,433},{6,3,421},{0,4,433},{3,0,505},{3,0,505},{3,0,505},{3,0,505},{2,5,173},{2,5,173},{2,5,173},{2,3,290},{1,4,13}, +{1,4,13},{3,7,854},{3,6,438},{3,5,746},{3,5,702},{3,6,1658},{3,5,801},{3,5,609},{3,4,845},{1,6,1758},{2,4,590},{3,7,710},{3,6,294},{4,5,558},{3,5,558},{6,1,1514},{2,6,481},{2,5,227},{2,4,509},{4,4,1514},{2,4,509},{3,6,434},{3,6,434},{3,6,434},{3,5,533},{3,5,484},{3,4,292},{3,4,292},{3,4,404},{1,5,357},{2,4,149},{3,6,290}, +{3,6,290},{3,6,290},{4,4,290},{6,0,340},{2,5,58},{2,5,58},{2,4,68},{3,4,340},{2,4,68},{6,2,421},{3,6,5},{4,5,269},{2,5,178},{6,2,421},{5,4,421},{2,5,178},{0,4,505},{5,4,421},{0,4,505},{3,0,433},{3,0,433},{3,0,433},{3,0,433},{3,4,148},{3,4,148},{3,4,148},{3,3,193},{2,4,85},{2,4,85},{3,7,1206},{3,6,726},{3,5,1066}, +{3,5,670},{3,7,1605},{3,5,785},{3,5,81},{3,4,893},{1,6,1598},{2,4,878},{4,6,502},{4,5,310},{4,5,110},{4,5,302},{7,0,1517},{2,6,465},{3,5,65},{2,4,877},{3,5,1517},{2,4,877},{3,7,677},{3,7,677},{3,7,677},{3,5,645},{3,6,426},{3,5,56},{3,5,56},{3,4,52},{2,5,542},{2,4,37},{4,5,85},{4,5,85},{4,5,85},{4,4,130},{5,2,346}, +{3,5,40},{3,5,40},{2,4,36},{7,2,346},{2,4,36},{7,1,421},{3,6,85},{4,5,29},{3,5,29},{7,1,421},{4,5,421},{3,5,29},{0,4,841},{4,5,421},{0,4,841},{3,0,641},{3,0,641},{3,0,641},{3,0,641},{3,4,52},{3,4,52},{3,4,52},{3,4,52},{2,4,37},{2,4,37},{4,7,1362},{4,6,938},{4,5,946},{4,5,946},{3,7,1557},{3,6,558},{3,5,65}, +{3,5,1101},{0,7,1662},{2,5,770},{4,7,462},{4,6,38},{4,5,46},{4,5,46},{5,4,1517},{3,6,542},{3,5,49},{1,5,721},{7,3,1517},{1,5,721},{4,5,937},{4,5,937},{4,5,937},{4,5,937},{3,6,362},{3,5,56},{3,5,56},{3,4,84},{1,6,350},{3,4,293},{4,5,37},{4,5,37},{4,5,37},{4,5,37},{6,1,346},{3,5,40},{3,5,40},{3,4,68},{6,3,346}, +{3,4,68},{5,5,421},{4,6,37},{4,5,45},{3,5,45},{5,5,421},{3,6,421},{3,5,45},{0,5,685},{3,6,421},{0,5,685},{4,0,901},{4,0,901},{4,0,901},{4,0,901},{3,5,20},{3,5,20},{3,5,20},{3,4,20},{2,5,85},{2,5,85},{4,7,978},{4,6,618},{4,5,850},{4,5,658},{3,7,2021},{3,6,686},{3,5,561},{3,5,733},{1,7,1530},{2,5,450},{4,7,494}, +{4,6,134},{4,5,366},{4,5,174},{6,3,1526},{2,7,446},{4,5,269},{2,5,446},{6,4,1526},{2,5,446},{4,6,537},{4,6,537},{4,6,537},{4,5,537},{3,7,500},{3,6,202},{3,6,202},{3,4,500},{1,6,510},{2,5,329},{4,6,53},{4,6,53},{4,6,53},{4,5,53},{7,0,340},{3,6,58},{3,6,58},{4,4,265},{3,5,340},{4,4,265},{6,4,421},{4,6,85},{5,5,170}, +{4,5,125},{6,4,421},{7,4,421},{4,5,125},{0,5,445},{7,4,421},{0,5,445},{4,0,533},{4,0,533},{4,0,533},{4,0,533},{3,6,153},{3,6,153},{3,6,153},{3,4,244},{2,5,5},{2,5,5},{4,7,1158},{4,7,438},{4,6,742},{4,6,742},{4,7,1686},{4,6,839},{3,6,677},{4,5,875},{1,7,1710},{3,5,590},{5,6,769},{4,7,269},{4,6,573},{4,6,573},{7,2,1517}, +{3,7,510},{3,6,236},{3,5,490},{5,5,1517},{3,5,490},{4,7,429},{4,7,429},{4,7,429},{4,5,546},{4,6,515},{4,5,299},{4,5,299},{4,5,475},{2,6,350},{3,5,190},{4,7,260},{4,7,260},{4,7,260},{5,5,328},{7,1,346},{3,6,40},{3,6,40},{3,5,90},{7,3,346},{3,5,90},{7,3,421},{4,7,13},{4,6,317},{3,6,200},{7,3,421},{6,5,421},{3,6,200}, +{0,5,481},{6,5,421},{0,5,481},{4,0,425},{4,0,425},{4,0,425},{4,0,425},{4,5,178},{4,5,178},{4,5,178},{4,4,205},{3,5,109},{3,5,109},{4,7,1862},{4,7,662},{4,6,998},{4,6,646},{4,7,1686},{4,6,759},{4,6,119},{4,5,859},{2,7,1590},{3,5,814},{5,7,521},{5,6,305},{5,6,145},{5,6,361},{5,6,1526},{3,7,446},{4,6,94},{3,5,810},{4,6,1526}, +{3,5,810},{4,7,637},{4,7,637},{4,7,637},{4,6,610},{4,6,435},{4,6,83},{4,6,83},{4,5,75},{1,7,565},{3,5,30},{5,6,109},{5,6,109},{5,6,109},{5,5,136},{6,3,340},{4,6,58},{4,6,58},{3,5,26},{6,4,340},{3,5,26},{5,7,421},{4,7,61},{5,6,45},{4,6,45},{5,7,421},{5,6,421},{4,6,45},{0,5,785},{5,6,421},{0,5,785},{4,0,601}, +{4,0,601},{4,0,601},{4,0,601},{4,5,50},{4,5,50},{4,5,50},{4,5,74},{3,5,29},{3,5,29},{5,7,1498},{5,7,1014},{5,6,994},{5,6,1018},{4,7,2198},{4,7,578},{4,6,39},{4,6,1183},{2,7,1878},{3,6,846},{5,7,537},{5,7,53},{5,6,33},{5,6,57},{7,3,1526},{4,7,569},{4,6,30},{2,6,758},{6,5,1526},{2,6,758},{5,6,990},{5,6,990},{5,6,990}, +{5,6,1014},{4,7,349},{4,6,35},{4,6,35},{4,5,59},{2,7,357},{3,5,254},{5,6,29},{5,6,29},{5,6,29},{5,6,53},{7,2,340},{4,6,26},{4,6,26},{4,5,50},{5,5,340},{4,5,50},{6,6,425},{5,7,49},{5,6,29},{4,6,29},{6,6,425},{4,7,425},{4,6,29},{0,6,733},{4,7,425},{0,6,733},{5,0,965},{5,0,965},{5,0,965},{5,0,965},{4,6,10}, +{4,6,10},{4,6,10},{4,5,10},{3,6,113},{3,6,113},{5,7,1466},{5,7,630},{5,6,834},{5,6,666},{5,7,2055},{4,7,642},{4,6,471},{4,6,751},{3,7,1766},{3,6,462},{5,7,937},{5,7,101},{5,6,305},{5,6,137},{5,7,1526},{4,7,521},{5,6,270},{3,6,461},{5,6,1526},{3,6,461},{5,7,566},{5,7,566},{5,7,566},{5,6,566},{4,7,621},{4,7,201},{4,7,201}, +{4,5,427},{2,7,469},{3,6,362},{5,7,37},{5,7,37},{5,7,37},{5,6,37},{5,6,338},{4,7,80},{4,7,80},{5,5,241},{4,6,338},{5,5,241},{7,5,425},{5,7,65},{6,6,164},{5,6,101},{7,5,425},{6,6,433},{5,6,101},{0,6,461},{6,6,433},{0,6,461},{5,0,565},{5,0,565},{5,0,565},{5,0,565},{4,7,137},{4,7,137},{4,7,137},{4,5,202},{3,6,1}, +{3,6,1},{5,7,2042},{5,7,810},{5,7,746},{5,7,790},{5,7,2073},{5,7,885},{4,7,651},{4,6,877},{4,7,2102},{4,6,598},{6,7,794},{6,7,530},{5,7,550},{5,7,594},{6,6,1526},{5,7,689},{4,7,251},{4,6,477},{6,6,1526},{4,6,477},{5,7,521},{5,7,521},{5,7,521},{5,6,521},{5,7,552},{5,6,312},{5,6,312},{4,6,516},{3,7,349},{4,6,237},{5,7,325}, +{5,7,325},{5,7,325},{5,6,325},{6,5,340},{4,7,26},{4,7,26},{4,6,116},{3,7,340},{4,6,116},{6,7,433},{6,7,169},{5,7,325},{4,7,226},{6,7,433},{7,6,425},{4,7,226},{0,6,461},{7,6,425},{0,6,461},{5,0,421},{5,0,421},{5,0,421},{5,0,421},{5,6,212},{5,6,212},{5,6,212},{5,5,221},{4,6,137},{4,6,137},{6,7,2362},{5,7,1514},{5,7,938}, +{5,7,630},{5,7,2633},{5,7,741},{5,7,165},{5,6,833},{4,7,2070},{4,6,758},{6,7,762},{6,7,306},{6,7,186},{6,7,426},{7,5,1526},{5,7,705},{5,7,129},{4,6,749},{5,7,1541},{4,6,749},{5,7,889},{5,7,889},{5,7,889},{5,7,581},{5,7,424},{5,7,116},{5,7,116},{5,6,104},{3,7,525},{4,6,29},{6,7,137},{6,7,137},{6,7,137},{6,6,146},{7,4,338}, +{5,7,80},{5,7,80},{4,6,20},{7,5,338},{4,6,20},{7,6,433},{6,7,185},{6,7,65},{5,7,65},{7,6,433},{6,7,425},{5,7,65},{0,6,733},{6,7,425},{0,6,733},{5,0,565},{5,0,565},{5,0,565},{5,0,565},{5,6,52},{5,6,52},{5,6,52},{5,6,100},{4,6,25},{4,6,25},{6,7,2073},{6,7,1449},{6,7,1049},{5,7,981},{6,7,2548},{5,7,1044},{5,7,20}, +{5,6,1196},{5,7,2365},{4,7,929},{6,7,1049},{6,7,425},{6,7,25},{6,7,73},{7,6,1492},{6,7,948},{5,7,16},{3,7,800},{7,6,1460},{3,7,800},{6,7,1049},{6,7,1049},{6,7,1049},{5,7,981},{5,7,680},{5,7,20},{5,7,20},{5,6,40},{4,7,434},{4,6,205},{6,7,25},{6,7,25},{6,7,25},{6,7,73},{7,5,370},{5,7,16},{5,7,16},{5,6,36},{6,6,338}, +{5,6,36},{7,7,410},{7,7,338},{6,7,16},{5,7,16},{7,7,410},{6,7,464},{5,7,16},{0,7,784},{6,7,464},{0,7,784},{5,0,965},{5,0,965},{5,0,965},{5,0,965},{5,7,4},{5,7,4},{5,7,4},{5,6,4},{4,7,145},{4,7,145},{6,7,1769},{6,7,1145},{6,7,745},{6,7,601},{6,7,1940},{6,7,1172},{5,7,308},{5,7,696},{5,7,1805},{4,7,401},{7,7,1043}, +{6,7,569},{6,7,169},{6,7,25},{7,6,1076},{6,7,596},{6,7,196},{4,7,401},{6,7,1076},{4,7,401},{6,7,745},{6,7,745},{6,7,745},{6,7,601},{6,7,916},{5,7,308},{5,7,308},{5,6,360},{4,7,626},{5,6,341},{6,7,169},{6,7,169},{6,7,169},{6,7,25},{6,7,340},{6,7,196},{6,7,196},{6,6,221},{5,7,340},{6,6,221},{7,7,202},{7,7,130},{7,7,81}, +{6,7,0},{7,7,202},{7,7,218},{6,7,0},{0,7,400},{7,7,218},{0,7,400},{6,0,601},{6,0,601},{6,0,601},{6,0,601},{5,7,164},{5,7,164},{5,7,164},{5,6,164},{4,7,1},{4,7,1},{6,7,1886},{6,7,1262},{6,7,862},{6,7,502},{6,7,1715},{6,7,731},{6,7,331},{5,7,507},{5,7,1634},{4,7,266},{7,7,521},{7,7,449},{7,7,400},{6,7,277},{7,7,797}, +{6,7,506},{6,7,106},{5,7,146},{6,7,770},{5,7,146},{6,7,862},{6,7,862},{6,7,862},{6,7,502},{6,7,691},{6,7,331},{6,7,331},{5,7,507},{5,7,610},{4,7,266},{7,7,400},{7,7,400},{7,7,400},{6,7,277},{7,6,338},{6,7,106},{6,7,106},{5,7,146},{7,6,370},{5,7,146},{7,7,121},{7,7,49},{7,7,0},{7,7,16},{7,7,121},{7,7,65},{7,7,16}, +{0,7,121},{7,7,65},{0,7,121},{6,0,421},{6,0,421},{6,0,421},{6,0,421},{6,7,250},{6,7,250},{6,7,250},{6,6,241},{4,7,145},{4,7,145},{7,7,2010},{6,7,1774},{6,7,1374},{6,7,822},{6,7,1923},{6,7,747},{6,7,347},{6,7,139},{6,7,1446},{5,7,34},{7,7,329},{7,7,257},{7,7,208},{7,7,160},{7,7,509},{7,7,389},{6,7,298},{5,7,18},{7,7,549}, +{5,7,18},{6,7,1374},{6,7,1374},{6,7,1374},{6,7,822},{6,7,899},{6,7,347},{6,7,347},{6,7,139},{5,7,866},{5,7,34},{7,7,208},{7,7,208},{7,7,208},{7,7,160},{7,7,388},{6,7,298},{6,7,298},{5,7,18},{6,7,370},{5,7,18},{7,7,185},{7,7,113},{7,7,64},{7,7,16},{7,7,185},{7,7,65},{7,7,16},{0,7,9},{7,7,65},{0,7,9},{6,0,533}, +{6,0,533},{6,0,533},{6,0,533},{6,7,58},{6,7,58},{6,7,58},{6,7,130},{5,7,25},{5,7,25},{7,7,1347},{7,7,1275},{7,7,1226},{7,7,1154},{7,7,1431},{6,7,922},{6,7,522},{6,7,2},{6,7,1125},{5,7,137},{7,7,258},{7,7,186},{7,7,137},{7,7,65},{7,7,342},{7,7,198},{7,7,149},{6,7,1},{7,7,294},{6,7,1},{7,7,1226},{7,7,1226},{7,7,1226}, +{7,7,1154},{6,7,1146},{6,7,522},{6,7,522},{6,7,2},{6,7,725},{5,7,137},{7,7,137},{7,7,137},{7,7,137},{7,7,65},{7,7,221},{7,7,149},{7,7,149},{6,7,1},{7,7,245},{6,7,1},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,901},{6,0,901},{6,0,901},{6,0,901},{6,7,122}, +{6,7,122},{6,7,122},{6,7,2},{5,7,137},{5,7,137},{7,7,883},{7,7,811},{7,7,762},{7,7,690},{7,7,871},{7,7,727},{7,7,678},{6,7,130},{6,7,949},{6,7,149},{7,7,258},{7,7,186},{7,7,137},{7,7,65},{7,7,246},{7,7,102},{7,7,53},{7,7,36},{7,7,134},{7,7,36},{7,7,762},{7,7,762},{7,7,762},{7,7,690},{7,7,750},{7,7,678},{7,7,678}, +{6,7,130},{6,7,549},{6,7,149},{7,7,137},{7,7,137},{7,7,137},{7,7,65},{7,7,125},{7,7,53},{7,7,53},{7,7,36},{7,7,85},{7,7,36},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{7,0,641},{7,0,641},{7,0,641},{7,0,641},{6,7,442},{6,7,442},{6,7,442},{6,7,130},{6,7,149}, +{6,7,149},{0,3,932},{0,2,218},{0,1,82},{0,1,250},{0,2,1971},{0,1,1371},{0,1,611},{0,0,1950},{0,1,2332},{0,0,1986},{0,3,932},{0,2,218},{0,1,82},{0,1,250},{1,0,1899},{0,1,1371},{0,1,611},{0,0,1950},{1,0,1923},{0,0,1950},{0,1,1},{0,1,1},{0,1,1},{0,0,64},{0,0,180},{0,0,100},{0,0,100},{0,0,101},{0,0,200},{0,0,137},{0,1,1}, +{0,1,1},{0,1,1},{0,0,64},{0,0,180},{0,0,100},{0,0,100},{0,0,101},{0,0,164},{0,0,101},{1,1,884},{0,2,218},{0,1,82},{0,1,250},{1,1,884},{2,0,900},{0,1,250},{0,1,1170},{2,0,900},{0,1,1170},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,3,900},{0,2,250},{0,2,314}, +{0,1,314},{0,2,2355},{0,1,1755},{0,1,675},{0,1,1875},{0,1,2716},{0,1,2236},{0,3,900},{0,2,250},{0,2,314},{0,1,314},{0,2,2355},{0,1,1755},{0,1,675},{0,1,1875},{0,1,2355},{0,1,1875},{0,2,25},{0,2,25},{0,2,25},{0,1,25},{0,1,410},{0,0,292},{0,0,292},{0,0,181},{0,0,392},{0,0,217},{0,2,25},{0,2,25},{0,2,25},{0,1,25},{0,1,410}, +{0,0,292},{0,0,292},{0,0,181},{0,0,356},{0,0,181},{2,0,884},{0,2,250},{0,2,314},{0,1,314},{2,0,884},{3,0,884},{0,1,314},{0,1,914},{3,0,884},{0,1,914},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,4,890},{0,3,104},{0,2,90},{0,2,442},{0,2,2995},{0,2,1851},{0,1,995}, +{0,1,1875},{0,1,3356},{0,1,2236},{0,4,890},{0,3,104},{0,2,90},{0,2,442},{1,1,2932},{0,2,1851},{0,1,995},{0,1,1875},{2,0,2900},{0,1,1875},{0,2,9},{0,2,9},{0,2,9},{0,1,9},{0,1,586},{0,1,370},{0,1,370},{0,0,389},{0,0,712},{0,0,425},{0,2,9},{0,2,9},{0,2,9},{0,1,9},{0,1,586},{0,1,370},{0,1,370},{0,0,389},{1,0,650}, +{0,0,389},{1,2,890},{0,3,104},{0,2,90},{0,2,442},{1,2,890},{2,1,890},{0,2,442},{0,1,914},{2,1,890},{0,1,914},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,4,990},{0,3,140},{0,2,158},{0,2,158},{0,3,3048},{0,2,1707},{0,2,747},{0,1,1795},{0,1,3916},{0,1,2156},{0,4,990}, +{0,3,140},{0,2,158},{0,2,158},{0,3,3048},{0,2,1707},{0,2,747},{0,1,1795},{1,1,3048},{0,1,1795},{0,3,40},{0,3,40},{0,3,40},{0,1,157},{0,1,698},{0,1,290},{0,1,290},{0,0,641},{0,0,1076},{0,0,677},{0,3,40},{0,3,40},{0,3,40},{0,1,157},{1,0,666},{0,1,290},{0,1,290},{0,0,641},{1,0,650},{0,0,641},{2,1,890},{0,3,104},{0,2,122}, +{0,2,122},{2,1,890},{4,0,890},{0,2,122},{0,1,1170},{4,0,890},{0,1,1170},{0,0,36},{0,0,36},{0,0,36},{0,0,36},{0,0,0},{0,0,0},{0,0,0},{0,0,16},{0,0,52},{0,0,52},{0,5,1115},{0,4,265},{0,2,689},{0,2,293},{0,4,3096},{0,3,1731},{0,2,324},{0,1,2020},{0,2,4009},{0,1,2381},{0,5,1115},{0,4,265},{1,2,429},{0,2,293},{1,2,3048}, +{0,3,1731},{0,2,324},{0,1,2020},{0,2,3048},{0,1,2020},{0,4,261},{0,4,261},{0,4,261},{0,2,229},{0,2,656},{0,2,260},{0,2,260},{0,1,256},{0,1,1017},{0,1,617},{0,4,261},{0,4,261},{0,4,261},{0,2,229},{0,2,656},{0,2,260},{0,2,260},{0,1,256},{0,1,656},{0,1,256},{3,0,890},{0,4,40},{1,2,68},{0,2,68},{3,0,890},{5,0,890},{0,2,68}, +{0,2,1220},{5,0,890},{0,2,1220},{0,0,225},{0,0,225},{0,0,225},{0,0,225},{0,1,16},{0,1,16},{0,1,16},{0,0,25},{0,0,61},{0,0,61},{0,6,1419},{0,4,569},{0,3,1078},{0,2,821},{0,4,3096},{0,3,1395},{0,2,356},{0,2,1832},{0,2,4201},{0,2,2793},{1,4,1011},{1,3,353},{1,2,413},{1,2,413},{2,1,3048},{0,3,1395},{0,2,356},{0,2,1832},{4,0,3048}, +{0,2,1832},{0,4,533},{0,4,533},{0,4,533},{0,2,565},{0,3,666},{0,2,100},{0,2,100},{0,1,128},{0,1,1209},{0,1,489},{1,2,157},{1,2,157},{1,2,157},{1,2,157},{1,1,650},{0,2,100},{0,2,100},{0,1,128},{1,1,666},{0,1,128},{3,1,890},{0,4,40},{1,2,292},{0,2,292},{3,1,890},{4,1,890},{0,2,292},{0,2,932},{4,1,890},{0,2,932},{0,0,529}, +{0,0,529},{0,0,529},{0,0,529},{0,1,16},{0,1,16},{0,1,16},{0,1,64},{0,0,205},{0,0,205},{0,6,1915},{0,5,1019},{1,3,1269},{0,3,1110},{0,5,3051},{0,3,1443},{0,3,318},{0,2,1384},{0,2,4777},{0,2,2345},{1,5,909},{1,4,131},{1,3,113},{1,3,509},{3,0,3051},{0,3,1443},{0,3,318},{0,2,1384},{3,1,3051},{0,2,1384},{0,5,970},{0,5,970},{0,5,970}, +{0,3,1010},{0,3,698},{0,2,196},{0,2,196},{0,1,256},{0,2,1641},{0,1,617},{1,3,13},{1,3,13},{1,3,13},{1,2,13},{2,0,650},{0,2,196},{0,2,196},{0,1,256},{3,0,650},{0,1,256},{2,3,884},{0,5,58},{1,3,104},{0,3,149},{2,3,884},{6,0,884},{0,3,149},{0,2,900},{6,0,884},{0,2,900},{0,0,961},{0,0,961},{0,0,961},{0,0,961},{0,2,0}, +{0,2,0},{0,2,0},{0,1,0},{0,1,361},{0,1,361},{1,5,2113},{1,4,1271},{1,3,1285},{1,3,1329},{0,6,3123},{0,4,1208},{0,3,30},{0,2,1320},{0,3,5011},{0,2,2281},{1,5,957},{1,4,115},{1,3,129},{1,3,173},{1,4,3051},{0,4,1208},{0,3,30},{0,2,1320},{2,2,3051},{0,2,1320},{1,4,1190},{1,4,1190},{1,4,1190},{1,2,1281},{0,4,648},{0,3,26},{0,3,26}, +{0,2,296},{0,2,1641},{0,1,1001},{1,4,34},{1,4,34},{1,4,34},{1,2,125},{0,4,648},{0,3,26},{0,3,26},{0,2,296},{2,1,648},{0,2,296},{3,2,884},{0,5,26},{1,3,104},{0,3,5},{3,2,884},{5,1,884},{0,3,5},{0,2,1124},{5,1,884},{0,2,1124},{1,0,1181},{1,0,1181},{1,0,1181},{1,0,1181},{0,3,25},{0,3,25},{0,3,25},{0,1,64},{0,1,425}, +{0,1,425},{1,6,1864},{1,5,1038},{1,3,1390},{1,3,1038},{0,6,3132},{0,4,1199},{0,3,201},{0,2,1743},{0,3,4924},{0,2,2332},{1,6,1080},{1,5,254},{2,3,458},{1,3,254},{2,3,3051},{0,4,1163},{0,3,165},{0,2,1707},{6,0,3051},{0,2,1707},{1,4,1016},{1,4,1016},{1,4,1016},{1,3,989},{0,5,716},{0,3,152},{0,3,152},{0,2,62},{0,2,1611},{0,2,651},{1,4,232}, +{1,4,232},{1,4,232},{1,3,205},{1,3,650},{0,3,116},{0,3,116},{0,2,26},{1,2,650},{0,2,26},{4,1,884},{1,5,58},{2,3,58},{1,3,58},{4,1,884},{4,2,884},{1,3,58},{0,3,1274},{4,2,884},{0,3,1274},{1,0,980},{1,0,980},{1,0,980},{1,0,980},{0,3,52},{0,3,52},{0,3,52},{0,2,61},{0,1,458},{0,1,458},{1,7,1784},{1,5,910},{1,4,1441}, +{1,3,1134},{0,7,3247},{0,5,1292},{0,4,567},{0,3,1474},{0,4,4900},{0,3,2178},{2,5,1028},{2,4,362},{2,3,394},{2,3,418},{3,2,3051},{0,5,1096},{1,3,331},{0,3,1278},{5,1,3051},{0,3,1278},{1,5,885},{1,5,885},{1,5,885},{1,3,909},{0,5,876},{0,4,206},{0,4,206},{0,2,254},{0,3,1548},{0,2,347},{2,3,169},{2,3,169},{2,3,169},{2,3,193},{2,2,648}, +{0,4,10},{0,4,10},{0,2,58},{5,0,648},{0,2,58},{5,0,884},{1,5,26},{2,3,250},{1,3,250},{5,0,884},{3,3,884},{1,3,250},{0,3,954},{3,3,884},{0,3,954},{1,0,884},{1,0,884},{1,0,884},{1,0,884},{0,4,197},{0,4,197},{0,4,197},{0,2,205},{0,2,298},{0,2,298},{1,7,1976},{1,6,1124},{1,4,1649},{1,4,1229},{1,6,3204},{0,5,1452},{1,4,525}, +{0,3,1474},{0,4,4420},{0,3,1474},{2,6,930},{2,5,160},{2,4,138},{2,3,546},{4,1,3060},{0,5,968},{0,4,195},{0,3,990},{4,2,3060},{0,3,990},{1,6,1060},{1,6,1060},{1,6,1060},{1,4,1108},{1,4,824},{1,3,314},{1,3,314},{1,2,370},{0,3,1260},{0,2,427},{2,4,17},{2,4,17},{2,4,17},{2,3,17},{3,1,648},{0,4,74},{0,4,74},{1,2,226},{4,1,648}, +{1,2,226},{3,4,882},{1,6,80},{2,4,122},{0,4,146},{3,4,882},{7,1,882},{0,4,146},{0,3,890},{7,1,882},{0,3,890},{1,0,1044},{1,0,1044},{1,0,1044},{1,0,1044},{1,3,145},{1,3,145},{1,3,145},{1,2,145},{0,2,202},{0,2,202},{2,6,2374},{1,6,1476},{2,4,1550},{1,4,1469},{1,6,3172},{1,5,1259},{1,4,61},{1,3,1323},{0,4,4452},{0,3,1282},{2,6,930}, +{2,5,96},{2,4,106},{2,4,194},{5,0,3060},{0,6,1144},{1,4,45},{0,3,1086},{6,1,3060},{0,3,1086},{2,5,1476},{2,5,1476},{2,5,1476},{1,4,1460},{1,5,666},{1,4,52},{1,4,52},{1,3,362},{0,3,1356},{0,3,321},{2,5,32},{2,5,32},{2,5,32},{2,3,97},{4,0,650},{1,4,36},{1,4,36},{0,3,125},{3,2,650},{0,3,125},{4,3,882},{1,6,16},{2,4,90}, +{1,4,9},{4,3,882},{6,2,882},{1,4,9},{0,3,1082},{6,2,882},{0,3,1082},{1,0,1460},{1,0,1460},{1,0,1460},{1,0,1460},{1,4,52},{1,4,52},{1,4,52},{1,2,65},{0,3,200},{0,3,200},{2,7,1892},{2,6,1090},{2,4,1370},{2,4,1062},{1,7,3100},{1,5,1169},{1,4,151},{1,3,1665},{0,5,4036},{0,3,1678},{2,7,1051},{2,6,249},{3,4,493},{2,4,221},{3,4,3060}, +{0,6,883},{1,4,126},{0,4,1528},{7,1,3060},{0,4,1528},{2,5,1035},{2,5,1035},{2,5,1035},{2,4,1026},{1,6,723},{1,4,115},{1,4,115},{1,3,65},{0,4,1004},{0,3,78},{2,5,194},{2,5,194},{2,5,194},{2,4,185},{2,4,648},{1,4,90},{1,4,90},{1,3,40},{7,0,648},{1,3,40},{5,2,882},{2,6,80},{3,4,52},{2,4,52},{5,2,882},{5,3,882},{2,4,52}, +{0,4,1332},{5,3,882},{0,4,1332},{2,0,1010},{2,0,1010},{2,0,1010},{2,0,1010},{1,4,34},{1,4,34},{1,4,34},{1,3,61},{0,3,74},{0,3,74},{2,7,1892},{2,6,898},{2,5,1451},{2,4,1094},{2,6,3501},{1,6,1308},{1,5,589},{1,4,1510},{0,5,3940},{0,4,1116},{3,6,1051},{3,5,377},{3,4,381},{3,4,429},{5,1,3060},{0,6,1059},{2,4,312},{0,4,1016},{6,2,3060}, +{0,4,1016},{2,6,882},{2,6,882},{2,6,882},{2,4,898},{1,6,835},{1,5,189},{1,5,189},{1,3,209},{0,4,1036},{0,3,270},{3,4,185},{3,4,185},{3,4,185},{3,4,233},{3,3,650},{1,5,20},{1,5,20},{1,3,40},{6,1,650},{1,3,40},{6,1,882},{2,6,16},{3,4,212},{2,4,212},{6,1,882},{4,4,882},{2,4,212},{0,4,980},{4,4,882},{0,4,980},{2,0,882}, +{2,0,882},{2,0,882},{2,0,882},{1,5,173},{1,5,173},{1,5,173},{1,3,173},{0,4,136},{0,4,136},{2,7,2404},{2,7,1116},{2,5,1595},{2,5,1235},{2,7,3244},{1,6,1404},{2,5,619},{1,4,1446},{0,6,3804},{0,4,892},{3,7,957},{3,6,195},{3,5,169},{3,4,509},{6,0,3060},{0,7,936},{1,5,196},{0,4,888},{3,4,3060},{0,4,888},{2,7,1035},{2,7,1035},{2,7,1035}, +{2,5,1091},{2,5,835},{2,4,317},{2,4,317},{2,3,369},{0,5,875},{1,3,396},{3,5,25},{3,5,25},{3,5,25},{3,4,25},{4,2,650},{1,5,52},{1,5,52},{2,3,200},{5,2,650},{2,3,200},{7,0,884},{2,7,106},{3,5,144},{1,5,160},{7,0,884},{3,5,884},{1,5,160},{0,4,884},{3,5,884},{0,4,884},{2,0,1010},{2,0,1010},{2,0,1010},{2,0,1010},{2,4,173}, +{2,4,173},{2,4,173},{2,3,173},{0,4,8},{0,4,8},{3,7,2430},{2,7,1404},{3,5,1610},{2,5,1411},{2,7,3148},{2,6,1309},{2,5,91},{2,4,1325},{0,6,3484},{0,4,1180},{3,7,909},{3,6,83},{3,5,89},{3,5,221},{4,4,3051},{0,7,1000},{2,5,66},{1,4,1053},{7,2,3051},{1,4,1053},{2,7,1403},{2,7,1403},{2,7,1403},{2,5,1395},{2,6,681},{2,5,75},{2,5,75}, +{2,4,425},{0,5,795},{0,4,280},{3,6,34},{3,6,34},{3,6,34},{3,4,73},{5,1,656},{2,5,50},{2,5,50},{1,4,153},{7,1,656},{1,4,153},{5,4,884},{2,7,10},{3,5,80},{2,5,17},{5,4,884},{7,3,884},{2,5,17},{0,4,1044},{7,3,884},{0,4,1044},{2,0,1394},{2,0,1394},{2,0,1394},{2,0,1394},{2,4,61},{2,4,61},{2,4,61},{2,3,61},{0,4,136}, +{0,4,136},{3,7,2214},{3,7,1150},{3,5,1358},{3,5,1094},{2,7,3652},{2,6,1147},{2,5,109},{2,4,1595},{0,7,3724},{0,5,1402},{3,7,1314},{3,7,250},{3,5,458},{3,5,194},{5,3,3060},{1,7,888},{2,5,93},{0,5,1398},{6,3,3060},{0,5,1398},{3,6,1060},{3,6,1060},{3,6,1060},{3,5,1069},{2,7,736},{2,5,84},{2,5,84},{2,4,74},{0,6,820},{1,4,81},{3,6,160}, +{3,6,160},{3,6,160},{3,5,169},{6,0,650},{2,5,68},{2,5,68},{1,4,45},{3,4,650},{1,4,45},{6,3,884},{3,7,106},{4,5,50},{3,5,50},{6,3,884},{6,4,884},{3,5,50},{0,5,1394},{6,4,884},{0,5,1394},{3,0,1044},{3,0,1044},{3,0,1044},{3,0,1044},{2,5,20},{2,5,20},{2,5,20},{2,4,65},{0,5,8},{0,5,8},{3,7,2566},{3,7,894},{3,6,1469}, +{3,5,1062},{3,7,3535},{2,7,1332},{2,6,619},{2,5,1554},{0,7,3276},{0,5,1146},{4,7,1080},{4,6,398},{4,5,374},{4,5,446},{6,2,3051},{1,7,1016},{3,5,299},{0,5,1046},{5,4,3051},{0,5,1046},{3,7,885},{3,7,885},{3,7,885},{3,5,893},{2,7,800},{2,6,178},{2,6,178},{2,4,170},{0,6,660},{1,4,225},{4,5,205},{4,5,205},{4,5,205},{4,5,277},{5,2,656}, +{2,6,34},{2,6,34},{2,4,26},{7,2,656},{2,4,26},{7,2,884},{3,7,10},{4,5,178},{3,5,178},{7,2,884},{5,5,884},{3,5,178},{0,5,1010},{5,5,884},{0,5,1010},{3,0,884},{3,0,884},{3,0,884},{3,0,884},{2,6,153},{2,6,153},{2,6,153},{2,4,145},{0,5,136},{0,5,136},{4,7,3320},{3,7,1150},{3,6,1549},{3,6,1249},{3,7,3487},{2,7,1364},{2,6,603}, +{2,5,1426},{0,7,3340},{1,5,892},{4,7,1016},{4,7,236},{4,6,206},{4,5,478},{7,1,3051},{2,7,964},{2,6,203},{1,5,883},{4,5,3051},{1,5,883},{3,7,1029},{3,7,1029},{3,7,1029},{3,6,1080},{3,6,852},{3,5,326},{3,5,326},{3,4,374},{0,6,884},{2,4,371},{4,6,37},{4,6,37},{4,6,37},{4,5,37},{6,1,656},{2,6,34},{2,6,34},{3,4,178},{6,3,656}, +{3,4,178},{5,6,890},{3,7,170},{4,6,170},{2,6,178},{5,6,890},{4,6,890},{2,6,178},{0,5,882},{4,6,890},{0,5,882},{3,0,980},{3,0,980},{3,0,980},{3,0,980},{3,5,205},{3,5,205},{3,5,205},{3,4,205},{1,5,10},{1,5,10},{4,7,2936},{4,7,1676},{4,6,1678},{3,6,1361},{3,7,3951},{3,7,1367},{3,6,129},{3,5,1335},{1,7,3496},{1,5,1116},{4,7,1336}, +{4,7,76},{4,6,78},{4,6,254},{5,5,3048},{2,7,1124},{3,6,93},{2,5,1026},{3,6,3048},{2,5,1026},{3,7,1557},{3,7,1557},{3,7,1557},{3,6,1336},{3,7,702},{3,6,104},{3,6,104},{3,5,494},{0,7,667},{1,5,275},{4,7,40},{4,7,40},{4,7,40},{4,5,53},{7,0,650},{3,6,68},{3,6,68},{2,5,185},{3,5,650},{2,5,185},{7,3,890},{4,7,72},{4,6,74}, +{3,6,29},{7,3,890},{6,5,890},{3,6,29},{0,5,1010},{6,5,890},{0,5,1010},{3,0,1332},{3,0,1332},{3,0,1332},{3,0,1332},{3,5,61},{3,5,61},{3,5,61},{3,4,61},{1,5,106},{1,5,106},{4,7,3116},{4,7,1316},{4,6,1354},{4,6,1134},{4,7,4084},{3,7,1133},{3,6,75},{3,5,1533},{1,7,3676},{1,6,1470},{5,7,1429},{4,7,355},{4,6,393},{4,6,173},{6,4,3051}, +{3,7,1124},{3,6,66},{1,6,1469},{7,4,3051},{1,6,1469},{4,7,1091},{4,7,1091},{4,7,1091},{4,6,1118},{3,7,729},{3,6,59},{3,6,59},{3,5,89},{0,7,820},{2,5,90},{4,7,130},{4,7,130},{4,7,130},{4,6,157},{7,1,656},{3,6,50},{3,6,50},{2,5,41},{7,3,656},{2,5,41},{7,4,890},{4,7,234},{5,6,52},{4,6,52},{7,4,890},{7,5,890},{4,6,52}, +{0,5,1460},{7,5,890},{0,5,1460},{4,0,1082},{4,0,1082},{4,0,1082},{4,0,1082},{3,6,10},{3,6,10},{3,6,10},{3,5,73},{1,6,10},{1,6,10},{4,7,3820},{4,7,1540},{4,7,1495},{4,6,1038},{4,7,4084},{3,7,1469},{3,6,571},{3,6,1606},{2,7,3916},{1,6,1150},{5,7,1349},{5,7,425},{5,6,373},{5,6,469},{7,3,3048},{3,7,1348},{4,6,292},{1,6,1069},{6,5,3048}, +{1,6,1069},{4,7,1011},{4,7,1011},{4,7,1011},{4,6,894},{3,7,1161},{3,7,173},{3,7,173},{3,5,137},{1,7,659},{2,5,186},{5,6,229},{5,6,229},{5,6,229},{5,6,325},{6,3,650},{3,7,52},{3,7,52},{3,5,16},{6,4,650},{3,5,16},{6,6,890},{5,7,200},{5,6,148},{4,6,148},{6,6,890},{6,6,890},{4,6,148},{0,6,1044},{6,6,890},{0,6,1044},{4,0,890}, +{4,0,890},{4,0,890},{4,0,890},{3,7,137},{3,7,137},{3,7,137},{3,5,121},{1,6,106},{1,6,106},{5,7,4054},{4,7,2276},{4,7,1511},{4,7,1271},{4,7,4596},{4,7,1596},{3,7,577},{3,6,1414},{2,7,4204},{2,6,900},{5,7,1653},{5,7,377},{5,7,249},{5,6,453},{5,7,3048},{4,7,1371},{3,7,216},{2,6,884},{5,6,3048},{2,6,884},{4,7,1315},{4,7,1315},{4,7,1315}, +{4,6,1054},{4,7,875},{4,6,341},{4,6,341},{4,5,385},{1,7,835},{3,5,352},{5,7,53},{5,7,53},{5,7,53},{5,6,53},{7,2,650},{3,7,20},{3,7,20},{4,5,160},{5,5,650},{4,5,160},{7,5,890},{5,7,328},{5,7,200},{3,7,200},{7,5,890},{5,7,900},{3,7,200},{0,6,884},{5,7,900},{0,6,884},{4,0,954},{4,0,954},{4,0,954},{4,0,954},{4,6,241}, +{4,6,241},{4,6,241},{4,5,241},{2,6,16},{2,6,16},{5,7,4022},{5,7,2394},{5,7,1754},{4,7,1319},{5,7,4921},{4,7,1660},{4,7,175},{4,6,1353},{3,7,4380},{2,6,1060},{6,7,2021},{5,7,713},{5,7,73},{5,7,293},{6,6,3051},{4,7,1611},{4,7,126},{3,6,1005},{4,7,3051},{3,6,1005},{5,7,1718},{5,7,1718},{5,7,1718},{4,7,1283},{4,7,859},{4,7,139},{4,7,139}, +{4,5,465},{2,7,779},{2,6,276},{5,7,37},{5,7,37},{5,7,37},{5,6,37},{5,6,648},{4,7,90},{4,7,90},{3,6,221},{4,6,648},{3,6,221},{7,6,900},{6,7,452},{5,7,72},{4,7,45},{7,6,900},{7,6,884},{4,7,45},{0,6,980},{7,6,884},{0,6,980},{4,0,1274},{4,0,1274},{4,0,1274},{4,0,1274},{4,6,65},{4,6,65},{4,6,65},{4,5,65},{2,6,80}, +{2,6,80},{5,7,4265},{5,7,2373},{5,7,1349},{5,7,1173},{5,7,4606},{4,7,2065},{4,7,40},{4,6,1266},{3,7,4455},{3,6,1261},{6,7,1649},{6,7,1025},{5,7,325},{5,7,149},{7,5,2817},{5,7,1514},{4,7,36},{3,6,1197},{6,6,2841},{3,6,1197},{5,7,1349},{5,7,1349},{5,7,1349},{5,7,1173},{4,7,1300},{4,7,40},{4,7,40},{4,6,110},{2,7,1040},{3,6,105},{5,7,325}, +{5,7,325},{5,7,325},{5,7,149},{6,5,650},{4,7,36},{4,7,36},{3,6,41},{3,7,650},{3,6,41},{7,6,801},{6,7,449},{6,7,49},{4,7,36},{7,6,801},{6,7,761},{4,7,36},{0,6,1181},{6,7,761},{0,6,1181},{5,0,1124},{5,0,1124},{5,0,1124},{5,0,1124},{4,7,4},{4,7,4},{4,7,4},{4,6,85},{2,7,16},{2,7,16},{5,7,4345},{5,7,2453},{5,7,1429}, +{5,7,901},{5,7,4190},{5,7,1770},{4,7,360},{4,6,1266},{4,7,3861},{2,7,1041},{6,7,1281},{6,7,657},{6,7,257},{5,7,325},{6,7,2250},{5,7,1194},{5,7,170},{2,7,977},{5,7,2250},{2,7,977},{5,7,1429},{5,7,1429},{5,7,1429},{5,7,901},{5,7,1274},{4,7,360},{4,7,360},{4,6,110},{3,7,979},{3,6,153},{6,7,257},{6,7,257},{6,7,257},{5,7,325},{7,4,648}, +{5,7,170},{5,7,170},{4,6,10},{7,5,648},{4,6,10},{7,7,521},{6,7,401},{6,7,1},{5,7,1},{7,7,521},{6,7,521},{5,7,1},{0,7,961},{6,7,521},{0,7,961},{5,0,900},{5,0,900},{5,0,900},{5,0,900},{4,7,164},{4,7,164},{4,7,164},{4,6,101},{2,7,80},{2,7,80},{6,7,3669},{5,7,2917},{5,7,1893},{5,7,1013},{5,7,4158},{5,7,1386},{5,7,362}, +{4,7,1049},{4,7,3381},{3,7,555},{6,7,1169},{6,7,545},{6,7,145},{6,7,73},{7,6,1802},{5,7,1130},{5,7,106},{3,7,530},{7,6,1770},{3,7,530},{5,7,1893},{5,7,1893},{5,7,1893},{5,7,1013},{5,7,1242},{5,7,362},{5,7,362},{5,6,402},{3,7,1251},{4,6,339},{6,7,145},{6,7,145},{6,7,145},{6,7,73},{7,5,680},{5,7,106},{5,7,106},{5,6,146},{6,6,648}, +{5,6,146},{7,7,265},{7,7,193},{6,7,81},{6,7,9},{7,7,265},{7,7,305},{6,7,9},{0,7,529},{7,7,305},{0,7,529},{5,0,932},{5,0,932},{5,0,932},{5,0,932},{5,7,281},{5,7,281},{5,7,281},{5,6,281},{3,7,26},{3,7,26},{6,7,3077},{6,7,2453},{6,7,2053},{5,7,1509},{6,7,3438},{5,7,1386},{5,7,362},{5,7,650},{5,7,3195},{3,7,283},{7,7,1293}, +{6,7,689},{6,7,289},{6,7,25},{7,6,1386},{6,7,786},{5,7,298},{4,7,261},{6,7,1386},{4,7,261},{6,7,2053},{6,7,2053},{6,7,2053},{5,7,1509},{5,7,1594},{5,7,362},{5,7,362},{5,6,434},{4,7,1260},{3,7,283},{6,7,289},{6,7,289},{6,7,289},{6,7,25},{6,7,650},{5,7,298},{5,7,298},{4,7,261},{5,7,650},{4,7,261},{7,7,137},{7,7,65},{7,7,16}, +{6,7,25},{7,7,137},{7,7,113},{6,7,25},{0,7,225},{7,7,113},{0,7,225},{5,0,1220},{5,0,1220},{5,0,1220},{5,0,1220},{5,7,73},{5,7,73},{5,7,73},{5,6,73},{3,7,58},{3,7,58},{6,7,2870},{6,7,2246},{6,7,1846},{6,7,1366},{6,7,2889},{6,7,1785},{5,7,821},{5,7,137},{5,7,2700},{4,7,126},{7,7,771},{7,7,699},{7,7,650},{6,7,277},{7,7,1107}, +{6,7,696},{6,7,296},{4,7,45},{6,7,1080},{4,7,45},{6,7,1846},{6,7,1846},{6,7,1846},{6,7,1366},{6,7,1865},{5,7,821},{5,7,821},{5,7,137},{4,7,1611},{4,7,126},{7,7,650},{7,7,650},{7,7,650},{6,7,277},{7,6,648},{6,7,296},{6,7,296},{4,7,45},{7,6,680},{4,7,45},{7,7,146},{7,7,74},{7,7,25},{7,7,1},{7,7,146},{7,7,50},{7,7,1}, +{0,7,36},{7,7,50},{0,7,36},{6,0,1170},{6,0,1170},{6,0,1170},{6,0,1170},{5,7,145},{5,7,145},{5,7,145},{5,7,101},{4,7,90},{4,7,90},{6,7,2962},{6,7,2338},{6,7,1938},{6,7,1314},{6,7,2677},{6,7,1429},{6,7,1029},{5,7,85},{5,7,2536},{4,7,122},{7,7,531},{7,7,459},{7,7,410},{7,7,338},{7,7,771},{7,7,627},{6,7,404},{5,7,4},{7,7,827}, +{5,7,4},{6,7,1938},{6,7,1938},{6,7,1938},{6,7,1314},{6,7,1653},{6,7,1029},{6,7,1029},{5,7,85},{5,7,1512},{4,7,122},{7,7,410},{7,7,410},{7,7,410},{7,7,338},{7,7,650},{6,7,404},{6,7,404},{5,7,4},{6,7,596},{5,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,914}, +{6,0,914},{6,0,914},{6,0,914},{5,7,481},{5,7,481},{5,7,481},{5,7,85},{4,7,122},{4,7,122},{7,7,2924},{6,7,2338},{6,7,1938},{6,7,1314},{6,7,2373},{6,7,1125},{6,7,725},{5,7,325},{6,7,2132},{5,7,232},{7,7,323},{7,7,251},{7,7,202},{7,7,130},{7,7,467},{7,7,323},{7,7,274},{5,7,36},{7,7,459},{5,7,36},{6,7,1938},{6,7,1938},{6,7,1938}, +{6,7,1314},{6,7,1349},{6,7,725},{6,7,725},{5,7,325},{5,7,1256},{5,7,232},{7,7,202},{7,7,202},{7,7,202},{7,7,130},{7,7,346},{7,7,274},{7,7,274},{5,7,36},{7,7,410},{5,7,36},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,914},{6,0,914},{6,0,914},{6,0,914},{6,7,325}, +{6,7,325},{6,7,325},{5,7,325},{5,7,232},{5,7,232},{7,7,2092},{7,7,2020},{7,7,1971},{6,7,1570},{7,7,2140},{6,7,1077},{6,7,677},{6,7,85},{6,7,1588},{5,7,232},{7,7,243},{7,7,171},{7,7,122},{7,7,50},{7,7,291},{7,7,147},{7,7,98},{6,7,4},{7,7,219},{6,7,4},{7,7,1971},{7,7,1971},{7,7,1971},{6,7,1570},{6,7,1301},{6,7,677},{6,7,677}, +{6,7,85},{6,7,1188},{5,7,232},{7,7,122},{7,7,122},{7,7,122},{7,7,50},{7,7,170},{7,7,98},{7,7,98},{6,7,4},{7,7,170},{6,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,1170},{6,0,1170},{6,0,1170},{6,0,1170},{6,7,277},{6,7,277},{6,7,277},{6,7,85},{5,7,232}, +{5,7,232},{0,4,1618},{0,3,436},{0,2,74},{0,2,866},{0,2,3411},{0,2,2531},{0,1,1251},{0,1,2531},{0,1,3772},{0,1,2892},{0,4,1618},{0,3,436},{0,2,74},{0,2,866},{0,2,3411},{0,2,2531},{0,1,1251},{0,1,2531},{2,0,3376},{0,1,2531},{0,1,25},{0,1,25},{0,1,25},{0,1,49},{0,0,360},{0,0,232},{0,0,232},{0,0,149},{0,0,332},{0,0,185},{0,1,25}, +{0,1,25},{0,1,25},{0,1,49},{0,0,360},{0,0,232},{0,0,232},{0,0,149},{0,0,296},{0,0,149},{1,2,1570},{0,3,436},{0,2,74},{0,2,866},{1,2,1570},{0,2,1570},{0,2,866},{0,1,1570},{0,2,1570},{0,1,1570},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,4,1586},{0,3,340},{0,2,10}, +{0,2,450},{0,3,4016},{0,2,2627},{0,2,1411},{0,1,2691},{0,1,4572},{0,1,3052},{0,4,1586},{0,3,340},{0,2,10},{0,2,450},{1,1,3968},{0,2,2627},{0,2,1411},{0,1,2691},{2,0,4016},{0,1,2691},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,530},{0,1,362},{0,1,362},{0,0,325},{0,0,620},{0,0,361},{0,2,1},{0,2,1},{0,2,1},{0,1,1},{0,1,530}, +{0,1,362},{0,1,362},{0,0,325},{0,0,584},{0,0,325},{2,1,1570},{0,3,340},{0,2,10},{0,2,450},{2,1,1570},{4,0,1570},{0,2,450},{0,1,1730},{4,0,1570},{0,1,1730},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,5,1576},{0,4,290},{0,2,202},{0,2,290},{0,3,4656},{0,2,2979},{0,2,1251}, +{0,1,3107},{0,1,5628},{0,1,3468},{0,5,1576},{0,4,290},{0,2,202},{0,2,290},{0,3,4656},{0,2,2979},{0,2,1251},{0,1,3107},{1,1,4656},{0,1,3107},{0,3,16},{0,3,16},{0,3,16},{0,1,81},{0,1,802},{0,1,442},{0,1,442},{0,0,629},{0,0,1036},{0,0,665},{0,3,16},{0,3,16},{0,3,16},{0,1,81},{0,1,802},{0,1,442},{0,1,442},{0,0,629},{1,0,818}, +{0,0,629},{3,0,1576},{0,4,290},{0,2,202},{0,2,290},{3,0,1576},{3,1,1576},{0,2,290},{0,1,2146},{3,1,1576},{0,1,2146},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,5,1640},{0,4,162},{0,3,241},{0,2,386},{0,4,5539},{0,3,3512},{0,2,1347},{0,1,3779},{0,2,6396},{0,1,4140},{0,5,1640}, +{0,4,162},{0,3,241},{0,2,386},{1,2,5435},{0,3,3512},{0,2,1347},{0,1,3779},{0,2,5435},{0,1,3779},{0,3,16},{0,3,16},{0,3,16},{0,2,25},{0,1,1202},{0,1,650},{0,1,650},{0,1,970},{0,0,1580},{0,0,1097},{0,3,16},{0,3,16},{0,3,16},{0,2,25},{1,0,1170},{0,1,650},{0,1,650},{0,1,970},{1,0,1154},{0,1,970},{2,2,1576},{0,4,162},{0,3,241}, +{0,2,386},{2,2,1576},{5,0,1576},{0,2,386},{0,2,1730},{5,0,1576},{0,2,1730},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,6,1667},{0,5,259},{0,3,286},{0,3,406},{0,4,5440},{0,3,3035},{0,2,1284},{0,2,3504},{0,2,6513},{0,2,4465},{0,6,1667},{0,5,259},{0,3,286},{0,3,406},{2,1,5424}, +{0,3,3035},{0,2,1284},{0,2,3504},{4,0,5424},{0,2,3504},{0,4,81},{0,4,81},{0,4,81},{0,2,97},{0,2,1160},{0,2,500},{0,2,500},{0,1,520},{0,1,1521},{0,1,881},{0,4,81},{0,4,81},{0,4,81},{0,2,97},{0,2,1160},{0,2,500},{0,2,500},{0,1,520},{0,1,1160},{0,1,520},{2,3,1576},{0,5,178},{1,3,100},{0,3,325},{2,3,1576},{6,0,1576},{0,3,325}, +{0,2,1568},{6,0,1576},{0,2,1568},{0,0,81},{0,0,81},{0,0,81},{0,0,81},{0,0,9},{0,0,9},{0,0,9},{0,0,1},{0,0,37},{0,0,37},{0,7,1865},{0,5,339},{0,3,734},{0,3,374},{0,5,5435},{0,3,3019},{0,3,814},{0,2,2992},{0,2,7025},{0,2,3953},{1,5,1865},{0,5,339},{1,3,293},{0,3,374},{3,0,5435},{0,3,3019},{0,3,814},{0,2,2992},{3,1,5435}, +{0,2,2992},{0,5,314},{0,5,314},{0,5,314},{0,3,370},{0,3,1170},{0,2,340},{0,2,340},{0,1,392},{0,1,1713},{0,1,753},{1,3,289},{1,3,289},{1,3,289},{1,2,289},{1,1,1154},{0,2,340},{0,2,340},{0,1,392},{1,1,1170},{0,1,392},{4,0,1576},{0,5,50},{1,3,4},{0,3,85},{4,0,1576},{5,1,1576},{0,3,85},{0,2,1696},{5,1,1576},{0,2,1696},{0,0,289}, +{0,0,289},{0,0,289},{0,0,289},{0,1,4},{0,1,4},{0,1,4},{0,0,49},{0,0,85},{0,0,85},{0,7,2265},{0,6,787},{1,3,1401},{0,3,726},{0,5,5515},{0,4,2664},{0,3,462},{0,2,2864},{0,3,7363},{0,2,3825},{1,6,1667},{1,5,405},{1,3,245},{1,3,377},{2,2,5427},{0,4,2664},{0,3,462},{0,2,2864},{5,0,5427},{0,2,2864},{0,5,634},{0,5,634},{0,5,634}, +{0,3,626},{0,3,1202},{0,3,362},{0,3,362},{0,1,520},{0,2,2145},{0,1,881},{1,4,106},{1,4,106},{1,4,106},{1,2,145},{2,0,1154},{0,3,362},{0,3,362},{0,1,520},{3,0,1154},{0,1,520},{2,4,1576},{0,6,162},{1,3,164},{0,3,101},{2,4,1576},{7,0,1576},{0,3,101},{0,2,2080},{7,0,1576},{0,2,2080},{0,0,625},{0,0,625},{0,0,625},{0,0,625},{0,1,36}, +{0,1,36},{0,1,36},{0,1,36},{0,0,261},{0,0,261},{1,6,2775},{0,6,1091},{1,4,1422},{0,3,1462},{0,6,5427},{0,4,2536},{0,3,494},{0,2,3120},{0,3,7635},{0,2,4081},{1,6,1619},{1,5,165},{1,4,266},{1,3,361},{3,1,5427},{0,4,2536},{0,3,494},{0,2,3120},{4,1,5427},{0,2,3120},{0,6,1090},{0,6,1090},{0,6,1090},{0,3,1138},{0,4,1152},{0,3,170},{0,3,170}, +{0,2,416},{0,2,2145},{0,1,1265},{1,4,10},{1,4,10},{1,4,10},{1,3,37},{0,4,1152},{0,3,170},{0,3,170},{0,2,416},{2,1,1152},{0,2,416},{3,3,1570},{0,6,2},{1,4,265},{1,3,360},{3,3,1570},{6,1,1570},{1,3,360},{0,3,1768},{6,1,1570},{0,3,1768},{0,0,1089},{0,0,1089},{0,0,1089},{0,0,1089},{0,2,4},{0,2,4},{0,2,4},{0,1,4},{0,1,365}, +{0,1,365},{1,7,2796},{1,6,1432},{1,4,1413},{1,4,1593},{0,7,5435},{0,5,2360},{0,4,299},{0,3,2594},{0,3,8400},{0,3,4530},{1,7,1640},{1,6,276},{1,4,257},{1,4,437},{4,0,5427},{0,5,2360},{0,4,299},{0,3,2594},{3,2,5427},{0,3,2594},{1,5,1221},{1,5,1221},{1,5,1221},{1,3,1229},{0,5,1184},{0,4,250},{0,4,250},{0,2,146},{0,2,2451},{0,2,1107},{1,5,65}, +{1,5,65},{1,5,65},{1,3,73},{1,3,1154},{0,4,250},{0,4,250},{0,2,146},{1,2,1154},{0,2,146},{4,2,1576},{0,6,128},{2,4,130},{0,4,74},{4,2,1576},{5,2,1576},{0,4,74},{0,3,1570},{5,2,1576},{0,3,1570},{1,0,1220},{1,0,1220},{1,0,1220},{1,0,1220},{0,3,4},{0,3,4},{0,3,4},{0,1,121},{0,1,482},{0,1,482},{1,7,3180},{1,6,1464},{1,4,1813}, +{1,4,1513},{0,7,5515},{0,5,2168},{0,4,59},{0,3,2242},{0,4,8764},{0,3,4178},{2,6,1894},{1,6,308},{2,4,326},{1,4,357},{2,4,5427},{0,5,2168},{0,4,59},{0,3,2242},{7,0,5427},{0,3,2242},{1,6,1448},{1,6,1448},{1,6,1448},{1,4,1512},{0,5,1184},{0,4,58},{0,4,58},{0,2,178},{0,2,2995},{0,2,1139},{1,6,292},{1,6,292},{1,6,292},{2,3,325},{2,2,1152}, +{0,4,58},{0,4,58},{0,2,178},{5,0,1152},{0,2,178},{5,1,1570},{0,7,34},{2,4,2},{0,4,10},{5,1,1570},{4,3,1570},{0,4,10},{0,3,1666},{4,3,1570},{0,3,1666},{1,0,1412},{1,0,1412},{1,0,1412},{1,0,1412},{0,3,36},{0,3,36},{0,3,36},{0,2,9},{0,1,722},{0,1,722},{1,7,3816},{1,6,1748},{1,5,2450},{1,4,1685},{0,7,5983},{0,6,2180},{0,4,207}, +{0,3,2278},{0,4,9004},{0,3,4038},{2,7,1700},{2,6,462},{2,4,230},{2,4,406},{3,3,5420},{0,6,2176},{0,4,203},{0,3,2274},{6,1,5420},{0,3,2274},{1,6,1604},{1,6,1604},{1,6,1604},{1,4,1604},{0,6,1156},{0,4,126},{0,4,126},{0,3,429},{0,3,3044},{0,2,1307},{2,5,136},{2,5,136},{2,5,136},{2,3,149},{3,1,1152},{0,4,122},{0,4,122},{0,3,425},{4,1,1152}, +{0,3,425},{6,0,1570},{0,7,130},{2,4,130},{1,4,85},{6,0,1570},{3,4,1570},{1,4,85},{0,3,2018},{3,4,1570},{0,3,2018},{1,0,1600},{1,0,1600},{1,0,1600},{1,0,1600},{0,4,5},{0,4,5},{0,4,5},{0,2,29},{0,2,866},{0,2,866},{1,7,4520},{1,7,1608},{1,5,2418},{1,4,1925},{1,7,5996},{0,6,1956},{0,5,409},{0,4,2751},{0,5,9020},{0,3,3846},{2,7,1604}, +{2,6,174},{2,5,297},{2,4,342},{4,2,5420},{0,6,1856},{0,5,309},{0,4,2651},{5,2,5420},{0,4,2651},{1,7,1604},{1,7,1604},{1,7,1604},{1,4,1636},{0,7,1302},{0,5,120},{0,5,120},{0,3,189},{0,3,2820},{0,3,1245},{2,5,8},{2,5,8},{2,5,8},{2,4,53},{4,0,1154},{0,5,20},{0,5,20},{0,3,89},{3,2,1154},{0,3,89},{4,4,1568},{1,7,8},{2,5,293}, +{0,5,293},{4,4,1568},{7,2,1568},{0,5,293},{0,4,1810},{7,2,1568},{0,4,1810},{1,0,1600},{1,0,1600},{1,0,1600},{1,0,1600},{0,5,116},{0,5,116},{0,5,116},{0,3,164},{0,2,610},{0,2,610},{2,7,4356},{1,7,2004},{2,5,2635},{1,5,2006},{1,7,5924},{0,6,2316},{0,5,499},{0,4,2337},{0,5,8300},{0,4,3420},{2,7,1955},{2,7,299},{2,5,234},{2,5,474},{5,1,5420}, +{0,6,1955},{0,5,138},{0,4,1976},{4,3,5420},{0,4,1976},{1,7,1955},{1,7,1955},{1,7,1955},{1,5,1942},{1,6,1427},{0,5,435},{0,5,435},{0,3,378},{0,4,2628},{0,3,642},{2,6,53},{2,6,53},{2,6,53},{2,4,53},{2,4,1152},{0,5,74},{0,5,74},{0,3,17},{7,0,1152},{0,3,17},{5,3,1570},{1,7,98},{3,5,164},{1,5,100},{5,3,1570},{6,3,1570},{1,5,100}, +{0,4,1576},{6,3,1570},{0,4,1576},{1,0,1906},{1,0,1906},{1,0,1906},{1,0,1906},{1,4,234},{1,4,234},{1,4,234},{1,2,325},{0,3,626},{0,3,626},{2,7,4356},{2,7,1964},{2,5,2267},{2,5,2027},{1,7,6404},{1,6,2220},{1,5,117},{1,4,2314},{0,5,8204},{0,4,2684},{3,7,1929},{2,7,283},{3,5,365},{2,5,346},{6,0,5420},{0,7,1712},{1,5,68},{0,4,1784},{3,4,5420}, +{0,4,1784},{2,6,1942},{2,6,1942},{2,6,1942},{2,4,2006},{1,6,1219},{1,5,117},{1,5,117},{1,3,209},{0,4,2340},{0,3,514},{2,6,261},{2,6,261},{2,6,261},{2,4,325},{3,3,1154},{0,6,50},{0,6,50},{1,3,160},{6,1,1154},{1,3,160},{6,2,1568},{2,7,58},{3,5,4},{1,5,4},{6,2,1568},{5,4,1568},{1,5,4},{0,4,1640},{5,4,1568},{0,4,1640},{2,0,1906}, +{2,0,1906},{2,0,1906},{2,0,1906},{1,4,74},{1,4,74},{1,4,74},{1,3,65},{0,3,370},{0,3,370},{2,7,4868},{2,7,1740},{2,5,2411},{2,5,1691},{2,7,6548},{1,7,2244},{1,5,165},{1,4,2250},{0,6,7668},{0,4,2460},{3,7,1817},{3,7,525},{3,5,221},{3,5,441},{4,4,5419},{0,7,1712},{1,5,164},{0,4,1976},{7,2,5419},{0,4,1976},{2,7,1619},{2,7,1619},{2,7,1619}, +{2,5,1627},{1,7,1155},{1,5,101},{1,5,101},{1,3,417},{0,5,2379},{0,4,696},{3,5,157},{3,5,157},{3,5,157},{3,4,157},{4,2,1154},{0,6,82},{0,6,82},{0,4,212},{5,2,1154},{0,4,212},{7,1,1568},{2,7,122},{3,5,100},{2,5,73},{7,1,1568},{4,5,1568},{2,5,73},{0,4,1960},{4,5,1568},{0,4,1960},{2,0,1618},{2,0,1618},{2,0,1618},{2,0,1618},{1,5,1}, +{1,5,1},{1,5,1},{1,3,17},{0,3,370},{0,3,370},{3,7,5570},{2,7,2028},{2,6,2394},{2,5,1867},{2,7,6452},{1,7,1956},{1,6,439},{1,4,2698},{0,6,7348},{0,4,2748},{3,7,2089},{3,7,189},{3,6,334},{3,5,329},{5,3,5419},{1,7,1875},{1,6,358},{0,5,2145},{6,3,5419},{0,5,2145},{2,7,1667},{2,7,1667},{2,7,1667},{2,5,1611},{1,7,1331},{1,6,115},{1,6,115}, +{1,4,198},{0,5,1979},{0,4,248},{3,6,10},{3,6,10},{3,6,10},{3,5,73},{5,1,1160},{1,6,34},{1,6,34},{0,4,52},{7,1,1160},{0,4,52},{5,5,1570},{3,7,180},{4,5,320},{2,5,281},{5,5,1570},{3,6,1570},{2,5,281},{0,5,1856},{3,6,1570},{0,5,1856},{2,0,1586},{2,0,1586},{2,0,1586},{2,0,1586},{1,6,106},{1,6,106},{1,6,106},{1,4,162},{0,4,212}, +{0,4,212},{3,7,5354},{3,7,2770},{3,6,2717},{2,6,1986},{2,7,6956},{1,7,2244},{1,6,457},{1,5,2351},{0,7,7268},{0,5,1974},{4,7,2384},{3,7,270},{3,6,217},{3,6,517},{6,2,5419},{1,7,1920},{1,6,133},{0,5,1650},{5,4,5419},{0,5,1650},{2,7,2180},{2,7,2180},{2,7,2180},{2,6,1905},{2,7,1480},{1,6,376},{1,6,376},{1,4,333},{0,5,1988},{0,4,203},{3,7,45}, +{3,7,45},{3,7,45},{3,5,37},{6,0,1154},{1,6,52},{1,6,52},{1,4,9},{3,4,1154},{1,4,9},{6,4,1568},{3,7,234},{3,6,181},{1,6,117},{6,4,1568},{7,4,1568},{1,6,117},{0,5,1586},{7,4,1568},{0,5,1586},{2,0,1856},{2,0,1856},{2,0,1856},{2,0,1856},{2,5,272},{2,5,272},{2,5,272},{1,4,324},{0,4,194},{0,4,194},{3,7,5706},{3,7,2514},{3,6,2285}, +{3,6,2105},{3,7,7359},{2,7,2244},{2,6,147},{2,5,2358},{0,7,6820},{0,5,1718},{4,7,2256},{3,7,750},{4,6,410},{3,6,341},{7,1,5419},{2,7,2180},{2,6,83},{0,5,1618},{4,5,5419},{0,5,1618},{3,7,1985},{3,7,1985},{3,7,1985},{3,5,2041},{2,7,1224},{2,6,146},{2,6,146},{2,4,210},{0,6,1644},{1,4,509},{3,7,221},{3,7,221},{3,7,221},{3,5,277},{5,2,1160}, +{1,7,64},{1,7,64},{2,4,146},{7,2,1160},{2,4,146},{7,3,1570},{4,7,356},{4,6,10},{2,6,2},{7,3,1570},{6,5,1570},{2,6,2},{0,5,1618},{6,5,1570},{0,5,1618},{3,0,1960},{3,0,1960},{3,0,1960},{3,0,1960},{2,5,80},{2,5,80},{2,5,80},{2,4,89},{0,5,100},{0,5,100},{3,7,6570},{3,7,2770},{3,6,2365},{3,6,1705},{3,7,7311},{2,7,2276},{2,6,131}, +{2,5,2230},{0,7,6884},{0,5,1974},{4,7,2512},{4,7,532},{4,6,218},{4,6,482},{5,5,5424},{2,7,2276},{2,6,131},{1,5,1931},{3,6,5424},{1,5,1931},{3,7,1809},{3,7,1809},{3,7,1809},{3,6,1656},{2,7,1352},{2,6,82},{2,6,82},{2,4,370},{0,6,1548},{0,5,293},{4,6,169},{4,6,169},{4,6,169},{4,5,169},{6,1,1160},{1,7,64},{1,7,64},{1,5,250},{6,3,1160}, +{1,5,250},{5,7,1570},{4,7,388},{4,6,74},{3,6,65},{5,7,1570},{5,6,1570},{3,6,65},{0,5,1906},{5,6,1570},{0,5,1906},{3,0,1640},{3,0,1640},{3,0,1640},{3,0,1640},{2,6,1},{2,6,1},{2,6,1},{2,4,9},{0,5,68},{0,5,68},{4,7,6752},{3,7,3538},{3,7,2378},{3,6,1817},{3,7,7775},{2,7,2820},{2,7,477},{2,5,2614},{1,7,7360},{0,6,1978},{5,7,3110}, +{4,7,692},{4,7,377},{4,6,322},{6,4,5424},{3,7,2539},{2,7,413},{0,6,1942},{7,4,5424},{0,6,1942},{3,7,2017},{3,7,2017},{3,7,2017},{3,6,1592},{3,7,1846},{2,7,116},{2,7,116},{2,5,213},{0,7,1531},{1,5,283},{4,7,16},{4,7,16},{4,7,16},{4,6,97},{7,0,1154},{2,7,52},{2,7,52},{1,5,58},{3,5,1154},{1,5,58},{7,4,1576},{5,7,610},{5,6,306}, +{3,6,241},{7,4,1576},{7,5,1576},{3,6,241},{0,6,1906},{7,5,1576},{0,6,1906},{3,0,1576},{3,0,1576},{3,0,1576},{3,0,1576},{2,7,100},{2,7,100},{2,7,100},{2,5,164},{0,6,72},{0,6,72},{4,7,6932},{4,7,3932},{4,7,2807},{3,7,1974},{4,7,8428},{3,7,2981},{2,7,423},{2,6,2373},{1,7,7540},{0,6,1618},{5,7,2921},{4,7,1331},{4,7,206},{4,7,566},{7,3,5424}, +{3,7,2692},{2,7,134},{0,6,1609},{6,5,5424},{0,6,1609},{4,7,2707},{4,7,2707},{4,7,2707},{3,7,1874},{3,7,1513},{2,7,323},{2,7,323},{2,5,294},{0,7,1324},{1,5,184},{4,7,106},{4,7,106},{4,7,106},{4,6,25},{7,1,1160},{2,7,34},{2,7,34},{2,5,5},{7,3,1160},{2,5,5},{7,5,1570},{5,7,628},{4,7,181},{2,7,125},{7,5,1570},{6,6,1586},{2,7,125}, +{0,6,1600},{6,6,1586},{0,6,1600},{3,0,1810},{3,0,1810},{3,0,1810},{3,0,1810},{2,7,298},{2,7,298},{2,7,298},{2,5,290},{0,6,18},{0,6,18},{4,7,7636},{4,7,4156},{4,7,2311},{4,7,2191},{4,7,8428},{3,7,3317},{3,7,185},{3,6,2410},{2,7,8180},{1,6,1722},{5,7,3161},{5,7,1357},{5,7,461},{4,7,342},{5,7,5424},{4,7,2979},{3,7,104},{1,6,1601},{5,6,5424}, +{1,6,1601},{4,7,2307},{4,7,2307},{4,7,2307},{4,6,2082},{3,7,1625},{3,7,181},{3,7,181},{3,5,217},{0,7,1548},{1,5,504},{5,7,457},{5,7,457},{5,7,457},{4,6,233},{6,3,1154},{3,7,100},{3,7,100},{3,5,136},{6,4,1154},{3,5,136},{6,7,1576},{5,7,916},{5,7,20},{3,7,4},{6,7,1576},{7,6,1576},{3,7,4},{0,6,1600},{7,6,1576},{0,6,1600},{4,0,2018}, +{4,0,2018},{4,0,2018},{4,0,2018},{3,6,90},{3,6,90},{3,6,90},{3,5,117},{0,7,104},{0,7,104},{5,7,7862},{4,7,4316},{4,7,2291},{4,7,1691},{4,7,8004},{3,7,3433},{3,7,69},{3,6,1774},{2,7,7580},{1,6,1470},{5,7,3101},{5,7,1209},{5,7,185},{4,7,466},{7,4,4803},{4,7,2579},{3,7,68},{2,6,1448},{7,5,4803},{2,6,1448},{4,7,2291},{4,7,2291},{4,7,2291}, +{4,7,1691},{3,7,2121},{3,7,69},{3,7,69},{3,5,329},{1,7,1539},{1,6,314},{5,7,185},{5,7,185},{5,7,185},{5,6,185},{7,2,1154},{3,7,68},{3,7,68},{2,6,292},{5,5,1154},{2,6,292},{7,6,1252},{6,7,724},{5,7,16},{4,7,25},{7,6,1252},{7,6,1268},{4,7,25},{0,6,1412},{7,6,1268},{0,6,1412},{4,0,1666},{4,0,1666},{4,0,1666},{4,0,1666},{3,7,5}, +{3,7,5},{3,7,5},{3,5,5},{0,7,40},{0,7,40},{5,7,6806},{4,7,4684},{4,7,2659},{4,7,1579},{4,7,7668},{4,7,2988},{3,7,341},{3,6,1390},{2,7,7084},{1,6,1470},{6,7,2645},{5,7,1193},{5,7,169},{5,7,125},{6,6,4059},{4,7,2259},{4,7,234},{2,6,1224},{4,7,4059},{2,6,1224},{4,7,2659},{4,7,2659},{4,7,2659},{4,7,1579},{4,7,2043},{3,7,341},{3,7,341}, +{3,6,234},{1,7,1779},{1,6,314},{5,7,169},{5,7,169},{5,7,169},{5,7,125},{5,6,1152},{4,7,234},{4,7,234},{2,6,68},{4,6,1152},{2,6,68},{7,6,900},{6,7,500},{6,7,100},{4,7,9},{7,6,900},{6,7,884},{4,7,9},{0,6,1220},{6,7,884},{0,6,1220},{4,0,1570},{4,0,1570},{4,0,1570},{4,0,1570},{3,7,85},{3,7,85},{3,7,85},{3,5,149},{1,7,98}, +{1,7,98},{5,7,6077},{5,7,4185},{5,7,3161},{4,7,1912},{5,7,6790},{4,7,2529},{4,7,504},{3,6,1417},{3,7,6199},{1,7,1097},{6,7,1925},{6,7,1301},{5,7,457},{5,7,17},{7,5,3321},{5,7,1754},{4,7,180},{1,7,1093},{6,6,3345},{1,7,1093},{5,7,3161},{5,7,3161},{5,7,3161},{4,7,1912},{4,7,2124},{4,7,504},{4,7,504},{3,6,261},{2,7,1944},{2,6,171},{5,7,457}, +{5,7,457},{5,7,457},{5,7,17},{6,5,1154},{4,7,180},{4,7,180},{3,6,5},{3,7,1154},{3,6,5},{7,7,605},{6,7,401},{6,7,1},{5,7,1},{7,7,605},{6,7,569},{5,7,1},{0,7,1089},{6,7,569},{0,7,1089},{4,0,1768},{4,0,1768},{4,0,1768},{4,0,1768},{4,7,360},{4,7,360},{4,7,360},{3,6,260},{1,7,8},{1,7,8},{5,7,5837},{5,7,3945},{5,7,2921}, +{5,7,2129},{5,7,6054},{4,7,2529},{4,7,504},{4,6,1386},{3,7,5767},{2,7,773},{6,7,1557},{6,7,933},{6,7,533},{5,7,193},{6,7,2754},{5,7,1434},{4,7,404},{2,7,629},{5,7,2754},{2,7,629},{5,7,2921},{5,7,2921},{5,7,2921},{5,7,2129},{4,7,2604},{4,7,504},{4,7,504},{4,6,230},{2,7,2264},{2,6,443},{6,7,533},{6,7,533},{6,7,533},{5,7,193},{7,4,1152}, +{4,7,404},{4,7,404},{3,6,117},{7,5,1152},{3,6,117},{7,7,317},{7,7,245},{6,7,49},{6,7,25},{7,7,317},{7,7,373},{6,7,25},{0,7,625},{7,7,373},{0,7,625},{5,0,2080},{5,0,2080},{5,0,2080},{5,0,2080},{4,7,104},{4,7,104},{4,7,104},{4,6,149},{2,7,148},{2,7,148},{5,7,5981},{5,7,4089},{5,7,3065},{5,7,1921},{5,7,5702},{5,7,2666},{4,7,888}, +{4,7,693},{4,7,5325},{2,7,341},{6,7,1445},{6,7,821},{6,7,421},{6,7,205},{7,6,2306},{5,7,1370},{5,7,346},{2,7,325},{7,6,2274},{2,7,325},{5,7,3065},{5,7,3065},{5,7,3065},{5,7,1921},{5,7,2786},{4,7,888},{4,7,888},{4,6,294},{3,7,2355},{2,7,341},{6,7,421},{6,7,421},{6,7,421},{6,7,205},{7,5,1184},{5,7,346},{5,7,346},{4,6,290},{6,6,1152}, +{4,6,290},{7,7,157},{7,7,85},{7,7,36},{6,7,9},{7,7,157},{7,7,149},{6,7,9},{0,7,289},{7,7,149},{0,7,289},{5,0,1696},{5,0,1696},{5,0,1696},{5,0,1696},{4,7,104},{4,7,104},{4,7,104},{4,6,5},{2,7,52},{2,7,52},{6,7,5433},{5,7,4617},{5,7,3593},{5,7,2097},{5,7,5734},{5,7,2346},{5,7,1322},{4,7,261},{4,7,4909},{2,7,293},{6,7,1589}, +{6,7,965},{6,7,565},{6,7,157},{7,6,1890},{6,7,1146},{5,7,538},{3,7,82},{6,7,1890},{3,7,82},{5,7,3593},{5,7,3593},{5,7,3593},{5,7,2097},{5,7,2818},{5,7,1322},{5,7,1322},{4,7,261},{3,7,2691},{2,7,293},{6,7,565},{6,7,565},{6,7,565},{6,7,157},{6,7,1154},{5,7,538},{5,7,538},{3,7,82},{5,7,1154},{3,7,82},{7,7,125},{7,7,53},{7,7,4}, +{7,7,4},{7,7,125},{7,7,53},{7,7,4},{0,7,81},{7,7,53},{0,7,81},{5,0,1568},{5,0,1568},{5,0,1568},{5,0,1568},{4,7,360},{4,7,360},{4,7,360},{4,6,117},{2,7,212},{2,7,212},{6,7,4866},{6,7,4242},{6,7,3842},{5,7,2754},{6,7,5113},{5,7,2445},{5,7,1421},{4,7,234},{5,7,4804},{3,7,164},{7,7,1203},{7,7,1131},{6,7,1033},{6,7,409},{7,7,1611}, +{6,7,1056},{6,7,656},{4,7,9},{6,7,1584},{4,7,9},{6,7,3842},{6,7,3842},{6,7,3842},{5,7,2754},{5,7,3313},{5,7,1421},{5,7,1421},{4,7,234},{4,7,2875},{3,7,164},{6,7,1033},{6,7,1033},{6,7,1033},{6,7,409},{7,6,1152},{6,7,656},{6,7,656},{4,7,9},{7,6,1184},{4,7,9},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49}, +{0,7,0},{7,7,98},{0,7,0},{5,0,1730},{5,0,1730},{5,0,1730},{5,0,1730},{5,7,397},{5,7,397},{5,7,397},{4,7,234},{3,7,164},{3,7,164},{6,7,4194},{6,7,3570},{6,7,3170},{6,7,2546},{6,7,4137},{5,7,2365},{5,7,1341},{5,7,185},{5,7,3876},{3,7,324},{7,7,771},{7,7,699},{7,7,650},{6,7,521},{7,7,1083},{6,7,864},{6,7,464},{4,7,25},{7,7,1187}, +{4,7,25},{6,7,3170},{6,7,3170},{6,7,3170},{6,7,2546},{6,7,3113},{5,7,1341},{5,7,1341},{5,7,185},{4,7,2491},{3,7,324},{7,7,650},{7,7,650},{7,7,650},{6,7,521},{7,6,832},{6,7,464},{6,7,464},{4,7,25},{6,7,800},{4,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,2146}, +{5,0,2146},{5,0,2146},{5,0,2146},{5,7,317},{5,7,317},{5,7,317},{5,7,185},{3,7,324},{3,7,324},{6,7,3778},{6,7,3154},{6,7,2754},{6,7,2130},{6,7,3417},{6,7,2169},{5,7,1517},{5,7,9},{5,7,3204},{4,7,338},{7,7,467},{7,7,395},{7,7,346},{7,7,274},{7,7,683},{7,7,539},{6,7,400},{5,7,0},{7,7,723},{5,7,0},{6,7,2754},{6,7,2754},{6,7,2754}, +{6,7,2130},{6,7,2393},{5,7,1517},{5,7,1517},{5,7,9},{5,7,2180},{4,7,338},{7,7,346},{7,7,346},{7,7,346},{7,7,274},{7,7,562},{6,7,400},{6,7,400},{5,7,0},{6,7,544},{5,7,0},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,1730},{6,0,1730},{6,0,1730},{6,0,1730},{5,7,493}, +{5,7,493},{5,7,493},{5,7,9},{4,7,338},{4,7,338},{6,7,3618},{6,7,2994},{6,7,2594},{6,7,1970},{6,7,2953},{6,7,1705},{6,7,1305},{5,7,89},{5,7,2788},{4,7,466},{7,7,291},{7,7,219},{7,7,170},{7,7,98},{7,7,411},{7,7,267},{7,7,218},{6,7,16},{7,7,387},{6,7,16},{6,7,2594},{6,7,2594},{6,7,2594},{6,7,1970},{6,7,1929},{6,7,1305},{6,7,1305}, +{5,7,89},{5,7,1764},{4,7,466},{7,7,170},{7,7,170},{7,7,170},{7,7,98},{7,7,290},{7,7,218},{7,7,218},{6,7,16},{7,7,338},{6,7,16},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{6,0,1570},{6,0,1570},{6,0,1570},{6,0,1570},{6,7,905},{6,7,905},{6,7,905},{5,7,89},{4,7,466}, +{4,7,466},{0,5,2665},{0,4,697},{0,3,290},{0,2,841},{0,3,5901},{0,2,4170},{0,2,1802},{0,1,4310},{0,1,6951},{0,1,4671},{0,5,2665},{0,4,697},{0,3,290},{0,2,841},{2,0,5893},{0,2,4170},{0,2,1802},{0,1,4310},{3,0,5893},{0,1,4310},{0,2,4},{0,2,4},{0,2,4},{0,1,4},{0,1,557},{0,1,365},{0,1,365},{0,0,356},{0,0,665},{0,0,392},{0,2,4}, +{0,2,4},{0,2,4},{0,1,4},{0,1,557},{0,1,365},{0,1,365},{0,0,356},{0,0,629},{0,0,356},{3,0,2665},{0,4,697},{0,3,290},{0,2,841},{3,0,2665},{3,1,2665},{0,2,841},{0,2,3145},{3,1,2665},{0,2,3145},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,6,2705},{0,4,617},{0,3,34}, +{0,2,985},{0,4,6754},{0,3,4625},{0,2,1946},{0,1,5030},{0,2,7635},{0,1,5391},{0,6,2705},{0,4,617},{0,3,34},{0,2,985},{1,2,6674},{0,3,4625},{0,2,1946},{0,1,5030},{0,2,6674},{0,1,5030},{0,3,9},{0,3,9},{0,3,9},{0,1,100},{0,1,845},{0,1,461},{0,1,461},{0,0,676},{0,0,1097},{0,0,712},{0,3,9},{0,3,9},{0,3,9},{0,1,100},{0,1,845}, +{0,1,461},{0,1,461},{0,0,676},{1,0,853},{0,0,676},{1,4,2665},{0,4,617},{0,3,34},{0,2,985},{1,4,2665},{2,2,2665},{0,2,985},{0,2,2777},{2,2,2665},{0,2,2777},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,6,2689},{0,5,477},{0,3,34},{0,3,634},{0,4,7538},{0,3,4865},{0,2,2346}, +{0,2,5474},{0,2,8547},{0,1,6367},{0,6,2689},{0,5,477},{0,3,34},{0,3,634},{0,4,7538},{0,3,4865},{0,2,2346},{0,2,5474},{2,1,7538},{0,2,5474},{0,3,25},{0,3,25},{0,3,25},{0,2,16},{0,1,1261},{0,1,685},{0,1,685},{0,1,965},{0,1,1646},{0,0,1160},{0,3,25},{0,3,25},{0,3,25},{0,2,16},{1,0,1213},{0,1,685},{0,1,685},{0,1,965},{1,0,1205}, +{0,1,965},{2,3,2669},{0,5,477},{0,3,34},{0,3,634},{2,3,2669},{6,0,2669},{0,3,634},{0,2,2665},{6,0,2669},{0,2,2665},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,7,2669},{0,5,365},{0,3,290},{0,3,410},{0,4,8578},{0,3,5361},{0,3,2346},{0,2,5618},{0,2,9715},{0,2,6579},{0,7,2669}, +{0,5,365},{0,3,290},{0,3,410},{2,1,8498},{0,3,5361},{0,3,2346},{0,2,5618},{4,0,8498},{0,2,5618},{0,4,0},{0,4,0},{0,4,0},{0,2,16},{0,2,1637},{0,2,977},{0,2,977},{0,1,997},{0,1,1998},{0,1,1358},{0,4,0},{0,4,0},{0,4,0},{0,2,16},{1,0,1629},{0,2,977},{0,2,977},{0,1,997},{0,1,1637},{0,1,997},{3,2,2669},{0,5,365},{1,3,185}, +{0,3,410},{3,2,2669},{5,1,2669},{0,3,410},{0,2,2809},{5,1,2669},{0,2,2809},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,7,2777},{0,6,257},{0,4,277},{0,3,464},{0,5,9677},{0,4,6026},{0,3,2400},{0,2,6086},{0,2,11335},{0,2,7047},{0,7,2777},{0,6,257},{0,4,277},{0,3,464},{3,0,9677}, +{0,4,6026},{0,3,2400},{0,2,6086},{3,1,9677},{0,2,6086},{0,5,16},{0,5,16},{0,5,16},{0,3,64},{0,2,2186},{0,2,1130},{0,2,1130},{0,1,1186},{0,1,2547},{0,1,1547},{0,5,16},{0,5,16},{0,5,16},{0,3,64},{0,2,2186},{0,2,1130},{0,2,1130},{0,1,1186},{0,1,2186},{0,1,1186},{4,1,2669},{0,6,257},{0,4,277},{0,3,464},{4,1,2669},{4,2,2669},{0,3,464}, +{0,3,3209},{4,2,2669},{0,3,3209},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{0,7,3209},{0,6,209},{0,4,389},{0,4,541},{0,6,9765},{0,4,5546},{0,3,2080},{0,2,5990},{0,3,11621},{0,2,6951},{0,7,3209},{0,6,209},{0,4,389},{0,4,541},{1,4,9677},{0,4,5546},{0,3,2080},{0,2,5990},{2,2,9677}, +{0,2,5990},{0,5,80},{0,5,80},{0,5,80},{0,3,64},{0,3,2196},{0,2,970},{0,2,970},{0,1,1058},{0,1,2739},{0,1,1419},{0,5,80},{0,5,80},{0,5,80},{0,3,64},{1,1,2180},{0,2,970},{0,2,970},{0,1,1058},{1,1,2196},{0,1,1058},{5,0,2669},{0,6,145},{1,4,52},{0,4,477},{5,0,2669},{3,3,2669},{0,4,477},{0,3,2809},{3,3,2669},{0,3,2809},{0,0,64}, +{0,0,64},{0,0,64},{0,0,64},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,40},{0,0,40},{0,7,4025},{0,7,441},{0,4,885},{0,4,429},{0,6,9685},{0,4,5450},{0,4,1854},{0,3,6029},{0,3,11925},{0,2,7239},{1,7,3001},{0,7,441},{1,4,344},{0,4,429},{3,1,9685},{0,4,5450},{0,4,1854},{0,3,6029},{4,1,9685},{0,3,6029},{0,6,256},{0,6,256},{0,6,256}, +{0,3,320},{0,3,2228},{0,3,848},{0,3,848},{0,1,1186},{0,2,3171},{0,1,1547},{0,6,256},{0,6,256},{0,6,256},{0,3,320},{2,0,2180},{0,3,848},{0,3,848},{0,1,1186},{3,0,2180},{0,1,1186},{4,2,2677},{0,7,185},{1,4,20},{0,4,173},{4,2,2677},{7,1,2677},{0,4,173},{0,3,2665},{7,1,2677},{0,3,2665},{0,0,256},{0,0,256},{0,0,256},{0,0,256},{0,1,9}, +{0,1,9},{0,1,9},{0,0,36},{0,0,72},{0,0,72},{1,7,4141},{0,7,617},{1,4,1500},{0,4,701},{0,7,9690},{0,5,5001},{0,4,1214},{0,3,5277},{0,3,12613},{0,3,7213},{1,7,2985},{1,6,465},{1,4,344},{1,4,524},{4,0,9674},{0,5,5001},{0,4,1214},{0,3,5277},{3,2,9674},{0,3,5277},{0,7,601},{0,7,601},{0,7,601},{0,4,601},{0,4,2178},{0,3,656},{0,3,656}, +{0,2,866},{0,2,3171},{0,2,1827},{1,5,101},{1,5,101},{1,5,101},{1,3,109},{0,4,2178},{0,3,656},{0,3,656},{0,2,866},{2,1,2178},{0,2,866},{5,1,2669},{0,7,41},{2,4,181},{0,4,125},{5,1,2669},{4,3,2669},{0,4,125},{0,3,2777},{4,3,2669},{0,3,2777},{0,0,576},{0,0,576},{0,0,576},{0,0,576},{0,1,25},{0,1,25},{0,1,25},{0,1,49},{0,0,232}, +{0,0,232},{1,7,4582},{0,7,1274},{1,5,1446},{0,4,1466},{0,7,9789},{0,5,4794},{0,4,953},{0,3,4890},{0,4,13038},{0,3,6826},{1,7,3426},{1,7,290},{1,5,290},{1,4,443},{2,4,9685},{0,5,4794},{0,4,953},{0,3,4890},{7,0,9685},{0,3,4890},{0,7,1105},{0,7,1105},{0,7,1105},{0,4,1105},{0,5,2210},{0,4,592},{0,4,592},{0,2,596},{0,2,3477},{0,2,1557},{1,6,26}, +{1,6,26},{1,6,26},{1,4,82},{1,3,2180},{0,4,592},{0,4,592},{0,2,596},{1,2,2180},{0,2,596},{6,0,2677},{0,7,185},{1,5,289},{0,4,377},{6,0,2677},{5,3,2677},{0,4,377},{0,3,3209},{5,3,2677},{0,3,3209},{0,0,1089},{0,0,1089},{0,0,1089},{0,0,1089},{0,2,4},{0,2,4},{0,2,4},{0,1,4},{0,1,365},{0,1,365},{1,7,5382},{1,7,1350},{1,5,1510}, +{1,5,1738},{0,7,10285},{0,6,4406},{0,5,971},{0,3,4954},{0,4,13534},{0,3,6890},{2,7,3454},{1,7,194},{1,5,354},{1,5,582},{3,3,9674},{0,6,4406},{0,5,971},{0,3,4954},{6,1,9674},{0,3,4954},{1,6,1214},{1,6,1214},{1,6,1214},{1,4,1206},{0,5,2210},{0,4,400},{0,4,400},{0,2,628},{0,2,4021},{0,2,1589},{1,6,58},{1,6,58},{1,6,58},{1,4,50},{2,2,2178}, +{0,4,400},{0,4,400},{0,2,628},{5,0,2178},{0,2,628},{4,4,2669},{1,7,145},{2,5,74},{0,5,130},{4,4,2669},{7,2,2669},{0,5,130},{0,4,2845},{7,2,2669},{0,4,2845},{1,0,1205},{1,0,1205},{1,0,1205},{1,0,1205},{0,3,9},{0,3,9},{0,3,9},{0,1,100},{0,1,461},{0,1,461},{1,7,6566},{1,7,1638},{1,5,1958},{1,5,1578},{1,7,10830},{0,6,4118},{0,5,443}, +{0,4,4785},{0,4,14414},{0,3,7338},{2,7,3390},{1,7,482},{2,5,371},{1,5,422},{4,2,9674},{0,6,4118},{0,5,443},{0,4,4785},{5,2,9674},{0,4,4785},{1,7,1382},{1,7,1382},{1,7,1382},{1,4,1430},{0,6,2178},{0,5,442},{0,5,442},{0,3,641},{0,3,4242},{0,2,1877},{1,7,226},{1,7,226},{1,7,226},{1,4,274},{3,1,2178},{0,5,442},{0,5,442},{0,3,641},{4,1,2178}, +{0,3,641},{5,3,2669},{1,7,257},{2,5,10},{0,5,2},{5,3,2669},{6,3,2669},{0,5,2},{0,4,2669},{6,3,2669},{0,4,2669},{1,0,1381},{1,0,1381},{1,0,1381},{1,0,1381},{0,3,25},{0,3,25},{0,3,25},{0,2,16},{0,1,685},{0,1,685},{1,7,8134},{1,7,2310},{1,6,2671},{1,5,1802},{1,7,11086},{0,7,4109},{0,5,299},{0,4,4193},{0,5,14830},{0,4,7442},{2,7,3710}, +{2,7,490},{2,5,323},{2,5,563},{5,1,9669},{0,7,4109},{0,5,299},{0,4,4193},{4,3,9669},{0,4,4193},{1,7,1734},{1,7,1734},{1,7,1734},{1,5,1721},{0,7,2228},{0,5,218},{0,5,218},{0,3,305},{0,3,4626},{0,3,2241},{2,6,125},{2,6,125},{2,6,125},{2,4,125},{4,0,2180},{0,5,218},{0,5,218},{0,3,305},{3,2,2180},{0,3,305},{6,2,2665},{2,7,369},{3,5,181}, +{1,5,117},{6,2,2665},{5,4,2665},{1,5,117},{0,4,2749},{5,4,2665},{0,4,2749},{1,0,1685},{1,0,1685},{1,0,1685},{1,0,1685},{0,4,0},{0,4,0},{0,4,0},{0,2,16},{0,2,977},{0,2,977},{2,7,9153},{1,7,3525},{1,6,3220},{1,5,2513},{1,7,11833},{0,7,3686},{0,6,548},{0,4,3986},{0,5,15577},{0,4,7235},{3,7,4141},{2,7,481},{2,6,309},{2,5,428},{6,0,9674}, +{0,7,3686},{0,6,548},{0,4,3986},{3,4,9674},{0,4,3986},{1,7,2436},{1,7,2436},{1,7,2436},{1,5,2189},{0,7,2210},{0,5,272},{0,5,272},{0,3,233},{0,3,5364},{0,3,2169},{2,7,40},{2,7,40},{2,7,40},{2,5,104},{2,4,2178},{0,5,272},{0,5,272},{0,3,233},{7,0,2178},{0,3,233},{7,1,2669},{2,7,477},{2,6,305},{0,6,292},{7,1,2669},{4,5,2669},{0,6,292}, +{0,4,3145},{4,5,2669},{0,4,3145},{1,0,2180},{1,0,2180},{1,0,2180},{1,0,2180},{0,5,16},{0,5,16},{0,5,16},{0,3,64},{0,2,1130},{0,2,1130},{2,7,10154},{1,7,4946},{1,6,4049},{1,6,2853},{1,7,12838},{0,7,3719},{0,6,133},{0,4,4211},{0,6,16286},{0,4,7346},{3,7,4061},{2,7,881},{2,6,325},{2,6,629},{4,4,9669},{0,7,3718},{0,6,132},{0,4,4210},{7,2,9669}, +{0,4,4210},{1,7,3265},{1,7,3265},{1,7,3265},{1,6,2789},{0,7,2467},{0,6,69},{0,6,69},{0,3,442},{0,4,5602},{0,3,2290},{2,7,40},{2,7,40},{2,7,40},{2,5,40},{3,3,2180},{0,6,68},{0,6,68},{0,3,441},{6,1,2180},{0,3,441},{5,5,2665},{3,7,617},{3,6,100},{0,6,68},{5,5,2665},{3,6,2665},{0,6,68},{0,5,2885},{3,6,2665},{0,5,2885},{1,0,2689}, +{1,0,2689},{1,0,2689},{1,0,2689},{0,5,17},{0,5,17},{0,5,17},{0,3,1},{0,2,1341},{0,2,1341},{2,7,10666},{2,7,5146},{2,6,4206},{1,6,2933},{2,7,13606},{0,7,4215},{0,6,181},{0,5,3914},{0,6,15454},{0,4,7122},{3,7,4365},{3,7,1097},{3,6,404},{2,6,421},{5,3,9669},{1,7,4133},{0,6,100},{0,5,3833},{6,3,9669},{0,5,3833},{2,7,3777},{2,7,3777},{2,7,3777}, +{1,6,2933},{1,7,2805},{0,6,181},{0,6,181},{0,4,275},{0,4,5282},{0,3,2130},{2,7,296},{2,7,296},{2,7,296},{2,5,232},{4,2,2180},{0,6,100},{0,6,100},{0,4,194},{5,2,2180},{0,4,194},{6,4,2665},{3,7,697},{3,6,4},{1,6,4},{6,4,2665},{7,4,2665},{1,6,4},{0,5,2677},{7,4,2665},{0,5,2677},{1,0,2929},{1,0,2929},{1,0,2929},{1,0,2929},{0,6,81}, +{0,6,81},{0,6,81},{0,3,145},{0,3,1289},{0,3,1289},{2,7,11690},{2,7,5434},{2,7,4085},{2,6,3198},{2,7,13510},{1,7,4470},{1,6,585},{0,5,3690},{0,6,15134},{0,5,6210},{3,7,5053},{3,7,1177},{3,6,308},{2,6,597},{6,2,9670},{1,7,4181},{1,6,296},{0,5,3401},{5,4,9670},{0,5,3401},{2,7,3409},{2,7,3409},{2,7,3409},{2,6,3134},{1,7,2565},{0,7,323},{0,7,323}, +{0,4,323},{0,5,5085},{0,4,1634},{3,7,153},{3,7,153},{3,7,153},{3,5,145},{5,1,2186},{0,7,34},{0,7,34},{0,4,34},{7,1,2186},{0,4,34},{7,3,2665},{4,7,937},{3,6,164},{1,6,100},{7,3,2665},{6,5,2665},{1,6,100},{0,5,2725},{6,5,2665},{0,5,2725},{2,0,3085},{2,0,3085},{2,0,3085},{2,0,3085},{1,5,290},{1,5,290},{1,5,290},{1,3,298},{0,3,985}, +{0,3,985},{3,7,12062},{2,7,6370},{2,7,3743},{2,6,3018},{2,7,14014},{1,7,4758},{1,6,603},{1,5,4049},{0,7,14638},{0,5,5310},{4,7,4958},{3,7,1726},{3,7,334},{3,6,419},{7,1,9669},{1,7,4694},{0,7,341},{0,5,3374},{4,5,9669},{0,5,3374},{2,7,3454},{2,7,3454},{2,7,3454},{2,6,2729},{1,7,2754},{1,6,314},{1,6,314},{1,4,289},{0,5,4626},{0,4,1121},{3,7,45}, +{3,7,45},{3,7,45},{3,5,109},{6,0,2180},{0,7,52},{0,7,52},{0,4,160},{3,4,2180},{0,4,160},{5,7,2665},{4,7,1009},{4,6,293},{2,6,293},{5,7,2665},{5,6,2665},{2,6,293},{0,5,3085},{5,6,2665},{0,5,3085},{2,0,2725},{2,0,2725},{2,0,2725},{2,0,2725},{1,6,89},{1,6,89},{1,6,89},{1,4,145},{0,3,949},{0,3,949},{3,7,12414},{3,7,7246},{2,7,3983}, +{2,7,2879},{2,7,15006},{1,7,5558},{1,7,163},{1,5,4161},{0,7,14190},{0,5,5054},{4,7,5246},{4,7,2186},{3,7,302},{3,6,659},{5,5,9670},{2,7,4926},{1,7,163},{0,5,3758},{3,6,9670},{0,5,3758},{2,7,3902},{2,7,3902},{2,7,3902},{2,6,2777},{1,7,3330},{1,7,82},{1,7,82},{1,4,401},{0,6,4490},{0,4,1073},{3,7,221},{3,7,221},{3,7,221},{3,6,34},{5,2,2186}, +{1,7,82},{1,7,82},{0,5,277},{7,2,2186},{0,5,277},{6,6,2665},{5,7,1313},{4,7,130},{1,7,82},{6,6,2665},{4,7,2665},{1,7,82},{0,6,2929},{4,7,2665},{0,6,2929},{2,0,2677},{2,0,2677},{2,0,2677},{2,0,2677},{1,6,9},{1,6,9},{1,6,9},{1,4,1},{0,4,673},{0,4,673},{3,7,13278},{3,7,7502},{3,7,4254},{2,7,2895},{3,7,15045},{2,7,6114},{1,7,147}, +{1,6,3978},{0,7,14254},{0,6,4818},{4,7,5918},{4,7,2378},{4,7,443},{3,7,426},{6,4,9670},{2,7,5438},{1,7,83},{0,6,3218},{7,4,9670},{0,6,3218},{3,7,4253},{3,7,4253},{3,7,4253},{2,7,2894},{2,7,3054},{1,7,146},{1,7,146},{1,5,296},{0,6,3978},{0,5,821},{4,7,442},{4,7,442},{4,7,442},{3,6,194},{6,1,2186},{1,7,82},{1,7,82},{0,5,37},{6,3,2186}, +{0,5,37},{7,5,2665},{5,7,1361},{4,7,2},{2,7,10},{7,5,2665},{6,6,2689},{2,7,10},{0,6,2689},{6,6,2689},{0,6,2689},{2,0,2885},{2,0,2885},{2,0,2885},{2,0,2885},{1,7,65},{1,7,65},{1,7,65},{1,4,113},{0,4,625},{0,4,625},{3,7,13261},{3,7,7409},{3,7,4045},{3,7,3209},{3,7,14116},{2,7,5615},{2,7,574},{1,6,3165},{0,7,13437},{0,6,3429},{5,7,5269}, +{4,7,2275},{4,7,250},{3,7,505},{5,6,8712},{3,7,4724},{2,7,250},{0,6,2405},{4,6,8712},{0,6,2405},{3,7,4045},{3,7,4045},{3,7,4045},{3,7,3209},{2,7,3150},{2,7,574},{2,7,574},{1,5,296},{0,6,3850},{0,5,453},{4,7,250},{4,7,250},{4,7,250},{4,6,169},{7,0,2180},{2,7,250},{2,7,250},{1,5,40},{3,5,2180},{1,5,40},{6,7,2180},{5,7,1168},{4,7,81}, +{2,7,25},{6,7,2180},{5,7,2180},{2,7,25},{0,6,2180},{5,7,2180},{0,6,2180},{3,0,3145},{3,0,3145},{3,0,3145},{3,0,3145},{1,7,305},{1,7,305},{1,7,305},{1,5,292},{0,5,449},{0,5,449},{4,7,11894},{3,7,7634},{3,7,4270},{3,7,2750},{3,7,13315},{2,7,5354},{2,7,313},{1,6,2634},{1,7,12414},{0,6,2250},{5,7,4369},{4,7,2365},{4,7,340},{4,7,160},{7,3,7590}, +{3,7,4094},{2,7,232},{0,6,1721},{6,5,7590},{0,6,1721},{3,7,4270},{3,7,4270},{3,7,4270},{3,7,2750},{2,7,3717},{2,7,313},{2,7,313},{2,5,302},{0,7,3546},{0,5,498},{4,7,340},{4,7,340},{4,7,340},{4,6,97},{7,1,2186},{2,7,232},{2,7,232},{1,5,130},{7,3,2186},{1,5,130},{6,7,1649},{6,7,1025},{5,7,9},{3,7,1},{6,7,1649},{7,6,1625},{3,7,1}, +{0,6,1685},{7,6,1625},{0,6,1685},{3,0,2749},{3,0,2749},{3,0,2749},{3,0,2749},{2,7,117},{2,7,117},{2,7,117},{2,5,181},{0,5,377},{0,5,377},{4,7,11078},{4,7,7478},{3,7,4878},{3,7,2750},{4,7,12662},{3,7,5031},{2,7,489},{2,6,1911},{1,7,11470},{0,6,1610},{5,7,3841},{5,7,1949},{4,7,692},{4,7,32},{5,7,6662},{4,7,3641},{3,7,442},{0,6,1385},{5,6,6662}, +{0,6,1385},{3,7,4878},{3,7,4878},{3,7,4878},{3,7,2750},{3,7,3795},{2,7,489},{2,7,489},{2,5,366},{0,7,3354},{0,6,454},{4,7,692},{4,7,692},{4,7,692},{4,7,32},{6,3,2180},{3,7,442},{3,7,442},{0,6,229},{6,4,2180},{0,6,229},{7,6,1201},{6,7,689},{5,7,25},{4,7,16},{7,6,1201},{7,6,1225},{4,7,16},{0,6,1381},{7,6,1225},{0,6,1381},{3,0,2669}, +{3,0,2669},{3,0,2669},{3,0,2669},{2,7,5},{2,7,5},{2,7,5},{2,5,5},{0,6,229},{0,6,229},{4,7,10646},{4,7,7046},{4,7,5021},{3,7,3134},{4,7,11526},{3,7,4503},{2,7,1049},{2,6,1479},{1,7,10910},{0,6,1354},{5,7,3569},{5,7,1677},{5,7,653},{4,7,160},{7,4,5829},{4,7,3065},{3,7,410},{1,6,1209},{7,5,5829},{1,6,1209},{4,7,5021},{4,7,5021},{4,7,5021}, +{3,7,3134},{3,7,3875},{2,7,1049},{2,7,1049},{2,6,323},{0,7,3546},{0,6,198},{5,7,653},{5,7,653},{5,7,653},{4,7,160},{7,2,2180},{3,7,410},{3,7,410},{1,6,53},{5,5,2180},{1,6,53},{7,6,865},{6,7,481},{6,7,81},{4,7,16},{7,6,865},{6,7,841},{4,7,16},{0,6,1205},{6,7,841},{0,6,1205},{3,0,2845},{3,0,2845},{3,0,2845},{3,0,2845},{2,7,149}, +{2,7,149},{2,7,149},{2,5,85},{0,6,149},{0,6,149},{4,7,10598},{4,7,6998},{4,7,4973},{4,7,3353},{4,7,10774},{3,7,4359},{3,7,995},{2,6,1431},{2,7,10294},{0,7,1242},{6,7,3329},{5,7,1661},{5,7,637},{5,7,197},{6,6,5085},{4,7,2745},{3,7,634},{0,7,1098},{4,7,5085},{0,7,1098},{4,7,4973},{4,7,4973},{4,7,4973},{4,7,3353},{3,7,4339},{3,7,995},{3,7,995}, +{2,6,275},{1,7,3845},{0,6,326},{5,7,637},{5,7,637},{5,7,637},{5,7,197},{5,6,2178},{3,7,634},{3,7,634},{1,6,37},{4,6,2178},{1,6,37},{7,7,605},{6,7,401},{6,7,1},{5,7,1},{7,7,605},{6,7,569},{5,7,1},{0,7,1089},{6,7,569},{0,7,1089},{4,0,3209},{4,0,3209},{4,0,3209},{4,0,3209},{3,7,370},{3,7,370},{3,7,370},{2,6,274},{0,7,153}, +{0,7,153},{5,7,9925},{4,7,7403},{4,7,5378},{4,7,3218},{4,7,10387},{4,7,4627},{3,7,1292},{3,6,1477},{2,7,9727},{0,7,621},{6,7,2609},{5,7,1949},{5,7,925},{5,7,89},{7,5,4347},{5,7,2384},{4,7,666},{0,7,612},{6,6,4371},{0,7,612},{4,7,5378},{4,7,5378},{4,7,5378},{4,7,3218},{4,7,4762},{3,7,1292},{3,7,1292},{3,6,321},{1,7,4106},{1,6,469},{5,7,925}, +{5,7,925},{5,7,925},{5,7,89},{6,5,2180},{4,7,666},{4,7,666},{2,6,104},{3,7,2180},{2,6,104},{7,7,290},{7,7,218},{6,7,64},{6,7,16},{7,7,290},{7,7,338},{6,7,16},{0,7,576},{7,7,338},{0,7,576},{4,0,2777},{4,0,2777},{4,0,2777},{4,0,2777},{3,7,136},{3,7,136},{3,7,136},{3,5,200},{0,7,45},{0,7,45},{5,7,9269},{5,7,7377},{4,7,6146}, +{4,7,3506},{5,7,10044},{4,7,4211},{3,7,1964},{3,7,836},{3,7,9185},{0,7,477},{6,7,2241},{6,7,1617},{6,7,1217},{5,7,265},{6,7,3780},{5,7,2064},{4,7,890},{1,7,257},{5,7,3780},{1,7,257},{4,7,6146},{4,7,6146},{4,7,6146},{4,7,3506},{4,7,4826},{3,7,1964},{3,7,1964},{3,6,337},{2,7,4590},{0,7,477},{6,7,1217},{6,7,1217},{6,7,1217},{5,7,265},{7,4,2178}, +{4,7,890},{4,7,890},{1,7,257},{7,5,2178},{1,7,257},{7,7,146},{7,7,74},{7,7,25},{6,7,16},{7,7,146},{7,7,130},{6,7,16},{0,7,256},{7,7,130},{0,7,256},{4,0,2665},{4,0,2665},{4,0,2665},{4,0,2665},{3,7,200},{3,7,200},{3,7,200},{3,6,13},{0,7,221},{0,7,221},{5,7,8997},{5,7,7105},{5,7,6081},{4,7,4178},{5,7,9276},{4,7,4179},{4,7,2154}, +{3,7,356},{3,7,8721},{1,7,209},{6,7,2129},{6,7,1505},{6,7,1105},{6,7,673},{7,6,3332},{5,7,2000},{5,7,976},{2,7,73},{7,6,3300},{2,7,73},{5,7,6081},{5,7,6081},{5,7,6081},{4,7,4178},{4,7,5274},{4,7,2154},{4,7,2154},{3,7,356},{2,7,4878},{1,7,209},{6,7,1105},{6,7,1105},{6,7,1105},{6,7,673},{7,5,2210},{5,7,976},{5,7,976},{2,7,73},{6,6,2178}, +{2,7,73},{7,7,130},{7,7,58},{7,7,9},{7,7,1},{7,7,130},{7,7,50},{7,7,1},{0,7,64},{7,7,50},{0,7,64},{4,0,2809},{4,0,2809},{4,0,2809},{4,0,2809},{3,7,520},{3,7,520},{3,7,520},{3,6,61},{1,7,145},{1,7,145},{5,7,9109},{5,7,7217},{5,7,6193},{5,7,4301},{5,7,8892},{4,7,4531},{4,7,2506},{3,7,260},{4,7,8587},{1,7,289},{6,7,2273}, +{6,7,1649},{6,7,1249},{6,7,625},{7,6,2916},{6,7,1956},{5,7,1168},{2,7,25},{6,7,2916},{2,7,25},{5,7,6193},{5,7,6193},{5,7,6193},{5,7,4301},{5,7,5976},{4,7,2506},{4,7,2506},{3,7,260},{3,7,5277},{1,7,289},{6,7,1249},{6,7,1249},{6,7,1249},{6,7,625},{6,7,2180},{5,7,1168},{5,7,1168},{2,7,25},{5,7,2180},{2,7,25},{7,7,242},{7,7,170},{7,7,121}, +{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,3209},{4,0,3209},{4,0,3209},{4,0,3209},{4,7,481},{4,7,481},{4,7,481},{3,7,260},{1,7,289},{1,7,289},{6,7,8325},{5,7,6749},{5,7,5725},{5,7,3833},{5,7,7866},{5,7,4082},{4,7,2470},{4,7,265},{4,7,7219},{2,7,365},{7,7,1842},{6,7,1460},{6,7,1060},{6,7,436},{7,6,2241}, +{6,7,1425},{6,7,1025},{3,7,1},{6,7,2169},{3,7,1},{5,7,5725},{5,7,5725},{5,7,5725},{5,7,3833},{5,7,4950},{4,7,2470},{4,7,2470},{4,7,265},{3,7,4521},{2,7,365},{6,7,1060},{6,7,1060},{6,7,1060},{6,7,436},{6,7,1649},{6,7,1025},{6,7,1025},{3,7,1},{7,6,1625},{3,7,1},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49}, +{0,7,0},{7,7,98},{0,7,0},{5,0,2809},{5,0,2809},{5,0,2809},{5,0,2809},{4,7,445},{4,7,445},{4,7,445},{4,6,202},{2,7,365},{2,7,365},{6,7,7093},{6,7,6469},{5,7,5581},{5,7,3689},{5,7,7226},{5,7,3442},{5,7,2418},{4,7,25},{4,7,6275},{2,7,509},{7,7,1266},{7,7,1194},{6,7,1028},{6,7,404},{7,7,1686},{6,7,1089},{6,7,689},{4,7,16},{6,7,1641}, +{4,7,16},{5,7,5581},{5,7,5581},{5,7,5581},{5,7,3689},{5,7,4310},{5,7,2418},{5,7,2418},{4,7,25},{3,7,4121},{2,7,509},{6,7,1028},{6,7,1028},{6,7,1028},{6,7,404},{7,6,1201},{6,7,689},{6,7,689},{4,7,16},{7,6,1225},{4,7,16},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,2665}, +{5,0,2665},{5,0,2665},{5,0,2665},{4,7,685},{4,7,685},{4,7,685},{4,7,25},{2,7,509},{2,7,509},{6,7,6117},{6,7,5493},{6,7,5093},{5,7,3801},{6,7,6098},{5,7,3058},{5,7,2034},{4,7,41},{4,7,5587},{3,7,613},{7,7,818},{7,7,746},{7,7,697},{6,7,500},{7,7,1142},{6,7,881},{6,7,481},{4,7,16},{6,7,1241},{4,7,16},{6,7,5093},{6,7,5093},{6,7,5093}, +{5,7,3801},{5,7,3926},{5,7,2034},{5,7,2034},{4,7,41},{4,7,3562},{3,7,613},{7,7,697},{7,7,697},{7,7,697},{6,7,500},{7,6,865},{6,7,481},{6,7,481},{4,7,16},{6,7,841},{4,7,16},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,2777},{5,0,2777},{5,0,2777},{5,0,2777},{5,7,1010}, +{5,7,1010},{5,7,1010},{4,7,41},{3,7,613},{3,7,613},{6,7,5397},{6,7,4773},{6,7,4373},{6,7,3749},{6,7,5074},{5,7,2930},{5,7,1906},{4,7,313},{5,7,4753},{3,7,725},{7,7,498},{7,7,426},{7,7,377},{7,7,305},{7,7,726},{7,7,582},{6,7,401},{5,7,1},{7,7,774},{5,7,1},{6,7,4373},{6,7,4373},{6,7,4373},{6,7,3749},{5,7,3798},{5,7,1906},{5,7,1906}, +{4,7,313},{4,7,3130},{3,7,725},{7,7,377},{7,7,377},{7,7,377},{7,7,305},{7,7,605},{6,7,401},{6,7,401},{5,7,1},{6,7,569},{5,7,1},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{5,0,3145},{5,0,3145},{5,0,3145},{5,0,3145},{5,7,882},{5,7,882},{5,7,882},{4,7,313},{3,7,725}, +{3,7,725},{1,7,34142},{0,7,5184},{0,5,609},{0,5,4841},{1,7,46442},{0,7,24449},{0,5,9741},{0,4,24761},{0,5,65162},{0,3,40820},{0,7,10048},{0,7,2880},{0,5,545},{0,4,3204},{1,4,18070},{0,4,13297},{0,4,6453},{0,2,13857},{2,2,18070},{0,2,13857},{0,3,9},{0,3,9},{0,3,9},{0,2,36},{0,1,1145},{0,1,617},{0,1,617},{0,1,977},{0,0,1505},{0,0,1036},{0,3,9}, +{0,3,9},{0,3,9},{0,2,36},{1,0,1129},{0,1,617},{0,1,617},{0,1,977},{1,0,1105},{0,1,977},{4,2,9250},{0,7,2880},{0,5,545},{0,4,3204},{4,2,9250},{5,2,9250},{0,4,3204},{0,3,9280},{5,2,9250},{0,3,9280},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,38782},{0,7,6720},{0,5,305}, +{0,5,3801},{1,7,51082},{0,7,24961},{0,5,8701},{0,4,25849},{0,5,65535},{0,4,42094},{1,7,10502},{0,7,2624},{0,5,241},{0,4,3044},{3,1,19334},{0,4,14065},{0,4,6293},{0,3,14756},{4,1,19334},{0,3,14756},{0,4,4},{0,4,4},{0,4,4},{0,2,4},{0,2,1537},{0,1,937},{0,1,937},{0,1,977},{0,1,1898},{0,1,1338},{0,4,4},{0,4,4},{0,4,4},{0,2,4},{1,0,1513}, +{0,1,937},{0,1,937},{0,1,977},{0,1,1537},{0,1,977},{5,1,9256},{0,7,2624},{0,5,241},{0,4,3044},{5,1,9256},{7,1,9256},{0,4,3044},{0,3,9280},{7,1,9256},{0,3,9280},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,44190},{0,7,9024},{0,5,769},{0,5,3529},{1,7,56490},{0,7,26241},{0,5,8429}, +{0,4,27705},{0,5,65535},{0,4,43950},{1,7,10854},{0,7,2624},{0,5,193},{0,5,2953},{2,3,20689},{0,5,14598},{0,4,6389},{0,3,15012},{6,0,20689},{0,3,15012},{0,4,36},{0,4,36},{0,4,36},{0,2,100},{0,2,1985},{0,2,1061},{0,2,1061},{0,1,1105},{0,1,2346},{0,1,1466},{0,4,36},{0,4,36},{0,4,36},{0,2,100},{0,2,1985},{0,2,1061},{0,2,1061},{0,1,1105},{0,1,1985}, +{0,1,1105},{6,0,9256},{0,7,2624},{0,5,193},{0,5,2953},{6,0,9256},{6,2,9256},{0,5,2953},{0,3,9536},{6,2,9256},{0,3,9536},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,50366},{0,7,12096},{0,6,1101},{0,5,4025},{1,7,62666},{0,7,28289},{0,5,8925},{0,5,28912},{0,6,65535},{0,4,46574},{1,7,11462}, +{0,7,2880},{0,6,317},{0,5,2425},{4,0,22137},{0,5,15206},{0,4,6741},{0,3,15524},{3,2,22137},{0,3,15524},{0,5,1},{0,5,1},{0,5,1},{0,3,9},{0,2,2561},{0,2,1285},{0,2,1285},{0,1,1361},{0,1,2922},{0,1,1722},{0,5,1},{0,5,1},{0,5,1},{0,3,9},{1,1,2561},{0,2,1285},{0,2,1285},{0,1,1361},{2,0,2521},{0,1,1361},{5,2,9250},{0,7,2880},{0,6,317}, +{0,5,2425},{5,2,9250},{5,3,9250},{0,5,2425},{0,4,9640},{5,3,9250},{0,4,9640},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,58232},{0,7,16470},{0,6,129},{0,6,3489},{1,7,65535},{0,7,31511},{0,6,10213},{0,5,29110},{0,6,65535},{0,4,50444},{1,7,12452},{0,7,3474},{0,6,29},{0,5,2137},{2,4,23851}, +{0,6,16172},{0,5,7037},{0,3,16406},{7,0,23851},{0,3,16406},{0,6,4},{0,6,4},{0,6,4},{0,3,36},{0,3,3232},{0,2,1690},{0,2,1690},{0,1,1802},{0,1,3723},{0,1,2163},{0,6,4},{0,6,4},{0,6,4},{0,3,36},{1,1,3200},{0,2,1690},{0,2,1690},{0,1,1802},{2,0,3232},{0,1,1802},{6,1,9256},{1,7,3232},{0,6,29},{0,5,2137},{6,1,9256},{6,3,9256},{0,5,2137}, +{0,4,9298},{6,3,9256},{0,4,9298},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{1,7,65535},{0,7,21174},{0,6,81},{0,6,2545},{1,7,65535},{0,7,35191},{0,6,9269},{0,5,30102},{0,6,65535},{0,5,54602},{1,7,13604},{0,7,4274},{0,6,45},{0,5,2153},{4,1,25472},{0,6,16620},{0,5,7053},{0,3,17462},{4,2,25472}, +{0,3,17462},{0,6,36},{0,6,36},{0,6,36},{0,4,49},{0,3,3872},{0,3,2132},{0,3,2132},{0,1,2330},{0,1,4571},{0,1,2691},{0,6,36},{0,6,36},{0,6,36},{0,4,49},{0,3,3872},{0,3,2132},{0,3,2132},{0,1,2330},{1,1,3872},{0,1,2330},{7,0,9250},{1,7,3488},{0,6,45},{0,5,2153},{7,0,9250},{3,5,9250},{0,5,2153},{0,4,9266},{3,5,9250},{0,4,9266},{0,0,0}, +{0,0,0},{0,0,0},{0,0,0},{0,0,36},{0,0,36},{0,0,36},{0,0,100},{0,0,136},{0,0,136},{2,7,65535},{1,7,25204},{0,6,805},{0,6,2373},{1,7,65535},{0,7,39263},{0,6,8769},{0,5,31402},{0,6,65535},{0,5,55902},{1,7,14880},{1,7,5024},{0,6,321},{0,6,1889},{5,0,26756},{0,6,17000},{0,5,7049},{0,4,18139},{6,1,26756},{0,4,18139},{0,7,5},{0,7,5},{0,7,5}, +{0,4,5},{0,3,4468},{0,3,2248},{0,3,2248},{0,2,2722},{0,2,5411},{0,1,3227},{0,7,5},{0,7,5},{0,7,5},{0,4,5},{2,0,4420},{0,3,2248},{0,3,2248},{0,2,2722},{3,0,4420},{0,2,2722},{5,4,9250},{1,7,4000},{1,6,185},{0,6,1885},{5,4,9250},{7,3,9250},{0,6,1885},{0,4,9490},{7,3,9250},{0,4,9490},{0,0,4},{0,0,4},{0,0,4},{0,0,4},{0,0,16}, +{0,0,16},{0,0,16},{0,0,64},{0,0,100},{0,0,100},{2,7,65535},{1,7,29620},{0,7,1306},{0,6,3061},{2,7,65535},{0,7,43055},{0,6,8145},{0,6,31878},{0,7,65535},{0,5,56670},{2,7,14924},{1,7,5344},{0,7,406},{0,6,1617},{4,2,26756},{0,6,16744},{0,5,6553},{0,4,17195},{5,2,26756},{0,4,17195},{0,7,181},{0,7,181},{0,7,181},{0,4,181},{0,4,4418},{0,3,2056},{0,3,2056}, +{0,2,2210},{0,2,5411},{0,2,3171},{0,7,181},{0,7,181},{0,7,181},{0,4,181},{0,4,4418},{0,3,2056},{0,3,2056},{0,2,2210},{2,1,4418},{0,2,2210},{6,3,9248},{2,7,4292},{0,7,306},{0,6,1517},{6,3,9248},{6,4,9248},{0,6,1517},{0,5,9698},{6,4,9248},{0,5,9698},{0,0,100},{0,0,100},{0,0,100},{0,0,100},{0,0,16},{0,0,16},{0,0,16},{0,0,0},{0,0,36}, +{0,0,36},{2,7,65535},{1,7,35659},{0,7,865},{0,7,2657},{2,7,65535},{1,7,48315},{0,7,8072},{0,6,29745},{0,7,65535},{0,5,58605},{2,7,15347},{1,7,6163},{1,7,270},{0,6,1770},{5,1,26756},{0,7,15992},{0,6,5378},{0,4,16592},{6,2,26756},{0,4,16592},{0,7,685},{0,7,685},{0,7,685},{0,5,370},{0,5,4450},{0,4,1768},{0,4,1768},{0,2,1940},{0,2,5717},{0,2,2901},{1,7,234}, +{1,7,234},{1,7,234},{1,4,250},{1,3,4420},{0,4,1768},{0,4,1768},{0,2,1940},{1,2,4420},{0,2,1940},{7,2,9250},{3,7,4820},{1,7,45},{0,6,1409},{7,2,9250},{5,5,9250},{0,6,1409},{0,5,9320},{5,5,9250},{0,5,9320},{0,0,361},{0,0,361},{0,0,361},{0,0,361},{0,1,0},{0,1,0},{0,1,0},{0,0,81},{0,0,117},{0,0,117},{2,7,65535},{1,7,40299},{0,7,1405}, +{0,7,2173},{2,7,65535},{1,7,50747},{0,7,6068},{0,6,28101},{0,7,65535},{0,5,59897},{2,7,15659},{1,7,6963},{1,7,74},{1,6,2046},{6,0,26264},{0,7,15284},{0,6,4470},{0,4,16052},{3,4,26264},{0,4,16052},{1,7,1230},{1,7,1230},{1,7,1230},{0,5,754},{0,5,4450},{0,4,1576},{0,4,1576},{0,2,1972},{0,2,6261},{0,2,2933},{1,7,74},{1,7,74},{1,7,74},{1,5,113},{2,2,4418}, +{0,4,1576},{0,4,1576},{0,2,1972},{5,0,4418},{0,2,1972},{5,6,8980},{3,7,4808},{1,7,25},{0,7,1444},{5,6,8980},{4,6,8980},{0,7,1444},{0,5,8980},{4,6,8980},{0,5,8980},{0,0,729},{0,0,729},{0,0,729},{0,0,729},{0,2,16},{0,2,16},{0,2,16},{0,1,16},{0,0,325},{0,0,325},{2,7,65535},{1,7,40395},{0,7,2381},{0,7,2125},{2,7,65535},{1,7,48635},{0,7,4500}, +{0,6,24853},{0,7,65535},{0,5,57545},{3,7,14605},{2,7,6211},{1,7,170},{1,6,1598},{5,2,24379},{0,7,13716},{0,6,3446},{0,5,14549},{5,3,24379},{0,5,14549},{1,7,1326},{1,7,1326},{1,7,1326},{1,5,1157},{0,6,4418},{0,5,1394},{0,5,1394},{0,3,1621},{0,3,6482},{0,2,3221},{1,7,170},{1,7,170},{1,7,170},{1,5,1},{3,1,4418},{0,5,1394},{0,5,1394},{0,3,1621},{4,1,4418}, +{0,3,1621},{7,3,7940},{3,7,4264},{2,7,81},{0,7,900},{7,3,7940},{6,5,7940},{0,7,900},{0,5,7988},{6,5,7940},{0,5,7988},{1,0,1157},{1,0,1157},{1,0,1157},{1,0,1157},{0,2,16},{0,2,16},{0,2,16},{0,1,16},{0,1,377},{0,1,377},{2,7,65535},{1,7,40747},{0,7,3613},{0,7,2333},{2,7,65535},{1,7,46779},{0,7,3188},{0,6,21861},{0,7,65535},{0,5,55449},{3,7,13181}, +{2,7,5667},{1,7,522},{1,7,1306},{6,1,22571},{0,7,12404},{0,6,2678},{0,5,12453},{4,4,22571},{0,5,12453},{1,7,1678},{1,7,1678},{1,7,1678},{1,5,1301},{0,7,4468},{0,5,1170},{0,5,1170},{0,3,1285},{0,3,6866},{0,3,3221},{1,7,522},{1,7,522},{1,7,522},{1,5,145},{4,0,4420},{0,5,1170},{0,5,1170},{0,3,1285},{3,2,4420},{0,3,1285},{6,5,6964},{3,7,3848},{2,7,1}, +{0,7,484},{6,5,6964},{3,7,6964},{0,7,484},{0,5,7124},{3,7,6964},{0,5,7124},{1,0,1237},{1,0,1237},{1,0,1237},{1,0,1237},{0,3,1},{0,3,1},{0,3,1},{0,2,100},{0,1,505},{0,1,505},{2,7,65535},{1,7,41449},{0,7,5305},{0,7,2873},{2,7,65535},{1,7,44997},{0,7,2018},{0,6,18801},{0,7,65535},{0,6,52421},{3,7,11885},{2,7,5361},{2,7,320},{1,7,1000},{5,3,20645}, +{0,7,11234},{0,7,2018},{0,5,10401},{6,3,20645},{0,5,10401},{1,7,2380},{1,7,2380},{1,7,2380},{1,6,1496},{0,7,4450},{0,6,964},{0,6,964},{0,3,1213},{0,3,7604},{0,3,3149},{2,7,320},{2,7,320},{2,7,320},{2,5,272},{2,4,4418},{0,6,964},{0,6,964},{0,3,1213},{7,0,4418},{0,3,1213},{5,7,5941},{4,7,3181},{2,7,64},{0,7,169},{5,7,5941},{5,6,5941},{0,7,169}, +{0,5,6305},{5,6,5941},{0,5,6305},{1,0,1480},{1,0,1480},{1,0,1480},{1,0,1480},{0,4,25},{0,4,25},{0,4,25},{0,2,1},{0,1,802},{0,1,802},{2,7,65535},{1,7,42345},{0,7,7081},{0,7,3625},{2,7,65535},{1,7,43685},{0,7,1250},{0,6,16353},{0,7,65535},{0,6,49973},{3,7,11005},{3,7,5153},{2,7,320},{2,7,964},{7,0,19026},{1,7,10349},{0,7,1250},{0,5,8849},{3,5,19026}, +{0,5,8849},{1,7,3276},{1,7,3276},{1,7,3276},{1,6,1848},{0,7,4706},{0,6,740},{0,6,740},{0,4,1226},{0,4,7955},{0,3,3357},{2,7,320},{2,7,320},{2,7,320},{2,6,145},{3,3,4420},{0,6,740},{0,6,740},{0,4,1226},{6,1,4420},{0,4,1226},{7,4,5105},{4,7,2701},{3,7,25},{0,7,25},{7,4,5105},{7,5,5105},{0,7,25},{0,6,5645},{7,5,5105},{0,6,5645},{1,0,1832}, +{1,0,1832},{1,0,1832},{1,0,1832},{0,4,9},{0,4,9},{0,4,9},{0,2,49},{0,2,1010},{0,2,1010},{2,7,65535},{1,7,43497},{1,7,9052},{0,7,4633},{2,7,65535},{1,7,42629},{0,7,738},{0,6,14161},{0,7,65535},{0,6,47781},{3,7,10381},{3,7,4529},{2,7,576},{2,7,484},{5,4,17490},{1,7,9293},{0,7,738},{0,5,7553},{7,3,17490},{0,5,7553},{1,7,4428},{1,7,4428},{1,7,4428}, +{1,7,2412},{0,7,5218},{0,7,738},{0,7,738},{0,4,810},{0,4,8467},{0,3,3821},{2,7,576},{2,7,576},{2,7,576},{2,6,1},{4,2,4420},{0,7,738},{0,7,738},{0,4,810},{5,2,4420},{0,4,810},{6,6,4329},{4,7,2349},{3,7,9},{0,7,9},{6,6,4329},{4,7,4329},{0,7,9},{0,6,4637},{4,7,4329},{0,6,4637},{1,0,2312},{1,0,2312},{1,0,2312},{1,0,2312},{0,5,4}, +{0,5,4},{0,5,4},{0,3,36},{0,2,1186},{0,2,1186},{2,7,65535},{1,7,44905},{1,7,10460},{0,7,5897},{2,7,65535},{1,7,41829},{0,7,482},{0,6,12225},{0,7,65535},{0,6,45845},{4,7,9325},{3,7,4161},{3,7,797},{2,7,260},{7,1,16034},{1,7,8493},{0,7,482},{0,5,6513},{4,5,16034},{0,5,6513},{2,7,5712},{2,7,5712},{2,7,5712},{1,7,2924},{1,7,5672},{0,7,482},{0,7,482}, +{0,4,650},{0,4,9235},{0,4,3899},{3,7,797},{3,7,797},{3,7,797},{2,6,113},{5,1,4426},{0,7,482},{0,7,482},{0,4,650},{7,1,4426},{0,4,650},{6,6,3625},{5,7,1985},{4,7,100},{1,7,4},{6,6,3625},{6,6,3617},{1,7,4},{0,6,3757},{6,6,3617},{0,6,3757},{1,0,2920},{1,0,2920},{1,0,2920},{1,0,2920},{0,5,36},{0,5,36},{0,5,36},{0,3,4},{0,2,1490}, +{0,2,1490},{2,7,65535},{1,7,46795},{1,7,12350},{0,7,7625},{2,7,65535},{1,7,41235},{0,7,500},{0,6,10353},{0,7,65535},{0,6,43973},{4,7,8227},{3,7,4053},{3,7,689},{2,7,314},{6,3,14507},{2,7,7875},{0,7,500},{0,5,5649},{6,4,14507},{0,5,5649},{2,7,6594},{2,7,6594},{2,7,6594},{1,7,3806},{1,7,6086},{0,7,500},{0,7,500},{0,4,776},{0,5,9830},{0,4,4025},{3,7,689}, +{3,7,689},{3,7,689},{3,6,298},{6,0,4420},{0,7,500},{0,7,500},{0,4,776},{3,4,4420},{0,4,776},{7,5,2890},{5,7,1508},{4,7,1},{2,7,25},{7,5,2890},{6,6,2906},{2,7,25},{0,6,2920},{6,6,2906},{0,6,2920},{1,0,3757},{1,0,3757},{1,0,3757},{1,0,3757},{0,6,9},{0,6,9},{0,6,9},{0,4,100},{0,2,1985},{0,2,1985},{2,7,65535},{1,7,48747},{1,7,14302}, +{0,7,9433},{2,7,65535},{1,7,40979},{0,7,788},{0,6,8961},{0,7,65535},{0,6,42581},{4,7,7523},{4,7,3923},{3,7,865},{3,7,181},{7,2,13243},{2,7,7075},{1,7,754},{0,6,4337},{5,5,13243},{0,6,4337},{2,7,7650},{2,7,7650},{2,7,7650},{1,7,4862},{1,7,6726},{0,7,788},{0,7,788},{0,5,529},{0,5,10470},{0,4,4409},{3,7,865},{3,7,865},{3,7,865},{3,7,181},{5,2,4426}, +{1,7,754},{1,7,754},{0,5,529},{7,2,4426},{0,5,529},{6,7,2320},{5,7,1220},{4,7,49},{2,7,9},{6,7,2320},{5,7,2320},{2,7,9},{0,6,2312},{5,7,2320},{0,6,2312},{1,0,4637},{1,0,4637},{1,0,4637},{1,0,4637},{0,7,4},{0,7,4},{0,7,4},{0,4,4},{0,3,2297},{0,3,2297},{2,7,65535},{1,7,50955},{1,7,16510},{1,7,10798},{2,7,65535},{1,7,40979},{0,7,1332}, +{0,7,6964},{0,7,65535},{0,6,41445},{4,7,7075},{4,7,3475},{3,7,1297},{3,7,5},{6,4,12051},{2,7,6531},{1,7,754},{0,6,3201},{7,4,12051},{0,6,3201},{2,7,8962},{2,7,8962},{2,7,8962},{2,7,5834},{1,7,7622},{0,7,1332},{0,7,1332},{0,5,289},{0,6,11342},{0,4,5049},{3,7,1297},{3,7,1297},{3,7,1297},{3,7,5},{6,1,4426},{1,7,754},{1,7,754},{0,5,289},{6,3,4426}, +{0,5,289},{6,7,1808},{5,7,1060},{5,7,36},{3,7,4},{6,7,1808},{7,6,1808},{3,7,4},{0,6,1832},{7,6,1808},{0,6,1832},{1,0,5645},{1,0,5645},{1,0,5645},{1,0,5645},{0,7,36},{0,7,36},{0,7,36},{0,4,36},{0,3,2665},{0,3,2665},{2,7,65535},{1,7,53419},{1,7,18974},{1,7,12366},{2,7,65535},{1,7,41235},{0,7,2132},{0,7,5204},{0,7,65535},{0,6,40565},{5,7,6641}, +{4,7,3283},{4,7,1258},{3,7,85},{5,6,10952},{3,7,5900},{1,7,1010},{0,6,2321},{4,6,10952},{0,6,2321},{2,7,10530},{2,7,10530},{2,7,10530},{2,7,6666},{1,7,8774},{0,7,2132},{0,7,2132},{0,5,305},{0,6,11790},{0,5,5205},{4,7,1258},{4,7,1258},{4,7,1258},{3,7,85},{7,0,4420},{1,7,1010},{1,7,1010},{0,5,305},{3,5,4420},{0,5,305},{7,6,1360},{6,7,800},{5,7,4}, +{3,7,36},{7,6,1360},{7,6,1360},{3,7,36},{0,6,1480},{7,6,1360},{0,6,1480},{2,0,6305},{2,0,6305},{2,0,6305},{2,0,6305},{0,7,196},{0,7,196},{0,7,196},{0,5,49},{0,3,3161},{0,3,3161},{2,7,65535},{2,7,56301},{1,7,22052},{1,7,14436},{2,7,65535},{1,7,41829},{0,7,3338},{0,7,3530},{0,7,65535},{0,6,39881},{5,7,5741},{4,7,3373},{4,7,1348},{4,7,328},{7,3,9830}, +{3,7,5270},{2,7,1184},{0,6,1637},{6,5,9830},{0,6,1637},{2,7,12600},{2,7,12600},{2,7,12600},{2,7,7908},{1,7,10376},{1,7,2760},{1,7,2760},{0,6,481},{0,6,12600},{0,5,5529},{4,7,1348},{4,7,1348},{4,7,1348},{4,7,328},{7,1,4426},{2,7,1184},{2,7,1184},{0,6,481},{7,3,4426},{0,6,481},{7,6,937},{6,7,521},{5,7,121},{4,7,4},{7,6,937},{6,7,929},{4,7,4}, +{0,6,1237},{6,7,929},{0,6,1237},{2,0,7124},{2,0,7124},{2,0,7124},{2,0,7124},{0,7,529},{0,7,529},{0,7,529},{0,5,4},{0,4,3778},{0,4,3778},{2,7,65535},{2,7,58413},{1,7,25060},{1,7,16548},{2,7,65535},{1,7,42629},{0,7,4682},{0,7,2314},{0,7,65535},{0,6,39545},{5,7,5213},{5,7,3321},{4,7,1700},{4,7,200},{5,7,8902},{3,7,4982},{2,7,1440},{0,6,1301},{5,6,8902}, +{0,6,1301},{3,7,14701},{3,7,14701},{3,7,14701},{2,7,9284},{2,7,11492},{1,7,3560},{1,7,3560},{0,6,145},{0,6,13592},{0,5,6089},{4,7,1700},{4,7,1700},{4,7,1700},{4,7,200},{6,3,4420},{2,7,1440},{2,7,1440},{0,6,145},{6,4,4420},{0,6,145},{7,6,697},{6,7,409},{6,7,9},{5,7,9},{7,6,697},{6,7,625},{5,7,9},{0,6,1157},{6,7,625},{0,6,1157},{2,0,7988}, +{2,0,7988},{2,0,7988},{2,0,7988},{0,7,961},{0,7,961},{0,7,961},{0,5,100},{0,4,4210},{0,4,4210},{3,7,65535},{2,7,60781},{1,7,28324},{1,7,18916},{2,7,65535},{1,7,43685},{0,7,6282},{0,7,1354},{0,7,65535},{0,6,39465},{5,7,4941},{5,7,3049},{5,7,2025},{4,7,328},{7,4,8069},{4,7,4465},{3,7,1586},{0,6,1221},{7,5,8069},{0,6,1221},{3,7,16189},{3,7,16189},{3,7,16189}, +{2,7,10916},{2,7,12740},{1,7,4616},{1,7,4616},{0,6,65},{0,7,14411},{0,6,6789},{5,7,2025},{5,7,2025},{5,7,2025},{4,7,328},{7,2,4420},{3,7,1586},{3,7,1586},{0,6,65},{5,5,4420},{0,6,65},{7,7,377},{7,7,305},{6,7,25},{5,7,25},{7,7,377},{6,7,449},{5,7,25},{0,7,729},{6,7,449},{0,7,729},{2,0,8980},{2,0,8980},{2,0,8980},{2,0,8980},{1,7,1480}, +{1,7,1480},{1,7,1480},{0,6,16},{0,4,4770},{0,4,4770},{3,7,65535},{2,7,59505},{1,7,29984},{1,7,19680},{2,7,65535},{1,7,43137},{0,7,8318},{0,7,830},{0,7,65535},{0,6,34901},{5,7,4925},{5,7,3033},{5,7,2009},{4,7,712},{6,6,7325},{4,7,4145},{3,7,1810},{0,7,650},{4,7,7325},{0,7,650},{3,7,16745},{3,7,16745},{3,7,16745},{2,7,12024},{2,7,13464},{1,7,5556},{1,7,5556}, +{0,6,277},{0,7,14139},{0,6,6017},{5,7,2009},{5,7,2009},{5,7,2009},{4,7,712},{5,6,4418},{3,7,1810},{3,7,1810},{0,6,241},{4,6,4418},{0,6,241},{7,7,185},{7,7,113},{7,7,64},{6,7,1},{7,7,185},{7,7,193},{6,7,1},{0,7,361},{7,7,193},{0,7,361},{2,0,9320},{2,0,9320},{2,0,9320},{2,0,9320},{1,7,1460},{1,7,1460},{1,7,1460},{0,6,52},{0,5,4772}, +{0,5,4772},{3,7,65535},{2,7,57588},{1,7,32135},{1,7,20823},{3,7,65535},{1,7,42804},{1,7,8359},{0,7,1289},{0,7,65535},{0,6,28970},{6,7,4317},{5,7,3321},{5,7,2297},{5,7,845},{7,5,6587},{5,7,4008},{4,7,2066},{0,7,164},{6,6,6611},{0,7,164},{3,7,17366},{3,7,17366},{3,7,17366},{3,7,12274},{2,7,14427},{2,7,6699},{2,7,6699},{0,7,389},{0,7,13860},{0,6,5234},{5,7,2297}, +{5,7,2297},{5,7,2297},{5,7,845},{6,5,4420},{4,7,2066},{4,7,2066},{0,7,164},{3,7,4420},{0,7,164},{7,7,122},{7,7,50},{7,7,1},{7,7,9},{7,7,122},{7,7,58},{7,7,9},{0,7,100},{7,7,58},{0,7,100},{2,0,9698},{2,0,9698},{2,0,9698},{2,0,9698},{1,7,1586},{1,7,1586},{1,7,1586},{0,7,289},{0,5,4250},{0,5,4250},{3,7,65535},{2,7,56836},{2,7,31631}, +{1,7,22791},{3,7,65535},{2,7,40532},{1,7,9015},{1,7,778},{0,7,65535},{0,6,24650},{6,7,3949},{6,7,3325},{5,7,2825},{5,7,1021},{6,7,6020},{5,7,3688},{4,7,2290},{0,7,4},{5,7,6020},{0,7,4},{3,7,18326},{3,7,18326},{3,7,18326},{3,7,12626},{3,7,15077},{2,7,7227},{2,7,7227},{1,7,294},{0,7,14020},{0,6,4946},{5,7,2825},{5,7,2825},{5,7,2825},{5,7,1021},{7,4,4418}, +{4,7,2290},{4,7,2290},{0,7,4},{7,5,4418},{0,7,4},{7,7,202},{7,7,130},{7,7,81},{7,7,25},{7,7,202},{7,7,74},{7,7,25},{0,7,4},{7,7,74},{0,7,4},{3,0,9490},{3,0,9490},{3,0,9490},{3,0,9490},{1,7,1970},{1,7,1970},{1,7,1970},{1,6,202},{0,6,3922},{0,6,3922},{3,7,65535},{3,7,55466},{2,7,30335},{2,7,21687},{3,7,65535},{2,7,37932},{1,7,9535}, +{1,7,70},{0,7,65535},{0,7,20544},{6,7,3417},{6,7,2793},{6,7,2393},{5,7,1033},{6,7,5184},{5,7,3204},{5,7,2180},{1,7,25},{7,6,5168},{1,7,25},{4,7,17611},{4,7,17611},{4,7,17611},{3,7,12630},{3,7,14321},{2,7,7251},{2,7,7251},{1,7,34},{0,7,13376},{0,7,4160},{6,7,2393},{6,7,2393},{6,7,2393},{5,7,1033},{6,6,3874},{5,7,2180},{5,7,2180},{1,7,25},{4,7,3874}, +{1,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{3,0,9266},{3,0,9266},{3,0,9266},{3,0,9266},{2,7,2210},{2,7,2210},{2,7,2210},{1,7,34},{0,6,3442},{0,6,3442},{3,7,65535},{3,7,51210},{2,7,29343},{2,7,20695},{3,7,65535},{2,7,35820},{1,7,10495},{1,7,134},{1,7,65535},{0,7,15936},{6,7,2889}, +{6,7,2265},{6,7,1865},{5,7,1049},{7,6,4288},{5,7,2724},{5,7,1700},{1,7,9},{7,6,4272},{1,7,9},{4,7,16555},{4,7,16555},{4,7,16555},{3,7,12662},{3,7,13441},{2,7,7251},{2,7,7251},{1,7,34},{0,7,12608},{0,7,3392},{6,7,1865},{6,7,1865},{6,7,1865},{5,7,1049},{7,5,3218},{5,7,1700},{5,7,1700},{1,7,9},{6,6,3202},{1,7,9},{7,7,242},{7,7,170},{7,7,121}, +{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{3,0,9298},{3,0,9298},{3,0,9298},{3,0,9298},{2,7,2210},{2,7,2210},{2,7,2210},{1,7,34},{0,6,3218},{0,6,3218},{4,7,65535},{3,7,47340},{2,7,29145},{2,7,20497},{3,7,65535},{2,7,34362},{2,7,9157},{1,7,1124},{1,7,64598},{0,7,11670},{6,7,2448},{6,7,1824},{6,7,1424},{6,7,800},{7,6,3361}, +{6,7,2321},{5,7,1313},{2,7,0},{6,7,3401},{2,7,0},{4,7,15673},{4,7,15673},{4,7,15673},{4,7,12073},{3,7,12757},{3,7,6905},{3,7,6905},{1,7,340},{1,7,11657},{0,7,2834},{6,7,1424},{6,7,1424},{6,7,1424},{6,7,800},{7,5,2525},{5,7,1313},{5,7,1313},{2,7,0},{5,7,2545},{2,7,0},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49}, +{0,7,0},{7,7,98},{0,7,0},{3,0,9640},{3,0,9640},{3,0,9640},{3,0,9640},{2,7,2516},{2,7,2516},{2,7,2516},{1,7,340},{0,7,2834},{0,7,2834},{4,7,65535},{3,7,44716},{3,7,27896},{2,7,21137},{4,7,65535},{3,7,31853},{2,7,8677},{2,7,784},{1,7,59734},{0,7,8694},{6,7,2192},{6,7,1568},{6,7,1168},{6,7,544},{7,6,2673},{6,7,1761},{5,7,1105},{3,7,25},{6,7,2649}, +{3,7,25},{4,7,15161},{4,7,15161},{4,7,15161},{4,7,11561},{4,7,12169},{3,7,6569},{3,7,6569},{2,7,208},{1,7,10889},{0,7,2610},{6,7,1168},{6,7,1168},{6,7,1168},{6,7,544},{6,7,1985},{5,7,1105},{5,7,1105},{3,7,25},{5,7,1985},{3,7,25},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,9536}, +{4,0,9536},{4,0,9536},{4,0,9536},{2,7,3060},{2,7,3060},{2,7,3060},{2,7,208},{0,7,2610},{0,7,2610},{4,7,63766},{3,7,42860},{3,7,26040},{3,7,20188},{4,7,60070},{3,7,29085},{2,7,8965},{2,7,336},{1,7,55638},{0,7,6486},{7,7,1686},{6,7,1440},{6,7,1040},{6,7,416},{7,6,2113},{6,7,1329},{6,7,929},{3,7,9},{6,7,2025},{3,7,9},{4,7,14905},{4,7,14905},{4,7,14905}, +{4,7,11305},{4,7,11209},{3,7,6489},{3,7,6489},{2,7,272},{1,7,10377},{0,7,2642},{6,7,1040},{6,7,1040},{6,7,1040},{6,7,416},{7,6,1537},{6,7,929},{6,7,929},{3,7,9},{7,6,1513},{3,7,9},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,9280},{4,0,9280},{4,0,9280},{4,0,9280},{3,7,3125}, +{3,7,3125},{3,7,3125},{2,7,272},{0,7,2642},{0,7,2642},{4,7,59414},{4,7,41414},{3,7,24952},{3,7,19100},{4,7,55014},{3,7,27085},{2,7,10021},{2,7,656},{1,7,52310},{0,7,5046},{7,7,1142},{7,7,1070},{7,7,1021},{6,7,416},{7,7,1538},{6,7,1025},{6,7,625},{4,7,4},{6,7,1529},{4,7,4},{5,7,13964},{5,7,13964},{5,7,13964},{4,7,11305},{4,7,10505},{3,7,6665},{3,7,6665}, +{2,7,592},{2,7,9973},{0,7,2930},{7,7,1021},{7,7,1021},{7,7,1021},{6,7,416},{7,6,1105},{6,7,625},{6,7,625},{4,7,4},{6,7,1129},{4,7,4},{7,7,242},{7,7,170},{7,7,121},{7,7,49},{7,7,242},{7,7,98},{7,7,49},{0,7,0},{7,7,98},{0,7,0},{4,0,9280},{4,0,9280},{4,0,9280},{4,0,9280},{3,7,3301},{3,7,3301},{3,7,3301},{2,7,592},{0,7,2930}, +{0,7,2930}, diff --git a/ext/basis_universal/basisu_transcoder_uastc.h b/ext/basis_universal/basisu_transcoder_uastc.h new file mode 100644 index 0000000000..f91314f4ff --- /dev/null +++ b/ext/basis_universal/basisu_transcoder_uastc.h @@ -0,0 +1,293 @@ +// basisu_transcoder_uastc.h +#pragma once +#include "basisu_transcoder_internal.h" + +namespace basist +{ + struct color_quad_u8 + { + uint8_t m_c[4]; + }; + + const uint32_t TOTAL_UASTC_MODES = 19; + const uint32_t UASTC_MODE_INDEX_SOLID_COLOR = 8; + + const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS2 = 30; + const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS3 = 11; + const uint32_t TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS = 19; + + extern const uint8_t g_uastc_mode_weight_bits[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_weight_ranges[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_endpoint_ranges[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_subsets[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_planes[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_comps[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_has_etc1_bias[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_has_bc1_hint0[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_has_bc1_hint1[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_has_alpha[TOTAL_UASTC_MODES]; + extern const uint8_t g_uastc_mode_is_la[TOTAL_UASTC_MODES]; + + struct astc_bc7_common_partition2_desc + { + uint8_t m_bc7; + uint16_t m_astc; + bool m_invert; + }; + + extern const astc_bc7_common_partition2_desc g_astc_bc7_common_partitions2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2]; + + struct bc73_astc2_common_partition_desc + { + uint8_t m_bc73; + uint16_t m_astc2; + uint8_t k; // 0-5 - how to modify the BC7 3-subset pattern to match the ASTC pattern (LSB=invert) + }; + + extern const bc73_astc2_common_partition_desc g_bc7_3_astc2_common_partitions[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS]; + + struct astc_bc7_common_partition3_desc + { + uint8_t m_bc7; + uint16_t m_astc; + uint8_t m_astc_to_bc7_perm; // converts ASTC to BC7 partition using g_astc_bc7_partition_index_perm_tables[][] + }; + + extern const astc_bc7_common_partition3_desc g_astc_bc7_common_partitions3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3]; + + extern const uint8_t g_astc_bc7_patterns2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][16]; + extern const uint8_t g_astc_bc7_patterns3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][16]; + extern const uint8_t g_bc7_3_astc2_patterns2[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][16]; + + extern const uint8_t g_astc_bc7_pattern2_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][3]; + extern const uint8_t g_astc_bc7_pattern3_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][3]; + extern const uint8_t g_bc7_3_astc2_patterns2_anchors[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][3]; + + extern const uint32_t g_uastc_mode_huff_codes[TOTAL_UASTC_MODES + 1][2]; + + extern const uint8_t g_astc_to_bc7_partition_index_perm_tables[6][3]; + extern const uint8_t g_bc7_to_astc_partition_index_perm_tables[6][3]; // inverse of g_astc_to_bc7_partition_index_perm_tables + + extern const uint8_t* s_uastc_to_bc1_weights[6]; + + uint32_t bc7_convert_partition_index_3_to_2(uint32_t p, uint32_t k); + + inline uint32_t astc_interpolate(uint32_t l, uint32_t h, uint32_t w, bool srgb) + { + if (srgb) + { + l = (l << 8) | 0x80; + h = (h << 8) | 0x80; + } + else + { + l = (l << 8) | l; + h = (h << 8) | h; + } + + uint32_t k = (l * (64 - w) + h * w + 32) >> 6; + + return k >> 8; + } + + struct astc_block_desc + { + int m_weight_range; // weight BISE range + + int m_subsets; // number of ASTC partitions + int m_partition_seed; // partition pattern seed + int m_cem; // color endpoint mode used by all subsets + + int m_ccs; // color component selector (dual plane only) + bool m_dual_plane; // true if dual plane + + // Weight and endpoint BISE values. + // Note these values are NOT linear, they must be BISE encoded. See Table 97 and Table 107. + uint8_t m_endpoints[18]; // endpoint values, in RR GG BB etc. order + uint8_t m_weights[64]; // weight index values, raster order, in P0 P1, P0 P1, etc. or P0, P0, P0, P0, etc. order + }; + + const uint32_t BC7ENC_TOTAL_ASTC_RANGES = 21; + + // See tables 81, 93, 18.13.Endpoint Unquantization + const uint32_t TOTAL_ASTC_RANGES = 21; + extern const int g_astc_bise_range_table[TOTAL_ASTC_RANGES][3]; + + struct astc_quant_bin + { + uint8_t m_unquant; // unquantized value + uint8_t m_index; // sorted index + }; + + extern astc_quant_bin g_astc_unquant[BC7ENC_TOTAL_ASTC_RANGES][256]; // [ASTC encoded endpoint index] + + int astc_get_levels(int range); + bool astc_is_valid_endpoint_range(uint32_t range); + uint32_t unquant_astc_endpoint(uint32_t packed_bits, uint32_t packed_trits, uint32_t packed_quints, uint32_t range); + uint32_t unquant_astc_endpoint_val(uint32_t packed_val, uint32_t range); + + const uint8_t* get_anchor_indices(uint32_t subsets, uint32_t mode, uint32_t common_pattern, const uint8_t*& pPartition_pattern); + + // BC7 + const uint32_t BC7ENC_BLOCK_SIZE = 16; + + struct bc7_block + { + uint64_t m_qwords[2]; + }; + + struct bc7_optimization_results + { + uint32_t m_mode; + uint32_t m_partition; + uint8_t m_selectors[16]; + uint8_t m_alpha_selectors[16]; + color_quad_u8 m_low[3]; + color_quad_u8 m_high[3]; + uint32_t m_pbits[3][2]; + uint32_t m_index_selector; + uint32_t m_rotation; + }; + + extern const uint32_t g_bc7_weights1[2]; + extern const uint32_t g_bc7_weights2[4]; + extern const uint32_t g_bc7_weights3[8]; + extern const uint32_t g_bc7_weights4[16]; + extern const uint32_t g_astc_weights4[16]; + extern const uint32_t g_astc_weights5[32]; + extern const uint32_t g_astc_weights_3levels[3]; + extern const uint8_t g_bc7_partition1[16]; + extern const uint8_t g_bc7_partition2[64 * 16]; + extern const uint8_t g_bc7_partition3[64 * 16]; + extern const uint8_t g_bc7_table_anchor_index_second_subset[64]; + extern const uint8_t g_bc7_table_anchor_index_third_subset_1[64]; + extern const uint8_t g_bc7_table_anchor_index_third_subset_2[64]; + extern const uint8_t g_bc7_num_subsets[8]; + extern const uint8_t g_bc7_partition_bits[8]; + extern const uint8_t g_bc7_color_index_bitcount[8]; + extern const uint8_t g_bc7_mode_has_p_bits[8]; + extern const uint8_t g_bc7_mode_has_shared_p_bits[8]; + extern const uint8_t g_bc7_color_precision_table[8]; + extern const int8_t g_bc7_alpha_precision_table[8]; + extern const uint8_t g_bc7_alpha_index_bitcount[8]; + + inline bool get_bc7_mode_has_seperate_alpha_selectors(int mode) { return (mode == 4) || (mode == 5); } + inline int get_bc7_color_index_size(int mode, int index_selection_bit) { return g_bc7_color_index_bitcount[mode] + index_selection_bit; } + inline int get_bc7_alpha_index_size(int mode, int index_selection_bit) { return g_bc7_alpha_index_bitcount[mode] - index_selection_bit; } + + struct endpoint_err + { + uint16_t m_error; uint8_t m_lo; uint8_t m_hi; + }; + + extern endpoint_err g_bc7_mode_6_optimal_endpoints[256][2]; // [c][pbit] + const uint32_t BC7ENC_MODE_6_OPTIMAL_INDEX = 5; + + extern endpoint_err g_bc7_mode_5_optimal_endpoints[256]; // [c] + const uint32_t BC7ENC_MODE_5_OPTIMAL_INDEX = 1; + + // Packs a BC7 block from a high-level description. Handles all BC7 modes. + void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults); + + // Packs an ASTC block + // Constraints: Always 4x4, all subset CEM's must be equal, only tested with LDR CEM's. + bool pack_astc_block(uint32_t* pDst, const astc_block_desc* pBlock, uint32_t mode); + + void pack_astc_solid_block(void* pDst_block, const color32& color); + +#ifdef _DEBUG + int astc_compute_texel_partition(int seed, int x, int y, int z, int partitioncount, bool small_block); +#endif + + struct uastc_block + { + union + { + uint8_t m_bytes[16]; + uint32_t m_dwords[4]; + }; + }; + + struct unpacked_uastc_block + { + astc_block_desc m_astc; + + uint32_t m_mode; + uint32_t m_common_pattern; + + color32 m_solid_color; + + bool m_bc1_hint0; + bool m_bc1_hint1; + + bool m_etc1_flip; + bool m_etc1_diff; + uint32_t m_etc1_inten0; + uint32_t m_etc1_inten1; + + uint32_t m_etc1_bias; + + uint32_t m_etc2_hints; + + uint32_t m_etc1_selector; + uint32_t m_etc1_r, m_etc1_g, m_etc1_b; + }; + + color32 apply_etc1_bias(const color32 &block_color, uint32_t bias, uint32_t limit, uint32_t subblock); + + struct decoder_etc_block; + struct eac_block; + + bool unpack_uastc(uint32_t mode, uint32_t common_pattern, const color32& solid_color, const astc_block_desc& astc, color32* pPixels, bool srgb); + bool unpack_uastc(const unpacked_uastc_block& unpacked_blk, color32* pPixels, bool srgb); + + bool unpack_uastc(const uastc_block& blk, color32* pPixels, bool srgb); + bool unpack_uastc(const uastc_block& blk, unpacked_uastc_block& unpacked, bool undo_blue_contract, bool read_hints = true); + + bool transcode_uastc_to_astc(const uastc_block& src_blk, void* pDst); + + bool transcode_uastc_to_bc7(const unpacked_uastc_block& unpacked_src_blk, bc7_optimization_results& dst_blk); + bool transcode_uastc_to_bc7(const uastc_block& src_blk, bc7_optimization_results& dst_blk); + bool transcode_uastc_to_bc7(const uastc_block& src_blk, void* pDst); + + void transcode_uastc_to_etc1(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst); + bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst); + bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst, uint32_t channel); + + void transcode_uastc_to_etc2_eac_a8(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst); + bool transcode_uastc_to_etc2_rgba(const uastc_block& src_blk, void* pDst); + + // Packs 16 scalar values to BC4. Same PSNR as stb_dxt's BC4 encoder, around 13% faster. + void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride); + + void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb); + + enum + { + cEncodeBC1HighQuality = 1, + cEncodeBC1HigherQuality = 2, + cEncodeBC1UseSelectors = 4, + }; + void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags); + + // Alternate PCA-free encoder, around 15% faster, same (or slightly higher) avg. PSNR + void encode_bc1_alt(void* pDst, const uint8_t* pPixels, uint32_t flags); + + void transcode_uastc_to_bc1_hint0(const unpacked_uastc_block& unpacked_src_blk, void* pDst); + void transcode_uastc_to_bc1_hint1(const unpacked_uastc_block& unpacked_src_blk, const color32 block_pixels[4][4], void* pDst, bool high_quality); + + bool transcode_uastc_to_bc1(const uastc_block& src_blk, void* pDst, bool high_quality); + bool transcode_uastc_to_bc3(const uastc_block& src_blk, void* pDst, bool high_quality); + bool transcode_uastc_to_bc4(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0); + bool transcode_uastc_to_bc5(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1); + + bool transcode_uastc_to_etc2_eac_r11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0); + bool transcode_uastc_to_etc2_eac_rg11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1); + + bool transcode_uastc_to_pvrtc1_4_rgb(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality, bool from_alpha); + bool transcode_uastc_to_pvrtc1_4_rgba(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality); + + // uastc_init() MUST be called before using this module. + void uastc_init(); + +} // namespace basist diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 3908a3bd08..3beb711568 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -243,6 +243,9 @@ SOURCES_CXX += \ SOURCES_CXX += $(EXTDIR)/cityhash/city.cpp +SOURCES_CXX += \ + $(EXTDIR)/basis_universal/basisu_transcoder.cpp + SOURCES_CXX += \ $(EXTDIR)/armips/Core/Types.cpp From a59297120909729a6950d1d2b4a1211142a4c32d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Mar 2023 16:48:47 +0100 Subject: [PATCH 308/424] Add translation strings for dark theme and "Scoped Storage" --- UI/DevScreens.cpp | 2 +- assets/lang/ar_AE.ini | 2 ++ assets/lang/az_AZ.ini | 2 ++ assets/lang/bg_BG.ini | 2 ++ assets/lang/ca_ES.ini | 2 ++ assets/lang/cz_CZ.ini | 2 ++ assets/lang/da_DK.ini | 2 ++ assets/lang/de_DE.ini | 2 ++ assets/lang/dr_ID.ini | 2 ++ assets/lang/en_US.ini | 2 ++ assets/lang/es_ES.ini | 2 ++ assets/lang/es_LA.ini | 2 ++ assets/lang/fa_IR.ini | 2 ++ assets/lang/fi_FI.ini | 2 ++ assets/lang/fr_FR.ini | 2 ++ assets/lang/gl_ES.ini | 2 ++ assets/lang/gr_EL.ini | 2 ++ assets/lang/he_IL.ini | 2 ++ assets/lang/he_IL_invert.ini | 2 ++ assets/lang/hr_HR.ini | 2 ++ assets/lang/hu_HU.ini | 2 ++ assets/lang/id_ID.ini | 2 ++ assets/lang/it_IT.ini | 2 ++ assets/lang/ja_JP.ini | 2 ++ assets/lang/jv_ID.ini | 2 ++ assets/lang/ko_KR.ini | 2 ++ assets/lang/lo_LA.ini | 2 ++ assets/lang/lt-LT.ini | 2 ++ assets/lang/ms_MY.ini | 2 ++ assets/lang/nl_NL.ini | 2 ++ assets/lang/no_NO.ini | 2 ++ assets/lang/pl_PL.ini | 2 ++ assets/lang/pt_BR.ini | 2 ++ assets/lang/pt_PT.ini | 2 ++ assets/lang/ro_RO.ini | 2 ++ assets/lang/ru_RU.ini | 2 ++ assets/lang/sv_SE.ini | 4 +++- assets/lang/tg_PH.ini | 2 ++ assets/lang/th_TH.ini | 2 ++ assets/lang/tr_TR.ini | 2 ++ assets/lang/uk_UA.ini | 2 ++ assets/lang/vi_VN.ini | 2 ++ assets/lang/zh_CN.ini | 2 ++ assets/lang/zh_TW.ini | 2 ++ 44 files changed, 88 insertions(+), 2 deletions(-) diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index d02791a59d..ce7cafc5c1 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -659,7 +659,7 @@ void SystemInfoScreen::CreateViews() { #if PPSSPP_PLATFORM(ANDROID) storage->Add(new InfoItem("ExtFilesDir", g_extFilesDir)); bool scoped = System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE); - storage->Add(new InfoItem("Scoped Storage Enabled", scoped ? di->T("Yes") : di->T("No"))); + storage->Add(new InfoItem(si->T("Scoped Storage"), scoped ? di->T("Yes") : di->T("No"))); if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 30) { // This flag is only relevant on Android API 30+. storage->Add(new InfoItem("IsStoragePreservedLegacy", Android_IsExternalStoragePreservedLegacy() ? di->T("Yes") : di->T("No"))); diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 446b1695a3..c8c9237c13 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -1080,6 +1080,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1216,6 +1217,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index e29291f540..0d84d5f9a7 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index eecca5adbd..71d3691558 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 586ea03f97..bbda05b855 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Per defecte [UI Elements] diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 998107a1b9..c6abcbfc4e 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 41869365cc..8a4a935fcd 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index 9d00fdb672..a3da455d83 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1072,6 +1072,7 @@ Refresh rate = Wiederholungsrate Release = Release RW/RX exclusive = RW/RX exklusiv Sample rate = Abtastrate +Scoped Storage = Scoped Storage Shading Language = Shadersprache Storage = Storage Sustained perf mode = Anhaltener Hochleistungsmodus @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 94bf9792a1..f18a7a1108 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index f716c73452..4dc2b1298e 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -1088,6 +1088,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1219,6 +1220,7 @@ Color Saturation = Color Saturation Show Memory Stick folder = Show Memory Stick folder [Themes] +Dark = Dark Default = Default [TextureShaders] diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 63effcd9ad..68223be8b8 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1073,6 +1073,7 @@ Refresh rate = frecuencia de actualización Release = Estable RW/RX exclusive = RW/RX exclusivo Sample rate = Frecuencia de muestreo +Scoped Storage = Scoped Storage Shading Language = Lenguaje de shader Storage = Almacenamiento Sustained perf mode = Modo de rendimiento sostenido @@ -1209,6 +1210,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Por defecto [UI Elements] diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index c8185aeb8a..3d6138a7a1 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1072,6 +1072,7 @@ Refresh rate = Tasa de refresco Release = Estable RW/RX exclusive = Exclusivo de RW/RX Sample rate = Ratio de muestra +Scoped Storage = Scoped Storage Shading Language = Lenguaje de shader Storage = Almacenamiento Sustained perf mode = Modo rendimiento sostenido @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index cfb06573aa..2a167a1eee 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = پیشفرض [UI Elements] diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index c08b051054..16597e96ed 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index cc6910abd2..d84d6e5164 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1063,6 +1063,7 @@ Refresh rate = Taux de rafraîchissement Release = Release RW/RX exclusive = Exclusif RW/RX Sample rate = Taux d'échantillonnage +Scoped Storage = Scoped Storage Shading Language = Language de shading Storage = Storage Sustained perf mode = Mode performance prolongée @@ -1199,6 +1200,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 21a4b5910d..cbd3747607 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 1018f93940..1e5dbaeea0 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1072,6 +1072,7 @@ Refresh rate = Ρυθμός ανανέωσης Release = Release RW/RX exclusive = RW/RX αποκλειστικό Sample rate = Ρυθμός δειγματοληψίας +Scoped Storage = Scoped Storage Shading Language = Γλώσσα σκίασης Storage = Storage Sustained perf mode = Διατηρημένη λειτουργία απόδοσης @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index e07fec542d..624c017ee0 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 97aa9296be..e73a2209a3 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 53c3ba984a..e2130f0fbb 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1072,6 +1072,7 @@ Refresh rate = Brzina osvježavanja Release = Pusti RW/RX exclusive = RW/RX ekskluzivno Sample rate = Brzina sample-ova +Scoped Storage = Scoped Storage Shading Language = Jezik sjenčanja Storage = Storage Sustained perf mode = Održiv perf način @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index f0e7a5019d..7f7c992036 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1072,6 +1072,7 @@ Refresh rate = Frissítési gyakoriság Release = Release RW/RX exclusive = RW/RX exkluzív Sample rate = Mintavételezési ráta +Scoped Storage = Scoped Storage Shading Language = Shading nyelv Storage = Storage Sustained perf mode = Fentartott teljesítmény mód @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 3b475db105..d8875218c1 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1072,6 +1072,7 @@ Refresh rate = Penyegaran Release = Rilis RW/RX exclusive = RW/RX eksklusif Sample rate = Tingkat penyegaran +Scoped Storage = Scoped Storage Shading Language = Bahasa shading Storage = Penyimpanan Sustained perf mode = Mode kinerja berkelanjutan @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Bawaan [UI Elements] diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index b1a4cd4526..9234601dc3 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1073,6 +1073,7 @@ Refresh rate = Frequenza d'aggiornamento Release = Rilascio RW/RX exclusive = Esclusiva RW/RX Sample rate = Frequenza di campionamento +Scoped Storage = Scoped Storage Shading Language = Linguaggio shading Storage = Storage Sustained perf mode = Modalità prestazioni prolungate @@ -1209,6 +1210,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 597962ad61..fdead00d08 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1072,6 +1072,7 @@ Refresh rate = リフレッシュレート Release = リリース RW/RX exclusive = RW/RX専用 Sample rate = サンプルレート +Scoped Storage = Scoped Storage Shading Language = シェーディング言語 Storage = ストレージ情報 Sustained perf mode = 性能維持モード @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = デフォルト [UI Elements] diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 88661aba4a..c403af18a1 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index e02490c1fb..58de9da885 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1064,6 +1064,7 @@ Refresh rate = 주사율 Release = 개정 RW/RX exclusive = RW/RX 전용 Sample rate = 샘플 속도 +Scoped Storage = Scoped Storage Shading Language = 쉐이딩 언어 Storage = 저장소 Sustained perf mode = 지속 성능 모드 @@ -1195,6 +1196,7 @@ Color Saturation = 채도 Show Memory Stick folder = 메모리 스틱 폴더 표시 [Themes] +Dark = Dark Default = 기본 [TextureShaders] diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 92099f2b5a..ebc02641ad 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 2e3d08a249..f046b42d06 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 1d8c739be5..2a3983823b 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index e1f86e1cf8..e0f3e11002 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1072,6 +1072,7 @@ Refresh rate = Vernieuwingsfrequentie Release = Release RW/RX exclusive = RW/RX-excusief Sample rate = Samplerate +Scoped Storage = Scoped Storage Shading Language = Shadingtaal Storage = Storage Sustained perf mode = Aanhoudende prestatiemodus @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 69a27e25c7..e9f92d1cf2 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index afaa3d12b5..d489a6ee73 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1072,6 +1072,7 @@ Refresh rate = Częstotliwość odświeżania Release = Release RW/RX exclusive = Wyłączne RW/RX Sample rate = Częstotliwość próbkowania +Scoped Storage = Scoped Storage Shading Language = Język shadingu Storage = Storage Sustained perf mode = Tryb wysokiej wydajności @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Domyślny [UI Elements] diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 7779d4fb65..6807538340 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -1088,6 +1088,7 @@ Refresh rate = Taxa de atualização Release = Lançamento RW/RX exclusive = RW/RX exclusivo Sample rate = Taxa de amostragem +Scoped Storage = Scoped Storage Shading Language = Idioma do shader Storage = Armazenagem Sustained perf mode = Modo de performance sustentado @@ -1219,6 +1220,7 @@ Color Saturation = Saturação das Cores Show Memory Stick folder = Mostrar a pasta do cartão de memória [Themes] +Dark = Dark Default = Padrão [TextureShaders] diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 3aeaeddb86..166b248fe8 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -1089,6 +1089,7 @@ Refresh rate = Taxa de atualização Release = Lançamento RW/RX exclusive = RW/RX exclusivo Sample rate = Taxa de amostragem +Scoped Storage = Scoped Storage Shading Language = Idioma do Shader Storage = Armazenamento Sustained perf mode = Modo de performance sustentado @@ -1220,6 +1221,7 @@ Color Saturation = Saturação das Cores Show Memory Stick folder = Mostrar a pasta do Cartão de Memória [Themes] +Dark = Dark Default = Padrão [TextureShaders] diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 1f1f8bfffe..34f74743dc 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index b42de7589c..3f7609bbc2 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1072,6 +1072,7 @@ Refresh rate = Частота обновления Release = Релизная RW/RX exclusive = Захват RW/RX Sample rate = Частота дискретизации +Scoped Storage = Scoped Storage Shading Language = Язык шейдеров Storage = Место хранения Sustained perf mode = Режим длительной работы @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = По умолчанию [UI Elements] diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 33fb006f19..ae20396e10 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,7 +1209,8 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] -Default = Default +Dark = Mörk +Default = Standard [UI Elements] %1 button = %1 button diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index e8dac4a33e..f4a576b675 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1072,6 +1072,7 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate +Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 94e6a2aca1..477c9bc145 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1078,6 +1078,7 @@ Refresh rate = อัตราการรีเฟรชของหน้า Release = ใช้งาน RW/RX exclusive = RW/RX แบบพิเศษ Sample rate = อัตราค่าความถี่เสียง +Scoped Storage = Scoped Storage Shading Language = ภาษาของเฉดเดอร์ Storage = พื้นที่เก็บข้อมูล Sustained perf mode = โหมดประสิทธิภาพที่ยั่งยืน @@ -1214,6 +1215,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = ค่าดั้งเดิม [UI Elements] diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 29e2bdf498..23cb66d317 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1073,6 +1073,7 @@ Refresh rate = Yenileme hızı Release = Release RW/RX exclusive = RW/RX'e özel Sample rate = Örnekleme hızı +Scoped Storage = Scoped Storage Shading Language = Gölgelendirme dili Storage = Depolama Sustained perf mode = Sürekli performans modu @@ -1209,6 +1210,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Varsayılan [UI Elements] diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 3a7a7dac29..86e406f97f 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1072,6 +1072,7 @@ Refresh rate = Частота оновлення Release = Реліз RW/RX exclusive = Ексклюзивний RW/RX Sample rate = Норма вибірки +Scoped Storage = Scoped Storage Shading Language = Мова шейдерів Storage = Storage Sustained perf mode = Режим тривалої роботи @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index fe04d93c6b..cfcfbf0df8 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1072,6 +1072,7 @@ Refresh rate = Tần số làm mới Release = Giải phóng RW/RX exclusive = Độc quyền RW/RX Sample rate = Tỷ lệ mẫu +Scoped Storage = Scoped Storage Shading Language = Ngôn ngữ tô bóng Storage = Storage Sustained perf mode = Chế độ hoàn thiện bền vững @@ -1208,6 +1209,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = Default [UI Elements] diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index fce8d07ded..ddf84c8312 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1064,6 +1064,7 @@ Refresh rate = 刷新率 Release = 发布版 RW/RX exclusive = RW/RX独占 Sample rate = 采样率 +Scoped Storage = Scoped Storage Shading Language = 着色语言 Storage = 存储 Sustained perf mode = 持久性能模式 @@ -1203,6 +1204,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] +Dark = Dark Default = 默认 [UI Elements] diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 7c17ef4702..cf906ad6b4 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1064,6 +1064,7 @@ Refresh rate = 重新整理速率 Release = 發行版本 RW/RX exclusive = RW/RX 排除 Sample rate = 取樣率 +Scoped Storage = Scoped Storage Shading Language = 網底語言 Storage = 儲存空間 Sustained perf mode = 持續效能模式 @@ -1195,6 +1196,7 @@ Color Saturation = 色彩飽和度 Show Memory Stick folder = 顯示記憶棒資料夾 [Themes] +Dark = Dark Default = 預設 [TextureShaders] From dae11c4ea6124d2b67e77039f116f6bee64ab277 Mon Sep 17 00:00:00 2001 From: haoruiwang <1905811497@qq.com> Date: Tue, 14 Mar 2023 14:22:13 +0800 Subject: [PATCH 309/424] [chore][gpu] Fix some clerical errors for GLQueueRunner but not effect logic --- Common/GPU/OpenGL/GLQueueRunner.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index eb6ee441a6..434bb5c1a9 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -514,8 +514,8 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex.wrapS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex.wrapT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex.magFilter); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex.minFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex.magFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex.minFilter); if (!gl_extensions.IsGLES || gl_extensions.GLES3) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); } @@ -1199,14 +1199,14 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last Crash(); } else if (c.bind_buffer.target == GL_ELEMENT_ARRAY_BUFFER) { GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0; - _dbg_assert_(!c.bind_buffer.buffer->Mapped()); + _dbg_assert_(!(c.bind_buffer.buffer && c.bind_buffer.buffer->Mapped())); if (buf != curElemArrayBuffer) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf); curElemArrayBuffer = buf; } } else { GLuint buf = c.bind_buffer.buffer ? c.bind_buffer.buffer->buffer_ : 0; - _dbg_assert_(!c.bind_buffer.buffer->Mapped()); + _dbg_assert_(!(c.bind_buffer.buffer && c.bind_buffer.buffer->Mapped())); glBindBuffer(c.bind_buffer.target, buf); } CHECK_GL_ERROR_IF_DEBUG(); @@ -1273,7 +1273,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last } case GLRRenderCommand::TEXTURELOD: { - GLint slot = c.textureSampler.slot; + GLint slot = c.textureLod.slot; if (slot != activeSlot) { glActiveTexture(GL_TEXTURE0 + slot); activeSlot = slot; @@ -1557,7 +1557,7 @@ void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) { glGetTexLevelParameteriv(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_TEXTURE_WIDTH, &w); glGetTexLevelParameteriv(GL_TEXTURE_2D, pass.readback_image.mipLevel, GL_TEXTURE_HEIGHT, &h); - int size = 4 * std::max((int)w, rect.x + rect.w) * std::max((int)h, rect.h); + int size = 4 * std::max((int)w, rect.x + rect.w) * std::max((int)h, rect.y + rect.h); if (size > readbackBufferSize_) { delete[] readbackBuffer_; readbackBuffer_ = new uint8_t[size]; From 577ffaec59d720b7ddc5251b8b70229f2b8f0515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=BA=E5=B7=A5=E7=9F=A5=E8=83=BD?= <42119227+Kaitul@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:41:12 +0800 Subject: [PATCH 310/424] Update zh_TW.ini --- assets/lang/zh_TW.ini | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index cf906ad6b4..45a5d91942 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -628,10 +628,10 @@ Search = 搜尋 [MappableControls] Alt speed 1 = 替代速度 1 Alt speed 2 = 替代速度 2 -An.Down = 類比搖桿:下 -An.Left = 類比搖桿:左 -An.Right = 類比搖桿:右 -An.Up = 類比搖桿:上 +An.Down = 類比搖桿 - 下 +An.Left = 類比搖桿 - 左 +An.Right = 類比搖桿 - 右 +An.Up = 類比搖桿 - 上 Analog limiter = 類比限制器 Analog Stick = 類比搖桿 Audio/Video Recording = 音訊/視訊錄製 @@ -648,19 +648,19 @@ Custom 7 = 自訂 7 Custom 8 = 自訂 8 Custom 9 = 自訂 9 Custom 10 = 自訂 10 -D-pad down = 方向鍵:下 -D-pad left = 方向鍵:左 -D-pad right = 方向鍵:右 -D-pad up = 方向鍵:上 +D-pad down = 方向鍵 - 下 +D-pad left = 方向鍵 - 左 +D-pad right = 方向鍵 - 右 +D-pad up = 方向鍵 - 上 DevMenu = 開發選單 Double tap button = 點兩下按鈕 -Down = 方向鍵:下 +Down = 方向鍵 - 下 Dpad = 方向鍵 Frame Advance = 逐影格 Hold = 固定 Home = PS 按鈕 L = L -Left = 方向鍵:左 +Left = 方向鍵 - 左 Load State = 載入存檔 Mute toggle = 靜音切換 Next Slot = 下一存檔插槽 @@ -673,12 +673,12 @@ RapidFire = 快速開火 Record = 錄製 Remote hold = 遠端固定 Rewind = 倒轉 -Right = 方向鍵:右 +Right = 方向鍵 - 右 Right Analog Stick = 右類比搖桿 -RightAn.Down = 右搖桿:下 -RightAn.Left = 右搖桿:左 -RightAn.Right = 右搖桿:右 -RightAn.Up = 右搖桿:上 +RightAn.Down = 右搖桿 - 下 +RightAn.Left = 右搖桿 - 左 +RightAn.Right = 右搖桿 - 右 +RightAn.Up = 右搖桿 - 上 Rotate Analog (CCW) = 旋轉類比 (CCW) Rotate Analog (CW) = 旋轉類比 (CW) Save State = 儲存存檔 @@ -1027,7 +1027,7 @@ Board = 主機板 Build Config = 組建組態 Build Configuration = 組建組態 Built by = 建置者 -Compressed texture formats = Compressed texture formats +Compressed texture formats = 壓縮的紋理格式 Core Context = 核心內容 Cores = 核心數 CPU Extensions = CPU 擴充 @@ -1064,7 +1064,7 @@ Refresh rate = 重新整理速率 Release = 發行版本 RW/RX exclusive = RW/RX 排除 Sample rate = 取樣率 -Scoped Storage = Scoped Storage +Scoped Storage = 限定範圍儲存空間 Shading Language = 網底語言 Storage = 儲存空間 Sustained perf mode = 持續效能模式 @@ -1196,7 +1196,7 @@ Color Saturation = 色彩飽和度 Show Memory Stick folder = 顯示記憶棒資料夾 [Themes] -Dark = Dark +Dark = 深色 Default = 預設 [TextureShaders] From c959d3fb332f4556a476f4d9326bd62040996c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=BA=E5=B7=A5=E7=9F=A5=E8=83=BD?= <42119227+Kaitul@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:43:18 +0800 Subject: [PATCH 311/424] Update zh_TW.ini --- assets/lang/zh_TW.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 45a5d91942..eece8dc9c8 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -699,7 +699,7 @@ Toggle Fullscreen = 切換全螢幕 Toggle mode = 切換模式 Triangle = △ Fast-forward = 快轉 -Up = 方向鍵:上 +Up = 方向鍵 - 上 Vol + = 音量 + Vol - = 音量 - Wlan = WLAN From 2b1e87792fa56b4247c08adc5573ce93e02a5005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 10:11:19 +0100 Subject: [PATCH 312/424] Vulkan: During texture upload, batch the buffer->image copies to do all the mips at once. --- Common/GPU/Vulkan/VulkanImage.cpp | 19 ++++++++++++++++--- Common/GPU/Vulkan/VulkanImage.h | 11 ++++++++++- Common/GPU/Vulkan/thin3d_vulkan.cpp | 8 ++++++-- GPU/Vulkan/TextureCacheVulkan.cpp | 23 ++++++++++++++--------- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanImage.cpp b/Common/GPU/Vulkan/VulkanImage.cpp index 8efcb69834..bbdc87a3e4 100644 --- a/Common/GPU/Vulkan/VulkanImage.cpp +++ b/Common/GPU/Vulkan/VulkanImage.cpp @@ -142,8 +142,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int depth, i return true; } -// TODO: Batch these. -void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, int depthLayer, VkBuffer buffer, uint32_t offset, size_t rowLength) { +void VulkanTexture::CopyBufferToMipLevel(VkCommandBuffer cmd, TextureCopyBatch *copyBatch, int mip, int mipWidth, int mipHeight, int depthLayer, VkBuffer buffer, uint32_t offset, size_t rowLength) { VkBufferImageCopy copy_region{}; copy_region.bufferOffset = offset; copy_region.bufferRowLength = (uint32_t)rowLength; @@ -157,7 +156,21 @@ void VulkanTexture::UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mi copy_region.imageSubresource.baseArrayLayer = 0; copy_region.imageSubresource.layerCount = 1; - vkCmdCopyBufferToImage(cmd, buffer, image_, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region); + if (!copyBatch->buffer) { + copyBatch->buffer = buffer; + } else if (copyBatch->buffer != buffer) { + // Need to flush the batch if this image isn't from the same buffer as the previous ones. + FinishCopyBatch(cmd, copyBatch); + copyBatch->buffer = buffer; + } + copyBatch->copies.push_back(copy_region); +} + +void VulkanTexture::FinishCopyBatch(VkCommandBuffer cmd, TextureCopyBatch *copyBatch) { + if (!copyBatch->copies.empty()) { + vkCmdCopyBufferToImage(cmd, copyBatch->buffer, image_, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (uint32_t)copyBatch->copies.size(), copyBatch->copies.data()); + copyBatch->copies.clear(); + } } void VulkanTexture::ClearMip(VkCommandBuffer cmd, int mip, uint32_t value) { diff --git a/Common/GPU/Vulkan/VulkanImage.h b/Common/GPU/Vulkan/VulkanImage.h index c088fdca5b..580e663713 100644 --- a/Common/GPU/Vulkan/VulkanImage.h +++ b/Common/GPU/Vulkan/VulkanImage.h @@ -7,6 +7,13 @@ class VulkanDeviceAllocator; VK_DEFINE_HANDLE(VmaAllocation); +struct TextureCopyBatch { + std::vector copies; + VkBuffer buffer = VK_NULL_HANDLE; + void reserve(size_t mips) { copies.reserve(mips); } + bool empty() const { return copies.empty(); } +}; + // Wrapper around what you need to use a texture. // ALWAYS use an allocator when calling CreateDirect. class VulkanTexture { @@ -23,7 +30,9 @@ public: void ClearMip(VkCommandBuffer cmd, int mip, uint32_t value); // Can also be used to copy individual levels of a 3D texture. - void UploadMip(VkCommandBuffer cmd, int mip, int mipWidth, int mipHeight, int depthLayer, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels + // If possible, will just add to the batch instead of submitting a copy. + void CopyBufferToMipLevel(VkCommandBuffer cmd, TextureCopyBatch *copyBatch, int mip, int mipWidth, int mipHeight, int depthLayer, VkBuffer buffer, uint32_t offset, size_t rowLength); // rowLength is in pixels + void FinishCopyBatch(VkCommandBuffer cmd, TextureCopyBatch *copyBatch); void GenerateMips(VkCommandBuffer cmd, int firstMipToGenerate, bool fromCompute); void EndCreate(VkCommandBuffer cmd, bool vertexTexture, VkPipelineStageFlags prevStage, VkImageLayout layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index ce76c90af2..008fcd0159 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -682,7 +682,9 @@ VulkanTexture *VKContext::GetNullTexture() { data[y*w + x] = 0; // black } } - nullTexture_->UploadMip(cmdInit, 0, w, h, 0, bindBuf, bindOffset, w); + TextureCopyBatch batch; + nullTexture_->CopyBufferToMipLevel(cmdInit, &batch, 0, w, h, 0, bindBuf, bindOffset, w); + nullTexture_->FinishCopyBatch(cmdInit, &batch); nullTexture_->EndCreate(cmdInit, false, VK_PIPELINE_STAGE_TRANSFER_BIT); } return nullTexture_; @@ -784,7 +786,9 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const Textur } else { offset = push->PushAligned((const void *)desc.initData[i], size, 16, &buf); } - vkTex_->UploadMip(cmd, i, w, h, 0, buf, offset, w); + TextureCopyBatch batch; + vkTex_->CopyBufferToMipLevel(cmd, &batch, i, w, h, 0, buf, offset, w); + vkTex_->FinishCopyBatch(cmd, &batch); w = (w + 1) / 2; h = (h + 1) / 2; d = (d + 1) / 2; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index e18fd7c5d5..20db0ddbe5 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -545,6 +545,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { VulkanPushBuffer *pushBuffer = drawEngine_->GetPushBufferForTextureData(); + // Batch the copies. + TextureCopyBatch copyBatch; + copyBatch.reserve(levels); + for (int i = 0; i < levels; i++) { int mipUnscaledWidth = gstate.getTextureWidth(i); int mipUnscaledHeight = gstate.getTextureHeight(i); @@ -595,15 +599,12 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // TODO: Fill with some pattern? } replacementTimeThisFrame_ += time_now_d() - replaceStart; - VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, - "Copy Upload (replaced): %dx%d", mipWidth, mipHeight); - entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, rowLength); - VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); + entry->vkTex->CopyBufferToMipLevel(cmdInit, ©Batch, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, rowLength); } else { if (plan.depth != 1) { // 3D texturing. loadLevel(uploadSize, i, byteStride, plan.scaleFactor); - entry->vkTex->UploadMip(cmdInit, 0, mipWidth, mipHeight, i, texBuf, bufferOffset, pixelStride); + entry->vkTex->CopyBufferToMipLevel(cmdInit, ©Batch, 0, mipWidth, mipHeight, i, texBuf, bufferOffset, pixelStride); } else if (computeUpload) { int srcBpp = VkFormatBytesPerPixel(dstFmt); int srcStride = mipUnscaledWidth * srcBpp; @@ -625,10 +626,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { vulkan->Delete().QueueDeleteImageView(view); } else { loadLevel(uploadSize, i == 0 ? plan.baseLevelSrc : i, byteStride, plan.scaleFactor); - VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, - "Copy Upload: %dx%d", mipWidth, mipHeight); - entry->vkTex->UploadMip(cmdInit, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, pixelStride); - VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); + entry->vkTex->CopyBufferToMipLevel(cmdInit, ©Batch, i, mipWidth, mipHeight, 0, texBuf, bufferOffset, pixelStride); } // Format might be wrong in lowMemoryMode_, so don't save. if (plan.saveTexture && !lowMemoryMode_) { @@ -650,6 +648,13 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { } } + if (!copyBatch.empty()) { + VK_PROFILE_BEGIN(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT, "Copy Upload"); + // Submit the whole batch of mip uploads. + entry->vkTex->FinishCopyBatch(cmdInit, ©Batch); + VK_PROFILE_END(vulkan, cmdInit, VK_PIPELINE_STAGE_TRANSFER_BIT); + } + VkImageLayout layout = computeUpload ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; VkPipelineStageFlags prevStage = computeUpload ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : VK_PIPELINE_STAGE_TRANSFER_BIT; From 0fd58d80d5371b2bb732011ad7f1c7ef57fa2fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Mar 2023 14:26:28 +0100 Subject: [PATCH 313/424] Detect BASIS files. Doesn't do much with them yet. --- GPU/Common/ReplacedTexture.cpp | 50 ++++++++++++++++++++++++++++------ GPU/Common/ReplacedTexture.h | 1 + 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index f2497ae9b5..9739089db3 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -16,11 +16,13 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include + #include "ppsspp_config.h" #include #include "ext/basis_universal/basisu_transcoder.h" +#include "ext/basis_universal/basisu_file_headers.h" #include "GPU/Common/ReplacedTexture.h" #include "GPU/Common/TextureReplacer.h" @@ -44,6 +46,12 @@ static ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { return ReplacedImageType::PNG; if (strncmp((const char *)magic, "DDS ", 4) == 0) return ReplacedImageType::DDS; + if (magic[0] == 's' && magic[1] == 'B') { + uint16_t ver = magic[2] | (magic[3] << 8); + if (ver >= 0x10) { + return ReplacedImageType::BASIS; + } + } return ReplacedImageType::INVALID; } @@ -68,13 +76,8 @@ class ReplacedTextureTask : public Task { public: ReplacedTextureTask(VFSBackend *vfs, ReplacedTexture &tex, LimitedWaitable *w) : vfs_(vfs), tex_(tex), waitable_(w) {} - TaskType Type() const override { - return TaskType::IO_BLOCKING; - } - - TaskPriority Priority() const override { - return TaskPriority::NORMAL; - } + TaskType Type() const override { return TaskType::IO_BLOCKING; } + TaskPriority Priority() const override { return TaskPriority::NORMAL; } void Run() override { tex_.Prepare(vfs_); @@ -267,7 +270,38 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string bool ddsDX10 = false; int numMips = 1; - if (imageType == ReplacedImageType::DDS) { + if (imageType == ReplacedImageType::BASIS) { + // Peek into the file using the header struct. + basist::basis_file_header header; + good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); + + if (header.m_tex_format == 0) { + // ETC1S texture data (transcodable to ETC2 or DXT1) + // Check what we should transcode to. + if (desc_->formatSupport.bc123) { + *pixelFormat = Draw::DataFormat::BC1_RGBA_UNORM_BLOCK; + } else if (desc_->formatSupport.etc2) { + *pixelFormat = Draw::DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK; + } else { + // We're in trouble. + good = false; + } + } else { + // UASTC texture data (transcodable to ASTC or BC7). + if (desc_->formatSupport.bc7) { + *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; + } else if (desc_->formatSupport.astc) { + *pixelFormat = Draw::DataFormat::ASTC_4x4_UNORM_BLOCK; + } else { + good = false; + } + } + + // TODO: Seek to the slice header array. + // vfs_->Seek(header.m_slice_desc_file_ofs); + + good = false; + } else if (imageType == ReplacedImageType::DDS) { DDSHeader header; DDSHeaderDXT10 header10{}; good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 0eccb0ab7f..7043c7a9e5 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -45,6 +45,7 @@ enum class ReplacedImageType { PNG, ZIM, DDS, + BASIS, INVALID, }; From 93bf82a906eb7cbe58131735c0d0b9f56ced4707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 13 Mar 2023 16:20:01 +0100 Subject: [PATCH 314/424] Add KTX2 basis/UASTC texture transcoding support --- Common/Data/Format/DDSLoad.h | 14 +++ GPU/Common/ReplacedTexture.cpp | 117 ++++++++++++++++++++---- GPU/Common/ReplacedTexture.h | 3 +- GPU/Common/TextureReplacer.cpp | 6 ++ ext/basis_universal/basisu_containers.h | 1 + 5 files changed, 124 insertions(+), 17 deletions(-) diff --git a/Common/Data/Format/DDSLoad.h b/Common/Data/Format/DDSLoad.h index 9862854b95..3f7d36cf27 100644 --- a/Common/Data/Format/DDSLoad.h +++ b/Common/Data/Format/DDSLoad.h @@ -67,3 +67,17 @@ struct DDSLoadInfo { }; bool DetectDDSParams(const DDSHeader *header, DDSLoadInfo *info); + +// We use the Basis library for the actual reading, but before we do, we pre-scan using this, similarly to the png trick. +struct KTXHeader { + uint8_t identifier[12]; + uint32_t vkFormat; + uint32_t typeSize; + uint32_t pixelWidth; + uint32_t pixelHeight; + uint32_t pixelDepth; + uint32_t layerCount; + uint32_t faceCount; + uint32_t levelCount; + uint32_t supercompressionScheme; +}; diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 9739089db3..5bece0600b 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -40,17 +40,20 @@ #define MK_FOURCC(str) (str[0] | ((uint8_t)str[1] << 8) | ((uint8_t)str[2] << 16) | ((uint8_t)str[3] << 24)) static ReplacedImageType IdentifyMagic(const uint8_t magic[4]) { - if (strncmp((const char *)magic, "ZIMG", 4) == 0) + if (memcmp((const char *)magic, "ZIMG", 4) == 0) return ReplacedImageType::ZIM; - if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) + else if (magic[0] == 0x89 && strncmp((const char *)&magic[1], "PNG", 3) == 0) return ReplacedImageType::PNG; - if (strncmp((const char *)magic, "DDS ", 4) == 0) + else if (memcmp((const char *)magic, "DDS ", 4) == 0) return ReplacedImageType::DDS; - if (magic[0] == 's' && magic[1] == 'B') { + else if (magic[0] == 's' && magic[1] == 'B') { uint16_t ver = magic[2] | (magic[3] << 8); if (ver >= 0x10) { return ReplacedImageType::BASIS; } + } else if (memcmp((const char *)magic, "\xabKTX", 4) == 0) { + // Technically, should read 12 bytes here, but this'll do. + return ReplacedImageType::KTX2; } return ReplacedImageType::INVALID; } @@ -192,6 +195,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { // We must lock around access to levelData_ in case two textures try to load it at once. std::lock_guard guard(levelData_->lock); + Draw::DataFormat pixelFormat; for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_->filenames.size()); ++i) { if (State() == ReplacementState::CANCEL_INIT) { break; @@ -212,7 +216,6 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { fmt = Draw::DataFormat::R8G8B8A8_UNORM; } - Draw::DataFormat pixelFormat; if (LoadLevelData(fileRef, desc_->filenames[i], i, &pixelFormat)) { if (i == 0) { fmt = pixelFormat; @@ -223,6 +226,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { } } } else { + fmt = pixelFormat; // Otherwise, we're done loading mips (bad PNG or bad size, either way.) break; } @@ -233,6 +237,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { if (levels_.empty()) { // Bad. + WARN_LOG(G3D, "Failed to load texture"); SetState(ReplacementState::NOT_FOUND); levelData_ = nullptr; return; @@ -270,7 +275,17 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string bool ddsDX10 = false; int numMips = 1; - if (imageType == ReplacedImageType::BASIS) { + if (imageType == ReplacedImageType::KTX2) { + KTXHeader header; + good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); + + level.w = header.pixelWidth; + level.h = header.pixelHeight; + numMips = header.levelCount; + + // Additional quick checks + good = good && header.layerCount <= 1; + } else if (imageType == ReplacedImageType::BASIS) { // Peek into the file using the header struct. basist::basis_file_header header; good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); @@ -300,6 +315,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string // TODO: Seek to the slice header array. // vfs_->Seek(header.m_slice_desc_file_ofs); + // We don't support basis files currently. good = false; } else if (imageType == ReplacedImageType::DDS) { DDSHeader header; @@ -422,7 +438,79 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string level.fileRef = fileRef; - if (imageType == ReplacedImageType::DDS) { + if (imageType == ReplacedImageType::KTX2) { + // Just slurp the whole file in one go and feed to the decoder. + std::vector buffer; + buffer.resize(fileSize); + buffer.resize(vfs_->Read(openFile, &buffer[0], buffer.size())); + + basist::ktx2_transcoder transcoder; + if (!transcoder.init(buffer.data(), (int)buffer.size())) { + WARN_LOG(G3D, "Error reading KTX file"); + cleanup(); + return false; + } + + // Figure out the target format. + basist::transcoder_texture_format transcoderFormat; + if (transcoder.is_etc1s()) { + // Let's pick a suitable compatible format. + if (desc_->formatSupport.bc123) { + transcoderFormat = basist::transcoder_texture_format::cTFBC1; + *pixelFormat = Draw::DataFormat::BC1_RGBA_UNORM_BLOCK; + } else if (desc_->formatSupport.etc2) { + transcoderFormat = basist::transcoder_texture_format::cTFETC1_RGB; + *pixelFormat = Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK; + } else { + // Bad. + cleanup(); + return false; + } + } else if (transcoder.is_uastc()) { + // Let's pick a suitable compatible format. + if (desc_->formatSupport.bc7) { + transcoderFormat = basist::transcoder_texture_format::cTFBC7_RGBA; + *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; + } else if (desc_->formatSupport.astc) { + transcoderFormat = basist::transcoder_texture_format::cTFASTC_4x4_RGBA; + *pixelFormat = Draw::DataFormat::ASTC_4x4_UNORM_BLOCK; + } else { + cleanup(); + return false; + } + } else { + WARN_LOG(G3D, "PPSSPP currently only supports KTX for basis/UASTC textures. This may change in the future."); + } + + int blockSize; + bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); + _dbg_assert_(bc); + + levelData_->data.resize(numMips); + + basist::ktx2_transcoder_state transcodeState; // Each thread needs one of these. + + transcoder.start_transcoding(); + for (int i = 0; i < numMips; i++) { + std::vector &out = levelData_->data[mipLevel + i]; + + basist::ktx2_image_level_info levelInfo; + bool result = transcoder.get_image_level_info(levelInfo, i, 0, 0); + _dbg_assert_(result); + + levelData_->data[i].resize(levelInfo.m_total_blocks * blockSize); + + transcoder.transcode_image_level(i, 0, 0, &out[0], levelInfo.m_total_blocks, transcoderFormat, 0, levelInfo.m_num_blocks_x, level.h, -1, -1, &transcodeState); + level.w = levelInfo.m_orig_width; + level.h = levelInfo.m_orig_height; + if (i != 0) + level.fileRef = nullptr; + levels_.push_back(level); + } + transcoder.clear(); + cleanup(); + return false; // don't read more levels + } else if (imageType == ReplacedImageType::DDS) { DDSHeader header; DDSHeaderDXT10 header10{}; vfs_->Read(openFile, &header, sizeof(header)); @@ -449,23 +537,24 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } levels_.push_back(level); - level.w /= 2; - level.h /= 2; - level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. + level.w = std::max(level.w / 2, 1); + level.h = std::max(level.h / 2, 1); + if (i != 0) + level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. } + cleanup(); + return false; // don't read more levels } else if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); - SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", filename.c_str()); - SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } @@ -476,7 +565,6 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > level.w || h > level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); - SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } @@ -508,13 +596,11 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", filename.c_str(), png.message); - SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } if (png.width > (uint32_t)level.w || png.height > (uint32_t)level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); - SetState(ReplacementState::NOT_FOUND); cleanup(); return false; } @@ -533,7 +619,6 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string out.resize(level.w * level.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); - SetState(ReplacementState::NOT_FOUND); cleanup(); out.resize(0); return false; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 7043c7a9e5..a237b1bd04 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -45,7 +45,8 @@ enum class ReplacedImageType { PNG, ZIM, DDS, - BASIS, + BASIS, // TODO: Might not even do this, KTX2 is a better container. + KTX2, INVALID, }; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 1a073f4558..57ab5b7d92 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -22,6 +22,7 @@ #include #include +#include "ext/basis_universal/basisu_transcoder.h" #include "ext/xxhash.h" #include "Common/Data/Convert/ColorConv.h" @@ -53,8 +54,13 @@ static const std::string ZIP_FILENAME = "textures.zip"; static const std::string NEW_TEXTURE_DIR = "new/"; static const int VERSION = 1; static const double MAX_CACHE_SIZE = 4.0; +static bool basisu_initialized = false; TextureReplacer::TextureReplacer(Draw::DrawContext *draw) { + if (!basisu_initialized) { + basist::basisu_transcoder_init(); + basisu_initialized = true; + } // We don't want to keep the draw object around, so extract the info we need. if (draw->GetDataFormatSupport(Draw::DataFormat::BC3_UNORM_BLOCK)) formatSupport_.bc123 = true; if (draw->GetDataFormatSupport(Draw::DataFormat::ASTC_4x4_UNORM_BLOCK)) formatSupport_.astc = true; diff --git a/ext/basis_universal/basisu_containers.h b/ext/basis_universal/basisu_containers.h index d123ce4788..b08523cd84 100644 --- a/ext/basis_universal/basisu_containers.h +++ b/ext/basis_universal/basisu_containers.h @@ -315,6 +315,7 @@ namespace basisu { scalar_type::destruct_array(m_p, m_size); free(m_p); + m_p = nullptr; } } From 91900eda7e47fa455731a69a4c2d5013f94f4892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 11:32:08 +0100 Subject: [PATCH 315/424] Don't try to generate mips for compressed replacement images --- Common/GPU/Vulkan/VulkanImage.cpp | 2 ++ GPU/Vulkan/TextureCacheVulkan.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanImage.cpp b/Common/GPU/Vulkan/VulkanImage.cpp index bbdc87a3e4..d40e422ff4 100644 --- a/Common/GPU/Vulkan/VulkanImage.cpp +++ b/Common/GPU/Vulkan/VulkanImage.cpp @@ -156,6 +156,8 @@ void VulkanTexture::CopyBufferToMipLevel(VkCommandBuffer cmd, TextureCopyBatch * copy_region.imageSubresource.baseArrayLayer = 0; copy_region.imageSubresource.layerCount = 1; + _dbg_assert_(mip < numMips_); + if (!copyBatch->buffer) { copyBatch->buffer = buffer; } else if (copyBatch->buffer != buffer) { diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 20db0ddbe5..9e65c4017f 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -430,6 +430,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { VkFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.scaleFactor > 1) { + _dbg_assert_(!plan.replaceValid); // Whether hardware or software scaling, this is the dest format. dstFmt = VULKAN_8888_FORMAT; } else if (plan.decodeToClut8) { @@ -438,9 +439,10 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // We don't generate mipmaps for 512x512 textures because they're almost exclusively used for menu backgrounds // and similar, which don't really need it. - if (g_Config.iTexFiltering == TEX_FILTER_AUTO_MAX_QUALITY && plan.w <= 256 && plan.h <= 256) { + // Also, if using replacements, check that we really can generate mips for this format - that's not possible for compressed ones. + if (g_Config.iTexFiltering == TEX_FILTER_AUTO_MAX_QUALITY && plan.w <= 256 && plan.h <= 256 && (!plan.replaceValid || plan.replaced->Format() == Draw::DataFormat::R8G8B8A8_UNORM)) { // Boost the number of mipmaps. - if (plan.maxPossibleLevels > plan.levelsToCreate) { + if (plan.maxPossibleLevels > plan.levelsToCreate) { // TODO: Should check against levelsToLoad, no? // We have to generate mips with a shader. This requires decoding to R8G8B8A8_UNORM format to avoid extra complications. dstFmt = VULKAN_8888_FORMAT; } From 6d520d6d6b25275995b7b3a28147ca0c1b694a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 11:48:31 +0100 Subject: [PATCH 316/424] Vulkan: Enable mobile compressed formats too (oops) --- GPU/Common/ReplacedTexture.cpp | 3 ++- GPU/Vulkan/TextureCacheVulkan.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 5bece0600b..788f0bc701 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -462,7 +462,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string transcoderFormat = basist::transcoder_texture_format::cTFETC1_RGB; *pixelFormat = Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK; } else { - // Bad. + // TODO: Transcode to RGBA8 instead as a fallback. cleanup(); return false; } @@ -475,6 +475,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string transcoderFormat = basist::transcoder_texture_format::cTFASTC_4x4_RGBA; *pixelFormat = Draw::DataFormat::ASTC_4x4_UNORM_BLOCK; } else { + // TODO: Transcode to RGBA8 instead as a fallback. cleanup(); return false; } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 9e65c4017f..7f60c27d2f 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -411,6 +411,11 @@ static VkFormat ToVulkanFormat(Draw::DataFormat fmt) { case Draw::DataFormat::BC4_UNORM_BLOCK: return VK_FORMAT_BC4_UNORM_BLOCK; case Draw::DataFormat::BC5_UNORM_BLOCK: return VK_FORMAT_BC5_UNORM_BLOCK; case Draw::DataFormat::BC7_UNORM_BLOCK: return VK_FORMAT_BC7_UNORM_BLOCK; + case Draw::DataFormat::ASTC_4x4_UNORM_BLOCK: return VK_FORMAT_ASTC_4x4_UNORM_BLOCK; + case Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + case Draw::DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + case Draw::DataFormat::ETC2_R8G8B8A8_UNORM_BLOCK: return VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + case Draw::DataFormat::R8G8B8A8_UNORM: return VULKAN_8888_FORMAT; default: _assert_msg_(false, "Bad texture pixel format"); return VULKAN_8888_FORMAT; } From fc6382140b43c3dd1953c4c6ac7d5f12a9332b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 13:42:00 +0100 Subject: [PATCH 317/424] UWP Buildfix --- UWP/CommonUWP/CommonUWP.vcxproj | 18 ++++++++ UWP/CommonUWP/CommonUWP.vcxproj.filters | 57 +++++++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index b6c7e04111..a76a85ef67 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -404,6 +404,13 @@ + + + + + + + @@ -528,6 +535,7 @@ + @@ -546,6 +554,16 @@ + + + + + + + + + + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index 63bccb6fcf..03f9424dfe 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -91,6 +91,9 @@ {096c3d00-fcfa-4877-8cf0-3b10d56b5d72} + + {8b92cc15-8e3e-45b1-ba80-ad39b1a9cdc8} + @@ -423,6 +426,9 @@ Data\Format + + ext\basis_universal + @@ -784,6 +790,27 @@ Data\Format + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + @@ -793,5 +820,35 @@ Math\lin + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + + + ext\basis_universal + \ No newline at end of file From 4bbc4c258a28f0e01ba08b0433c222b552ce004e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 14:09:21 +0100 Subject: [PATCH 318/424] Remove sketch of Basis container format support (we go with KTX2 instead as the container) --- GPU/Common/ReplacedTexture.cpp | 31 ++----------------------------- GPU/Common/TextureCacheCommon.h | 2 +- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 788f0bc701..df7c917ae8 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -286,36 +286,9 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string // Additional quick checks good = good && header.layerCount <= 1; } else if (imageType == ReplacedImageType::BASIS) { - // Peek into the file using the header struct. - basist::basis_file_header header; - good = vfs_->Read(openFile, &header, sizeof(header)) == sizeof(header); + WARN_LOG(G3D, "The basis texture format is not supported. Use KTX2 (basisu texture.png -uastc -ktx2 -mipmap)"); - if (header.m_tex_format == 0) { - // ETC1S texture data (transcodable to ETC2 or DXT1) - // Check what we should transcode to. - if (desc_->formatSupport.bc123) { - *pixelFormat = Draw::DataFormat::BC1_RGBA_UNORM_BLOCK; - } else if (desc_->formatSupport.etc2) { - *pixelFormat = Draw::DataFormat::ETC2_R8G8B8A1_UNORM_BLOCK; - } else { - // We're in trouble. - good = false; - } - } else { - // UASTC texture data (transcodable to ASTC or BC7). - if (desc_->formatSupport.bc7) { - *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; - } else if (desc_->formatSupport.astc) { - *pixelFormat = Draw::DataFormat::ASTC_4x4_UNORM_BLOCK; - } else { - good = false; - } - } - - // TODO: Seek to the slice header array. - // vfs_->Seek(header.m_slice_desc_file_ofs); - - // We don't support basis files currently. + // We simply don't support basis files currently. good = false; } else if (imageType == ReplacedImageType::DDS) { DDSHeader header; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index f50b042d89..f655fe249c 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013- PPSSPP Project. + // Copyright (c) 2013- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by From 00d5658ff2b80709259693e9cc49f20329b27256 Mon Sep 17 00:00:00 2001 From: TotalCaesar659 <14265316+TotalCaesar659@users.noreply.github.com> Date: Tue, 14 Mar 2023 17:37:51 +0300 Subject: [PATCH 319/424] Revert "Scoped Storage" translatability --- UI/DevScreens.cpp | 2 +- assets/lang/ar_AE.ini | 1 - assets/lang/az_AZ.ini | 1 - assets/lang/bg_BG.ini | 1 - assets/lang/ca_ES.ini | 1 - assets/lang/cz_CZ.ini | 1 - assets/lang/da_DK.ini | 1 - assets/lang/de_DE.ini | 1 - assets/lang/dr_ID.ini | 1 - assets/lang/en_US.ini | 1 - assets/lang/es_ES.ini | 1 - assets/lang/es_LA.ini | 1 - assets/lang/fa_IR.ini | 1 - assets/lang/fi_FI.ini | 1 - assets/lang/fr_FR.ini | 1 - assets/lang/gl_ES.ini | 1 - assets/lang/gr_EL.ini | 1 - assets/lang/he_IL.ini | 1 - assets/lang/he_IL_invert.ini | 1 - assets/lang/hr_HR.ini | 1 - assets/lang/hu_HU.ini | 1 - assets/lang/id_ID.ini | 1 - assets/lang/it_IT.ini | 1 - assets/lang/ja_JP.ini | 1 - assets/lang/jv_ID.ini | 1 - assets/lang/ko_KR.ini | 1 - assets/lang/lo_LA.ini | 1 - assets/lang/lt-LT.ini | 1 - assets/lang/ms_MY.ini | 1 - assets/lang/nl_NL.ini | 1 - assets/lang/no_NO.ini | 1 - assets/lang/pl_PL.ini | 1 - assets/lang/pt_BR.ini | 1 - assets/lang/pt_PT.ini | 1 - assets/lang/ro_RO.ini | 1 - assets/lang/ru_RU.ini | 1 - assets/lang/sv_SE.ini | 1 - assets/lang/tg_PH.ini | 1 - assets/lang/th_TH.ini | 1 - assets/lang/tr_TR.ini | 1 - assets/lang/uk_UA.ini | 1 - assets/lang/vi_VN.ini | 1 - assets/lang/zh_CN.ini | 1 - assets/lang/zh_TW.ini | 1 - 44 files changed, 1 insertion(+), 44 deletions(-) diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index ce7cafc5c1..170cb99414 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -659,7 +659,7 @@ void SystemInfoScreen::CreateViews() { #if PPSSPP_PLATFORM(ANDROID) storage->Add(new InfoItem("ExtFilesDir", g_extFilesDir)); bool scoped = System_GetPropertyBool(SYSPROP_ANDROID_SCOPED_STORAGE); - storage->Add(new InfoItem(si->T("Scoped Storage"), scoped ? di->T("Yes") : di->T("No"))); + storage->Add(new InfoItem("Scoped Storage", scoped ? di->T("Yes") : di->T("No"))); if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 30) { // This flag is only relevant on Android API 30+. storage->Add(new InfoItem("IsStoragePreservedLegacy", Android_IsExternalStoragePreservedLegacy() ? di->T("Yes") : di->T("No"))); diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index c8c9237c13..461295a85a 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -1080,7 +1080,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 0d84d5f9a7..e8a197072a 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index 71d3691558..35774afa64 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index bbda05b855..03bf12572d 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index c6abcbfc4e..6052de0562 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 8a4a935fcd..6fa8bf2e34 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index a3da455d83..cf78feb4b9 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -1072,7 +1072,6 @@ Refresh rate = Wiederholungsrate Release = Release RW/RX exclusive = RW/RX exklusiv Sample rate = Abtastrate -Scoped Storage = Scoped Storage Shading Language = Shadersprache Storage = Storage Sustained perf mode = Anhaltener Hochleistungsmodus diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index f18a7a1108..4226051826 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 4dc2b1298e..8b2c8715d0 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -1088,7 +1088,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 68223be8b8..7dffaf6552 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -1073,7 +1073,6 @@ Refresh rate = frecuencia de actualización Release = Estable RW/RX exclusive = RW/RX exclusivo Sample rate = Frecuencia de muestreo -Scoped Storage = Scoped Storage Shading Language = Lenguaje de shader Storage = Almacenamiento Sustained perf mode = Modo de rendimiento sostenido diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index 3d6138a7a1..c537e9566c 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -1072,7 +1072,6 @@ Refresh rate = Tasa de refresco Release = Estable RW/RX exclusive = Exclusivo de RW/RX Sample rate = Ratio de muestra -Scoped Storage = Scoped Storage Shading Language = Lenguaje de shader Storage = Almacenamiento Sustained perf mode = Modo rendimiento sostenido diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 2a167a1eee..92ff1b406c 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 16597e96ed..5c62718b08 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index d84d6e5164..e2eb49f59b 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -1063,7 +1063,6 @@ Refresh rate = Taux de rafraîchissement Release = Release RW/RX exclusive = Exclusif RW/RX Sample rate = Taux d'échantillonnage -Scoped Storage = Scoped Storage Shading Language = Language de shading Storage = Storage Sustained perf mode = Mode performance prolongée diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index cbd3747607..11ef02432c 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index 1e5dbaeea0..aa9dde34a7 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -1072,7 +1072,6 @@ Refresh rate = Ρυθμός ανανέωσης Release = Release RW/RX exclusive = RW/RX αποκλειστικό Sample rate = Ρυθμός δειγματοληψίας -Scoped Storage = Scoped Storage Shading Language = Γλώσσα σκίασης Storage = Storage Sustained perf mode = Διατηρημένη λειτουργία απόδοσης diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index 624c017ee0..32013364f8 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index e73a2209a3..240da1cdd2 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index e2130f0fbb..b873743723 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -1072,7 +1072,6 @@ Refresh rate = Brzina osvježavanja Release = Pusti RW/RX exclusive = RW/RX ekskluzivno Sample rate = Brzina sample-ova -Scoped Storage = Scoped Storage Shading Language = Jezik sjenčanja Storage = Storage Sustained perf mode = Održiv perf način diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 7f7c992036..8920fb5b9a 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -1072,7 +1072,6 @@ Refresh rate = Frissítési gyakoriság Release = Release RW/RX exclusive = RW/RX exkluzív Sample rate = Mintavételezési ráta -Scoped Storage = Scoped Storage Shading Language = Shading nyelv Storage = Storage Sustained perf mode = Fentartott teljesítmény mód diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index d8875218c1..75bc24cc01 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -1072,7 +1072,6 @@ Refresh rate = Penyegaran Release = Rilis RW/RX exclusive = RW/RX eksklusif Sample rate = Tingkat penyegaran -Scoped Storage = Scoped Storage Shading Language = Bahasa shading Storage = Penyimpanan Sustained perf mode = Mode kinerja berkelanjutan diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 9234601dc3..ec58a24f29 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -1073,7 +1073,6 @@ Refresh rate = Frequenza d'aggiornamento Release = Rilascio RW/RX exclusive = Esclusiva RW/RX Sample rate = Frequenza di campionamento -Scoped Storage = Scoped Storage Shading Language = Linguaggio shading Storage = Storage Sustained perf mode = Modalità prestazioni prolungate diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index fdead00d08..f3e0658528 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -1072,7 +1072,6 @@ Refresh rate = リフレッシュレート Release = リリース RW/RX exclusive = RW/RX専用 Sample rate = サンプルレート -Scoped Storage = Scoped Storage Shading Language = シェーディング言語 Storage = ストレージ情報 Sustained perf mode = 性能維持モード diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index c403af18a1..15f3ae2248 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 58de9da885..18f72236d8 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -1064,7 +1064,6 @@ Refresh rate = 주사율 Release = 개정 RW/RX exclusive = RW/RX 전용 Sample rate = 샘플 속도 -Scoped Storage = Scoped Storage Shading Language = 쉐이딩 언어 Storage = 저장소 Sustained perf mode = 지속 성능 모드 diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index ebc02641ad..c4fb69568c 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index f046b42d06..7708f8fdc2 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 2a3983823b..072affd878 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index e0f3e11002..03730e79fe 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -1072,7 +1072,6 @@ Refresh rate = Vernieuwingsfrequentie Release = Release RW/RX exclusive = RW/RX-excusief Sample rate = Samplerate -Scoped Storage = Scoped Storage Shading Language = Shadingtaal Storage = Storage Sustained perf mode = Aanhoudende prestatiemodus diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index e9f92d1cf2..85ad21d76d 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index d489a6ee73..5af4c6c860 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -1072,7 +1072,6 @@ Refresh rate = Częstotliwość odświeżania Release = Release RW/RX exclusive = Wyłączne RW/RX Sample rate = Częstotliwość próbkowania -Scoped Storage = Scoped Storage Shading Language = Język shadingu Storage = Storage Sustained perf mode = Tryb wysokiej wydajności diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 6807538340..25dfb9755a 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -1088,7 +1088,6 @@ Refresh rate = Taxa de atualização Release = Lançamento RW/RX exclusive = RW/RX exclusivo Sample rate = Taxa de amostragem -Scoped Storage = Scoped Storage Shading Language = Idioma do shader Storage = Armazenagem Sustained perf mode = Modo de performance sustentado diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 166b248fe8..eccd69ecae 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -1089,7 +1089,6 @@ Refresh rate = Taxa de atualização Release = Lançamento RW/RX exclusive = RW/RX exclusivo Sample rate = Taxa de amostragem -Scoped Storage = Scoped Storage Shading Language = Idioma do Shader Storage = Armazenamento Sustained perf mode = Modo de performance sustentado diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 34f74743dc..b262ed7d21 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 3f7609bbc2..b61e7c5fc0 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -1072,7 +1072,6 @@ Refresh rate = Частота обновления Release = Релизная RW/RX exclusive = Захват RW/RX Sample rate = Частота дискретизации -Scoped Storage = Scoped Storage Shading Language = Язык шейдеров Storage = Место хранения Sustained perf mode = Режим длительной работы diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index ae20396e10..7570246282 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index f4a576b675..aa3dcbab93 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -1072,7 +1072,6 @@ Refresh rate = Refresh rate Release = Release RW/RX exclusive = RW/RX exclusive Sample rate = Sample rate -Scoped Storage = Scoped Storage Shading Language = Shading language Storage = Storage Sustained perf mode = Sustained perf mode diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 477c9bc145..9bb3fdac31 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -1078,7 +1078,6 @@ Refresh rate = อัตราการรีเฟรชของหน้า Release = ใช้งาน RW/RX exclusive = RW/RX แบบพิเศษ Sample rate = อัตราค่าความถี่เสียง -Scoped Storage = Scoped Storage Shading Language = ภาษาของเฉดเดอร์ Storage = พื้นที่เก็บข้อมูล Sustained perf mode = โหมดประสิทธิภาพที่ยั่งยืน diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 23cb66d317..cf9583ace4 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -1073,7 +1073,6 @@ Refresh rate = Yenileme hızı Release = Release RW/RX exclusive = RW/RX'e özel Sample rate = Örnekleme hızı -Scoped Storage = Scoped Storage Shading Language = Gölgelendirme dili Storage = Depolama Sustained perf mode = Sürekli performans modu diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 86e406f97f..f03c6bd823 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -1072,7 +1072,6 @@ Refresh rate = Частота оновлення Release = Реліз RW/RX exclusive = Ексклюзивний RW/RX Sample rate = Норма вибірки -Scoped Storage = Scoped Storage Shading Language = Мова шейдерів Storage = Storage Sustained perf mode = Режим тривалої роботи diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index cfcfbf0df8..1c2d60e972 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -1072,7 +1072,6 @@ Refresh rate = Tần số làm mới Release = Giải phóng RW/RX exclusive = Độc quyền RW/RX Sample rate = Tỷ lệ mẫu -Scoped Storage = Scoped Storage Shading Language = Ngôn ngữ tô bóng Storage = Storage Sustained perf mode = Chế độ hoàn thiện bền vững diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index ddf84c8312..0636097c09 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1064,7 +1064,6 @@ Refresh rate = 刷新率 Release = 发布版 RW/RX exclusive = RW/RX独占 Sample rate = 采样率 -Scoped Storage = Scoped Storage Shading Language = 着色语言 Storage = 存储 Sustained perf mode = 持久性能模式 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index eece8dc9c8..5e165dbe8b 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -1064,7 +1064,6 @@ Refresh rate = 重新整理速率 Release = 發行版本 RW/RX exclusive = RW/RX 排除 Sample rate = 取樣率 -Scoped Storage = 限定範圍儲存空間 Shading Language = 網底語言 Storage = 儲存空間 Sustained perf mode = 持續效能模式 From 21a0a91818ec82189b702574eedd6e1b6e841a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 15:48:10 +0100 Subject: [PATCH 320/424] Remove a misplaced ForgetLastTexture. Fixes #17115 --- GPU/Common/TextureCacheCommon.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 778c4319fb..70d8682d38 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2267,7 +2267,6 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer gstate_c.SetTextureFullAlpha(alphaStatus == CHECKALPHA_FULL); draw_->Invalidate(InvalidationFlags::CACHED_RENDER_STATE); - ForgetLastTexture(); return; } From 6c8da44779f766d93f15e281e300da71e60ae61e Mon Sep 17 00:00:00 2001 From: Narugakuruga <31060534+Narugakuruga@users.noreply.github.com> Date: Tue, 14 Mar 2023 23:07:53 +0800 Subject: [PATCH 321/424] Update zh_CN.ini --- assets/lang/zh_CN.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 0636097c09..91d76768ab 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -1203,7 +1203,7 @@ Tex2xBRZ = Tex2xBRZ Tex4xBRZ = Tex4xBRZ [Themes] -Dark = Dark +Dark = 深色模式 Default = 默认 [UI Elements] From c6e00276041d0d6121a8114adaadc5ec33e4fa8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 16:09:40 +0100 Subject: [PATCH 322/424] OpenGL: Try a different way to exclude desktop compression formats in build May fix #17110 --- Common/GPU/OpenGL/DataFormatGL.cpp | 2 +- Common/GPU/OpenGL/GLFeatures.cpp | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp index 67a4fdbc72..be3b8d8aa2 100644 --- a/Common/GPU/OpenGL/DataFormatGL.cpp +++ b/Common/GPU/OpenGL/DataFormatGL.cpp @@ -86,7 +86,7 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin alignment = 16; break; -#if PPSSPP_PLATFORM(WINDOWS) +#ifndef USING_GLES2 case DataFormat::BC1_RGBA_UNORM_BLOCK: internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; format = GL_RGB; diff --git a/Common/GPU/OpenGL/GLFeatures.cpp b/Common/GPU/OpenGL/GLFeatures.cpp index 847778e514..9b1e313372 100644 --- a/Common/GPU/OpenGL/GLFeatures.cpp +++ b/Common/GPU/OpenGL/GLFeatures.cpp @@ -593,10 +593,8 @@ bool CheckGLExtensions() { switch (compressedFormats[i]) { case GL_COMPRESSED_RGB8_ETC2: gl_extensions.supportsETC2 = true; break; case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: gl_extensions.supportsASTC = true; break; -#if !PPSSPP_PLATFORM(IOS) && !PPSSPP_PLATFORM(MAC) +#ifndef USING_GLES2 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: gl_extensions.supportsBC123 = true; break; -#endif -#if PPSSPP_PLATFORM(WINDOWS) case GL_COMPRESSED_RGBA_BPTC_UNORM: gl_extensions.supportsBC7 = true; break; #endif } From d8c3269cc65e10ec20bf6198d4299e602c927c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 17:52:40 +0100 Subject: [PATCH 323/424] Fix zipped texture packs (it didn't load the ini from the zip, the rest worked). Plus a few other things. --- GPU/Common/ReplacedTexture.cpp | 13 ++++++++----- GPU/Common/TextureReplacer.cpp | 8 ++++++-- GPU/D3D11/TextureCacheD3D11.cpp | 3 +-- GPU/Directx9/DrawEngineDX9.cpp | 4 +++- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index df7c917ae8..d4a788a813 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -232,20 +232,23 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { } } - delete desc_; - desc_ = nullptr; - if (levels_.empty()) { - // Bad. - WARN_LOG(G3D, "Failed to load texture"); + // No replacement found. + std::string name = TextureReplacer::HashName(desc_->cachekey, desc_->hash, 0); + INFO_LOG(G3D, "Failed to load replacement texture. %s", name.c_str()); SetState(ReplacementState::NOT_FOUND); levelData_ = nullptr; + delete desc_; + desc_ = nullptr; return; } levelData_->fmt = fmt; SetState(ReplacementState::ACTIVE); + delete desc_; + desc_ = nullptr; + if (threadWaitable_) threadWaitable_->Notify(); } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 57ab5b7d92..429c3aeb67 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -135,7 +135,7 @@ bool TextureReplacer::LoadIni() { } IniFile ini; - bool iniLoaded = ini.LoadFromVFS(g_VFS, (basePath_ / INI_FILENAME).ToString()); + bool iniLoaded = ini.LoadFromVFS(*dir, INI_FILENAME); if (iniLoaded) { if (!LoadIniValues(ini)) { @@ -183,7 +183,11 @@ bool TextureReplacer::LoadIni() { repl.second->vfs_ = vfs_; } - INFO_LOG(G3D, "Texture pack activated from '%s'", basePath_.c_str()); + if (vfsIsZip_) { + INFO_LOG(G3D, "Texture pack activated from '%s'", (basePath_ / ZIP_FILENAME).c_str()); + } else { + INFO_LOG(G3D, "Texture pack activated from '%s'", basePath_.c_str()); + } // The ini doesn't have to exist for the texture directory or zip to be valid. return true; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index ffdf94c61a..70f0a4e941 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -301,7 +301,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (plan.replaceValid) { int blockSize = 0; if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { - stride = ((mipWidth + 3) & ~3) * 4; // This stride value doesn't quite make sense to me, but it works. + stride = ((mipWidth + 3) & ~3) * blockSize / 4; // This stride value doesn't quite make sense to me, but it works? dataSize = plan.replaced->GetLevelDataSize(i); } else { int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); @@ -364,7 +364,6 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { desc.Format = dstFmt; desc.MipLevels = levels; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - ASSERT_SUCCESS(device_->CreateTexture2D(&desc, subresData, &tex)); texture = tex; } else { diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index eddfcc5d29..ce59de44aa 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -129,7 +129,9 @@ void DrawEngineDX9::InitDeviceObjects() { } void DrawEngineDX9::DestroyDeviceObjects() { - draw_->SetInvalidationCallback(InvalidationCallback()); + if (draw_) { + draw_->SetInvalidationCallback(InvalidationCallback()); + } ClearTrackedVertexArrays(); } From b45f1db0054c62e482e75fa9e532cc16dae528d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 18:34:22 +0100 Subject: [PATCH 324/424] Correct some error reporting --- GPU/Common/ReplacedTexture.cpp | 75 +++++++++++++++++++++++----------- GPU/Common/ReplacedTexture.h | 8 +++- 2 files changed, 59 insertions(+), 24 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index d4a788a813..b52b398dbe 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -195,7 +195,13 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { // We must lock around access to levelData_ in case two textures try to load it at once. std::lock_guard guard(levelData_->lock); + fmt = Draw::DataFormat::UNDEFINED; + Draw::DataFormat pixelFormat; + LoadLevelResult result = LoadLevelResult::LOAD_ERROR; + if (desc_->filenames.empty()) { + result = LoadLevelResult::DONE; + } for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_->filenames.size()); ++i) { if (State() == ReplacementState::CANCEL_INIT) { break; @@ -209,6 +215,8 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { VFSFileReference *fileRef = vfs_->GetFile(desc_->filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. + // Mark as DONE, not error. + result = LoadLevelResult::DONE; break; } @@ -216,7 +224,12 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { fmt = Draw::DataFormat::R8G8B8A8_UNORM; } - if (LoadLevelData(fileRef, desc_->filenames[i], i, &pixelFormat)) { + result = LoadLevelData(fileRef, desc_->filenames[i], i, &pixelFormat); + if (result == LoadLevelResult::DONE) { + // Loaded all the levels we're gonna get. + fmt = pixelFormat; + break; + } else if (result == LoadLevelResult::CONTINUE) { if (i == 0) { fmt = pixelFormat; } else { @@ -226,8 +239,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { } } } else { - fmt = pixelFormat; - // Otherwise, we're done loading mips (bad PNG or bad size, either way.) + // Error state. break; } } @@ -235,7 +247,9 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { if (levels_.empty()) { // No replacement found. std::string name = TextureReplacer::HashName(desc_->cachekey, desc_->hash, 0); - INFO_LOG(G3D, "Failed to load replacement texture. %s", name.c_str()); + if (result == LoadLevelResult::LOAD_ERROR) { + WARN_LOG(G3D, "Failed to load replacement texture '%s'", name.c_str()); + } SetState(ReplacementState::NOT_FOUND); levelData_ = nullptr; delete desc_; @@ -258,7 +272,7 @@ inline uint32_t RoundUpTo4(uint32_t value) { } // Returns true if Prepare should keep calling this to load more levels. -bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int mipLevel, Draw::DataFormat *pixelFormat) { +ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int mipLevel, Draw::DataFormat *pixelFormat) { bool good = false; if (levelData_->data.size() <= mipLevel) { @@ -269,7 +283,8 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string size_t fileSize; VFSOpenFile *openFile = vfs_->OpenFileForRead(fileRef, &fileSize); if (!openFile) { - return false; + // File missing, no more levels. This is alright. + return LoadLevelResult::DONE; } std::string magic; @@ -385,7 +400,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string if (!levelData_->data[mipLevel].empty()) { vfs_->CloseFile(openFile); *pixelFormat = levelData_->fmt; - return true; + return LoadLevelResult::DONE; } // Is this really the right place to do it? @@ -403,7 +418,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string if (!good) { vfs_->CloseFile(openFile); - return false; + return LoadLevelResult::LOAD_ERROR; } auto cleanup = [&] { @@ -424,12 +439,14 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string if (!transcoder.init(buffer.data(), (int)buffer.size())) { WARN_LOG(G3D, "Error reading KTX file"); cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } // Figure out the target format. basist::transcoder_texture_format transcoderFormat; if (transcoder.is_etc1s()) { + // We only support opaque colors with this compression method. + alphaStatus_ = ReplacedTextureAlpha::FULL; // Let's pick a suitable compatible format. if (desc_->formatSupport.bc123) { transcoderFormat = basist::transcoder_texture_format::cTFBC1; @@ -440,9 +457,11 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } else { // TODO: Transcode to RGBA8 instead as a fallback. cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } } else if (transcoder.is_uastc()) { + // TODO: Try to recover some indication of alpha from the actual data blocks. + alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; // Let's pick a suitable compatible format. if (desc_->formatSupport.bc7) { transcoderFormat = basist::transcoder_texture_format::cTFBC7_RGBA; @@ -453,7 +472,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } else { // TODO: Transcode to RGBA8 instead as a fallback. cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } } else { WARN_LOG(G3D, "PPSSPP currently only supports KTX for basis/UASTC textures. This may change in the future."); @@ -486,8 +505,12 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } transcoder.clear(); cleanup(); - return false; // don't read more levels + + return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::DDS) { + // TODO: Do better with alphaStatus, it's possible. + alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; + DDSHeader header; DDSHeaderDXT10 header10{}; vfs_->Read(openFile, &header, sizeof(header)); @@ -520,30 +543,31 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. } cleanup(); - return false; // don't read more levels + return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", filename.c_str()); cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } int w, h, f; uint8_t *image; std::vector &out = levelData_->data[mipLevel]; + // TODO: Zim files can actually hold mipmaps (although no tool has ever been made to create them :P) if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > level.w || h > level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } out.resize(level.w * level.h * 4); @@ -564,6 +588,10 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } else { good = false; } + + cleanup(); + return LoadLevelResult::CONTINUE; + } else if (imageType == ReplacedImageType::PNG) { png_image png = {}; png.version = PNG_IMAGE_VERSION; @@ -574,12 +602,12 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", filename.c_str(), png.message); cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } if (png.width > (uint32_t)level.w || png.height > (uint32_t)level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); cleanup(); - return false; + return LoadLevelResult::LOAD_ERROR; } bool checkedAlpha = false; @@ -598,7 +626,7 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); cleanup(); out.resize(0); - return false; + return LoadLevelResult::LOAD_ERROR; } png_image_free(&png); @@ -611,13 +639,14 @@ bool ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string } levels_.push_back(level); + + cleanup(); + return LoadLevelResult::CONTINUE; } else { WARN_LOG(G3D, "Don't know how to load this image type! %d", (int)imageType); + cleanup(); } - - cleanup(); - - return good; + return LoadLevelResult::LOAD_ERROR; } bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index a237b1bd04..713d2c010f 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -153,8 +153,14 @@ struct ReplacedTexture { std::string logId_; private: + enum class LoadLevelResult { + LOAD_ERROR = 0, + CONTINUE = 1, + DONE = 2, + }; + void Prepare(VFSBackend *vfs); - bool LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat); + LoadLevelResult LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat); void PurgeIfOlder(double t); std::vector levels_; From 13e63c109f9bc006d502e279d15736b6ebacfe6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 18:52:42 +0100 Subject: [PATCH 325/424] If the target compression format is not supported, just transcode to RGBA8888. --- GPU/Common/ReplacedTexture.cpp | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index b52b398dbe..5c9721e1d0 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -455,9 +455,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference transcoderFormat = basist::transcoder_texture_format::cTFETC1_RGB; *pixelFormat = Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK; } else { - // TODO: Transcode to RGBA8 instead as a fallback. - cleanup(); - return LoadLevelResult::LOAD_ERROR; + // Transcode to RGBA8 instead as a fallback. A bit slow and takes a lot of memory, but better than nothing. + WARN_LOG(G3D, "Replacement texture format not supported - transcoding to RGBA8888"); + transcoderFormat = basist::transcoder_texture_format::cTFRGBA32; + *pixelFormat = Draw::DataFormat::R8G8B8A8_UNORM; } } else if (transcoder.is_uastc()) { // TODO: Try to recover some indication of alpha from the actual data blocks. @@ -470,17 +471,20 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference transcoderFormat = basist::transcoder_texture_format::cTFASTC_4x4_RGBA; *pixelFormat = Draw::DataFormat::ASTC_4x4_UNORM_BLOCK; } else { - // TODO: Transcode to RGBA8 instead as a fallback. - cleanup(); - return LoadLevelResult::LOAD_ERROR; + // Transcode to RGBA8 instead as a fallback. A bit slow and takes a lot of memory, but better than nothing. + WARN_LOG(G3D, "Replacement texture format not supported - transcoding to RGBA8888"); + transcoderFormat = basist::transcoder_texture_format::cTFRGBA32; + *pixelFormat = Draw::DataFormat::R8G8B8A8_UNORM; } } else { WARN_LOG(G3D, "PPSSPP currently only supports KTX for basis/UASTC textures. This may change in the future."); + cleanup(); + return LoadLevelResult::LOAD_ERROR; } int blockSize; bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); - _dbg_assert_(bc); + _dbg_assert_(bc || *pixelFormat == Draw::DataFormat::R8G8B8A8_UNORM); levelData_->data.resize(numMips); @@ -494,9 +498,18 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool result = transcoder.get_image_level_info(levelInfo, i, 0, 0); _dbg_assert_(result); - levelData_->data[i].resize(levelInfo.m_total_blocks * blockSize); + size_t dataSizeBytes = levelInfo.m_total_blocks * blockSize; + size_t outputSize = levelInfo.m_total_blocks; + size_t outputPitch = levelInfo.m_num_blocks_x; + // Support transcoded-to-RGBA8888 images too. + if (!bc) { + dataSizeBytes = levelInfo.m_orig_width * levelInfo.m_orig_height * 4; + outputSize = levelInfo.m_orig_width * levelInfo.m_orig_height; + outputPitch = levelInfo.m_orig_width; + } + levelData_->data[i].resize(dataSizeBytes); - transcoder.transcode_image_level(i, 0, 0, &out[0], levelInfo.m_total_blocks, transcoderFormat, 0, levelInfo.m_num_blocks_x, level.h, -1, -1, &transcodeState); + transcoder.transcode_image_level(i, 0, 0, &out[0], outputSize, transcoderFormat, 0, outputPitch, level.h, -1, -1, &transcodeState); level.w = levelInfo.m_orig_width; level.h = levelInfo.m_orig_height; if (i != 0) From effbe6376ad185c347f6acbf19b6342ec3ae8113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 23:38:52 +0100 Subject: [PATCH 326/424] Remove an unused VulkanPushBuffer. Saves about 0.75MB of VRAM, but mainly just to clean things up. I think I meant to use this one instead of grabbing the one from DrawEngine in the TextureCache. --- GPU/Vulkan/GPU_Vulkan.cpp | 26 +------------------------- GPU/Vulkan/GPU_Vulkan.h | 6 ------ GPU/Vulkan/TextureCacheVulkan.h | 4 ---- 3 files changed, 1 insertion(+), 35 deletions(-) diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 065dc5b1c5..0ee619f4db 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -295,13 +295,8 @@ void GPU_Vulkan::BeginHostFrame() { VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); int curFrame = vulkan->GetCurFrame(); - FrameData &frame = frameData_[curFrame]; - - frame.push_->Reset(); - frame.push_->Begin(vulkan); framebufferManager_->BeginFrame(); - textureCacheVulkan_->SetPushBuffer(frameData_[curFrame].push_); shaderManagerVulkan_->DirtyShader(); gstate_c.Dirty(DIRTY_ALL); @@ -329,9 +324,6 @@ void GPU_Vulkan::BeginHostFrame() { void GPU_Vulkan::EndHostFrame() { VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - int curFrame = vulkan->GetCurFrame(); - FrameData &frame = frameData_[curFrame]; - frame.push_->End(); drawEngine_.EndFrame(); @@ -395,15 +387,7 @@ void GPU_Vulkan::FinishDeferred() { void GPU_Vulkan::InitDeviceObjects() { INFO_LOG(G3D, "GPU_Vulkan::InitDeviceObjects"); - VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - // Initialize framedata - for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { - _assert_(!frameData_[i].push_); - VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - frameData_[i].push_ = new VulkanPushBuffer(vulkan, "gpuPush", 256 * 1024, usage, PushBufferType::CPU_TO_GPU); - } - VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); uint32_t hacks = 0; if (PSP_CoreParameter().compat.flags().MGS2AcidHack) hacks |= QUEUE_HACK_MGS2_ACID; @@ -414,21 +398,13 @@ void GPU_Vulkan::InitDeviceObjects() { hacks |= QUEUE_HACK_RENDERPASS_MERGE; if (hacks) { + VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); rm->GetQueueRunner()->EnableHacks(hacks); } } void GPU_Vulkan::DestroyDeviceObjects() { INFO_LOG(G3D, "GPU_Vulkan::DestroyDeviceObjects"); - for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { - if (frameData_[i].push_) { - VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - frameData_[i].push_->Destroy(vulkan); - delete frameData_[i].push_; - frameData_[i].push_ = nullptr; - } - } - // Need to turn off hacks when shutting down the GPU. Don't want them running in the menu. if (draw_) { VulkanRenderManager *rm = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 1fad919ab1..78229a77f2 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -84,12 +84,6 @@ private: // Manages state and pipeline objects PipelineManagerVulkan *pipelineManager_; - struct FrameData { - VulkanPushBuffer *push_; - }; - - FrameData frameData_[VulkanContext::MAX_INFLIGHT_FRAMES]{}; - Path shaderCachePath_; std::atomic shaderCacheLoaded_{}; }; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 2a6fb5d2a9..727bd04e38 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -66,9 +66,6 @@ public: void SetDrawEngine(DrawEngineVulkan *td) { drawEngine_ = td; } - void SetPushBuffer(VulkanPushBuffer *push) { - push_ = push; - } void ForgetLastTexture() override {} void NotifyConfigChanged() override; @@ -106,7 +103,6 @@ private: void CompileScalingShader(); VulkanDeviceAllocator *allocator_ = nullptr; - VulkanPushBuffer *push_ = nullptr; VulkanComputeShaderManager computeShaderManager_; From c31b4be69053017e627911fa1eca562a5755b8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 01:23:32 +0100 Subject: [PATCH 327/424] Crashfix in ReplacedTexture. Thought I fixed this one before, hm. --- GPU/Common/ReplacedTexture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 5c9721e1d0..4246919faf 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -114,7 +114,7 @@ void ReplacedTexture::PurgeIfOlder(double t) { if (lastUsed_ >= t) return; - if (levelData_->lastUsed < t) { + if (levelData_ && levelData_->lastUsed < t) { // We have to lock since multiple textures might reference this same data. std::lock_guard guard(levelData_->lock); levelData_->data.clear(); From 56d792f4222dc2d684aa29fd2d86aa84b1d6a8b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 22:44:37 +0100 Subject: [PATCH 328/424] Sketch the new VulkanPushPool --- Common/GPU/Vulkan/VulkanContext.h | 1 + Common/GPU/Vulkan/VulkanMemory.cpp | 136 ++++++++++++++++++++++++++--- Common/GPU/Vulkan/VulkanMemory.h | 97 ++++++++++++++++++-- GPU/Vulkan/DebugVisVulkan.cpp | 14 +-- 4 files changed, 225 insertions(+), 23 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanContext.h b/Common/GPU/Vulkan/VulkanContext.h index 21dbaad08e..49e6eb96c3 100644 --- a/Common/GPU/Vulkan/VulkanContext.h +++ b/Common/GPU/Vulkan/VulkanContext.h @@ -330,6 +330,7 @@ public: } int GetInflightFrames() const { + // out of MAX_INFLIGHT_FRAMES. return inflightFrames_; } // Don't call while a frame is in progress. diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index 9a25e5cbb0..9015e0d0ba 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -25,6 +25,7 @@ #include "Common/Log.h" #include "Common/TimeUtil.h" +#include "Common/Math/math_util.h" #include "Common/GPU/Vulkan/VulkanMemory.h" using namespace PPSSPP_VK; @@ -32,7 +33,16 @@ using namespace PPSSPP_VK; // Global push buffer tracker for vulkan memory profiling. // Don't want to manually dig up all the active push buffers. static std::mutex g_pushBufferListMutex; -static std::set g_pushBuffers; +static std::set g_pushBuffers; + +std::vector GetActiveVulkanMemoryManagers() { + std::vector buffers; + std::lock_guard guard(g_pushBufferListMutex); + for (auto iter : g_pushBuffers) { + buffers.push_back(iter); + } + return buffers; +} VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage, PushBufferType type) : vulkan_(vulkan), name_(name), size_(size), usage_(usage), type_(type) { @@ -55,15 +65,6 @@ VulkanPushBuffer::~VulkanPushBuffer() { _assert_(buffers_.empty()); } -std::vector VulkanPushBuffer::GetAllActive() { - std::vector buffers; - std::lock_guard guard(g_pushBufferListMutex); - for (auto iter : g_pushBuffers) { - buffers.push_back(iter); - } - return buffers; -} - bool VulkanPushBuffer::AddBuffer() { BufInfo info; VkDevice device = vulkan_->GetDevice(); @@ -264,3 +265,118 @@ VkResult VulkanDescSetPool::Recreate(bool grow) { } return result; } + +VulkanPushPool::VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage) + : vulkan_(vulkan), name_(name), originalBlockSize_(originalBlockSize), usage_(usage) { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.insert(this); + } + + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { + blocks_.push_back(CreateBlock(originalBlockSize)); + blocks_.back().original = true; + blocks_.back().frameIndex = i; + } +} + +VulkanPushPool::~VulkanPushPool() { + { + std::lock_guard guard(g_pushBufferListMutex); + g_pushBuffers.erase(this); + } + + _dbg_assert_(blocks_.empty()); +} + +void VulkanPushPool::Destroy() { + for (auto &block : blocks_) { + block.Destroy(vulkan_); + } + blocks_.clear(); +} + +VulkanPushPool::Block VulkanPushPool::CreateBlock(size_t size) { + Block block{}; + block.size = size; + block.frameIndex = -1; + + VkBufferCreateInfo b{ VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + b.size = size; + b.usage = usage_; + b.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + VmaAllocationCreateInfo allocCreateInfo{}; + allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + VmaAllocationInfo allocInfo{}; + + VkResult result = vmaCreateBuffer(vulkan_->Allocator(), &b, &allocCreateInfo, &block.buffer, &block.allocation, &allocInfo); + _dbg_assert_(result == VK_SUCCESS); + + result = vmaMapMemory(vulkan_->Allocator(), block.allocation, (void **)(&block.writePtr)); + _dbg_assert_(result == VK_SUCCESS); + + return block; +} + +VulkanPushPool::Block::~Block() {} + +void VulkanPushPool::Block::Destroy(VulkanContext *vulkan) { + vmaUnmapMemory(vulkan->Allocator(), allocation); + vulkan->Delete().QueueDeleteBufferAllocation(buffer, allocation); +} + +void VulkanPushPool::BeginFrame() { + curBlockIndex_ = -1; + for (auto &block : blocks_) { + if (block.frameIndex == vulkan_->GetCurFrame()) { + if (curBlockIndex_ == -1) { + // Pick a block associated with the current frame to start at. + // We always start with one block per frame index. + curBlockIndex_ = block.frameIndex; + } + block.used = 0; + if (!block.original) { + // Return block to the common pool + block.frameIndex = -1; + } + } + // TODO: Also garbage collect blocks that have been unused for many frames here. + } +} + +void VulkanPushPool::NextBlock(VkDeviceSize allocationSize) { + int curFrameIndex = vulkan_->GetCurFrame(); + curBlockIndex_++; + while (curBlockIndex_ < blocks_.size()) { + Block &block = blocks_[curBlockIndex_]; + if (block.frameIndex == curFrameIndex) { + _assert_(block.used == 0); + block.used = allocationSize; + return; + } + curBlockIndex_++; + } + + VkDeviceSize newBlockSize = std::max(originalBlockSize_, (VkDeviceSize)RoundUpToPowerOf2((uint32_t)allocationSize)); + // We're still here and ran off the end of blocks. Create a new one. + blocks_.push_back(CreateBlock(newBlockSize)); + blocks_.back().frameIndex = curFrameIndex; + blocks_.back().used = allocationSize; + // curBlockIndex_ is already set correctly here. +} + +size_t VulkanPushPool::GetTotalSize() const { + size_t sz = 0; + for (auto &block : blocks_) { + sz += block.used; + } + return sz; +} + +size_t VulkanPushPool::GetTotalCapacity() const { + size_t sz = 0; + for (auto &block : blocks_) { + sz += block.size; + } + return sz; +} diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index 863e4f965e..a27cd9e3e7 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -19,6 +19,16 @@ enum class PushBufferType { GPU_ONLY, }; +// Just an abstract thing to get debug information. +class VulkanMemoryManager { +public: + virtual ~VulkanMemoryManager() {} + + virtual size_t GetTotalSize() const = 0; + virtual size_t GetTotalCapacity() const = 0; + virtual const char *Name() const = 0; +}; + // VulkanPushBuffer // Simple incrementing allocator. // Use these to push vertex, index and uniform data. Generally you'll have two of these @@ -26,7 +36,7 @@ enum class PushBufferType { // has completed. // // TODO: Make it possible to suballocate pushbuffers from a large DeviceMemory block. -class VulkanPushBuffer { +class VulkanPushBuffer : public VulkanMemoryManager { struct BufInfo { VkBuffer buffer; VmaAllocation allocation; @@ -102,7 +112,7 @@ public: return offset_; } - const char *Name() const { + const char *Name() const override { return name_; } @@ -131,10 +141,8 @@ public: info->range = sizeof(T); } - size_t GetTotalSize() const; // Used size - size_t GetTotalCapacity() const; - - static std::vector GetAllActive(); + size_t GetTotalSize() const override; // Used size + size_t GetTotalCapacity() const override; private: bool AddBuffer(); @@ -153,6 +161,80 @@ private: const char *name_; }; +// Simple memory pushbuffer pool that can share blocks between the "frames", to reduce the impact of push memory spikes - +// a later frame can gobble up redundant buffers from an earlier frame even if they don't share frame index. +class VulkanPushPool : public VulkanMemoryManager { +public: + VulkanPushPool(VulkanContext *vulkan, const char *name, size_t originalBlockSize, VkBufferUsageFlags usage); + ~VulkanPushPool(); + + void Destroy(); + void BeginFrame(); + + size_t GetTotalSize() const override; // Used size + size_t GetTotalCapacity() const override; + + // When using the returned memory, make sure to bind the returned vkbuf. + uint8_t *Allocate(VkDeviceSize numBytes, VkDeviceSize alignment, VkBuffer *vkbuf, uint32_t *bindOffset) { + _dbg_assert_(curBlockIndex_ >= 0); + + Block &block = blocks_[curBlockIndex_]; + + VkDeviceSize offset = (block.used + (alignment - 1)) & ~(alignment - 1); + if (offset + numBytes <= block.size) { + block.used = offset + numBytes; + *vkbuf = block.buffer; + *bindOffset = (uint32_t)offset; + return block.writePtr + offset; + } + + NextBlock(numBytes); + + *vkbuf = blocks_[curBlockIndex_].buffer; + *bindOffset = 0; // Newly allocated buffer will start at 0. + return blocks_[curBlockIndex_].writePtr; + } + + VkDeviceSize Push(const void *data, VkDeviceSize numBytes, int alignment, VkBuffer *vkbuf) { + uint32_t bindOffset; + uint8_t *ptr = Allocate(numBytes, alignment, vkbuf, &bindOffset); + memcpy(ptr, data, numBytes); + return bindOffset; + } + + const char *Name() const override { + return name_; + } + +private: + void NextBlock(VkDeviceSize allocationSize); + + struct Block { + ~Block(); + VkBuffer buffer; + VmaAllocation allocation; + + VkDeviceSize size; + VkDeviceSize used; + + int frameIndex; + bool original; // these blocks aren't garbage collected. + + uint8_t *writePtr; + + void Destroy(VulkanContext *vulkan); + }; + + Block CreateBlock(size_t sz); + + VulkanContext *vulkan_; + VkDeviceSize originalBlockSize_; + std::vector blocks_; + VkBufferUsageFlags usage_; + int curBlockIndex_ = -1; + const char *name_; +}; + // Only appropriate for use in a per-frame pool. class VulkanDescSetPool { public: @@ -182,3 +264,6 @@ private: uint32_t usage_ = 0; bool grow_; }; + +std::vector GetActiveVulkanMemoryManagers(); + diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index ff03218efd..74bf57100d 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -39,7 +39,7 @@ #undef DrawText -bool comparePushBufferNames(const VulkanPushBuffer *a, const VulkanPushBuffer *b) { +bool comparePushBufferNames(const VulkanMemoryManager *a, const VulkanMemoryManager *b) { return strcmp(a->Name(), b->Name()) < 0; } @@ -75,13 +75,13 @@ void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { str << "Push buffers:" << std::endl; // Now list the various push buffers. - auto pushBuffers = VulkanPushBuffer::GetAllActive(); - std::sort(pushBuffers.begin(), pushBuffers.end(), comparePushBufferNames); + auto managers = GetActiveVulkanMemoryManagers(); + std::sort(managers.begin(), managers.end(), comparePushBufferNames); - for (auto push : pushBuffers) { - str << " " << push->Name() << " " - << NiceSizeFormat(push->GetTotalCapacity()) << ", used: " - << NiceSizeFormat(push->GetTotalSize()) << std::endl; + for (auto manager : managers) { + str << " " << manager->Name() << " " + << NiceSizeFormat(manager->GetTotalCapacity()) << ", used: " + << NiceSizeFormat(manager->GetTotalSize()) << std::endl; } const int padding = 10 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT); From 3d372400e1da819c9e79e1d2f66fbde7fc3deb38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 23:13:08 +0100 Subject: [PATCH 329/424] Start converting over to it --- GPU/Vulkan/DrawEngineVulkan.cpp | 70 +++++++++++++++++++-------------- GPU/Vulkan/DrawEngineVulkan.h | 7 +++- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 11907c13b7..39e2d8bebb 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -172,10 +172,11 @@ void DrawEngineVulkan::InitDeviceObjects() { // Note that pushUBO is also used for tessellation data (search for SetPushBuffer), and to upload // the null texture. This should be cleaned up... frame_[i].pushUBO = new VulkanPushBuffer(vulkan, "pushUBO", 8 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, PushBufferType::CPU_TO_GPU); - frame_[i].pushVertex = new VulkanPushBuffer(vulkan, "pushVertex", 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU); - frame_[i].pushIndex = new VulkanPushBuffer(vulkan, "pushIndex", 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU); } + pushVertex = new VulkanPushPool(vulkan, "pushVertex", 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; pl.pPushConstantRanges = nullptr; pl.pushConstantRangeCount = 0; @@ -227,16 +228,6 @@ void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) { delete pushUBO; pushUBO = nullptr; } - if (pushVertex) { - pushVertex->Destroy(vulkan); - delete pushVertex; - pushVertex = nullptr; - } - if (pushIndex) { - pushIndex->Destroy(vulkan); - delete pushIndex; - pushIndex = nullptr; - } } void DrawEngineVulkan::DestroyDeviceObjects() { @@ -256,6 +247,17 @@ void DrawEngineVulkan::DestroyDeviceObjects() { for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { frame_[i].Destroy(vulkan); } + + if (pushVertex) { + pushVertex->Destroy(); + delete pushVertex; + pushVertex = nullptr; + } + if (pushIndex) { + pushIndex->Destroy(); + delete pushIndex; + pushIndex = nullptr; + } if (samplerSecondaryNearest_ != VK_NULL_HANDLE) vulkan->Delete().QueueDeleteSampler(samplerSecondaryNearest_); if (samplerSecondaryLinear_ != VK_NULL_HANDLE) @@ -302,14 +304,13 @@ void DrawEngineVulkan::BeginFrame() { // needs to grow in the same frame. The state where many buffers are reset can also be used to // defragment memory. frame->pushUBO->Reset(); - frame->pushVertex->Reset(); - frame->pushIndex->Reset(); VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); frame->pushUBO->Begin(vulkan); - frame->pushVertex->Begin(vulkan); - frame->pushIndex->Begin(vulkan); + + pushVertex->BeginFrame(); + pushIndex->BeginFrame(); tessDataTransferVulkan->SetPushBuffer(frame->pushUBO); @@ -360,11 +361,9 @@ void DrawEngineVulkan::BeginFrame() { void DrawEngineVulkan::EndFrame() { FrameData *frame = &GetCurFrame(); stats_.pushUBOSpaceUsed = (int)frame->pushUBO->GetOffset(); - stats_.pushVertexSpaceUsed = (int)frame->pushVertex->GetOffset(); - stats_.pushIndexSpaceUsed = (int)frame->pushIndex->GetOffset(); + stats_.pushVertexSpaceUsed = 0; // (int)frame->pushVertex->GetOffset(); + stats_.pushIndexSpaceUsed = 0; // (int)frame->pushIndex->GetOffset(); frame->pushUBO->End(); - frame->pushVertex->End(); - frame->pushIndex->End(); vertexCache_->End(); } @@ -379,6 +378,17 @@ void DrawEngineVulkan::DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t DecodeVerts(dest); } +void DrawEngineVulkan::DecodeVertsToPushPool(VulkanPushPool *push, uint32_t *bindOffset, VkBuffer *vkbuf) { + u8 *dest = decoded; + + // Figure out how much pushbuffer space we need to allocate. + if (push) { + int vertsToDecode = ComputeNumVertsToDecode(); + dest = push->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, vkbuf, bindOffset); + } + DecodeVerts(dest); +} + VkDescriptorSet DrawEngineVulkan::GetOrCreateDescriptorSet(VkImageView imageView, VkSampler sampler, VkBuffer base, VkBuffer light, VkBuffer bone, bool tess) { _dbg_assert_(base != VK_NULL_HANDLE); _dbg_assert_(light != VK_NULL_HANDLE); @@ -620,7 +630,7 @@ void DrawEngineVulkan::DoFlush() { vai->minihash = ComputeMiniHash(); vai->status = VertexArrayInfoVulkan::VAI_HASHING; vai->drawsUntilNextFullHash = 0; - DecodeVertsToPushBuffer(frameData.pushVertex, &vbOffset, &vbuf); // writes to indexGen + DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); // writes to indexGen vai->numVerts = indexGen.VertexCount(); vai->prim = indexGen.Prim(); vai->maxIndex = indexGen.MaxIndex(); @@ -646,7 +656,7 @@ void DrawEngineVulkan::DoFlush() { } if (newMiniHash != vai->minihash || newHash != vai->hash) { MarkUnreliable(vai); - DecodeVertsToPushBuffer(frameData.pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); goto rotateVBO; } if (vai->numVerts > 64) { @@ -665,7 +675,7 @@ void DrawEngineVulkan::DoFlush() { u32 newMiniHash = ComputeMiniHash(); if (newMiniHash != vai->minihash) { MarkUnreliable(vai); - DecodeVertsToPushBuffer(frameData.pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); goto rotateVBO; } } @@ -737,7 +747,7 @@ void DrawEngineVulkan::DoFlush() { if (vai->lastFrame != gpuStats.numFlips) { vai->numFrames++; } - DecodeVertsToPushBuffer(frameData.pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); goto rotateVBO; } default: @@ -747,11 +757,11 @@ void DrawEngineVulkan::DoFlush() { if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { // If software skinning, we've already predecoded into "decoded". So push that content. VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; - u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vbOffset, &vbuf); + u8 *dest = (u8 *)pushVertex->Allocate(size, 4, &vbuf, &vbOffset); memcpy(dest, decoded, size); } else { // Decode directly into the pushbuffer - DecodeVertsToPushBuffer(frameData.pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); } rotateVBO: @@ -834,7 +844,7 @@ void DrawEngineVulkan::DoFlush() { }; if (useElements) { if (!ibuf) { - ibOffset = (uint32_t)frameData.pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), &ibuf); + ibOffset = (uint32_t)pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), 4, &ibuf); } renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16); } else { @@ -972,12 +982,12 @@ void DrawEngineVulkan::DoFlush() { if (result.drawIndexed) { VkBuffer vbuf, ibuf; - vbOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), &vbuf); - ibOffset = (uint32_t)frameData.pushIndex->Push(inds, sizeof(short) * result.drawNumTrans, &ibuf); + vbOffset = (uint32_t)pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vbuf); + ibOffset = (uint32_t)pushIndex->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf); renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1, VK_INDEX_TYPE_UINT16); } else { VkBuffer vbuf; - vbOffset = (uint32_t)frameData.pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), &vbuf); + vbOffset = (uint32_t)pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), 4, &vbuf); renderManager->Draw(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, result.drawNumTrans); } } else if (result.action == SW_CLEAR) { diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index b0e99a7c24..16693d2f4c 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -55,6 +55,7 @@ class FramebufferManagerVulkan; class VulkanContext; class VulkanPushBuffer; +class VulkanPushPool; struct VulkanPipeline; struct DrawEngineVulkanStats { @@ -218,6 +219,7 @@ private: void DestroyDeviceObjects(); + void DecodeVertsToPushPool(VulkanPushPool *push, uint32_t *bindOffset, VkBuffer *vkbuf); void DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t *bindOffset, VkBuffer *vkbuf); void DoFlush(); @@ -269,8 +271,6 @@ private: VulkanDescSetPool descPool; VulkanPushBuffer *pushUBO = nullptr; - VulkanPushBuffer *pushVertex = nullptr; - VulkanPushBuffer *pushIndex = nullptr; // We do rolling allocation and reset instead of caching across frames. That we might do later. DenseHashMap descSets; @@ -281,6 +281,9 @@ private: GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; + VulkanPushPool *pushVertex = nullptr; + VulkanPushPool *pushIndex = nullptr; + // Other ShaderManagerVulkan *shaderManager_ = nullptr; PipelineManagerVulkan *pipelineManager_ = nullptr; From 700b1cd6a7f8b59ead015aaa021bcdf1ab8f8766 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 23:21:43 +0100 Subject: [PATCH 330/424] More conversion to pushPool --- GPU/Vulkan/DrawEngineVulkan.cpp | 48 ++++++++++++++----------------- GPU/Vulkan/DrawEngineVulkan.h | 11 ++++--- GPU/Vulkan/ShaderManagerVulkan.h | 14 ++++----- GPU/Vulkan/TextureCacheVulkan.cpp | 8 +++--- 4 files changed, 38 insertions(+), 43 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 39e2d8bebb..ca64ae4e11 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -171,9 +171,9 @@ void DrawEngineVulkan::InitDeviceObjects() { // Note that pushUBO is also used for tessellation data (search for SetPushBuffer), and to upload // the null texture. This should be cleaned up... - frame_[i].pushUBO = new VulkanPushBuffer(vulkan, "pushUBO", 8 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT, PushBufferType::CPU_TO_GPU); } + pushUBO = new VulkanPushPool(vulkan, "pushUBO", 4 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); pushVertex = new VulkanPushPool(vulkan, "pushVertex", 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); @@ -222,12 +222,6 @@ DrawEngineVulkan::~DrawEngineVulkan() { void DrawEngineVulkan::FrameData::Destroy(VulkanContext *vulkan) { descPool.Destroy(); - - if (pushUBO) { - pushUBO->Destroy(vulkan); - delete pushUBO; - pushUBO = nullptr; - } } void DrawEngineVulkan::DestroyDeviceObjects() { @@ -258,6 +252,12 @@ void DrawEngineVulkan::DestroyDeviceObjects() { delete pushIndex; pushIndex = nullptr; } + if (pushUBO) { + pushUBO->Destroy(); + delete pushUBO; + pushUBO = nullptr; + } + if (samplerSecondaryNearest_ != VK_NULL_HANDLE) vulkan->Delete().QueueDeleteSampler(samplerSecondaryNearest_); if (samplerSecondaryLinear_ != VK_NULL_HANDLE) @@ -297,25 +297,22 @@ void DrawEngineVulkan::BeginFrame() { lastPipeline_ = nullptr; + pushUBO->BeginFrame(); + pushVertex->BeginFrame(); + pushIndex->BeginFrame(); + + tessDataTransferVulkan->SetPushPool(pushUBO); + + DirtyAllUBOs(); + FrameData *frame = &GetCurFrame(); // First reset all buffers, then begin. This is so that Reset can free memory and Begin can allocate it, // if growing the buffer is needed. Doing it this way will reduce fragmentation if more than one buffer // needs to grow in the same frame. The state where many buffers are reset can also be used to // defragment memory. - frame->pushUBO->Reset(); - VulkanContext *vulkan = (VulkanContext *)draw_->GetNativeObject(Draw::NativeObject::CONTEXT); - frame->pushUBO->Begin(vulkan); - - pushVertex->BeginFrame(); - pushIndex->BeginFrame(); - - tessDataTransferVulkan->SetPushBuffer(frame->pushUBO); - - DirtyAllUBOs(); - // Wipe the vertex cache if it's grown too large. if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) { vertexCache_->Destroy(vulkan); @@ -360,10 +357,9 @@ void DrawEngineVulkan::BeginFrame() { void DrawEngineVulkan::EndFrame() { FrameData *frame = &GetCurFrame(); - stats_.pushUBOSpaceUsed = (int)frame->pushUBO->GetOffset(); + stats_.pushUBOSpaceUsed = 0; // (int)pushUBO->GetOffset(); stats_.pushVertexSpaceUsed = 0; // (int)frame->pushVertex->GetOffset(); stats_.pushIndexSpaceUsed = 0; // (int)frame->pushIndex->GetOffset(); - frame->pushUBO->End(); vertexCache_->End(); } @@ -1042,15 +1038,15 @@ void DrawEngineVulkan::DoFlush() { void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { if ((dirtyUniforms_ & DIRTY_BASE_UNIFORMS) || baseBuf == VK_NULL_HANDLE) { - baseUBOOffset = shaderManager_->PushBaseBuffer(frame->pushUBO, &baseBuf); + baseUBOOffset = shaderManager_->PushBaseBuffer(pushUBO, &baseBuf); dirtyUniforms_ &= ~DIRTY_BASE_UNIFORMS; } if ((dirtyUniforms_ & DIRTY_LIGHT_UNIFORMS) || lightBuf == VK_NULL_HANDLE) { - lightUBOOffset = shaderManager_->PushLightBuffer(frame->pushUBO, &lightBuf); + lightUBOOffset = shaderManager_->PushLightBuffer(pushUBO, &lightBuf); dirtyUniforms_ &= ~DIRTY_LIGHT_UNIFORMS; } if ((dirtyUniforms_ & DIRTY_BONE_UNIFORMS) || boneBuf == VK_NULL_HANDLE) { - boneUBOOffset = shaderManager_->PushBoneBuffer(frame->pushUBO, &boneBuf); + boneUBOOffset = shaderManager_->PushBoneBuffer(pushUBO, &boneBuf); dirtyUniforms_ &= ~DIRTY_BONE_UNIFORMS; } } @@ -1072,7 +1068,7 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const int size = size_u * size_v; int ssboAlignment = vulkan_->GetPhysicalDeviceProperties().properties.limits.minStorageBufferOffsetAlignment; - uint8_t *data = (uint8_t *)push_->PushAligned(size * sizeof(TessData), (uint32_t *)&bufInfo_[0].offset, &bufInfo_[0].buffer, ssboAlignment); + uint8_t *data = (uint8_t *)push_->Allocate(size * sizeof(TessData), ssboAlignment, &bufInfo_[0].buffer, (uint32_t *)&bufInfo_[0].offset); bufInfo_[0].range = size * sizeof(TessData); float *pos = (float *)(data); @@ -1085,12 +1081,12 @@ void TessellationDataTransferVulkan::SendDataToShader(const SimpleVertex *const using Spline::Weight; // Weights U - data = (uint8_t *)push_->PushAligned(weights.size_u * sizeof(Weight), (uint32_t *)&bufInfo_[1].offset, &bufInfo_[1].buffer, ssboAlignment); + data = (uint8_t *)push_->Allocate(weights.size_u * sizeof(Weight), ssboAlignment, &bufInfo_[1].buffer, (uint32_t *)&bufInfo_[1].offset); memcpy(data, weights.u, weights.size_u * sizeof(Weight)); bufInfo_[1].range = weights.size_u * sizeof(Weight); // Weights V - data = (uint8_t *)push_->PushAligned(weights.size_v * sizeof(Weight), (uint32_t *)&bufInfo_[2].offset, &bufInfo_[2].buffer, ssboAlignment); + data = (uint8_t *)push_->Allocate(weights.size_v * sizeof(Weight), ssboAlignment, &bufInfo_[2].buffer, (uint32_t *)&bufInfo_[2].offset); memcpy(data, weights.v, weights.size_v * sizeof(Weight)); bufInfo_[2].range = weights.size_v * sizeof(Weight); } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 16693d2f4c..1c209eb38f 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -113,13 +113,13 @@ class TessellationDataTransferVulkan : public TessellationDataTransfer { public: TessellationDataTransferVulkan(VulkanContext *vulkan) : vulkan_(vulkan) {} - void SetPushBuffer(VulkanPushBuffer *push) { push_ = push; } + void SetPushPool(VulkanPushPool *push) { push_ = push; } // Send spline/bezier's control points and weights to vertex shader through structured shader buffer. void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) override; const VkDescriptorBufferInfo *GetBufferInfo() { return bufInfo_; } private: VulkanContext *vulkan_; - VulkanPushBuffer *push_; // Updated each frame. + VulkanPushPool *push_; // Updated each frame. VkDescriptorBufferInfo bufInfo_[3]{}; }; @@ -193,8 +193,8 @@ public: lastPipeline_ = nullptr; } - VulkanPushBuffer *GetPushBufferForTextureData() { - return GetCurFrame().pushUBO; + VulkanPushPool *GetPushBufferForTextureData() { + return pushUBO; } const DrawEngineVulkanStats &GetStats() const { @@ -270,8 +270,6 @@ private: VulkanDescSetPool descPool; - VulkanPushBuffer *pushUBO = nullptr; - // We do rolling allocation and reset instead of caching across frames. That we might do later. DenseHashMap descSets; @@ -281,6 +279,7 @@ private: GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; + VulkanPushPool *pushUBO = nullptr; VulkanPushPool *pushVertex = nullptr; VulkanPushPool *pushIndex = nullptr; diff --git a/GPU/Vulkan/ShaderManagerVulkan.h b/GPU/Vulkan/ShaderManagerVulkan.h index 38b4b2e1e1..13013fa498 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.h +++ b/GPU/Vulkan/ShaderManagerVulkan.h @@ -34,7 +34,7 @@ class VulkanContext; class DrawEngineVulkan; -class VulkanPushBuffer; +class VulkanPushPool; class VulkanFragmentShader { public: @@ -145,15 +145,15 @@ public: bool IsLightDirty() { return true; } bool IsBoneDirty() { return true; } - uint32_t PushBaseBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_base, sizeof(ub_base), uboAlignment_, buf); + uint32_t PushBaseBuffer(VulkanPushPool *dest, VkBuffer *buf) { + return dest->Push(&ub_base, sizeof(ub_base), uboAlignment_, buf); } - uint32_t PushLightBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_lights, sizeof(ub_lights), uboAlignment_, buf); + uint32_t PushLightBuffer(VulkanPushPool *dest, VkBuffer *buf) { + return dest->Push(&ub_lights, sizeof(ub_lights), uboAlignment_, buf); } // TODO: Only push half the bone buffer if we only have four bones. - uint32_t PushBoneBuffer(VulkanPushBuffer *dest, VkBuffer *buf) { - return dest->PushAligned(&ub_bones, sizeof(ub_bones), uboAlignment_, buf); + uint32_t PushBoneBuffer(VulkanPushPool *dest, VkBuffer *buf) { + return dest->Push(&ub_bones, sizeof(ub_bones), uboAlignment_, buf); } bool LoadCacheFlags(FILE *f, DrawEngineVulkan *drawEngine); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 7f60c27d2f..a08f231cd5 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -550,7 +550,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { levels = plan.levelsToLoad; } - VulkanPushBuffer *pushBuffer = drawEngine_->GetPushBufferForTextureData(); + VulkanPushPool *pushBuffer = drawEngine_->GetPushBufferForTextureData(); // Batch the copies. TextureCopyBatch copyBatch; @@ -583,11 +583,11 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { saveData.resize(sz); data = &saveData[0]; } else { - data = pushBuffer->PushAligned(sz, &bufferOffset, &texBuf, pushAlignment); + data = pushBuffer->Allocate(sz, pushAlignment, &texBuf, &bufferOffset); } LoadVulkanTextureLevel(*entry, (uint8_t *)data, lstride, srcLevel, lfactor, actualFmt); if (plan.saveTexture) - bufferOffset = pushBuffer->PushAligned(&saveData[0], sz, pushAlignment, &texBuf); + bufferOffset = pushBuffer->Push(&saveData[0], sz, pushAlignment, &texBuf); }; bool dataScaled = true; @@ -599,7 +599,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { rowLength = (mipWidth + 3) & ~3; } // Directly load the replaced image. - data = pushBuffer->PushAligned(uploadSize, &bufferOffset, &texBuf, pushAlignment); + data = pushBuffer->Allocate(uploadSize, pushAlignment, &texBuf, &bufferOffset); double replaceStart = time_now_d(); if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, data, byteStride)) { // If plan.replaceValid, this shouldn't fail. WARN_LOG(G3D, "Failed to copy replaced texture level"); From 23fe57e774e3cec1b791630fe636736630b4367e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 14 Mar 2023 23:28:24 +0100 Subject: [PATCH 331/424] Use VulkanPushPool for thin3d --- Common/GPU/Vulkan/thin3d_vulkan.cpp | 49 ++++++++++++----------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 008fcd0159..91957b923c 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -283,8 +283,8 @@ public: } // Returns the binding offset, and the VkBuffer to bind. - size_t PushUBO(VulkanPushBuffer *buf, VulkanContext *vulkan, VkBuffer *vkbuf) { - return buf->PushAligned(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment, vkbuf); + size_t PushUBO(VulkanPushPool *buf, VulkanContext *vulkan, VkBuffer *vkbuf) { + return buf->Push(ubo_, uboSize_, vulkan->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment, vkbuf); } int GetUBOSize() const { @@ -334,9 +334,9 @@ struct DescriptorSetKey { class VKTexture : public Texture { public: - VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc) + VKTexture(VulkanContext *vulkan, VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const TextureDesc &desc) : vulkan_(vulkan), mipLevels_(desc.mipLevels), format_(desc.format) {} - bool Create(VkCommandBuffer cmd, VulkanPushBuffer *pushBuffer, const TextureDesc &desc); + bool Create(VkCommandBuffer cmd, VulkanPushPool *pushBuffer, const TextureDesc &desc); ~VKTexture() { Destroy(); @@ -536,12 +536,12 @@ private: VkImageView boundImageView_[MAX_BOUND_TEXTURES]{}; TextureBindFlags boundTextureFlags_[MAX_BOUND_TEXTURES]; + VulkanPushPool *push_ = nullptr; + struct FrameData { FrameData() : descriptorPool("VKContext", false) { descriptorPool.Setup([this] { descSets_.clear(); }); } - - VulkanPushBuffer *pushBuffer = nullptr; // Per-frame descriptor set cache. As it's per frame and reset every frame, we don't need to // worry about invalidating descriptors pointing to deleted textures. // However! ARM is not a fan of doing it this way. @@ -551,8 +551,6 @@ private: FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; - VulkanPushBuffer *push_ = nullptr; - DeviceCaps caps_{}; uint8_t stencilRef_ = 0; @@ -675,7 +673,7 @@ VulkanTexture *VKContext::GetNullTexture() { VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); uint32_t bindOffset; VkBuffer bindBuf; - uint32_t *data = (uint32_t *)push_->Push(w * h * 4, &bindOffset, &bindBuf); + uint32_t *data = (uint32_t *)push_->Allocate(w * h * 4, 4, &bindBuf, &bindOffset); for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { // data[y*w + x] = ((x ^ y) & 1) ? 0xFF808080 : 0xFF000000; // gray/black checkerboard @@ -739,7 +737,7 @@ enum class TextureState { PENDING_DESTRUCTION, }; -bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const TextureDesc &desc) { +bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushPool *push, const TextureDesc &desc) { // Zero-sized textures not allowed. _assert_(desc.width * desc.height * desc.depth > 0); // remember to set depth to 1! if (desc.width * desc.height * desc.depth <= 0) { @@ -779,12 +777,12 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const Textur VkBuffer buf; size_t size = w * h * d * bytesPerPixel; if (desc.initDataCallback) { - uint8_t *dest = (uint8_t *)push->PushAligned(size, &offset, &buf, 16); + uint8_t *dest = (uint8_t *)push->Allocate(size, 16, &buf, &offset); if (!desc.initDataCallback(dest, desc.initData[i], w, h, d, w * bytesPerPixel, h * w * bytesPerPixel)) { memcpy(dest, desc.initData[i], size); } } else { - offset = push->PushAligned((const void *)desc.initData[i], size, 16, &buf); + offset = push->Push((const void *)desc.initData[i], size, 16, &buf); } TextureCopyBatch batch; vkTex_->CopyBufferToMipLevel(cmd, &batch, i, w, h, 0, buf, offset, w); @@ -983,9 +981,10 @@ VKContext::VKContext(VulkanContext *vulkan) // 200 textures per frame was not enough for the UI. dp.maxSets = 4096; + VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + push_ = new VulkanPushPool(vulkan_, "pushBuffer", 1024 * 1024, usage); + for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { - VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - frame_[i].pushBuffer = new VulkanPushBuffer(vulkan_, "pushBuffer", 1024 * 1024, usage, PushBufferType::CPU_TO_GPU); frame_[i].descriptorPool.Create(vulkan_, dp, dpTypes); } @@ -1037,9 +1036,9 @@ VKContext::~VKContext() { // This also destroys all descriptor sets. for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { frame_[i].descriptorPool.Destroy(); - frame_[i].pushBuffer->Destroy(vulkan_); - delete frame_[i].pushBuffer; } + push_->Destroy(); + delete push_; vulkan_->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout_); vulkan_->Delete().QueueDeletePipelineLayout(pipelineLayout_); vulkan_->Delete().QueueDeletePipelineCache(pipelineCache_); @@ -1050,23 +1049,15 @@ void VKContext::BeginFrame() { renderManager_.BeginFrame(debugFlags_ & DebugFlags::PROFILE_TIMESTAMPS, debugFlags_ & DebugFlags::PROFILE_SCOPES); FrameData &frame = frame_[vulkan_->GetCurFrame()]; - push_ = frame.pushBuffer; - // OK, we now know that nothing is reading from this frame's data pushbuffer, - push_->Reset(); - push_->Begin(vulkan_); + push_->BeginFrame(); frame.descriptorPool.Reset(); } void VKContext::EndFrame() { - // Stop collecting data in the frame's data pushbuffer. - push_->End(); - renderManager_.Finish(); - push_ = nullptr; - // Unbind stuff, to avoid accidentally relying on it across frames (and provide some protection against forgotten unbinds of deleted things). Invalidate(InvalidationFlags::CACHED_RENDER_STATE); } @@ -1452,7 +1443,7 @@ void VKContext::Draw(int vertexCount, int offset) { VkBuffer vulkanVbuf; VkBuffer vulkanUBObuf; uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); - size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), &vulkanVbuf); + size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), 4, &vulkanVbuf); VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf); if (descSet == VK_NULL_HANDLE) { @@ -1471,8 +1462,8 @@ void VKContext::DrawIndexed(int vertexCount, int offset) { VkBuffer vulkanVbuf, vulkanIbuf, vulkanUBObuf; uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); - size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), &vulkanVbuf); - size_t ibBindOffset = push_->Push(ibuf->GetData(), ibuf->GetSize(), &vulkanIbuf); + size_t vbBindOffset = push_->Push(vbuf->GetData(), vbuf->GetSize(), 4, &vulkanVbuf); + size_t ibBindOffset = push_->Push(ibuf->GetData(), ibuf->GetSize(), 4, &vulkanIbuf); VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf); if (descSet == VK_NULL_HANDLE) { @@ -1487,7 +1478,7 @@ void VKContext::DrawIndexed(int vertexCount, int offset) { void VKContext::DrawUP(const void *vdata, int vertexCount) { VkBuffer vulkanVbuf, vulkanUBObuf; - size_t vbBindOffset = push_->Push(vdata, vertexCount * curPipeline_->stride[0], &vulkanVbuf); + size_t vbBindOffset = push_->Push(vdata, vertexCount * curPipeline_->stride[0], 4, &vulkanVbuf); uint32_t ubo_offset = (uint32_t)curPipeline_->PushUBO(push_, vulkan_, &vulkanUBObuf); VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf); From 9fcd6d66127d65e003abd0b7a5aa96ac0ae6452b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 00:02:57 +0100 Subject: [PATCH 332/424] Use thin3d's push pool in the draw engine too. --- Common/GPU/Vulkan/VulkanMemory.cpp | 4 +++- Common/GPU/Vulkan/thin3d_vulkan.cpp | 5 +++-- Common/GPU/thin3d.h | 1 + GPU/Vulkan/DrawEngineVulkan.cpp | 9 ++------- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index 9015e0d0ba..b4ee6297a5 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -349,9 +349,11 @@ void VulkanPushPool::NextBlock(VkDeviceSize allocationSize) { curBlockIndex_++; while (curBlockIndex_ < blocks_.size()) { Block &block = blocks_[curBlockIndex_]; - if (block.frameIndex == curFrameIndex) { + // Grab the first matching block, or unused block (frameIndex == -1). + if ((block.frameIndex == curFrameIndex || block.frameIndex == -1) && block.size >= allocationSize) { _assert_(block.used == 0); block.used = allocationSize; + block.frameIndex = curFrameIndex; return; } curBlockIndex_++; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index 91957b923c..ad4a8c2057 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -981,7 +981,7 @@ VKContext::VKContext(VulkanContext *vulkan) // 200 textures per frame was not enough for the UI. dp.maxSets = 4096; - VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; push_ = new VulkanPushPool(vulkan_, "pushBuffer", 1024 * 1024, usage); for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { @@ -1770,7 +1770,8 @@ uint64_t VKContext::GetNativeObject(NativeObject obj, void *srcObject) { return (uint64_t)curFramebuffer_->GetFB()->GetRTView(); case NativeObject::THIN3D_PIPELINE_LAYOUT: return (uint64_t)pipelineLayout_; - + case NativeObject::PUSH_POOL: + return (uint64_t)push_; default: Crash(); return 0; diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h index 3013470e95..ae3db6af00 100644 --- a/Common/GPU/thin3d.h +++ b/Common/GPU/thin3d.h @@ -252,6 +252,7 @@ enum class NativeObject { NULL_IMAGEVIEW, NULL_IMAGEVIEW_ARRAY, THIN3D_PIPELINE_LAYOUT, + PUSH_POOL, }; enum FBChannel { diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index ca64ae4e11..a88581759e 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -173,7 +173,7 @@ void DrawEngineVulkan::InitDeviceObjects() { // the null texture. This should be cleaned up... } - pushUBO = new VulkanPushPool(vulkan, "pushUBO", 4 * 1024 * 1024, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT); + pushUBO = (VulkanPushPool *)draw_->GetNativeObject(Draw::NativeObject::PUSH_POOL); pushVertex = new VulkanPushPool(vulkan, "pushVertex", 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); @@ -252,11 +252,6 @@ void DrawEngineVulkan::DestroyDeviceObjects() { delete pushIndex; pushIndex = nullptr; } - if (pushUBO) { - pushUBO->Destroy(); - delete pushUBO; - pushUBO = nullptr; - } if (samplerSecondaryNearest_ != VK_NULL_HANDLE) vulkan->Delete().QueueDeleteSampler(samplerSecondaryNearest_); @@ -297,7 +292,7 @@ void DrawEngineVulkan::BeginFrame() { lastPipeline_ = nullptr; - pushUBO->BeginFrame(); + // pushUBO is the thin3d push pool, don't need to BeginFrame again. pushVertex->BeginFrame(); pushIndex->BeginFrame(); From c8b25e50b0b3e9bbc9ff21a02afce4a79fd1f2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 00:54:50 +0100 Subject: [PATCH 333/424] Better debug vis for push pools --- Common/GPU/Vulkan/VulkanMemory.cpp | 27 ++++++++++++++------------- Common/GPU/Vulkan/VulkanMemory.h | 27 ++++++++++++--------------- GPU/Vulkan/DebugVisVulkan.cpp | 6 +++--- 3 files changed, 29 insertions(+), 31 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index b4ee6297a5..8fea4abafa 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -27,6 +27,7 @@ #include "Common/TimeUtil.h" #include "Common/Math/math_util.h" #include "Common/GPU/Vulkan/VulkanMemory.h" +#include "Common/Data/Text/Parsers.h" using namespace PPSSPP_VK; @@ -150,8 +151,13 @@ size_t VulkanPushBuffer::GetTotalSize() const { return sum; } -size_t VulkanPushBuffer::GetTotalCapacity() const { - return size_ * buffers_.size(); +void VulkanPushBuffer::GetDebugString(char *buffer, size_t bufSize) const { + size_t sum = 0; + if (buffers_.size() > 1) + sum += size_ * (buffers_.size() - 1); + sum += offset_; + size_t capacity = size_ * buffers_.size(); + snprintf(buffer, bufSize, "Push %s: %s/%s", name_, NiceSizeFormat(capacity).c_str(), NiceSizeFormat(sum).c_str()); } void VulkanPushBuffer::Map() { @@ -367,18 +373,13 @@ void VulkanPushPool::NextBlock(VkDeviceSize allocationSize) { // curBlockIndex_ is already set correctly here. } -size_t VulkanPushPool::GetTotalSize() const { - size_t sz = 0; +void VulkanPushPool::GetDebugString(char *buffer, size_t bufSize) const { + size_t used = 0; + size_t capacity = 0; for (auto &block : blocks_) { - sz += block.used; + used += block.used; + capacity += block.size; } - return sz; -} -size_t VulkanPushPool::GetTotalCapacity() const { - size_t sz = 0; - for (auto &block : blocks_) { - sz += block.size; - } - return sz; + snprintf(buffer, bufSize, "Pool %s: %s / %s (%d extra blocks)", name_, NiceSizeFormat(used).c_str(), NiceSizeFormat(capacity).c_str(), (int)blocks_.size() - 3); } diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index a27cd9e3e7..e280e02c42 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -24,9 +24,8 @@ class VulkanMemoryManager { public: virtual ~VulkanMemoryManager() {} - virtual size_t GetTotalSize() const = 0; - virtual size_t GetTotalCapacity() const = 0; - virtual const char *Name() const = 0; + virtual void GetDebugString(char *buffer, size_t bufSize) const = 0; + virtual const char *Name() const = 0; // for sorting }; // VulkanPushBuffer @@ -53,6 +52,11 @@ public: void Reset() { offset_ = 0; } + void GetDebugString(char *buffer, size_t bufSize) const override; + const char *Name() const override { + return name_; + } + // Needs context in case of defragment. void Begin(VulkanContext *vulkan) { buf_ = 0; @@ -112,10 +116,6 @@ public: return offset_; } - const char *Name() const override { - return name_; - } - // "Zero-copy" variant - you can write the data directly as you compute it. // Recommended. void *Push(size_t size, uint32_t *bindOffset, VkBuffer *vkbuf) { @@ -141,8 +141,7 @@ public: info->range = sizeof(T); } - size_t GetTotalSize() const override; // Used size - size_t GetTotalCapacity() const override; + size_t GetTotalSize() const; private: bool AddBuffer(); @@ -171,8 +170,10 @@ public: void Destroy(); void BeginFrame(); - size_t GetTotalSize() const override; // Used size - size_t GetTotalCapacity() const override; + const char *Name() const override { + return name_; + } + void GetDebugString(char *buffer, size_t bufSize) const override; // When using the returned memory, make sure to bind the returned vkbuf. uint8_t *Allocate(VkDeviceSize numBytes, VkDeviceSize alignment, VkBuffer *vkbuf, uint32_t *bindOffset) { @@ -202,10 +203,6 @@ public: return bindOffset; } - const char *Name() const override { - return name_; - } - private: void NextBlock(VkDeviceSize allocationSize); diff --git a/GPU/Vulkan/DebugVisVulkan.cpp b/GPU/Vulkan/DebugVisVulkan.cpp index 74bf57100d..1c1cf1ff7a 100644 --- a/GPU/Vulkan/DebugVisVulkan.cpp +++ b/GPU/Vulkan/DebugVisVulkan.cpp @@ -78,10 +78,10 @@ void DrawAllocatorVis(UIContext *ui, GPUInterface *gpu) { auto managers = GetActiveVulkanMemoryManagers(); std::sort(managers.begin(), managers.end(), comparePushBufferNames); + char buffer[512]; for (auto manager : managers) { - str << " " << manager->Name() << " " - << NiceSizeFormat(manager->GetTotalCapacity()) << ", used: " - << NiceSizeFormat(manager->GetTotalSize()) << std::endl; + manager->GetDebugString(buffer, sizeof(buffer)); + str << " " << buffer << std::endl; } const int padding = 10 + System_GetPropertyFloat(SYSPROP_DISPLAY_SAFE_INSET_LEFT); From f3bdf324f9cd3785c16fdf228400231fe6c69b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 01:22:32 +0100 Subject: [PATCH 334/424] Garbage collect old buffers in push pool. --- Common/GPU/Vulkan/VulkanMemory.cpp | 25 ++++++++++++++++++++++++- Common/GPU/Vulkan/VulkanMemory.h | 1 + Common/GPU/Vulkan/thin3d_vulkan.cpp | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index 8fea4abafa..e0bfa741e5 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -332,6 +332,7 @@ void VulkanPushPool::Block::Destroy(VulkanContext *vulkan) { } void VulkanPushPool::BeginFrame() { + double now = time_now_d(); curBlockIndex_ = -1; for (auto &block : blocks_) { if (block.frameIndex == vulkan_->GetCurFrame()) { @@ -339,6 +340,7 @@ void VulkanPushPool::BeginFrame() { // Pick a block associated with the current frame to start at. // We always start with one block per frame index. curBlockIndex_ = block.frameIndex; + block.lastUsed = now; } block.used = 0; if (!block.original) { @@ -348,6 +350,23 @@ void VulkanPushPool::BeginFrame() { } // TODO: Also garbage collect blocks that have been unused for many frames here. } + + // Do a single pass of bubblesort to move the bigger buffers earlier in the sequence. + for (size_t i = 3; i < blocks_.size() - 1; i++) { + if (blocks_[i].frameIndex == -1 && blocks_[i + 1].frameIndex == -1 && blocks_[i].size < blocks_[i + 1].size) { + std::swap(blocks_[i], blocks_[i + 1]); + } + } + + // If we have lots of little buffers and the last one hasn't been used in a while, drop it. + // Still, let's keep around a few big ones. + if (blocks_.size() > 6 && blocks_.back().lastUsed < now - 10.0) { + double start = time_now_d(); + size_t size = blocks_.back().size; + blocks_.back().Destroy(vulkan_); + blocks_.pop_back(); + DEBUG_LOG(G3D, "%s: Garbage collected block of size %s in %0.2f ms", name_, NiceSizeFormat(size).c_str(), time_now_d() - start); + } } void VulkanPushPool::NextBlock(VkDeviceSize allocationSize) { @@ -359,18 +378,22 @@ void VulkanPushPool::NextBlock(VkDeviceSize allocationSize) { if ((block.frameIndex == curFrameIndex || block.frameIndex == -1) && block.size >= allocationSize) { _assert_(block.used == 0); block.used = allocationSize; + block.lastUsed = time_now_d(); block.frameIndex = curFrameIndex; return; } curBlockIndex_++; } - VkDeviceSize newBlockSize = std::max(originalBlockSize_, (VkDeviceSize)RoundUpToPowerOf2((uint32_t)allocationSize)); + double start = time_now_d(); + VkDeviceSize newBlockSize = std::max(originalBlockSize_ * 2, (VkDeviceSize)RoundUpToPowerOf2((uint32_t)allocationSize)); // We're still here and ran off the end of blocks. Create a new one. blocks_.push_back(CreateBlock(newBlockSize)); blocks_.back().frameIndex = curFrameIndex; blocks_.back().used = allocationSize; + blocks_.back().lastUsed = time_now_d(); // curBlockIndex_ is already set correctly here. + DEBUG_LOG(G3D, "%s: Created new block of size %s in %0.2f ms", name_, NiceSizeFormat(newBlockSize).c_str(), 1000.0 * (time_now_d() - start)); } void VulkanPushPool::GetDebugString(char *buffer, size_t bufSize) const { diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index e280e02c42..cafc8206b7 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -216,6 +216,7 @@ private: int frameIndex; bool original; // these blocks aren't garbage collected. + double lastUsed; uint8_t *writePtr; diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp index ad4a8c2057..fe1929cd52 100644 --- a/Common/GPU/Vulkan/thin3d_vulkan.cpp +++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp @@ -982,7 +982,7 @@ VKContext::VKContext(VulkanContext *vulkan) dp.maxSets = 4096; VkBufferUsageFlags usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - push_ = new VulkanPushPool(vulkan_, "pushBuffer", 1024 * 1024, usage); + push_ = new VulkanPushPool(vulkan_, "pushBuffer", 4 * 1024 * 1024, usage); for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { frame_[i].descriptorPool.Create(vulkan_, dp, dpTypes); From 6d3a25e81f320b8a359b70ea71af4de3f775b38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 01:23:15 +0100 Subject: [PATCH 335/424] Tweak some sizes. --- GPU/Vulkan/DrawEngineVulkan.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index a88581759e..fbf8f7ac79 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -174,8 +174,8 @@ void DrawEngineVulkan::InitDeviceObjects() { } pushUBO = (VulkanPushPool *)draw_->GetNativeObject(Draw::NativeObject::PUSH_POOL); - pushVertex = new VulkanPushPool(vulkan, "pushVertex", 2 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 1024 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + pushVertex = new VulkanPushPool(vulkan, "pushVertex", 4 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 512 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; pl.pPushConstantRanges = nullptr; From 181ddf8266ea667f8ae796beecdc054314a7e6ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 09:56:32 +0100 Subject: [PATCH 336/424] Change the API of the old VulkanPushBuffer to match VulkanPushPool. --- Common/GPU/Vulkan/VulkanMemory.h | 68 ++++++-------------------------- GPU/Common/ReplacedTexture.cpp | 2 +- GPU/Vulkan/DrawEngineVulkan.cpp | 4 +- 3 files changed, 16 insertions(+), 58 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index cafc8206b7..5d4e4b8659 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -30,11 +30,9 @@ public: // VulkanPushBuffer // Simple incrementing allocator. -// Use these to push vertex, index and uniform data. Generally you'll have two of these +// Use these to push vertex, index and uniform data. Generally you'll have two or three of these // and alternate on each frame. Make sure not to reset until the fence from the last time you used it // has completed. -// -// TODO: Make it possible to suballocate pushbuffers from a large DeviceMemory block. class VulkanPushBuffer : public VulkanMemoryManager { struct BufInfo { VkBuffer buffer; @@ -78,69 +76,29 @@ public: } void Map(); - void Unmap(); // When using the returned memory, make sure to bind the returned vkbuf. - // This will later allow for handling overflow correctly. - size_t Allocate(size_t numBytes, VkBuffer *vkbuf) { - size_t out = offset_; - offset_ += (numBytes + 3) & ~3; // Round up to 4 bytes. - - if (offset_ >= size_) { + uint8_t *Allocate(VkDeviceSize numBytes, VkDeviceSize alignment, VkBuffer *vkbuf, uint32_t *bindOffset) { + size_t offset = (offset_ + alignment - 1) & ~(alignment - 1); + if (offset + numBytes > size_) { NextBuffer(numBytes); - out = offset_; - offset_ += (numBytes + 3) & ~3; + offset = offset_; } + offset_ = offset + numBytes; + *bindOffset = (uint32_t)offset; *vkbuf = buffers_[buf_].buffer; - return out; + return writePtr_ + offset; } - // Returns the offset that should be used when binding this buffer to get this data. - size_t Push(const void *data, size_t size, VkBuffer *vkbuf) { - _dbg_assert_(writePtr_); - size_t off = Allocate(size, vkbuf); - memcpy(writePtr_ + off, data, size); - return off; - } - - uint32_t PushAligned(const void *data, size_t size, int align, VkBuffer *vkbuf) { - _dbg_assert_(writePtr_); - offset_ = (offset_ + align - 1) & ~(align - 1); - size_t off = Allocate(size, vkbuf); - memcpy(writePtr_ + off, data, size); - return (uint32_t)off; - } - - size_t GetOffset() const { - return offset_; - } - - // "Zero-copy" variant - you can write the data directly as you compute it. - // Recommended. - void *Push(size_t size, uint32_t *bindOffset, VkBuffer *vkbuf) { - _dbg_assert_(writePtr_); - size_t off = Allocate(size, vkbuf); - *bindOffset = (uint32_t)off; - return writePtr_ + off; - } - void *PushAligned(size_t size, uint32_t *bindOffset, VkBuffer *vkbuf, int align) { - _dbg_assert_(writePtr_); - offset_ = (offset_ + align - 1) & ~(align - 1); - size_t off = Allocate(size, vkbuf); - *bindOffset = (uint32_t)off; - return writePtr_ + off; - } - - template - void PushUBOData(const T &data, VkDescriptorBufferInfo *info) { + VkDeviceSize Push(const void *data, VkDeviceSize numBytes, int alignment, VkBuffer *vkbuf) { uint32_t bindOffset; - void *ptr = PushAligned(sizeof(T), &bindOffset, &info->buffer, vulkan_->GetPhysicalDeviceProperties().properties.limits.minUniformBufferOffsetAlignment); - memcpy(ptr, &data, sizeof(T)); - info->offset = bindOffset; - info->range = sizeof(T); + uint8_t *ptr = Allocate(numBytes, alignment, vkbuf, &bindOffset); + memcpy(ptr, data, numBytes); + return bindOffset; } + size_t GetOffset() const { return offset_; } size_t GetTotalSize() const; private: diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 4246919faf..3a9d47e3a4 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -509,7 +509,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } levelData_->data[i].resize(dataSizeBytes); - transcoder.transcode_image_level(i, 0, 0, &out[0], outputSize, transcoderFormat, 0, outputPitch, level.h, -1, -1, &transcodeState); + transcoder.transcode_image_level(i, 0, 0, &out[0], (uint32_t)outputSize, transcoderFormat, 0, (uint32_t)outputPitch, level.h, -1, -1, &transcodeState); level.w = levelInfo.m_orig_width; level.h = levelInfo.m_orig_height; if (i != 0) diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index fbf8f7ac79..68302f8855 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -364,7 +364,7 @@ void DrawEngineVulkan::DecodeVertsToPushBuffer(VulkanPushBuffer *push, uint32_t // Figure out how much pushbuffer space we need to allocate. if (push) { int vertsToDecode = ComputeNumVertsToDecode(); - dest = (u8 *)push->Push(vertsToDecode * dec_->GetDecVtxFmt().stride, bindOffset, vkbuf); + dest = (u8 *)push->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, vkbuf, bindOffset); } DecodeVerts(dest); } @@ -691,7 +691,7 @@ void DrawEngineVulkan::DoFlush() { if (useElements) { u32 size = sizeof(uint16_t) * indexGen.VertexCount(); - void *dest = vertexCache_->Push(size, &vai->ibOffset, &vai->ib); + void *dest = vertexCache_->Allocate(size, 4, &vai->ib, &vai->ibOffset); memcpy(dest, decIndex, size); } else { vai->ib = VK_NULL_HANDLE; From 2ac74e3d375eabeafac296ccb9ff6b7ea99690eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 09:59:00 +0100 Subject: [PATCH 337/424] Remove the PushBufferType enum --- Common/GPU/Vulkan/VulkanMemory.cpp | 12 +++++------- Common/GPU/Vulkan/VulkanMemory.h | 23 +++++------------------ GPU/Vulkan/DrawEngineVulkan.cpp | 4 ++-- 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index e0bfa741e5..ae2f812e7a 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -45,8 +45,8 @@ std::vector GetActiveVulkanMemoryManagers() { return buffers; } -VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage, PushBufferType type) - : vulkan_(vulkan), name_(name), size_(size), usage_(usage), type_(type) { +VulkanPushBuffer::VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage) + : vulkan_(vulkan), name_(name), size_(size), usage_(usage) { { std::lock_guard guard(g_pushBufferListMutex); g_pushBuffers.insert(this); @@ -79,7 +79,7 @@ bool VulkanPushBuffer::AddBuffer() { b.pQueueFamilyIndices = nullptr; VmaAllocationCreateInfo allocCreateInfo{}; - allocCreateInfo.usage = type_ == PushBufferType::CPU_TO_GPU ? VMA_MEMORY_USAGE_CPU_TO_GPU : VMA_MEMORY_USAGE_GPU_ONLY; + allocCreateInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; VmaAllocationInfo allocInfo{}; VkResult res = vmaCreateBuffer(vulkan_->Allocator(), &b, &allocCreateInfo, &info.buffer, &info.allocation, &allocInfo); @@ -105,8 +105,7 @@ void VulkanPushBuffer::Destroy(VulkanContext *vulkan) { void VulkanPushBuffer::NextBuffer(size_t minSize) { // First, unmap the current memory. - if (type_ == PushBufferType::CPU_TO_GPU) - Unmap(); + Unmap(); buf_++; if (buf_ >= buffers_.size() || minSize > size_) { @@ -125,8 +124,7 @@ void VulkanPushBuffer::NextBuffer(size_t minSize) { // Now, move to the next buffer and map it. offset_ = 0; - if (type_ == PushBufferType::CPU_TO_GPU) - Map(); + Map(); } void VulkanPushBuffer::Defragment(VulkanContext *vulkan) { diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index 5d4e4b8659..50b9f35da9 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -14,11 +14,6 @@ VK_DEFINE_HANDLE(VmaAllocation); // // Vulkan memory management utils. -enum class PushBufferType { - CPU_TO_GPU, - GPU_ONLY, -}; - // Just an abstract thing to get debug information. class VulkanMemoryManager { public: @@ -33,6 +28,7 @@ public: // Use these to push vertex, index and uniform data. Generally you'll have two or three of these // and alternate on each frame. Make sure not to reset until the fence from the last time you used it // has completed. +// NOTE: This has now been replaced with VulkanPushPool for all uses except the vertex cache. class VulkanPushBuffer : public VulkanMemoryManager { struct BufInfo { VkBuffer buffer; @@ -43,7 +39,7 @@ public: // NOTE: If you create a push buffer with PushBufferType::GPU_ONLY, // then you can't use any of the push functions as pointers will not be reachable from the CPU. // You must in this case use Allocate() only, and pass the returned offset and the VkBuffer to Vulkan APIs. - VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage, PushBufferType type); + VulkanPushBuffer(VulkanContext *vulkan, const char *name, size_t size, VkBufferUsageFlags usage); ~VulkanPushBuffer(); void Destroy(VulkanContext *vulkan); @@ -61,19 +57,11 @@ public: offset_ = 0; // Note: we must defrag because some buffers may be smaller than size_. Defragment(vulkan); - if (type_ == PushBufferType::CPU_TO_GPU) - Map(); + Map(); } - void BeginNoReset() { - if (type_ == PushBufferType::CPU_TO_GPU) - Map(); - } - - void End() { - if (type_ == PushBufferType::CPU_TO_GPU) - Unmap(); - } + void BeginNoReset() { Map(); } + void End() { Unmap(); } void Map(); void Unmap(); @@ -107,7 +95,6 @@ private: void Defragment(VulkanContext *vulkan); VulkanContext *vulkan_; - PushBufferType type_; std::vector buffers_; size_t buf_ = 0; diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 68302f8855..0d92bbef9b 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -205,7 +205,7 @@ void DrawEngineVulkan::InitDeviceObjects() { res = vkCreateSampler(device, &samp, nullptr, &nullSampler_); _dbg_assert_(VK_SUCCESS == res); - vertexCache_ = new VulkanPushBuffer(vulkan, "pushVertexCache", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU); + vertexCache_ = new VulkanPushBuffer(vulkan, "pushVertexCache", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); tessDataTransferVulkan = new TessellationDataTransferVulkan(vulkan); tessDataTransfer = tessDataTransferVulkan; @@ -312,7 +312,7 @@ void DrawEngineVulkan::BeginFrame() { if (vertexCache_->GetTotalSize() > VERTEX_CACHE_SIZE) { vertexCache_->Destroy(vulkan); delete vertexCache_; // orphans the buffers, they'll get deleted once no longer used by an in-flight frame. - vertexCache_ = new VulkanPushBuffer(vulkan, "vertexCacheR", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, PushBufferType::CPU_TO_GPU); + vertexCache_ = new VulkanPushBuffer(vulkan, "vertexCacheR", VERTEX_CACHE_SIZE, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); vai_.Iterate([&](uint32_t hash, VertexArrayInfoVulkan *vai) { delete vai; }); From 089b63c22fddfd965fd2844511c3a70230c99eaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 10:09:39 +0100 Subject: [PATCH 338/424] Address feedback, except the stats. --- Common/GPU/Vulkan/VulkanMemory.cpp | 13 ++++--- GPU/Vulkan/DrawEngineVulkan.cpp | 58 +++++++++++++++--------------- GPU/Vulkan/DrawEngineVulkan.h | 10 +++--- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index ae2f812e7a..5c675ec9a2 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -31,6 +31,9 @@ using namespace PPSSPP_VK; +// Always keep around push buffers at least this long (seconds). +static const double PUSH_GARBAGE_COLLECTION_DELAY = 10.0; + // Global push buffer tracker for vulkan memory profiling. // Don't want to manually dig up all the active push buffers. static std::mutex g_pushBufferListMutex; @@ -314,10 +317,10 @@ VulkanPushPool::Block VulkanPushPool::CreateBlock(size_t size) { VmaAllocationInfo allocInfo{}; VkResult result = vmaCreateBuffer(vulkan_->Allocator(), &b, &allocCreateInfo, &block.buffer, &block.allocation, &allocInfo); - _dbg_assert_(result == VK_SUCCESS); + _assert_(result == VK_SUCCESS); result = vmaMapMemory(vulkan_->Allocator(), block.allocation, (void **)(&block.writePtr)); - _dbg_assert_(result == VK_SUCCESS); + _assert_(result == VK_SUCCESS); return block; } @@ -346,10 +349,10 @@ void VulkanPushPool::BeginFrame() { block.frameIndex = -1; } } - // TODO: Also garbage collect blocks that have been unused for many frames here. } // Do a single pass of bubblesort to move the bigger buffers earlier in the sequence. + // Over multiple frames this will quickly converge to the right order. for (size_t i = 3; i < blocks_.size() - 1; i++) { if (blocks_[i].frameIndex == -1 && blocks_[i + 1].frameIndex == -1 && blocks_[i].size < blocks_[i + 1].size) { std::swap(blocks_[i], blocks_[i + 1]); @@ -357,8 +360,8 @@ void VulkanPushPool::BeginFrame() { } // If we have lots of little buffers and the last one hasn't been used in a while, drop it. - // Still, let's keep around a few big ones. - if (blocks_.size() > 6 && blocks_.back().lastUsed < now - 10.0) { + // Still, let's keep around a few big ones (6 - 3). + if (blocks_.size() > 6 && blocks_.back().lastUsed < now - PUSH_GARBAGE_COLLECTION_DELAY) { double start = time_now_d(); size_t size = blocks_.back().size; blocks_.back().Destroy(vulkan_); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 0d92bbef9b..83636e88f5 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -169,13 +169,13 @@ void DrawEngineVulkan::InitDeviceObjects() { for (int i = 0; i < VulkanContext::MAX_INFLIGHT_FRAMES; i++) { frame_[i].descPool.Create(vulkan, dp, dpTypes); - // Note that pushUBO is also used for tessellation data (search for SetPushBuffer), and to upload + // Note that pushUBO_ is also used for tessellation data (search for SetPushBuffer), and to upload // the null texture. This should be cleaned up... } - pushUBO = (VulkanPushPool *)draw_->GetNativeObject(Draw::NativeObject::PUSH_POOL); - pushVertex = new VulkanPushPool(vulkan, "pushVertex", 4 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); - pushIndex = new VulkanPushPool(vulkan, "pushIndex", 1 * 512 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); + pushUBO_ = (VulkanPushPool *)draw_->GetNativeObject(Draw::NativeObject::PUSH_POOL); + pushVertex_ = new VulkanPushPool(vulkan, "pushVertex", 4 * 1024 * 1024, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); + pushIndex_ = new VulkanPushPool(vulkan, "pushIndex", 1 * 512 * 1024, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); VkPipelineLayoutCreateInfo pl{ VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; pl.pPushConstantRanges = nullptr; @@ -242,15 +242,17 @@ void DrawEngineVulkan::DestroyDeviceObjects() { frame_[i].Destroy(vulkan); } - if (pushVertex) { - pushVertex->Destroy(); - delete pushVertex; - pushVertex = nullptr; + pushUBO_ = nullptr; + + if (pushVertex_) { + pushVertex_->Destroy(); + delete pushVertex_; + pushVertex_ = nullptr; } - if (pushIndex) { - pushIndex->Destroy(); - delete pushIndex; - pushIndex = nullptr; + if (pushIndex_) { + pushIndex_->Destroy(); + delete pushIndex_; + pushIndex_ = nullptr; } if (samplerSecondaryNearest_ != VK_NULL_HANDLE) @@ -293,10 +295,10 @@ void DrawEngineVulkan::BeginFrame() { lastPipeline_ = nullptr; // pushUBO is the thin3d push pool, don't need to BeginFrame again. - pushVertex->BeginFrame(); - pushIndex->BeginFrame(); + pushVertex_->BeginFrame(); + pushIndex_->BeginFrame(); - tessDataTransferVulkan->SetPushPool(pushUBO); + tessDataTransferVulkan->SetPushPool(pushUBO_); DirtyAllUBOs(); @@ -621,7 +623,7 @@ void DrawEngineVulkan::DoFlush() { vai->minihash = ComputeMiniHash(); vai->status = VertexArrayInfoVulkan::VAI_HASHING; vai->drawsUntilNextFullHash = 0; - DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); // writes to indexGen + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); // writes to indexGen vai->numVerts = indexGen.VertexCount(); vai->prim = indexGen.Prim(); vai->maxIndex = indexGen.MaxIndex(); @@ -647,7 +649,7 @@ void DrawEngineVulkan::DoFlush() { } if (newMiniHash != vai->minihash || newHash != vai->hash) { MarkUnreliable(vai); - DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); goto rotateVBO; } if (vai->numVerts > 64) { @@ -666,7 +668,7 @@ void DrawEngineVulkan::DoFlush() { u32 newMiniHash = ComputeMiniHash(); if (newMiniHash != vai->minihash) { MarkUnreliable(vai); - DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); goto rotateVBO; } } @@ -738,7 +740,7 @@ void DrawEngineVulkan::DoFlush() { if (vai->lastFrame != gpuStats.numFlips) { vai->numFrames++; } - DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); goto rotateVBO; } default: @@ -748,11 +750,11 @@ void DrawEngineVulkan::DoFlush() { if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) { // If software skinning, we've already predecoded into "decoded". So push that content. VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride; - u8 *dest = (u8 *)pushVertex->Allocate(size, 4, &vbuf, &vbOffset); + u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset); memcpy(dest, decoded, size); } else { // Decode directly into the pushbuffer - DecodeVertsToPushPool(pushVertex, &vbOffset, &vbuf); + DecodeVertsToPushPool(pushVertex_, &vbOffset, &vbuf); } rotateVBO: @@ -835,7 +837,7 @@ void DrawEngineVulkan::DoFlush() { }; if (useElements) { if (!ibuf) { - ibOffset = (uint32_t)pushIndex->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), 4, &ibuf); + ibOffset = (uint32_t)pushIndex_->Push(decIndex, sizeof(uint16_t) * indexGen.VertexCount(), 4, &ibuf); } renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1, VK_INDEX_TYPE_UINT16); } else { @@ -973,12 +975,12 @@ void DrawEngineVulkan::DoFlush() { if (result.drawIndexed) { VkBuffer vbuf, ibuf; - vbOffset = (uint32_t)pushVertex->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vbuf); - ibOffset = (uint32_t)pushIndex->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf); + vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, maxIndex * sizeof(TransformedVertex), 4, &vbuf); + ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf); renderManager->DrawIndexed(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1, VK_INDEX_TYPE_UINT16); } else { VkBuffer vbuf; - vbOffset = (uint32_t)pushVertex->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), 4, &vbuf); + vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, result.drawNumTrans * sizeof(TransformedVertex), 4, &vbuf); renderManager->Draw(ds, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, result.drawNumTrans); } } else if (result.action == SW_CLEAR) { @@ -1033,15 +1035,15 @@ void DrawEngineVulkan::DoFlush() { void DrawEngineVulkan::UpdateUBOs(FrameData *frame) { if ((dirtyUniforms_ & DIRTY_BASE_UNIFORMS) || baseBuf == VK_NULL_HANDLE) { - baseUBOOffset = shaderManager_->PushBaseBuffer(pushUBO, &baseBuf); + baseUBOOffset = shaderManager_->PushBaseBuffer(pushUBO_, &baseBuf); dirtyUniforms_ &= ~DIRTY_BASE_UNIFORMS; } if ((dirtyUniforms_ & DIRTY_LIGHT_UNIFORMS) || lightBuf == VK_NULL_HANDLE) { - lightUBOOffset = shaderManager_->PushLightBuffer(pushUBO, &lightBuf); + lightUBOOffset = shaderManager_->PushLightBuffer(pushUBO_, &lightBuf); dirtyUniforms_ &= ~DIRTY_LIGHT_UNIFORMS; } if ((dirtyUniforms_ & DIRTY_BONE_UNIFORMS) || boneBuf == VK_NULL_HANDLE) { - boneUBOOffset = shaderManager_->PushBoneBuffer(pushUBO, &boneBuf); + boneUBOOffset = shaderManager_->PushBoneBuffer(pushUBO_, &boneBuf); dirtyUniforms_ &= ~DIRTY_BONE_UNIFORMS; } } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 1c209eb38f..4135e04725 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -194,7 +194,7 @@ public: } VulkanPushPool *GetPushBufferForTextureData() { - return pushUBO; + return pushUBO_; } const DrawEngineVulkanStats &GetStats() const { @@ -279,9 +279,11 @@ private: GEPrimitiveType lastPrim_ = GE_PRIM_INVALID; FrameData frame_[VulkanContext::MAX_INFLIGHT_FRAMES]; - VulkanPushPool *pushUBO = nullptr; - VulkanPushPool *pushVertex = nullptr; - VulkanPushPool *pushIndex = nullptr; + // This one's not accurately named, it's used for all kinds of stuff that's not vertices or indices. + VulkanPushPool *pushUBO_ = nullptr; + + VulkanPushPool *pushVertex_ = nullptr; + VulkanPushPool *pushIndex_ = nullptr; // Other ShaderManagerVulkan *shaderManager_ = nullptr; From 87a16b0386719e265731874670a54b2c40e8e72a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 10:19:00 +0100 Subject: [PATCH 339/424] Fix the stats --- Common/GPU/Vulkan/VulkanMemory.cpp | 10 ++++++++++ Common/GPU/Vulkan/VulkanMemory.h | 2 ++ GPU/Vulkan/DrawEngineVulkan.cpp | 5 ++--- GPU/Vulkan/DrawEngineVulkan.h | 1 - GPU/Vulkan/GPU_Vulkan.cpp | 3 +-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index 5c675ec9a2..f679ff63be 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -397,6 +397,16 @@ void VulkanPushPool::NextBlock(VkDeviceSize allocationSize) { DEBUG_LOG(G3D, "%s: Created new block of size %s in %0.2f ms", name_, NiceSizeFormat(newBlockSize).c_str(), 1000.0 * (time_now_d() - start)); } +size_t VulkanPushPool::GetUsedThisFrame() const { + size_t used = 0; + for (auto &block : blocks_) { + if (block.frameIndex == vulkan_->GetCurFrame()) { + used += block.used; + } + } + return used; +} + void VulkanPushPool::GetDebugString(char *buffer, size_t bufSize) const { size_t used = 0; size_t capacity = 0; diff --git a/Common/GPU/Vulkan/VulkanMemory.h b/Common/GPU/Vulkan/VulkanMemory.h index 50b9f35da9..f4d502e138 100644 --- a/Common/GPU/Vulkan/VulkanMemory.h +++ b/Common/GPU/Vulkan/VulkanMemory.h @@ -148,6 +148,8 @@ public: return bindOffset; } + size_t GetUsedThisFrame() const; + private: void NextBlock(VkDeviceSize allocationSize); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 83636e88f5..39c72b27a7 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -354,9 +354,8 @@ void DrawEngineVulkan::BeginFrame() { void DrawEngineVulkan::EndFrame() { FrameData *frame = &GetCurFrame(); - stats_.pushUBOSpaceUsed = 0; // (int)pushUBO->GetOffset(); - stats_.pushVertexSpaceUsed = 0; // (int)frame->pushVertex->GetOffset(); - stats_.pushIndexSpaceUsed = 0; // (int)frame->pushIndex->GetOffset(); + stats_.pushVertexSpaceUsed = (int)pushVertex_->GetUsedThisFrame(); + stats_.pushIndexSpaceUsed = (int)pushIndex_->GetUsedThisFrame(); vertexCache_->End(); } diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 4135e04725..c84ae19602 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -59,7 +59,6 @@ class VulkanPushPool; struct VulkanPipeline; struct DrawEngineVulkanStats { - int pushUBOSpaceUsed; int pushVertexSpaceUsed; int pushIndexSpaceUsed; }; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 0ee619f4db..b8cd310244 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -455,12 +455,11 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { textureCacheVulkan_->GetStats(texStats, sizeof(texStats)); snprintf(buffer, bufsize, "Vertex, Fragment, Pipelines loaded: %i, %i, %i\n" - "Pushbuffer space used: UBO %d, Vtx %d, Idx %d\n" + "Pushbuffer space used: Vtx %d, Idx %d\n" "%s\n", shaderManagerVulkan_->GetNumVertexShaders(), shaderManagerVulkan_->GetNumFragmentShaders(), pipelineManager_->GetNumPipelines(), - drawStats.pushUBOSpaceUsed, drawStats.pushVertexSpaceUsed, drawStats.pushIndexSpaceUsed, texStats From e625727543fe15521b22f9e0763bec4464206969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 12:03:23 +0100 Subject: [PATCH 340/424] Fix debug symbols for ThreadContext by renaming it (was clashing with something else) Also reorder the fields. --- Common/Thread/ThreadManager.cpp | 24 ++++++++++++------------ Common/Thread/ThreadManager.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index 0fc8574091..a43d8ea55e 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -25,25 +25,25 @@ const int MIN_IO_BLOCKING_THREADS = 4; static constexpr size_t TASK_PRIORITY_COUNT = (size_t)TaskPriority::COUNT; struct GlobalThreadContext { - std::mutex mutex; // associated with each respective condition variable + std::mutex mutex; std::deque compute_queue[TASK_PRIORITY_COUNT]; std::atomic compute_queue_size; std::deque io_queue[TASK_PRIORITY_COUNT]; std::atomic io_queue_size; - std::vector threads_; + std::vector threads_; std::atomic roundRobin; }; -struct ThreadContext { +struct TaskThreadContext { + std::atomic queue_size; + std::deque private_queue[TASK_PRIORITY_COUNT]; std::thread thread; // the worker thread std::condition_variable cond; // used to signal new work std::mutex mutex; // protects the local queue. - std::atomic queue_size; int index; TaskType type; std::atomic cancelled; - std::deque private_queue[TASK_PRIORITY_COUNT]; char name[16]; }; @@ -58,7 +58,7 @@ ThreadManager::~ThreadManager() { } void ThreadManager::Teardown() { - for (ThreadContext *&threadCtx : global_->threads_) { + for (TaskThreadContext *&threadCtx : global_->threads_) { threadCtx->cancelled = true; std::unique_lock lock(threadCtx->mutex); threadCtx->cond.notify_one(); @@ -86,7 +86,7 @@ void ThreadManager::Teardown() { continue; } - for (ThreadContext *&threadCtx : global_->threads_) { + for (TaskThreadContext *&threadCtx : global_->threads_) { threadCtx->thread.join(); // TODO: Is it better to just delete these? for (size_t i = 0; i < TASK_PRIORITY_COUNT; ++i) { @@ -128,7 +128,7 @@ bool ThreadManager::TeardownTask(Task *task, bool enqueue) { return false; } -static void WorkerThreadFunc(GlobalThreadContext *global, ThreadContext *thread) { +static void WorkerThreadFunc(GlobalThreadContext *global, TaskThreadContext *thread) { if (thread->type == TaskType::CPU_COMPUTE) { snprintf(thread->name, sizeof(thread->name), "PoolWorker %d", thread->index); } else { @@ -223,7 +223,7 @@ void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) { INFO_LOG(SYSTEM, "ThreadManager::Init(compute threads: %d, all: %d)", numComputeThreads_, numThreads_); for (int i = 0; i < numThreads; i++) { - ThreadContext *thread = new ThreadContext(); + TaskThreadContext *thread = new TaskThreadContext(); thread->cancelled.store(false); thread->type = i < numComputeThreads_ ? TaskType::CPU_COMPUTE : TaskType::IO_BLOCKING; thread->index = i; @@ -261,7 +261,7 @@ void ThreadManager::EnqueueTask(Task *task) { // Find a thread with no outstanding work. _assert_(maxThread <= (int)global_->threads_.size()); for (int threadNum = minThread; threadNum < maxThread; threadNum++) { - ThreadContext *thread = global_->threads_[threadNum]; + TaskThreadContext *thread = global_->threads_[threadNum]; if (thread->queue_size.load() == 0) { std::unique_lock lock(thread->mutex); thread->private_queue[queueIndex].push_back(task); @@ -289,7 +289,7 @@ void ThreadManager::EnqueueTask(Task *task) { int chosenIndex = global_->roundRobin++; chosenIndex = minThread + (chosenIndex % (maxThread - minThread)); - ThreadContext *&chosenThread = global_->threads_[chosenIndex]; + TaskThreadContext *&chosenThread = global_->threads_[chosenIndex]; // Lock the thread to ensure it gets the message. std::unique_lock lock(chosenThread->mutex); @@ -300,7 +300,7 @@ void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task) { _assert_msg_(task->Type() != TaskType::DEDICATED_THREAD, "Dedicated thread tasks can't be put on specific threads"); _assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized"); - ThreadContext *thread = global_->threads_[threadNum]; + TaskThreadContext *thread = global_->threads_[threadNum]; size_t queueIndex = (size_t)task->Priority(); thread->queue_size++; diff --git a/Common/Thread/ThreadManager.h b/Common/Thread/ThreadManager.h index 12ba50c3f2..66d67fcee5 100644 --- a/Common/Thread/ThreadManager.h +++ b/Common/Thread/ThreadManager.h @@ -44,7 +44,7 @@ public: } }; -struct ThreadContext; +struct TaskThreadContext; struct GlobalThreadContext; class ThreadManager { @@ -81,7 +81,7 @@ private: int numThreads_ = 0; int numComputeThreads_ = 0; - friend struct ThreadContext; + friend struct TaskThreadContext; }; extern ThreadManager g_threadManager; From 0fb7ff488e5bd960bf0630bd1f6120963de52f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 14:48:32 +0100 Subject: [PATCH 341/424] Add a convenient define to experiment with parallel copy --- GPU/Common/ReplacedTexture.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 3a9d47e3a4..d183743688 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -682,6 +682,8 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { return false; } +#define PARALLEL_COPY + if (fmt == Draw::DataFormat::R8G8B8A8_UNORM) { if (rowPitch < info.w * 4) { ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); @@ -691,18 +693,32 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { _assert_msg_(data.size() == info.w * info.h * 4, "Data has wrong size"); if (rowPitch == info.w * 4) { +#ifdef PARALLEL_COPY + memcpy(out, data.data(), info.w * 4 * info.h); +#else ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); +#endif } else { +#ifdef PARALLEL_COPY + for (int y = 0; y < info.h; ++y) { + memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); + } +#else const int MIN_LINES_PER_THREAD = 4; ParallelRangeLoop(&g_threadManager, [&](int l, int h) { for (int y = l; y < h; ++y) { memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); } }, 0, info.h, MIN_LINES_PER_THREAD); +#endif } } else { +#ifdef PARALLEL_COPY // TODO: Add sanity checks here for other formats? ParallelMemcpy(&g_threadManager, out, data.data(), data.size()); +#else + memcpy(out, data.data(), data.size()); +#endif } return true; From c45376ddc7a2e49d77b51e5f3181f64cb92f9483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 20:31:27 +0100 Subject: [PATCH 342/424] Typo fix, thanks iota97 --- GPU/Common/ReplacedTexture.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index d183743688..a4afe23827 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -694,22 +694,22 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { if (rowPitch == info.w * 4) { #ifdef PARALLEL_COPY - memcpy(out, data.data(), info.w * 4 * info.h); -#else ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); +#else + memcpy(out, data.data(), info.w * 4 * info.h); #endif } else { #ifdef PARALLEL_COPY - for (int y = 0; y < info.h; ++y) { - memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); - } -#else const int MIN_LINES_PER_THREAD = 4; ParallelRangeLoop(&g_threadManager, [&](int l, int h) { for (int y = l; y < h; ++y) { memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); } }, 0, info.h, MIN_LINES_PER_THREAD); +#else + for (int y = 0; y < info.h; ++y) { + memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); + } #endif } } else { From 1cf4e838246fbd6daec5e2caf9f9a21f8ea4980b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 22:26:23 +0100 Subject: [PATCH 343/424] Show thread name in assert messagebox caption on Windows. Minor cleanup --- Common/Log.cpp | 3 ++- Common/Thread/Channel.h | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Common/Log.cpp b/Common/Log.cpp index d3f7ed9b02..28c2f821d0 100644 --- a/Common/Log.cpp +++ b/Common/Log.cpp @@ -24,6 +24,7 @@ #include "Common/Log.h" #include "StringUtils.h" #include "Common/Data/Encoding/Utf8.h" +#include "Common/Thread/ThreadUtil.h" #if PPSSPP_PLATFORM(ANDROID) #include @@ -71,7 +72,7 @@ bool HandleAssert(const char *function, const char *file, int line, const char * if (!getenv("CI")) { int msgBoxStyle = MB_ICONINFORMATION | MB_YESNO; std::wstring wtext = ConvertUTF8ToWString(formatted) + L"\n\nTry to continue?"; - std::wstring wcaption = ConvertUTF8ToWString(caption); + std::wstring wcaption = ConvertUTF8ToWString(std::string(caption) + " " + GetCurrentThreadName()); OutputDebugString(wtext.c_str()); if (IDYES != MessageBox(0, wtext.c_str(), wcaption.c_str(), msgBoxStyle)) { return false; diff --git a/Common/Thread/Channel.h b/Common/Thread/Channel.h index 82772bb6f4..836290240a 100644 --- a/Common/Thread/Channel.h +++ b/Common/Thread/Channel.h @@ -24,9 +24,7 @@ struct Mailbox { T Wait() { std::unique_lock lock(mutex_); - while (!dataReceived_) { - condvar_.wait(lock); - } + condvar_.wait(lock, [&] {return dataReceived_;}); return data_; } From f0f96750b1793c4b9a7ef05f5e785aac711fb617 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 15 Mar 2023 22:31:24 +0100 Subject: [PATCH 344/424] After picking a task from the global queue, gotta break from the loop. --- Common/Thread/ThreadManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Common/Thread/ThreadManager.cpp b/Common/Thread/ThreadManager.cpp index a43d8ea55e..d6eb76e5ec 100644 --- a/Common/Thread/ThreadManager.cpp +++ b/Common/Thread/ThreadManager.cpp @@ -164,12 +164,14 @@ static void WorkerThreadFunc(GlobalThreadContext *global, TaskThreadContext *thr // We are processing one now, so mark that. thread->queue_size++; + break; } else if (thread->queue_size != 0) { // Check the thread, as we prefer a HIGH thread task to a global NORMAL task. std::unique_lock lock(thread->mutex); if (!thread->private_queue[p].empty()) { task = thread->private_queue[p].front(); thread->private_queue[p].pop_front(); + break; } } } @@ -198,9 +200,9 @@ static void WorkerThreadFunc(GlobalThreadContext *global, TaskThreadContext *thr if (task) { task->Run(); task->Release(); - // Reduce the queue size once complete. thread->queue_size--; + // _dbg_assert_(thread->queue_size == thread->private_queue[0].size() + thread->private_queue[1].size() + thread->private_queue[2].size()); } } From 34926472aa40c3cbe74b21ce318187ee50aee36e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 00:30:20 +0100 Subject: [PATCH 345/424] Log fix --- Common/GPU/Vulkan/VulkanMemory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index f679ff63be..c1d87c0f34 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -158,7 +158,7 @@ void VulkanPushBuffer::GetDebugString(char *buffer, size_t bufSize) const { sum += size_ * (buffers_.size() - 1); sum += offset_; size_t capacity = size_ * buffers_.size(); - snprintf(buffer, bufSize, "Push %s: %s/%s", name_, NiceSizeFormat(capacity).c_str(), NiceSizeFormat(sum).c_str()); + snprintf(buffer, bufSize, "Push %s: %s / %s", name_, NiceSizeFormat(sum).c_str(), NiceSizeFormat(capacity).c_str()); } void VulkanPushBuffer::Map() { From de4eb642982bc27c49c50a8e0ba90ab1d09ee8d6 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 15 Mar 2023 21:28:46 -0700 Subject: [PATCH 346/424] Build: Fix MSVC 2019 again. --- Common/GPU/Vulkan/VulkanMemory.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/GPU/Vulkan/VulkanMemory.cpp b/Common/GPU/Vulkan/VulkanMemory.cpp index f679ff63be..c038f9f160 100644 --- a/Common/GPU/Vulkan/VulkanMemory.cpp +++ b/Common/GPU/Vulkan/VulkanMemory.cpp @@ -18,6 +18,7 @@ // Additionally, Common/Vulkan/* , including this file, are also licensed // under the public domain. +#include #include #include From fa1a4d26dc046e863f5923e8ea85048c0f8ab472 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 15 Mar 2023 21:29:08 -0700 Subject: [PATCH 347/424] Windows: Fix crash dependent on alloc order. Without IR, we don't allocate executable memory, so the first allocation always fails. --- Common/MemoryUtil.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index 28464006a2..5e539e27e8 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -206,11 +206,12 @@ void *AllocateExecutableMemory(size_t size) { } void *AllocateMemoryPages(size_t size, uint32_t memProtFlags) { - size = ppsspp_round_page(size); #ifdef _WIN32 if (sys_info.dwPageSize == 0) GetSystemInfo(&sys_info); uint32_t protect = ConvertProtFlagsWin32(memProtFlags); + // Make sure to do this after GetSystemInfo(). + size = ppsspp_round_page(size); #if PPSSPP_PLATFORM(UWP) void* ptr = VirtualAllocFromApp(0, size, MEM_COMMIT, protect); #else @@ -221,6 +222,7 @@ void *AllocateMemoryPages(size_t size, uint32_t memProtFlags) { return nullptr; } #else + size = ppsspp_round_page(size); uint32_t protect = ConvertProtFlagsUnix(memProtFlags); void *ptr = mmap(0, size, protect, MAP_ANON | MAP_PRIVATE, -1, 0); if (ptr == MAP_FAILED) { From d97790e28e2ac7e4e08d99cbd1148bf3e57872a5 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 15 Mar 2023 21:30:35 -0700 Subject: [PATCH 348/424] irjit: Fix vi2us/vi2s with non-consecutive. Vec2ClampToZero and similar assume consecutive. --- Core/MIPS/IR/IRCompVFPU.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Core/MIPS/IR/IRCompVFPU.cpp b/Core/MIPS/IR/IRCompVFPU.cpp index bfdcf69bed..70128b4c62 100644 --- a/Core/MIPS/IR/IRCompVFPU.cpp +++ b/Core/MIPS/IR/IRCompVFPU.cpp @@ -72,6 +72,10 @@ namespace MIPSComp { regs[3] == regs[2] + 1; } + static bool IsVec2(VectorSize sz, const u8 regs[2]) { + return sz == V_Pair && IsConsecutive2(regs) && (regs[0] & 1) == 0; + } + static bool IsVec4(VectorSize sz, const u8 regs[4]) { return sz == V_Quad && IsConsecutive4(regs) && (regs[0] & 3) == 0; } @@ -1534,10 +1538,10 @@ namespace MIPSComp { int nOut = GetNumVectorElements(outsize); - // If src registers aren't contiguous, make them (mainly for bits == 8.) - if (sz == V_Quad && !IsVec4(sz, sregs)) { + // If src registers aren't contiguous, make them. + if (!IsVec2(sz, sregs) && !IsVec4(sz, sregs)) { // T prefix is unused. - for (int i = 0; i < 4; i++) { + for (int i = 0; i < GetNumVectorElements(sz); i++) { srcregs[i] = IRVTEMP_PFX_T + i; ir.Write(IROp::FMov, srcregs[i], sregs[i]); } From 6bf58274078339aae062899b783dafa5bd3d13c8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 15 Mar 2023 22:02:36 -0700 Subject: [PATCH 349/424] Windows: Fix small atom leak. --- Windows/TouchInputHandler.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Windows/TouchInputHandler.cpp b/Windows/TouchInputHandler.cpp index 63b25934de..56b91c5275 100644 --- a/Windows/TouchInputHandler.cpp +++ b/Windows/TouchInputHandler.cpp @@ -98,24 +98,18 @@ void TouchInputHandler::handleTouchEvent(HWND hWnd, UINT message, WPARAM wParam, // from http://msdn.microsoft.com/en-us/library/ms812373.aspx // disable the press and hold gesture for the given window -void TouchInputHandler::disablePressAndHold(HWND hWnd) -{ +void TouchInputHandler::disablePressAndHold(HWND hWnd) { // The atom identifier and Tablet PC atom - ATOM atomID = 0; LPCTSTR tabletAtom = _T("MicrosoftTabletPenServiceProperty"); - - // Get the Tablet PC atom ID - atomID = GlobalAddAtom(tabletAtom); + ATOM atomID = GlobalAddAtom(tabletAtom); // If getting the ID failed, return false - if (atomID == 0) - { - return; + if (atomID != 0) { + // Try to disable press and hold gesture by setting the window property. + SetProp(hWnd, tabletAtom, (HANDLE)1); } - - // Try to disable press and hold gesture by - // setting the window property, return the result - SetProp(hWnd, tabletAtom, (HANDLE)1); + + GlobalDeleteAtom(atomID); } void TouchInputHandler::touchUp(int id, float x, float y){ From 3fcecfa5ec2d898b5b2393a2aa0e2b2a62f4679b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 15 Mar 2023 22:02:56 -0700 Subject: [PATCH 350/424] Atrac: Ensure codecCtx doesn't leak. Although, I don't think we're reallocating it. --- Core/HLE/sceAtrac.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index dac70d4b27..bf16281139 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1853,6 +1853,11 @@ int __AtracSetContext(Atrac *atrac) { return hleReportError(ME, ATRAC_ERROR_UNKNOWN_FORMAT, "unknown codec type in set context"); } + if (atrac->codecCtx_) { + // Shouldn't happen, but just in case. + atrac->ReleaseFFMPEGContext(); + } + const AVCodec *codec = avcodec_find_decoder(ff_codec); atrac->codecCtx_ = avcodec_alloc_context3(codec); From 41d561895b83a9dd658def56fa4ecaa60ad2389d Mon Sep 17 00:00:00 2001 From: haoruiwang <1905811497@qq.com> Date: Thu, 16 Mar 2023 15:07:24 +0800 Subject: [PATCH 351/424] [what][style][gpu] some coding style refine [how] 1. use comment instead of unnecessary logic comparison 2. remove some useless code 3. move some implemention code from header to source 4. some more assert --- Common/GPU/OpenGL/GLQueueRunner.cpp | 43 ++++++++++++----------------- Common/GPU/OpenGL/GLQueueRunner.h | 8 ------ 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/Common/GPU/OpenGL/GLQueueRunner.cpp b/Common/GPU/OpenGL/GLQueueRunner.cpp index 434bb5c1a9..097ecdc2c4 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.cpp +++ b/Common/GPU/OpenGL/GLQueueRunner.cpp @@ -109,14 +109,14 @@ static std::string GetInfoLog(GLuint name, Getiv getiv, GetLog getLog) { return infoLog; } -int GLQueueRunner::GetStereoBufferIndex(const char *uniformName) { +static int GetStereoBufferIndex(const char *uniformName) { if (!uniformName) return -1; else if (strcmp(uniformName, "u_view") == 0) return 0; else if (strcmp(uniformName, "u_proj_lens") == 0) return 1; else return -1; } -std::string GLQueueRunner::GetStereoBufferLayout(const char *uniformName) { +static std::string GetStereoBufferLayout(const char *uniformName) { if (strcmp(uniformName, "u_view") == 0) return "ViewMatrices"; else if (strcmp(uniformName, "u_proj_lens") == 0) return "ProjectionMatrix"; else return "undefined"; @@ -753,11 +753,6 @@ void GLQueueRunner::RunSteps(const std::vector &steps, bool skipGLCal CHECK_GL_ERROR_IF_DEBUG(); } -void GLQueueRunner::LogSteps(const std::vector &steps) { - -} - - void GLQueueRunner::PerformBlit(const GLRStep &step) { CHECK_GL_ERROR_IF_DEBUG(); // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing @@ -854,7 +849,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last glDepthFunc(c.depth.func); depthFunc = c.depth.func; } - } else if (!c.depth.enabled && depthEnabled) { + } else if (/* !c.depth.enabled && */ depthEnabled) { glDisable(GL_DEPTH_TEST); depthEnabled = false; } @@ -866,7 +861,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last stencilEnabled = true; } glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask); - } else if (stencilEnabled) { + } else if (/* !c.stencilFunc.enabled && */stencilEnabled) { glDisable(GL_STENCIL_TEST); stencilEnabled = false; } @@ -888,7 +883,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last blendEqAlpha = c.blend.funcAlpha; } glBlendFuncSeparate(c.blend.srcColor, c.blend.dstColor, c.blend.srcAlpha, c.blend.dstAlpha); - } else if (!c.blend.enabled && blendEnabled) { + } else if (/* !c.blend.enabled && */ blendEnabled) { glDisable(GL_BLEND); blendEnabled = false; } @@ -908,7 +903,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last if (logicOp != c.logic.logicOp) { glLogicOp(c.logic.logicOp); } - } else if (!c.logic.enabled && logicEnabled) { + } else if (/* !c.logic.enabled && */ logicEnabled) { glDisable(GL_COLOR_LOGIC_OP); logicEnabled = false; } @@ -989,24 +984,18 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last } case GLRRenderCommand::UNIFORM4F: { + _dbg_assert_(curProgram); int loc = c.uniform4.loc ? *c.uniform4.loc : -1; if (c.uniform4.name) { loc = curProgram->GetUniformLoc(c.uniform4.name); } if (loc >= 0) { + _dbg_assert_(c.uniform4.count >=1 && c.uniform4.count <=4); switch (c.uniform4.count) { - case 1: - glUniform1f(loc, c.uniform4.v[0]); - break; - case 2: - glUniform2fv(loc, 1, c.uniform4.v); - break; - case 3: - glUniform3fv(loc, 1, c.uniform4.v); - break; - case 4: - glUniform4fv(loc, 1, c.uniform4.v); - break; + case 1: glUniform1f(loc, c.uniform4.v[0]); break; + case 2: glUniform2fv(loc, 1, c.uniform4.v); break; + case 3: glUniform3fv(loc, 1, c.uniform4.v); break; + case 4: glUniform4fv(loc, 1, c.uniform4.v); break; } } CHECK_GL_ERROR_IF_DEBUG(); @@ -1020,6 +1009,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last loc = curProgram->GetUniformLoc(c.uniform4.name); } if (loc >= 0) { + _dbg_assert_(c.uniform4.count >=1 && c.uniform4.count <=4); switch (c.uniform4.count) { case 1: glUniform1uiv(loc, 1, (GLuint *)c.uniform4.v); break; case 2: glUniform2uiv(loc, 1, (GLuint *)c.uniform4.v); break; @@ -1038,6 +1028,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last loc = curProgram->GetUniformLoc(c.uniform4.name); } if (loc >= 0) { + _dbg_assert_(c.uniform4.count >=1 && c.uniform4.count <=4); switch (c.uniform4.count) { case 1: glUniform1iv(loc, 1, (GLint *)c.uniform4.v); break; case 2: glUniform2iv(loc, 1, (GLint *)c.uniform4.v); break; @@ -1331,7 +1322,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last } glFrontFace(c.raster.frontFace); glCullFace(c.raster.cullFace); - } else if (!c.raster.cullEnable && cullEnabled) { + } else if (/* !c.raster.cullEnable && */ cullEnabled) { glDisable(GL_CULL_FACE); cullEnabled = false; } @@ -1340,7 +1331,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last glEnable(GL_DITHER); ditherEnabled = true; } - } else if (!c.raster.ditherEnable && ditherEnabled) { + } else if (/* !c.raster.ditherEnable && */ ditherEnabled) { glDisable(GL_DITHER); ditherEnabled = false; } @@ -1350,7 +1341,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last glEnable(GL_DEPTH_CLAMP); depthClampEnabled = true; } - } else if (!c.raster.depthClampEnable && depthClampEnabled) { + } else if (/* !c.raster.depthClampEnable && */ depthClampEnabled) { glDisable(GL_DEPTH_CLAMP); depthClampEnabled = false; } diff --git a/Common/GPU/OpenGL/GLQueueRunner.h b/Common/GPU/OpenGL/GLQueueRunner.h index 9ef6614bfc..f51f8e9999 100644 --- a/Common/GPU/OpenGL/GLQueueRunner.h +++ b/Common/GPU/OpenGL/GLQueueRunner.h @@ -359,21 +359,13 @@ public: caps_ = caps; } - int GetStereoBufferIndex(const char *uniformName); - std::string GetStereoBufferLayout(const char *uniformName); - void RunInitSteps(const std::vector &steps, bool skipGLCalls); void RunSteps(const std::vector &steps, bool skipGLCalls, bool keepSteps, bool useVR); - void LogSteps(const std::vector &steps); void CreateDeviceObjects(); void DestroyDeviceObjects(); - inline int RPIndex(GLRRenderPassAction color, GLRRenderPassAction depth) { - return (int)depth * 3 + (int)color; - } - void CopyFromReadbackBuffer(GLRFramebuffer *framebuffer, int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels); void Resize(int width, int height) { From c58ceb516092c60074a02852479609daefa95a6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 09:55:49 +0100 Subject: [PATCH 352/424] Mini refactor: Separate input and output arguments for LookupHashRange --- GPU/Common/TextureReplacer.cpp | 22 ++++++++++++---------- GPU/Common/TextureReplacer.h | 6 ++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 429c3aeb67..2dbfe03053 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -395,7 +395,7 @@ void TextureReplacer::ParseReduceHashRange(const std::string& key, const std::st u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV) { _dbg_assert_msg_(enabled_, "Replacement not enabled"); - if (!LookupHashRange(addr, w, h)) { + if (!LookupHashRange(addr, w, h, &w, &h)) { // There wasn't any hash range, let's fall back to maxSeenV logic. if (h == 512 && maxSeenV < 512 && maxSeenV != 0) { h = (int)maxSeenV; @@ -502,7 +502,7 @@ void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey desc->hash = hash; desc->basePath = basePath_; desc->formatSupport = formatSupport_; - LookupHashRange(cachekey >> 32, desc->newW, desc->newH); + LookupHashRange(cachekey >> 32, w, h, &desc->newW, &desc->newH); if (ignoreAddress_) { cachekey = cachekey & 0xFFFFFFFFULL; @@ -675,9 +675,9 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl } // Only save the hashed portion of the PNG. - int lookupW = w / replacedInfo.scaleFactor; - int lookupH = h / replacedInfo.scaleFactor; - if (LookupHashRange(replacedInfo.addr, lookupW, lookupH)) { + int lookupW; + int lookupH; + if (LookupHashRange(replacedInfo.addr, w / replacedInfo.scaleFactor, h / replacedInfo.scaleFactor, &lookupW, &lookupH)) { w = lookupW * replacedInfo.scaleFactor; h = lookupH * replacedInfo.scaleFactor; } @@ -852,17 +852,19 @@ std::string TextureReplacer::HashName(u64 cachekey, u32 hash, int level) { return hashname; } -bool TextureReplacer::LookupHashRange(u32 addr, int &w, int &h) { +bool TextureReplacer::LookupHashRange(u32 addr, int w, int h, int *newW, int *newH) { const u64 rangeKey = ((u64)addr << 32) | ((u64)w << 16) | h; auto range = hashranges_.find(rangeKey); if (range != hashranges_.end()) { const WidthHeightPair &wh = range->second; - w = wh.first; - h = wh.second; + *newW = wh.first; + *newH = wh.second; return true; + } else { + *newW = w; + *newH = h; + return false; } - - return false; } float TextureReplacer::LookupReduceHashRange(int& w, int& h) { diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 5fecf5020f..e85e3e5901 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -131,7 +131,7 @@ protected: void ParseHashRange(const std::string &key, const std::string &value); void ParseFiltering(const std::string &key, const std::string &value); void ParseReduceHashRange(const std::string& key, const std::string& value); - bool LookupHashRange(u32 addr, int &w, int &h); + bool LookupHashRange(u32 addr, int w, int h, int *newW, int *newH); float LookupReduceHashRange(int& w, int& h); std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored); void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); @@ -157,12 +157,14 @@ protected: typedef std::pair WidthHeightPair; std::unordered_map hashranges_; std::unordered_map reducehashranges_; + std::unordered_map aliases_; std::unordered_map filtering_; std::unordered_map cache_; std::unordered_map savedCache_; - // the key is from aliases_. It's a |-separated sequence of texture filenames of the levels of a texture. + // the key is either from aliases_, in which case it's a |-separated sequence of texture filenames of the levels of a texture. + // alternatively the key is from the generated texture filename. std::unordered_map levelCache_; }; From f2a5a5abe7620fcad0c524ffbf87ab8442cd4919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 10:14:41 +0100 Subject: [PATCH 353/424] Avoid input/output arguments in the texture scaler too --- GPU/Common/TextureCacheCommon.cpp | 2 +- GPU/Common/TextureScalerCommon.cpp | 28 +++++++++++++++------------- GPU/Common/TextureScalerCommon.h | 6 +++--- GPU/Vulkan/TextureCacheVulkan.cpp | 2 +- 4 files changed, 20 insertions(+), 18 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 70d8682d38..09fc10023e 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2924,7 +2924,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i if (plan.scaleFactor > 1) { // Note that this updates w and h! - scaler_.ScaleAlways((u32 *)data, pixelData, w, h, plan.scaleFactor); + scaler_.ScaleAlways((u32 *)data, pixelData, w, h, &w, &h, plan.scaleFactor); pixelData = (u32 *)data; decPitch = w * 4; diff --git a/GPU/Common/TextureScalerCommon.cpp b/GPU/Common/TextureScalerCommon.cpp index a2662a4c04..40e686bdde 100644 --- a/GPU/Common/TextureScalerCommon.cpp +++ b/GPU/Common/TextureScalerCommon.cpp @@ -605,29 +605,31 @@ bool TextureScalerCommon::IsEmptyOrFlat(const u32 *data, int pixels) const { return true; } -void TextureScalerCommon::ScaleAlways(u32 *out, u32 *src, int &width, int &height, int factor) { +void TextureScalerCommon::ScaleAlways(u32 *out, u32 *src, int width, int height, int *scaledWidth, int *scaledHeight, int factor) { if (IsEmptyOrFlat(src, width * height)) { // This means it was a flat texture. Vulkan wants the size up front, so we need to make it happen. u32 pixel = *src; - width *= factor; - height *= factor; + *scaledWidth = width * factor; + *scaledHeight = height * factor; + + size_t pixelCount = *scaledWidth * *scaledHeight; // ABCD. If A = D, and AB = CD, then they must all be equal (B = C, etc.) if ((pixel & 0x000000FF) == (pixel >> 24) && (pixel & 0x0000FFFF) == (pixel >> 16)) { - memset(out, pixel & 0xFF, width * height * sizeof(u32)); + memset(out, pixel & 0xFF, pixelCount * sizeof(u32)); } else { // Let's hope this is vectorized. - for (int i = 0; i < width * height; ++i) { + for (int i = 0; i < pixelCount; ++i) { out[i] = pixel; } } } else { - ScaleInto(out, src, width, height, factor); + ScaleInto(out, src, width, height, scaledWidth, scaledHeight, factor); } } -bool TextureScalerCommon::ScaleInto(u32 *outputBuf, u32 *src, int &width, int &height, int factor) { +bool TextureScalerCommon::ScaleInto(u32 *outputBuf, u32 *src, int width, int height, int *scaledWidth, int *scaledHeight, int factor) { #ifdef SCALING_MEASURE_TIME double t_start = time_now_d(); #endif @@ -660,21 +662,21 @@ bool TextureScalerCommon::ScaleInto(u32 *outputBuf, u32 *src, int &width, int &h } // update values accordingly - width *= factor; - height *= factor; + *scaledWidth = width * factor; + *scaledHeight = height * factor; #ifdef SCALING_MEASURE_TIME - if (width*height > 64 * 64 * factor*factor) { + if (*scaledWidth* *scaledHeight > 64 * 64 * factor*factor) { double t = time_now_d() - t_start; NOTICE_LOG(G3D, "TextureScaler: processed %9d pixels in %6.5lf seconds. (%9.2lf Mpixels/second)", - width*height, t, (width*height) / (t * 1000 * 1000)); + *scaledWidth * *scaledHeight, t, (*scaledWidth * *scaledHeight) / (t * 1000 * 1000)); } #endif return true; } -bool TextureScalerCommon::Scale(u32* &data, int &width, int &height, int factor) { +bool TextureScalerCommon::Scale(u32* &data, int width, int height, int *scaledWidth, int *scaledHeight, int factor) { // prevent processing empty or flat textures (this happens a lot in some games) // doesn't hurt the standard case, will be very quick for textures with actual texture if (IsEmptyOrFlat(data, width*height)) { @@ -685,7 +687,7 @@ bool TextureScalerCommon::Scale(u32* &data, int &width, int &height, int factor) bufOutput.resize(width * height * (factor * factor)); // used to store the upscaled image u32 *outputBuf = bufOutput.data(); - if (ScaleInto(outputBuf, data, width, height, factor)) { + if (ScaleInto(outputBuf, data, width, height, scaledWidth, scaledHeight, factor)) { data = outputBuf; return true; } diff --git a/GPU/Common/TextureScalerCommon.h b/GPU/Common/TextureScalerCommon.h index ee5b2f550c..a01457ae43 100644 --- a/GPU/Common/TextureScalerCommon.h +++ b/GPU/Common/TextureScalerCommon.h @@ -30,9 +30,9 @@ public: TextureScalerCommon(); ~TextureScalerCommon(); - void ScaleAlways(u32 *out, u32 *src, int &width, int &height, int factor); - bool Scale(u32 *&data, int &width, int &height, int factor); - bool ScaleInto(u32 *out, u32 *src, int &width, int &height, int factor); + void ScaleAlways(u32 *out, u32 *src, int width, int height, int *scaledWidth, int *scaledHeight, int factor); + bool Scale(u32 *&data, int width, int height, int *scaledWidth, int *scaledHeight, int factor); + bool ScaleInto(u32 *out, u32 *src, int width, int height, int *scaledWidth, int *scaledHeight, int factor); enum { XBRZ = 0, HYBRID = 1, BICUBIC = 2, HYBRID_BICUBIC = 3 }; diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index a08f231cd5..425905dd8f 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -754,7 +754,7 @@ void TextureCacheVulkan::LoadVulkanTextureLevel(TexCacheEntry &entry, uint8_t *w u32 fmt = dstFmt; // CPU scaling reads from the destination buffer so we want cached RAM. uint8_t *rearrange = (uint8_t *)AllocateAlignedMemory(w * scaleFactor * h * scaleFactor * 4, 16); - scaler_.ScaleAlways((u32 *)rearrange, pixelData, w, h, scaleFactor); + scaler_.ScaleAlways((u32 *)rearrange, pixelData, w, h, &w, &h, scaleFactor); pixelData = (u32 *)writePtr; // We always end up at 8888. Other parts assume this. From cf6cce0744a351af81d5355359214fbce042aa2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 10:21:57 +0100 Subject: [PATCH 354/424] Remove scaleFactor from struct ReplacedTextureDecodeInfo, instead pass in both unscaled and scaled dimensions --- GPU/Common/TextureCacheCommon.cpp | 15 +++++++-------- GPU/Common/TextureReplacer.cpp | 24 +++++++++++------------- GPU/Common/TextureReplacer.h | 5 ++--- GPU/Vulkan/TextureCacheVulkan.cpp | 4 +--- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 09fc10023e..02c8016fdc 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2847,7 +2847,6 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt replacedInfo.hash = entry->fullhash; replacedInfo.addr = entry->addr; replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; - replacedInfo.scaleFactor = plan.scaleFactor; replacedInfo.isVideo = plan.isVideo; replacedInfo.fmt = Draw::DataFormat::R8G8B8A8_UNORM; plan.saveTexture = replacer_.WillSave(replacedInfo); @@ -2899,7 +2898,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i GETextureFormat tfmt = (GETextureFormat)entry.format; GEPaletteFormat clutformat = gstate.getClutPaletteFormat(); u32 texaddr = gstate.getTextureAddress(srcLevel); - int bufw = GetTextureBufw(srcLevel, texaddr, tfmt); + const int bufw = GetTextureBufw(srcLevel, texaddr, tfmt); u32 *pixelData; int decPitch; if (plan.scaleFactor > 1) { @@ -2922,19 +2921,20 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i CheckAlphaResult alphaResult = DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, srcLevel, bufw, texDecFlags); entry.SetAlphaStatus(alphaResult, srcLevel); + int scaledW = w, scaledH = h; if (plan.scaleFactor > 1) { // Note that this updates w and h! - scaler_.ScaleAlways((u32 *)data, pixelData, w, h, &w, &h, plan.scaleFactor); + scaler_.ScaleAlways((u32 *)data, pixelData, w, h, &scaledW, &scaledH, plan.scaleFactor); pixelData = (u32 *)data; - decPitch = w * 4; + decPitch = scaledW * sizeof(u32); if (decPitch != stride) { // Rearrange in place to match the requested pitch. // (it can only be larger than w * bpp, and a match is likely.) // Note! This is bad because it reads the mapped memory! TODO: Look into if DX9 does this right. - for (int y = h - 1; y >= 0; --y) { - memcpy((u8 *)data + stride * y, (u8 *)data + decPitch * y, w * 4); + for (int y = scaledH - 1; y >= 0; --y) { + memcpy((u8 *)data + stride * y, (u8 *)data + decPitch * y, scaledW *4); } decPitch = stride; } @@ -2947,11 +2947,10 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i replacedInfo.addr = entry.addr; replacedInfo.isVideo = IsVideo(entry.addr); replacedInfo.isFinal = (entry.status & TexCacheEntry::STATUS_TO_SCALE) == 0; - replacedInfo.scaleFactor = plan.scaleFactor; replacedInfo.fmt = dstFmt; // NOTE: Reading the decoded texture here may be very slow, if we just wrote it to write-combined memory. - replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h); + replacer_.NotifyTextureDecoded(replacedInfo, pixelData, decPitch, srcLevel, w, h, scaledW, scaledH); } } } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 2dbfe03053..446ebe6d27 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -631,7 +631,7 @@ bool TextureReplacer::WillSave(const ReplacedTextureDecodeInfo &replacedInfo) { return true; } -void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h) { +void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int origW, int origH, int scaledW, int scaledH) { _assert_msg_(enabled_, "Replacement not enabled"); if (!WillSave(replacedInfo)) { // Ignore. @@ -663,23 +663,21 @@ void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &repl bool skipIfExists = false; double now = time_now_d(); if (it != savedCache_.end()) { - // We've already saved this texture. Let's only save if it's bigger (e.g. scaled now.) - // This check isn't backwards, it's just to check if we should *skip* saving, a bit confusing. - if (it->second.levelW[level] >= w && it->second.levelH[level] >= h) { - // If it's been more than 5 seconds, we'll check again. Maybe they deleted. - double age = now - it->second.lastTimeSaved; - if (age < 5.0) - return; - skipIfExists = true; - } + // We've already saved this texture. Ignore it. + // We don't really care about changing the scale factor during runtime, only confusing. + return; } + // Width/height of the image to save. + int w = scaledW; + int h = scaledH; + // Only save the hashed portion of the PNG. int lookupW; int lookupH; - if (LookupHashRange(replacedInfo.addr, w / replacedInfo.scaleFactor, h / replacedInfo.scaleFactor, &lookupW, &lookupH)) { - w = lookupW * replacedInfo.scaleFactor; - h = lookupH * replacedInfo.scaleFactor; + if (LookupHashRange(replacedInfo.addr, origW, origH, &lookupW, &lookupH)) { + w = lookupW * (scaledW / origW); + h = lookupH * (scaledH / origH); } std::vector saveBuf; diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index e85e3e5901..e73a35150c 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -81,7 +81,6 @@ struct ReplacedTextureDecodeInfo { u32 addr; bool isVideo; bool isFinal; - int scaleFactor; Draw::DataFormat fmt; }; @@ -112,8 +111,8 @@ public: // Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.) bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo); - // Notify that a new texture was decoded. May already be upscaled, saves the data passed. - void NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h); + // Notify that a new texture was decoded. May already be upscaled, saves the data passed. + void NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int origW, int origH, int scaledW, int scaledH); void Decimate(ReplacerDecimateMode mode); diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 425905dd8f..61b8033daa 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -647,10 +647,8 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { replacedInfo.addr = entry->addr; replacedInfo.isVideo = IsVideo(entry->addr); replacedInfo.isFinal = (entry->status & TexCacheEntry::STATUS_TO_SCALE) == 0; - replacedInfo.scaleFactor = plan.scaleFactor; replacedInfo.fmt = FromVulkanFormat(actualFmt); - - replacer_.NotifyTextureDecoded(replacedInfo, data, byteStride, plan.baseLevelSrc + i, w, h); + replacer_.NotifyTextureDecoded(replacedInfo, data, byteStride, plan.baseLevelSrc + i, mipUnscaledWidth, mipUnscaledHeight, w, h); } } } From 35f46ec161410d3d89d9d070f0f8bb9be27b2347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 11:44:38 +0100 Subject: [PATCH 355/424] Rework the replacement cache. No more duplicate ReplacedTexture objects. --- GPU/Common/ReplacedTexture.cpp | 103 ++++++++++++--------------- GPU/Common/ReplacedTexture.h | 62 ++++++++++------- GPU/Common/TextureCacheCommon.cpp | 4 +- GPU/Common/TextureReplacer.cpp | 112 +++++++++++++++--------------- GPU/Common/TextureReplacer.h | 7 +- 5 files changed, 140 insertions(+), 148 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index a4afe23827..fc5c1cde43 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -93,11 +93,18 @@ private: LimitedWaitable *waitable_; }; +ReplacedTexture::ReplacedTexture(VFSBackend *vfs, const ReplacementDesc &desc) : vfs_(vfs), desc_(desc) { + logId_ = desc.logId; + SetState(ReplacementState::POPULATED); + + // TODO: What used to be here is now done on the thread task. +} + ReplacedTexture::~ReplacedTexture() { if (threadWaitable_) { SetState(ReplacementState::CANCEL_INIT); - std::unique_lock lock(mutex_); + std::unique_lock lock(lock_); threadWaitable_->WaitAndRelease(); threadWaitable_ = nullptr; } @@ -114,10 +121,10 @@ void ReplacedTexture::PurgeIfOlder(double t) { if (lastUsed_ >= t) return; - if (levelData_ && levelData_->lastUsed < t) { + std::lock_guard guard(lock_); + if (data_.size() && lastUsed < t) { // We have to lock since multiple textures might reference this same data. - std::lock_guard guard(levelData_->lock); - levelData_->data.clear(); + data_.clear(); // This means we have to reload. If we never purge any, there's no need. SetState(ReplacementState::POPULATED); } @@ -140,9 +147,7 @@ bool ReplacedTexture::IsReady(double budget) { // Successfully waited! Can get rid of it. threadWaitable_->WaitAndRelease(); threadWaitable_ = nullptr; - if (levelData_) { - levelData_->lastUsed = now; - } + lastUsed = now; } lastUsed_ = now; return true; @@ -176,43 +181,29 @@ bool ReplacedTexture::IsReady(double budget) { return false; } -void ReplacedTexture::FinishPopulate(ReplacementDesc *desc) { - logId_ = desc->logId; - levelData_ = desc->cache; - desc_ = desc; - SetState(ReplacementState::POPULATED); - - // TODO: What used to be here is now done on the thread task. -} - void ReplacedTexture::Prepare(VFSBackend *vfs) { this->vfs_ = vfs; - std::unique_lock lock(mutex_); - - _assert_msg_(levelData_ != nullptr, "Level cache not set"); - - // We must lock around access to levelData_ in case two textures try to load it at once. - std::lock_guard guard(levelData_->lock); + std::unique_lock lock(lock_); fmt = Draw::DataFormat::UNDEFINED; Draw::DataFormat pixelFormat; LoadLevelResult result = LoadLevelResult::LOAD_ERROR; - if (desc_->filenames.empty()) { + if (desc_.filenames.empty()) { result = LoadLevelResult::DONE; } - for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_->filenames.size()); ++i) { + for (int i = 0; i < std::min(MAX_REPLACEMENT_MIP_LEVELS, (int)desc_.filenames.size()); ++i) { if (State() == ReplacementState::CANCEL_INIT) { break; } - if (desc_->filenames[i].empty()) { + if (desc_.filenames[i].empty()) { // Out of valid mip levels. Bail out. break; } - VFSFileReference *fileRef = vfs_->GetFile(desc_->filenames[i].c_str()); + VFSFileReference *fileRef = vfs_->GetFile(desc_.filenames[i].c_str()); if (!fileRef) { // If the file doesn't exist, let's just bail immediately here. // Mark as DONE, not error. @@ -224,7 +215,7 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { fmt = Draw::DataFormat::R8G8B8A8_UNORM; } - result = LoadLevelData(fileRef, desc_->filenames[i], i, &pixelFormat); + result = LoadLevelData(fileRef, desc_.filenames[i], i, &pixelFormat); if (result == LoadLevelResult::DONE) { // Loaded all the levels we're gonna get. fmt = pixelFormat; @@ -246,23 +237,17 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { if (levels_.empty()) { // No replacement found. - std::string name = TextureReplacer::HashName(desc_->cachekey, desc_->hash, 0); + std::string name = TextureReplacer::HashName(desc_.cachekey, desc_.hash, 0); if (result == LoadLevelResult::LOAD_ERROR) { WARN_LOG(G3D, "Failed to load replacement texture '%s'", name.c_str()); } SetState(ReplacementState::NOT_FOUND); - levelData_ = nullptr; - delete desc_; - desc_ = nullptr; return; } - levelData_->fmt = fmt; + fmt = fmt; SetState(ReplacementState::ACTIVE); - delete desc_; - desc_ = nullptr; - if (threadWaitable_) threadWaitable_->Notify(); } @@ -275,8 +260,8 @@ inline uint32_t RoundUpTo4(uint32_t value) { ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int mipLevel, Draw::DataFormat *pixelFormat) { bool good = false; - if (levelData_->data.size() <= mipLevel) { - levelData_->data.resize(mipLevel + 1); + if (data_.size() <= mipLevel) { + data_.resize(mipLevel + 1); } ReplacedTextureLevel level; @@ -325,7 +310,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference switch (format) { case 98: // DXGI_FORMAT_BC7_UNORM: case 99: // DXGI_FORMAT_BC7_UNORM_SRGB: - if (!desc_->formatSupport.bc7) { + if (!desc_.formatSupport.bc7) { WARN_LOG(G3D, "BC1-3 formats not supported, skipping texture"); good = false; } @@ -336,7 +321,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference good = false; } } else { - if (!desc_->formatSupport.bc123) { + if (!desc_.formatSupport.bc123) { WARN_LOG(G3D, "BC1-3 formats not supported"); good = false; } @@ -397,15 +382,15 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. - if (!levelData_->data[mipLevel].empty()) { + if (!data_[mipLevel].empty()) { vfs_->CloseFile(openFile); - *pixelFormat = levelData_->fmt; + *pixelFormat = fmt; return LoadLevelResult::DONE; } // Is this really the right place to do it? - level.w = (level.w * desc_->w) / desc_->newW; - level.h = (level.h * desc_->h) / desc_->newH; + level.w = (level.w * desc_.w) / desc_.newW; + level.h = (level.h * desc_.h) / desc_.newH; if (good && mipLevel != 0) { // Check that the mipmap size is correct. Can't load mips of the wrong size. @@ -448,10 +433,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference // We only support opaque colors with this compression method. alphaStatus_ = ReplacedTextureAlpha::FULL; // Let's pick a suitable compatible format. - if (desc_->formatSupport.bc123) { + if (desc_.formatSupport.bc123) { transcoderFormat = basist::transcoder_texture_format::cTFBC1; *pixelFormat = Draw::DataFormat::BC1_RGBA_UNORM_BLOCK; - } else if (desc_->formatSupport.etc2) { + } else if (desc_.formatSupport.etc2) { transcoderFormat = basist::transcoder_texture_format::cTFETC1_RGB; *pixelFormat = Draw::DataFormat::ETC2_R8G8B8_UNORM_BLOCK; } else { @@ -464,10 +449,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference // TODO: Try to recover some indication of alpha from the actual data blocks. alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; // Let's pick a suitable compatible format. - if (desc_->formatSupport.bc7) { + if (desc_.formatSupport.bc7) { transcoderFormat = basist::transcoder_texture_format::cTFBC7_RGBA; *pixelFormat = Draw::DataFormat::BC7_UNORM_BLOCK; - } else if (desc_->formatSupport.astc) { + } else if (desc_.formatSupport.astc) { transcoderFormat = basist::transcoder_texture_format::cTFASTC_4x4_RGBA; *pixelFormat = Draw::DataFormat::ASTC_4x4_UNORM_BLOCK; } else { @@ -486,13 +471,13 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc || *pixelFormat == Draw::DataFormat::R8G8B8A8_UNORM); - levelData_->data.resize(numMips); + data_.resize(numMips); basist::ktx2_transcoder_state transcodeState; // Each thread needs one of these. transcoder.start_transcoding(); for (int i = 0; i < numMips; i++) { - std::vector &out = levelData_->data[mipLevel + i]; + std::vector &out = data_[mipLevel + i]; basist::ktx2_image_level_info levelInfo; bool result = transcoder.get_image_level_info(levelInfo, i, 0, 0); @@ -507,7 +492,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference outputSize = levelInfo.m_orig_width * levelInfo.m_orig_height; outputPitch = levelInfo.m_orig_width; } - levelData_->data[i].resize(dataSizeBytes); + data_[i].resize(dataSizeBytes); transcoder.transcode_image_level(i, 0, 0, &out[0], (uint32_t)outputSize, transcoderFormat, 0, (uint32_t)outputPitch, level.h, -1, -1, &transcodeState); level.w = levelInfo.m_orig_width; @@ -535,11 +520,11 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc); - levelData_->data.resize(numMips); + data_.resize(numMips); // A DDS File can contain multiple mipmaps. for (int i = 0; i < numMips; i++) { - std::vector &out = levelData_->data[mipLevel + i]; + std::vector &out = data_[mipLevel + i]; int bytesToRead = RoundUpTo4(level.w) * RoundUpTo4(level.h) * blockSize / 16; out.resize(bytesToRead); @@ -574,7 +559,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference int w, h, f; uint8_t *image; - std::vector &out = levelData_->data[mipLevel]; + std::vector &out = data_[mipLevel]; // TODO: Zim files can actually hold mipmaps (although no tool has ever been made to create them :P) if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > level.w || h > level.h) { @@ -633,7 +618,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } png.format = PNG_FORMAT_RGBA; - std::vector &out = levelData_->data[mipLevel]; + std::vector &out = data_[mipLevel]; out.resize(level.w * level.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); @@ -672,10 +657,10 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { } // We probably could avoid this lock, but better to play it safe. - std::lock_guard guard(levelData_->lock); + std::lock_guard guard(lock_); const ReplacedTextureLevel &info = levels_[level]; - const std::vector &data = levelData_->data[level]; + const std::vector &data = data_[level]; if (data.empty()) { WARN_LOG(G3D, "Level %d is empty", level); @@ -694,7 +679,7 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { if (rowPitch == info.w * 4) { #ifdef PARALLEL_COPY - ParallelMemcpy(&g_threadManager, out, &data[0], info.w * 4 * info.h); + ParallelMemcpy(&g_threadManager, out, data.data(), info.w * 4 * info.h); #else memcpy(out, data.data(), info.w * 4 * info.h); #endif @@ -703,12 +688,12 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { const int MIN_LINES_PER_THREAD = 4; ParallelRangeLoop(&g_threadManager, [&](int l, int h) { for (int y = l; y < h; ++y) { - memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); + memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4); } }, 0, info.h, MIN_LINES_PER_THREAD); #else for (int y = 0; y < info.h; ++y) { - memcpy((uint8_t *)out + rowPitch * y, &data[0] + info.w * 4 * y, info.w * 4); + memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4); } #endif } diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 713d2c010f..138494594c 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -24,7 +24,6 @@ #include "Common/GPU/thin3d.h" #include "Common/Log.h" -struct ReplacedLevelsCache; class TextureReplacer; class LimitedWaitable; @@ -52,16 +51,6 @@ enum class ReplacedImageType { static const int MAX_REPLACEMENT_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP. -// Metadata about a given texture level. -struct ReplacedTextureLevel { - int w = 0; - int h = 0; - - // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. - // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. - VFSFileReference *fileRef = nullptr; -}; - enum class ReplacementState : uint32_t { UNINITIALIZED, POPULATED, // We located the texture files but have not started the thread. @@ -89,23 +78,33 @@ struct ReplacementDesc { int h; std::string hashfiles; Path basePath; - bool foundAlias; std::vector filenames; std::string logId; - ReplacedLevelsCache *cache; GPUFormatSupport formatSupport; }; -struct ReplacedLevelsCache { - Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; - std::mutex lock; - std::vector> data; - double lastUsed = 0.0; -}; +class ReplacedTexture; // These aren't actually all replaced, they can also represent a placeholder for a not-found -// replacement (state_ == NOT_FOUND). -struct ReplacedTexture { +// replacement (texture == nullptr). +struct ReplacedTextureRef { + ReplacedTexture *texture; // shortcut + std::string hashfiles; // key into the cache +}; + +// Metadata about a given texture level. +struct ReplacedTextureLevel { + int w = 0; + int h = 0; + + // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. + // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. + VFSFileReference *fileRef = nullptr; +}; + +class ReplacedTexture { +public: + ReplacedTexture(VFSBackend *vfs, const ReplacementDesc &desc); ~ReplacedTexture(); inline ReplacementState State() const { @@ -129,7 +128,18 @@ struct ReplacedTexture { int GetLevelDataSize(int level) const { _dbg_assert_(State() == ReplacementState::ACTIVE); - return (int)levelData_->data[level].size(); + return (int)data_[level].size(); + } + + size_t GetTotalDataSize() const { + if (State() != ReplacementState::ACTIVE) { + return 0; + } + size_t sz = 0; + for (auto &data : data_) { + sz += data.size(); + } + return sz; } int NumLevels() const { @@ -149,7 +159,6 @@ struct ReplacedTexture { bool IsReady(double budget); bool CopyLevelTo(int level, void *out, int rowPitch); - void FinishPopulate(ReplacementDesc *desc); std::string logId_; private: @@ -163,19 +172,20 @@ private: LoadLevelResult LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat); void PurgeIfOlder(double t); + std::vector> data_; std::vector levels_; - ReplacedLevelsCache *levelData_ = nullptr; ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; double lastUsed_ = 0.0; LimitedWaitable *threadWaitable_ = nullptr; - std::mutex mutex_; + std::mutex lock_; Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. + double lastUsed = 0.0; std::atomic state_ = ReplacementState::UNINITIALIZED; VFSBackend *vfs_ = nullptr; - ReplacementDesc *desc_ = nullptr; + ReplacementDesc desc_; friend class TextureReplacer; friend class ReplacedTextureTask; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 02c8016fdc..93e7521d59 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1523,9 +1523,8 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0; double replaceStart = time_now_d(); - double budget = std::min(MAX_BUDGET_PER_TEX, replacementFrameBudget_ - replacementTimeThisFrame_); u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; - ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h, budget); + ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); if (!replaced) { // TODO: Remove the flag here? // entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; @@ -1533,6 +1532,7 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & return nullptr; } + double budget = std::min(MAX_BUDGET_PER_TEX, replacementFrameBudget_ - replacementTimeThisFrame_); if (replaced->IsReady(budget)) { if (replaced->State() == ReplacementState::ACTIVE) { replaced->GetSize(0, &w, &h); diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 446ebe6d27..c2a7394709 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -69,10 +69,9 @@ TextureReplacer::TextureReplacer(Draw::DrawContext *draw) { } TextureReplacer::~TextureReplacer() { - for (auto &iter : cache_) { + for (auto iter : levelCache_) { delete iter.second; } - delete vfs_; } @@ -179,7 +178,7 @@ bool TextureReplacer::LoadIni() { // If we have stuff loaded from before, need to update the vfs pointers to avoid // crash on exit. The actual problem is that we tend to call LoadIni a little too much... - for (auto &repl : cache_) { + for (auto &repl : levelCache_) { repl.second->vfs_ = vfs_; } @@ -461,7 +460,7 @@ u32 TextureReplacer::ComputeHash(u32 addr, int bufw, int w, int h, GETextureForm } } -ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, int h, double budget) { +ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, int h) { // Only actually replace if we're replacing. We might just be saving. if (!Enabled() || !g_Config.bReplaceTextures) { return nullptr; @@ -470,74 +469,76 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, ReplacementCacheKey replacementKey(cachekey, hash); auto it = cache_.find(replacementKey); if (it != cache_.end()) { - if (it->second->State() == ReplacementState::UNINITIALIZED && budget > 0.0) { - // We don't do this on a thread, but we only do it while within budget. - PopulateReplacement(it->second, cachekey, hash, w, h); - } - return it->second; + return it->second.texture; } - // Okay, let's construct the result. - - ReplacedTexture *result = new ReplacedTexture(); - result->vfs_ = this->vfs_; - if (budget > 0.0) { - _dbg_assert_(result->State() == ReplacementState::UNINITIALIZED); - PopulateReplacement(result, cachekey, hash, w, h); - } else { - // WARN_LOG(G3D, "Postponing preparing texture (%dx%d)", w, h); - } - cache_[replacementKey] = result; - return result; -} - -void TextureReplacer::PopulateReplacement(ReplacedTexture *texture, u64 cachekey, u32 hash, int w, int h) { - // We pass this to a thread, so can't keep it on the stack. - ReplacementDesc *desc = new ReplacementDesc(); - desc->newW = w; - desc->newH = h; - desc->w = w; - desc->h = h; - desc->cachekey = cachekey; - desc->hash = hash; - desc->basePath = basePath_; - desc->formatSupport = formatSupport_; - LookupHashRange(cachekey >> 32, w, h, &desc->newW, &desc->newH); + ReplacementDesc desc; + desc.newW = w; + desc.newH = h; + desc.w = w; + desc.h = h; + desc.cachekey = cachekey; + desc.hash = hash; + LookupHashRange(cachekey >> 32, w, h, &desc.newW, &desc.newH); if (ignoreAddress_) { cachekey = cachekey & 0xFFFFFFFFULL; } - desc->foundAlias = false; + bool foundAlias = false; bool ignored = false; - desc->hashfiles = LookupHashFile(cachekey, hash, &desc->foundAlias, &ignored); + std::string hashfiles = LookupHashFile(cachekey, hash, &foundAlias, &ignored); // Early-out for ignored textures, let's not bother even starting a thread task. if (ignored) { // WARN_LOG(G3D, "Not found/ignored: %s (%d, %d)", hashfiles.c_str(), (int)foundReplacement, (int)ignored); - // nothing to do? - texture->SetState(ReplacementState::NOT_FOUND); - return; + // Insert an entry into the cache for faster lookup next time. + ReplacedTextureRef ref{}; + cache_.emplace(std::make_pair(replacementKey, ref)); + return nullptr; } - if (!desc->foundAlias) { + if (!foundAlias) { // We'll just need to generate the names for each level. // By default, we look for png since that's also what's dumped. // For other file formats, use the ini to create aliases. - desc->filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); - for (int level = 0; level < desc->filenames.size(); level++) { - desc->filenames[level] = TextureReplacer::HashName(desc->cachekey, desc->hash, level) + ".png"; + desc.filenames.resize(MAX_REPLACEMENT_MIP_LEVELS); + for (int level = 0; level < desc.filenames.size(); level++) { + desc.filenames[level] = TextureReplacer::HashName(cachekey, hash, level) + ".png"; } - desc->logId = desc->filenames[0]; - desc->hashfiles = desc->filenames[0]; // This is used as the key in the data cache. + desc.logId = desc.filenames[0]; + desc.hashfiles = desc.filenames[0]; // The generated filename of the top level is used as the key in the data cache. } else { - desc->logId = desc->hashfiles; - SplitString(desc->hashfiles, '|', desc->filenames); + desc.logId = hashfiles; + SplitString(hashfiles, '|', desc.filenames); + desc.hashfiles = hashfiles; } - desc->cache = &levelCache_[desc->hashfiles]; + // OK, we might already have a matching texture, we use hashfiles as a key. Look it up in the level cache. + auto iter = levelCache_.find(hashfiles); + if (iter != levelCache_.end()) { + // Insert an entry into the cache for faster lookup next time. + ReplacedTextureRef ref; + ref.hashfiles = hashfiles; + ref.texture = iter->second; + cache_.emplace(std::make_pair(replacementKey, ref)); + return iter->second; + } - texture->FinishPopulate(desc); + // Final path - we actually need a new replacement texture, because we haven't seen "hashfiles" before. + desc.basePath = basePath_; + desc.formatSupport = formatSupport_; + + ReplacedTexture *texture = new ReplacedTexture(vfs_, desc); + + ReplacedTextureRef ref; + ref.hashfiles = hashfiles; + ref.texture = texture; + cache_.emplace(std::make_pair(replacementKey, ref)); + + // Also, insert the level in the level cache so we can look up by desc_->hashfiles again. + levelCache_.emplace(std::make_pair(hashfiles, texture)); + return texture; } static bool WriteTextureToPNG(png_imagep image, const Path &filename, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { @@ -742,15 +743,12 @@ void TextureReplacer::Decimate(ReplacerDecimateMode mode) { } const double threshold = time_now_d() - age; - for (auto &item : cache_) { - item.second->PurgeIfOlder(threshold); - // don't actually delete the items here, just clean out the data. - } - size_t totalSize = 0; for (auto &item : levelCache_) { - std::lock_guard guard(item.second.lock); - totalSize += item.second.data.size(); + std::lock_guard guard(item.second->lock_); + item.second->PurgeIfOlder(threshold); + totalSize += item.second->GetTotalDataSize(); // TODO: Make something better. + // don't actually delete the items here, just clean out the data. } double totalSizeGB = totalSize / (1024.0 * 1024.0 * 1024.0); diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index e73a35150c..5b1f962663 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -105,7 +105,7 @@ public: u32 ComputeHash(u32 addr, int bufw, int w, int h, GETextureFormat fmt, u16 maxSeenV); // Returns nullptr if not found. - ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h, double budget); + ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h); bool FindFiltering(u64 cachekey, u32 hash, TextureFiltering *forceFiltering); // Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.) @@ -133,7 +133,6 @@ protected: bool LookupHashRange(u32 addr, int w, int h, int *newW, int *newH); float LookupReduceHashRange(int& w, int& h); std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored); - void PopulateReplacement(ReplacedTexture *result, u64 cachekey, u32 hash, int w, int h); bool enabled_ = false; bool allowVideo_ = false; @@ -160,10 +159,10 @@ protected: std::unordered_map aliases_; std::unordered_map filtering_; - std::unordered_map cache_; + std::unordered_map cache_; std::unordered_map savedCache_; // the key is either from aliases_, in which case it's a |-separated sequence of texture filenames of the levels of a texture. // alternatively the key is from the generated texture filename. - std::unordered_map levelCache_; + std::unordered_map levelCache_; }; From 725d4195df78fa9efef29d4e162cdad1d69904a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 11:53:39 +0100 Subject: [PATCH 356/424] Small cleanup of purging code --- GPU/Common/ReplacedTexture.cpp | 40 ++++++++++++++++++++++++---------- GPU/Common/ReplacedTexture.h | 6 ++--- GPU/Common/TextureReplacer.cpp | 2 +- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index fc5c1cde43..ed4915e1cd 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -95,9 +95,6 @@ private: ReplacedTexture::ReplacedTexture(VFSBackend *vfs, const ReplacementDesc &desc) : vfs_(vfs), desc_(desc) { logId_ = desc.logId; - SetState(ReplacementState::POPULATED); - - // TODO: What used to be here is now done on the thread task. } ReplacedTexture::~ReplacedTexture() { @@ -115,19 +112,38 @@ ReplacedTexture::~ReplacedTexture() { } } -void ReplacedTexture::PurgeIfOlder(double t) { - if (threadWaitable_ && !threadWaitable_->WaitFor(0.0)) +void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) { + if (State() != ReplacementState::ACTIVE) { return; - if (lastUsed_ >= t) + } + + // If there's some leftover threadWaitable, get rid of it. + if (threadWaitable_) { + if (threadWaitable_->WaitFor(0.0)) { + delete threadWaitable_; + threadWaitable_ = nullptr; + // Continue with purging. + } else { + // Try next time. + return; + } + } + + // "atomic-enough" to not lock? + if (lastUsed_ >= t) { return; + } std::lock_guard guard(lock_); - if (data_.size() && lastUsed < t) { - // We have to lock since multiple textures might reference this same data. - data_.clear(); - // This means we have to reload. If we never purge any, there's no need. - SetState(ReplacementState::POPULATED); - } + + // We have to lock since multiple textures might reference this same data. + data_.clear(); + levels_.clear(); + fmt = Draw::DataFormat::UNDEFINED; + alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; + + // This means we have to reload. If we never purge any, there's no need. + SetState(ReplacementState::POPULATED); } // This can only return true if ACTIVE or NOT_FOUND. diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 138494594c..4b6657fee2 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -170,19 +170,19 @@ private: void Prepare(VFSBackend *vfs); LoadLevelResult LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int level, Draw::DataFormat *pixelFormat); - void PurgeIfOlder(double t); + void PurgeIfNotUsedSinceTime(double t); std::vector> data_; std::vector levels_; - ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; double lastUsed_ = 0.0; LimitedWaitable *threadWaitable_ = nullptr; std::mutex lock_; Draw::DataFormat fmt = Draw::DataFormat::UNDEFINED; // NOTE: Right now, the only supported format is Draw::DataFormat::R8G8B8A8_UNORM. + ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; double lastUsed = 0.0; - std::atomic state_ = ReplacementState::UNINITIALIZED; + std::atomic state_ = ReplacementState::POPULATED; VFSBackend *vfs_ = nullptr; ReplacementDesc desc_; diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index c2a7394709..432cf51c07 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -746,7 +746,7 @@ void TextureReplacer::Decimate(ReplacerDecimateMode mode) { size_t totalSize = 0; for (auto &item : levelCache_) { std::lock_guard guard(item.second->lock_); - item.second->PurgeIfOlder(threshold); + item.second->PurgeIfNotUsedSinceTime(threshold); totalSize += item.second->GetTotalDataSize(); // TODO: Make something better. // don't actually delete the items here, just clean out the data. } From e34a5a68de88b61e96b18d5efe4787d9382d4133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 12:04:14 +0100 Subject: [PATCH 357/424] Remove some locking --- GPU/Common/ReplacedTexture.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index ed4915e1cd..d5db6e22c8 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -129,14 +129,12 @@ void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) { } } - // "atomic-enough" to not lock? + // This is the only place except shutdown where a texture can transition + // from ACTIVE to anything else, so we don't actually need to lock here. if (lastUsed_ >= t) { return; } - std::lock_guard guard(lock_); - - // We have to lock since multiple textures might reference this same data. data_.clear(); levels_.clear(); fmt = Draw::DataFormat::UNDEFINED; From 4e4209c63038e7932d912b6698bad5c77a1581b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 14:59:18 +0100 Subject: [PATCH 358/424] Include zstd as a system header from basis_universal. Fixes #17133 --- ext/basis_universal/basisu_transcoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/basis_universal/basisu_transcoder.cpp b/ext/basis_universal/basisu_transcoder.cpp index b5bef83c29..c698861f3b 100644 --- a/ext/basis_universal/basisu_transcoder.cpp +++ b/ext/basis_universal/basisu_transcoder.cpp @@ -155,7 +155,7 @@ // If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded. #if BASISD_SUPPORT_KTX2_ZSTD // We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError() - #include "../zstd/lib/zstd.h" + #include #endif #endif From f154f4a29d301d52d45b7b344ebc1a6515d1eaa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 15:06:38 +0100 Subject: [PATCH 359/424] Warning fix --- GPU/Common/ReplacedTexture.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index d5db6e22c8..e964d2a4e8 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -259,7 +259,6 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { return; } - fmt = fmt; SetState(ReplacementState::ACTIVE); if (threadWaitable_) From 8484dd4917965dcf4ad9bbca203c3fcd0fd20ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 22:59:26 +0100 Subject: [PATCH 360/424] Nicer logging if no texture.zip file is there --- Common/File/VFS/ZipFileReader.cpp | 10 +++++++--- Common/File/VFS/ZipFileReader.h | 2 +- GPU/Common/TextureReplacer.cpp | 5 ++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Common/File/VFS/ZipFileReader.cpp b/Common/File/VFS/ZipFileReader.cpp index d4e4f69e66..8935fafe55 100644 --- a/Common/File/VFS/ZipFileReader.cpp +++ b/Common/File/VFS/ZipFileReader.cpp @@ -15,13 +15,15 @@ #include "Common/File/VFS/ZipFileReader.h" #include "Common/StringUtils.h" -ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath) { +ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath, bool logErrors) { int error = 0; zip *zip_file; if (zipFile.Type() == PathType::CONTENT_URI) { int fd = File::OpenFD(zipFile, File::OPEN_READ); if (!fd) { - ERROR_LOG(IO, "Failed to open FD for %s as zip file", zipFile.c_str()); + if (logErrors) { + ERROR_LOG(IO, "Failed to open FD for '%s' as zip file", zipFile.c_str()); + } return nullptr; } zip_file = zip_fdopen(fd, 0, &error); @@ -30,7 +32,9 @@ ZipFileReader *ZipFileReader::Create(const Path &zipFile, const char *inZipPath) } if (!zip_file) { - ERROR_LOG(IO, "Failed to open %s as a zip file", zipFile.c_str()); + if (logErrors) { + ERROR_LOG(IO, "Failed to open %s as a zip file", zipFile.c_str()); + } return nullptr; } diff --git a/Common/File/VFS/ZipFileReader.h b/Common/File/VFS/ZipFileReader.h index f39058beed..44a3292ede 100644 --- a/Common/File/VFS/ZipFileReader.h +++ b/Common/File/VFS/ZipFileReader.h @@ -16,7 +16,7 @@ class ZipFileReader : public VFSBackend { public: - static ZipFileReader *Create(const Path &zipFile, const char *inZipPath); + static ZipFileReader *Create(const Path &zipFile, const char *inZipPath, bool logErrors = true); ~ZipFileReader(); bool IsValid() const { return zip_file_ != nullptr; } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 432cf51c07..00275dcd97 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -124,9 +124,12 @@ bool TextureReplacer::LoadIni() { delete vfs_; vfs_ = nullptr; + Path zipPath = basePath_ / ZIP_FILENAME; + // First, check for textures.zip, which is used to reduce IO. - VFSBackend *dir = ZipFileReader::Create(basePath_ / ZIP_FILENAME, ""); + VFSBackend *dir = ZipFileReader::Create(zipPath, "", false); if (!dir) { + INFO_LOG(G3D, "%s wasn't a zip file - opening the directory %s instead.", zipPath.c_str(), basePath_.c_str()); vfsIsZip_ = false; dir = new DirectoryReader(basePath_); } else { From 66d2fb2aa4a0a93112ddf0afdd6720bbbb8f3314 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Mar 2023 23:08:49 +0100 Subject: [PATCH 361/424] Reduce logspam from fonts, and a less angry error message for missing textures.zip. --- Core/FileSystems/DirectoryFileSystem.cpp | 8 +++++--- Core/FileSystems/FileSystem.h | 5 +++++ Core/FileSystems/MetaFileSystem.cpp | 8 ++++++-- Core/FileSystems/MetaFileSystem.h | 2 +- Core/FileSystems/VirtualDiscFileSystem.cpp | 17 ++++++++++------- Core/HLE/sceFont.cpp | 4 ++-- 6 files changed, 29 insertions(+), 15 deletions(-) diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index b4fc833452..1695e4c0c1 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -561,7 +561,7 @@ int DirectoryFileSystem::OpenFile(std::string filename, FileAccess access, const OpenFileEntry entry; entry.hFile.fileSystemFlags_ = flags; u32 err = 0; - bool success = entry.hFile.Open(basePath, filename, access, err); + bool success = entry.hFile.Open(basePath, filename, (FileAccess)(access & FILEACCESS_PSP_FLAGS), err); if (err == 0 && !success) { err = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; } @@ -577,7 +577,9 @@ int DirectoryFileSystem::OpenFile(std::string filename, FileAccess access, const #else logError = (int)errno; #endif - ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile('%s'): FAILED, %d - access = %d '%s'", filename.c_str(), logError, (int)access, errorString.c_str()); + if (!(access & FILEACCESS_PPSSPP_QUIET)) { + ERROR_LOG(FILESYS, "DirectoryFileSystem::OpenFile('%s'): FAILED, %d - access = %d '%s'", filename.c_str(), logError, (int)(access & FILEACCESS_PSP_FLAGS), errorString.c_str()); + } return err; } else { #ifdef _WIN32 @@ -589,7 +591,7 @@ int DirectoryFileSystem::OpenFile(std::string filename, FileAccess access, const u32 newHandle = hAlloc->GetNewHandle(); entry.guestFilename = filename; - entry.access = access; + entry.access = (FileAccess)(access & FILEACCESS_PSP_FLAGS); entries[newHandle] = entry; diff --git a/Core/FileSystems/FileSystem.h b/Core/FileSystems/FileSystem.h index d2eeca6651..9e64d16f20 100644 --- a/Core/FileSystems/FileSystem.h +++ b/Core/FileSystems/FileSystem.h @@ -34,6 +34,11 @@ enum FileAccess { FILEACCESS_CREATE = 8, FILEACCESS_TRUNCATE = 16, FILEACCESS_EXCL = 32, + + FILEACCESS_PSP_FLAGS = 63, // Sum of all the above. + + // Non-PSP flags + FILEACCESS_PPSSPP_QUIET = 128, }; enum FileMove { diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 49ddcc892b..26c2824f50 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -581,8 +581,12 @@ size_t MetaFileSystem::SeekFile(u32 handle, s32 position, FileMove type) return 0; } -int MetaFileSystem::ReadEntireFile(const std::string &filename, std::vector &data) { - int handle = OpenFile(filename, FILEACCESS_READ); +int MetaFileSystem::ReadEntireFile(const std::string &filename, std::vector &data, bool quiet) { + FileAccess access = FILEACCESS_READ; + if (quiet) { + access = (FileAccess)(access | FILEACCESS_PPSSPP_QUIET); + } + int handle = OpenFile(filename, access); if (handle < 0) return handle; diff --git a/Core/FileSystems/MetaFileSystem.h b/Core/FileSystems/MetaFileSystem.h index e574423dd6..bd18bfaf22 100644 --- a/Core/FileSystems/MetaFileSystem.h +++ b/Core/FileSystems/MetaFileSystem.h @@ -129,7 +129,7 @@ public: u64 FreeSpace(const std::string &path) override; // Convenience helper - returns < 0 on failure. - int ReadEntireFile(const std::string &filename, std::vector &data); + int ReadEntireFile(const std::string &filename, std::vector &data, bool quiet = false); void SetStartingDirectory(const std::string &dir) { std::lock_guard guard(lock); diff --git a/Core/FileSystems/VirtualDiscFileSystem.cpp b/Core/FileSystems/VirtualDiscFileSystem.cpp index 5c5a6714e2..e02184ad81 100644 --- a/Core/FileSystems/VirtualDiscFileSystem.cpp +++ b/Core/FileSystems/VirtualDiscFileSystem.cpp @@ -340,7 +340,7 @@ int VirtualDiscFileSystem::OpenFile(std::string filename, FileAccess access, con return newHandle; } - if (filename.compare(0,8,"/sce_lbn") == 0) + if (filename.compare(0, 8, "/sce_lbn") == 0) { u32 sectorStart = 0xFFFFFFFF, readSize = 0xFFFFFFFF; parseLBN(filename, §orStart, &readSize); @@ -365,11 +365,13 @@ int VirtualDiscFileSystem::OpenFile(std::string filename, FileAccess access, con bool success = entry.Open(basePath, fileList[entry.fileIndex].fileName, FILEACCESS_READ); if (!success) { + if (!(access & FILEACCESS_PPSSPP_QUIET)) { #ifdef _WIN32 - ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, %i", (int)GetLastError()); + ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, %i", (int)GetLastError()); #else - ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED"); + ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED"); #endif + } return 0; } @@ -388,15 +390,16 @@ int VirtualDiscFileSystem::OpenFile(std::string filename, FileAccess access, con if (entry.fileIndex != (u32)-1 && fileList[entry.fileIndex].handler != NULL) { entry.handler = fileList[entry.fileIndex].handler; } - bool success = entry.Open(basePath, filename, access); + bool success = entry.Open(basePath, filename, (FileAccess)(access & FILEACCESS_PSP_FLAGS)); if (!success) { + if (!(access & FILEACCESS_PPSSPP_QUIET)) { #ifdef _WIN32 - ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, %i - access = %i", (int)GetLastError(), (int)access); + ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, %i - access = %i", (int)GetLastError(), (int)access); #else - ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, access = %i", (int)access); + ERROR_LOG(FILESYS, "VirtualDiscFileSystem::OpenFile: FAILED, access = %i", (int)access); #endif - //wwwwaaaaahh!! + } return SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND; } else { u32 newHandle = hAlloc->GetNewHandle(); diff --git a/Core/HLE/sceFont.cpp b/Core/HLE/sceFont.cpp index d0b23ece26..48e612f9fa 100644 --- a/Core/HLE/sceFont.cpp +++ b/Core/HLE/sceFont.cpp @@ -891,12 +891,12 @@ static void __LoadInternalFonts() { bool bufferRead = false; std::string fontFilename = gameFontPath + entry.fileName; - bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer) >= 0; + bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer, true) >= 0; if (!bufferRead) { // No game font, let's try override path. fontFilename = fontOverridePath + entry.fileName; - bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer) >= 0; + bufferRead = pspFileSystem.ReadEntireFile(fontFilename, buffer, true) >= 0; } if (!bufferRead) { From 6a430f2a14082a0edc479936d7f4795de87aebcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Mar 2023 00:02:01 +0100 Subject: [PATCH 362/424] ReplacedTexture: Some initialization. For UASTC, seems we need to clear the transcoder state. --- GPU/Common/ReplacedTexture.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index e964d2a4e8..7aab3f9cb1 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -480,7 +480,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference return LoadLevelResult::LOAD_ERROR; } - int blockSize; + int blockSize = 0; bool bc = Draw::DataFormatIsBlockCompressed(*pixelFormat, &blockSize); _dbg_assert_(bc || *pixelFormat == Draw::DataFormat::R8G8B8A8_UNORM); @@ -492,7 +492,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference for (int i = 0; i < numMips; i++) { std::vector &out = data_[mipLevel + i]; - basist::ktx2_image_level_info levelInfo; + basist::ktx2_image_level_info levelInfo{}; bool result = transcoder.get_image_level_info(levelInfo, i, 0, 0); _dbg_assert_(result); @@ -507,6 +507,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } data_[i].resize(dataSizeBytes); + transcodeState.clear(); transcoder.transcode_image_level(i, 0, 0, &out[0], (uint32_t)outputSize, transcoderFormat, 0, (uint32_t)outputPitch, level.h, -1, -1, &transcodeState); level.w = levelInfo.m_orig_width; level.h = levelInfo.m_orig_height; @@ -555,6 +556,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } cleanup(); return LoadLevelResult::DONE; // don't read more levels + } else if (imageType == ReplacedImageType::ZIM) { std::unique_ptr zim(new uint8_t[fileSize]); From 1b0d5ec3aa6376274579fedeafe54724879c2efc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Mar 2023 00:52:38 +0100 Subject: [PATCH 363/424] Remove a unused state from ReplacedTexture, rename POPULATED to UNLOADED --- GPU/Common/ReplacedTexture.cpp | 10 +++------- GPU/Common/ReplacedTexture.h | 5 ++--- GPU/Common/TextureCacheCommon.cpp | 3 +-- GPU/Common/TextureCacheCommon.h | 1 + 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 7aab3f9cb1..b4c412c27b 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -141,7 +141,7 @@ void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) { alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; // This means we have to reload. If we never purge any, there's no need. - SetState(ReplacementState::POPULATED); + SetState(ReplacementState::UNLOADED); } // This can only return true if ACTIVE or NOT_FOUND. @@ -165,13 +165,10 @@ bool ReplacedTexture::IsReady(double budget) { } lastUsed_ = now; return true; - case ReplacementState::UNINITIALIZED: - // _dbg_assert_(false); - return false; case ReplacementState::CANCEL_INIT: case ReplacementState::PENDING: return false; - case ReplacementState::POPULATED: + case ReplacementState::UNLOADED: // We're gonna need to spawn a task. break; } @@ -726,8 +723,7 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { const char *StateString(ReplacementState state) { switch (state) { - case ReplacementState::UNINITIALIZED: return "UNINITIALIZED"; - case ReplacementState::POPULATED: return "PREPARED"; + case ReplacementState::UNLOADED: return "PREPARED"; case ReplacementState::PENDING: return "PENDING"; case ReplacementState::NOT_FOUND: return "NOT_FOUND"; case ReplacementState::ACTIVE: return "ACTIVE"; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 4b6657fee2..e9aaf27cdc 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -52,8 +52,7 @@ enum class ReplacedImageType { static const int MAX_REPLACEMENT_MIP_LEVELS = 12; // 12 should be plenty, 8 is the max mip levels supported by the PSP. enum class ReplacementState : uint32_t { - UNINITIALIZED, - POPULATED, // We located the texture files but have not started the thread. + UNLOADED, PENDING, NOT_FOUND, // Also used on error loading the images. ACTIVE, @@ -182,7 +181,7 @@ private: ReplacedTextureAlpha alphaStatus_ = ReplacedTextureAlpha::UNKNOWN; double lastUsed = 0.0; - std::atomic state_ = ReplacementState::POPULATED; + std::atomic state_ = ReplacementState::UNLOADED; VFSBackend *vfs_ = nullptr; ReplacementDesc desc_; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 93e7521d59..ddb9ee71f1 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -1545,9 +1545,8 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & } switch (replaced->State()) { - case ReplacementState::POPULATED: + case ReplacementState::UNLOADED: case ReplacementState::PENDING: - case ReplacementState::UNINITIALIZED: // Make sure we keep polling. entry->status |= TexCacheEntry::STATUS_TO_REPLACE; break; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index f655fe249c..f1ee7be387 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -180,6 +180,7 @@ struct TexCacheEntry { u32 fullhash; u32 cluthash; u16 maxSeenV; + ReplacedTexture *replacedTexture; TexStatus GetHashStatus() { return TexStatus(status & STATUS_MASK); From df41a5cebdbfc7a0cbcd7a54f0c658bfdbf9d106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Mar 2023 12:47:12 +0100 Subject: [PATCH 364/424] Improve default ini, logging fixes --- Core/FileSystems/MetaFileSystem.cpp | 1 - GPU/Common/TextureReplacer.cpp | 11 ++++++++--- GPU/Common/TextureReplacer.h | 4 +++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Core/FileSystems/MetaFileSystem.cpp b/Core/FileSystems/MetaFileSystem.cpp index 49ddcc892b..b7c6f6094a 100644 --- a/Core/FileSystems/MetaFileSystem.cpp +++ b/Core/FileSystems/MetaFileSystem.cpp @@ -79,7 +79,6 @@ static bool RealPath(const std::string ¤tDirectory, const std::string &inP size_t inLen = inPath.length(); if (inLen == 0) { - WARN_LOG(FILESYS, "RealPath: inPath is empty"); outPath = currentDirectory; return true; } diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 432cf51c07..a67a992968 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -904,12 +904,14 @@ bool TextureReplacer::GenerateIni(const std::string &gameID, Path &generatedFile // Let's also write some defaults. fprintf(f, R"(# This file is optional and describes your textures. -# Some information on syntax available here: -# https://github.com/hrydgard/ppsspp/wiki/Texture-replacement-ini-syntax +# Documentation about the options and syntax is available here: +# https://www.ppsspp.org/docs/reference/texture-replacement [options] version = 1 hash = quick -ignoreMipmap = false +ignoreMipmap = false # Set to true to avoid dumping mipmaps. Instead use basisu to generate them, see docs. +reduceHash = false # Usually a good idea to use. +allowVideo = false [games] # Used to make it easier to install, and override settings for other regions. @@ -921,8 +923,11 @@ ignoreMipmap = false # See wiki for more info. [hashranges] +# See the documentation. +# Example: 08b31020,512,512 = 480,272 [filtering] +# You can enforce specific filtering modes with this. See the docs. [reducehashranges] )", gameID.c_str(), INI_FILENAME.c_str()); diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 5b1f962663..bd6dd29807 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -138,11 +138,12 @@ protected: bool allowVideo_ = false; bool ignoreAddress_ = false; bool reduceHash_ = false; + bool ignoreMipmap_ = false; + float reduceHashSize = 1.0f; // default value with reduceHash to false float reduceHashGlobalValue = 0.5f; // Global value for textures dump pngs of all sizes, 0.5 by default but can be set in textures.ini double lastTextureCacheSizeGB_ = 0.0; - bool ignoreMipmap_ = false; std::string gameID_; Path basePath_; Path newTextureDir_; @@ -150,6 +151,7 @@ protected: VFSBackend *vfs_ = nullptr; bool vfsIsZip_ = false; + GPUFormatSupport formatSupport_{}; typedef std::pair WidthHeightPair; From 79f4e7311002c102b6beced167e6458f8af1a2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Mar 2023 13:08:35 +0100 Subject: [PATCH 365/424] Replacer: Perform the padding to pow2 size during CopyLevelTo, not during load. Saves memory. --- Common/MemoryUtil.cpp | 2 +- GPU/Common/ReplacedTexture.cpp | 33 +++++++++++++++++++++++++-------- GPU/Common/ReplacedTexture.h | 8 ++++++-- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/Common/MemoryUtil.cpp b/Common/MemoryUtil.cpp index 5e539e27e8..139cd4f9e0 100644 --- a/Common/MemoryUtil.cpp +++ b/Common/MemoryUtil.cpp @@ -250,7 +250,7 @@ void *AllocateAlignedMemory(size_t size, size_t alignment) { #endif #endif - _assert_msg_(ptr != nullptr, "Failed to allocate aligned memory"); + _assert_msg_(ptr != nullptr, "Failed to allocate aligned memory of size %llu", size); return ptr; } diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index b4c412c27b..7083b85048 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -256,6 +256,12 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { return; } + // Update the level dimensions. + for (auto &level : levels_) { + level.fullW = (level.w * desc_.w) / desc_.newW; + level.fullH = (level.h * desc_.h) / desc_.newH; + } + SetState(ReplacementState::ACTIVE); if (threadWaitable_) @@ -390,7 +396,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", filename.c_str(), magic.c_str()); } - // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. if (!data_[mipLevel].empty()) { vfs_->CloseFile(openFile); @@ -398,13 +403,10 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference return LoadLevelResult::DONE; } - // Is this really the right place to do it? - level.w = (level.w * desc_.w) / desc_.newW; - level.h = (level.h * desc_.h) / desc_.newH; - if (good && mipLevel != 0) { - // Check that the mipmap size is correct. Can't load mips of the wrong size. - if (level.w != (levels_[0].w >> mipLevel) || level.h != (levels_[0].h >> mipLevel)) { + // If loading a low mip directly (through png most likely), check that the mipmap size is correct. + // Can't load mips of the wrong size. + if (level.w != std::max(1, (levels_[0].w >> mipLevel)) || level.h != std::max(1, (levels_[0].h >> mipLevel))) { WARN_LOG(G3D, "Replacement mipmap invalid: size=%dx%d, expected=%dx%d (level %d)", level.w, level.h, levels_[0].w >> mipLevel, levels_[0].h >> mipLevel, mipLevel); good = false; @@ -668,6 +670,13 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { return false; } + // We pad the images right here during the copy. + // TODO: Add support for the texture cache to scale texture coordinates instead. + // It already supports this for render target textures that aren't powers of 2. + + int outW = levels_[level].fullW; + int outH = levels_[level].fullH; + // We probably could avoid this lock, but better to play it safe. std::lock_guard guard(lock_); @@ -683,7 +692,7 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { if (fmt == Draw::DataFormat::R8G8B8A8_UNORM) { if (rowPitch < info.w * 4) { - ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d)", rowPitch, info.w * 4, level); + ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d) (too small)", rowPitch, info.w * 4, level); return false; } @@ -699,10 +708,18 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { #ifdef PARALLEL_COPY const int MIN_LINES_PER_THREAD = 4; ParallelRangeLoop(&g_threadManager, [&](int l, int h) { + int extraPixels = outW - info.w; for (int y = l; y < h; ++y) { memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4); + // Fill the rest of the line with black. + memset((uint8_t *)out + rowPitch * y + info.w * 4, 0, extraPixels * 4); } }, 0, info.h, MIN_LINES_PER_THREAD); + // Memset the rest of the padding. + for (int y = info.h; y < outH; y++) { + uint8_t *dest = (uint8_t *)out + rowPitch * y; + memset(dest, 0, outW * 4); + } #else for (int y = 0; y < info.h; ++y) { memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index e9aaf27cdc..507fca4eed 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -93,8 +93,12 @@ struct ReplacedTextureRef { // Metadata about a given texture level. struct ReplacedTextureLevel { + // Data dimensions int w = 0; int h = 0; + // PSP texture dimensions + int fullW = 0; + int fullH = 0; // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. @@ -121,8 +125,8 @@ public: void GetSize(int level, int *w, int *h) const { _dbg_assert_(State() == ReplacementState::ACTIVE); _dbg_assert_(level < levels_.size()); - *w = levels_[level].w; - *h = levels_[level].h; + *w = levels_[level].fullW; + *h = levels_[level].fullH; } int GetLevelDataSize(int level) const { From 5f76fbe1ade35fb73c5f94794dc445e0231fabaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Mar 2023 13:58:36 +0100 Subject: [PATCH 366/424] Implement padding-on-copy for compressed textures as well. --- GPU/Common/ReplacedTexture.cpp | 67 ++++++++++++++++++++++++------- GPU/Common/ReplacedTexture.h | 10 +++-- GPU/Common/TextureCacheCommon.cpp | 5 ++- GPU/Common/TextureCacheCommon.h | 2 +- GPU/D3D11/TextureCacheD3D11.cpp | 6 +-- GPU/Directx9/TextureCacheDX9.cpp | 4 +- GPU/GLES/TextureCacheGLES.cpp | 9 +++-- GPU/Vulkan/TextureCacheVulkan.cpp | 4 +- 8 files changed, 74 insertions(+), 33 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 7083b85048..293d7c1a76 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -192,6 +192,10 @@ bool ReplacedTexture::IsReady(double budget) { return false; } +inline uint32_t RoundUpTo4(uint32_t value) { + return (value + 3) & ~3; +} + void ReplacedTexture::Prepare(VFSBackend *vfs) { this->vfs_ = vfs; @@ -260,6 +264,14 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { for (auto &level : levels_) { level.fullW = (level.w * desc_.w) / desc_.newW; level.fullH = (level.h * desc_.h) / desc_.newH; + + int blockSize; + bool bc = Draw::DataFormatIsBlockCompressed(fmt, &blockSize); + if (!bc) { + level.fullDataSize = level.fullW * level.fullH * 4; + } else { + level.fullDataSize = RoundUpTo4(level.fullW) * RoundUpTo4(level.fullH) * blockSize / 16; + } } SetState(ReplacementState::ACTIVE); @@ -268,10 +280,6 @@ void ReplacedTexture::Prepare(VFSBackend *vfs) { threadWaitable_->Notify(); } -inline uint32_t RoundUpTo4(uint32_t value) { - return (value + 3) & ~3; -} - // Returns true if Prepare should keep calling this to load more levels. ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference *fileRef, const std::string &filename, int mipLevel, Draw::DataFormat *pixelFormat) { bool good = false; @@ -661,7 +669,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference return LoadLevelResult::LOAD_ERROR; } -bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { +bool ReplacedTexture::CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch) { _assert_msg_((size_t)level < levels_.size(), "Invalid miplevel"); _assert_msg_(out != nullptr && rowPitch > 0, "Invalid out/pitch"); @@ -690,7 +698,13 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { #define PARALLEL_COPY - if (fmt == Draw::DataFormat::R8G8B8A8_UNORM) { + int blockSize; + if (!Draw::DataFormatIsBlockCompressed(fmt, &blockSize)) { + if (fmt != Draw::DataFormat::R8G8B8A8_UNORM) { + ERROR_LOG(G3D, "Unexpected linear data format"); + return false; + } + if (rowPitch < info.w * 4) { ERROR_LOG(G3D, "Replacement rowPitch=%d, but w=%d (level=%d) (too small)", rowPitch, info.w * 4, level); return false; @@ -715,24 +729,47 @@ bool ReplacedTexture::CopyLevelTo(int level, void *out, int rowPitch) { memset((uint8_t *)out + rowPitch * y + info.w * 4, 0, extraPixels * 4); } }, 0, info.h, MIN_LINES_PER_THREAD); - // Memset the rest of the padding. - for (int y = info.h; y < outH; y++) { - uint8_t *dest = (uint8_t *)out + rowPitch * y; - memset(dest, 0, outW * 4); - } #else for (int y = 0; y < info.h; ++y) { memcpy((uint8_t *)out + rowPitch * y, data.data() + info.w * 4 * y, info.w * 4); } #endif + // Memset the rest of the padding to avoid leaky edge pixels. Guess we could parallelize this too, but meh. + for (int y = info.h; y < outH; y++) { + uint8_t *dest = (uint8_t *)out + rowPitch * y; + memset(dest, 0, outW * 4); + } } } else { #ifdef PARALLEL_COPY - // TODO: Add sanity checks here for other formats? - ParallelMemcpy(&g_threadManager, out, data.data(), data.size()); -#else - memcpy(out, data.data(), data.size()); + // Only parallel copy in the simple case for now. + if (info.w == outW && info.h == outH) { + // TODO: Add sanity checks here for other formats? + ParallelMemcpy(&g_threadManager, out, data.data(), data.size()); + return true; + } #endif + // Alright, so careful copying of blocks it is, padding with zero-blocks as needed. + int inBlocksW = (info.w + 3) / 4; + int inBlocksH = (info.h + 3) / 4; + int outBlocksW = (info.fullW + 3) / 4; + int outBlocksH = (info.fullH + 3) / 4; + + int paddingBlocksX = outBlocksW - inBlocksW; + + // Copy all the known blocks, and zero-fill out the lines. + for (int y = 0; y < inBlocksH; y++) { + const uint8_t *input = data.data() + y * inBlocksW * blockSize; + uint8_t *output = (uint8_t *)out + y * outBlocksW * blockSize; + memcpy(output, input, inBlocksW * blockSize); + memset(output + inBlocksW * blockSize, 0, paddingBlocksX * blockSize); + } + + // Vertical zero-padding. + for (int y = inBlocksH; y < outBlocksH; y++) { + uint8_t *output = (uint8_t *)out + y * outBlocksW * blockSize; + memset(output, 0, outBlocksW * blockSize); + } } return true; diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index 507fca4eed..eaeb5ed230 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -100,6 +100,8 @@ struct ReplacedTextureLevel { int fullW = 0; int fullH = 0; + int fullDataSize = 0; + // To be able to reload, we need to be able to reopen, unfortunate we can't use zip_file_t. // TODO: This really belongs on the level in the cache, not in the individual ReplacedTextureLevel objects. VFSFileReference *fileRef = nullptr; @@ -129,9 +131,9 @@ public: *h = levels_[level].fullH; } - int GetLevelDataSize(int level) const { - _dbg_assert_(State() == ReplacementState::ACTIVE); - return (int)data_[level].size(); + int GetLevelDataSizeAfterCopy(int level) const { + // Includes padding etc. + return levels_[level].fullDataSize; } size_t GetTotalDataSize() const { @@ -160,7 +162,7 @@ public: } bool IsReady(double budget); - bool CopyLevelTo(int level, void *out, int rowPitch); + bool CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch); std::string logId_; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index ddb9ee71f1..7c3b0d3b92 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -2882,7 +2882,8 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt return true; } -void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, int stride, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags) { +// Passing 0 into dataSize will disable checking. +void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, size_t dataSize, int stride, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags) { int w = gstate.getTextureWidth(srcLevel); int h = gstate.getTextureHeight(srcLevel); @@ -2891,7 +2892,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, i if (plan.replaceValid) { plan.replaced->GetSize(srcLevel, &w, &h); double replaceStart = time_now_d(); - plan.replaced->CopyLevelTo(srcLevel, data, stride); + plan.replaced->CopyLevelTo(srcLevel, data, dataSize, stride); replacementTimeThisFrame_ += time_now_d() - replaceStart; } else { GETextureFormat tfmt = (GETextureFormat)entry.format; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index f1ee7be387..b70e1ea1a4 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -386,7 +386,7 @@ protected: ReplacedTexture *FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d); // Return value is mapData normally, but could be another buffer allocated with AllocateAlignedMemory. - void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, int mapRowPitch, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags); + void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, size_t dataSize, int mapRowPitch, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags); template inline const T *GetCurrentClut() { diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index 70f0a4e941..d26d48a5fa 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -301,8 +301,8 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { if (plan.replaceValid) { int blockSize = 0; if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { - stride = ((mipWidth + 3) & ~3) * blockSize / 4; // This stride value doesn't quite make sense to me, but it works? - dataSize = plan.replaced->GetLevelDataSize(i); + stride = ((mipWidth + 3) & ~3) * blockSize / 4; // Number of blocks * 4 * Size of a block / 4 + dataSize = plan.replaced->GetLevelDataSizeAfterCopy(i); } else { int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); stride = std::max(mipWidth * bpp, 16); @@ -338,7 +338,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { return; } - LoadTextureLevel(*entry, data, stride, plan, srcLevel, texFmt, TexDecodeFlags{}); + LoadTextureLevel(*entry, data, 0, stride, plan, srcLevel, texFmt, TexDecodeFlags{}); } int tw; diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 55433f5c1b..3de9c870c1 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -290,7 +290,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { } uint8_t *data = (uint8_t *)rect.pBits; int stride = rect.Pitch; - LoadTextureLevel(*entry, data, stride, plan, (i == 0) ? plan.baseLevelSrc : i, FromD3D9Format(dstFmt), TexDecodeFlags{}); + LoadTextureLevel(*entry, data, 0, stride, plan, (i == 0) ? plan.baseLevelSrc : i, FromD3D9Format(dstFmt), TexDecodeFlags{}); ((LPDIRECT3DTEXTURE9)texture)->UnlockRect(dstLevel); } } else { @@ -305,7 +305,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { uint8_t *data = (uint8_t *)box.pBits; int stride = box.RowPitch; for (int i = 0; i < plan.depth; i++) { - LoadTextureLevel(*entry, data, stride, plan, (i == 0) ? plan.baseLevelSrc : i, FromD3D9Format(dstFmt), TexDecodeFlags{}); + LoadTextureLevel(*entry, data, 0, stride, plan, (i == 0) ? plan.baseLevelSrc : i, FromD3D9Format(dstFmt), TexDecodeFlags{}); data += box.SlicePitch; } ((LPDIRECT3DVOLUMETEXTURE9)texture)->UnlockBox(0); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index b5d8fdd63e..9445d67421 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -300,7 +300,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { int blockSize = 0; if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { stride = mipWidth * 4; - dataSize = plan.replaced->GetLevelDataSize(i); + dataSize = plan.replaced->GetLevelDataSizeAfterCopy(i); bc = true; } else { int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format()); @@ -325,7 +325,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { return; } - LoadTextureLevel(*entry, data, stride, plan, srcLevel, dstFmt, TexDecodeFlags::REVERSE_COLORS); + LoadTextureLevel(*entry, data, dataSize, stride, plan, srcLevel, dstFmt, TexDecodeFlags::REVERSE_COLORS); // NOTE: TextureImage takes ownership of data, so we don't free it afterwards. render_->TextureImage(entry->textureName, i, mipWidth, mipHeight, 1, dstFmt, data, GLRAllocType::ALIGNED); @@ -339,12 +339,13 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { int stride = bpp * (plan.w * plan.scaleFactor); int levelStride = stride * (plan.h * plan.scaleFactor); - u8 *data = (u8 *)AllocateAlignedMemory(levelStride * plan.depth, 16); + size_t dataSize = levelStride * plan.depth; + u8 *data = (u8 *)AllocateAlignedMemory(dataSize, 16); memset(data, 0, levelStride * plan.depth); u8 *p = data; for (int i = 0; i < plan.depth; i++) { - LoadTextureLevel(*entry, p, stride, plan, i, dstFmt, TexDecodeFlags::REVERSE_COLORS); + LoadTextureLevel(*entry, p, dataSize, stride, plan, i, dstFmt, TexDecodeFlags::REVERSE_COLORS); p += levelStride; } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index 61b8033daa..dcbb764a38 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -595,13 +595,13 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { int rowLength = pixelStride; if (bcFormat) { // For block compressed formats, we just set the upload size to the data size.. - uploadSize = plan.replaced->GetLevelDataSize(plan.baseLevelSrc + i); + uploadSize = plan.replaced->GetLevelDataSizeAfterCopy(plan.baseLevelSrc + i); rowLength = (mipWidth + 3) & ~3; } // Directly load the replaced image. data = pushBuffer->Allocate(uploadSize, pushAlignment, &texBuf, &bufferOffset); double replaceStart = time_now_d(); - if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, data, byteStride)) { // If plan.replaceValid, this shouldn't fail. + if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, (uint8_t *)data, uploadSize, byteStride)) { // If plan.replaceValid, this shouldn't fail. WARN_LOG(G3D, "Failed to copy replaced texture level"); // TODO: Fill with some pattern? } From 75bcb9b10c8d84c1721003452050f3c3a307e619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 11:45:26 +0100 Subject: [PATCH 367/424] Some renaming, flag updates --- GPU/Common/TextureCacheCommon.cpp | 21 ++++++++++++--------- GPU/Common/TextureCacheCommon.h | 6 +++--- GPU/D3D11/TextureCacheD3D11.cpp | 6 +++--- GPU/Directx9/TextureCacheDX9.cpp | 4 ++-- GPU/GLES/TextureCacheGLES.cpp | 6 +++--- GPU/Vulkan/TextureCacheVulkan.cpp | 12 ++++++------ 6 files changed, 29 insertions(+), 26 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 7c3b0d3b92..e7a4b87012 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -328,7 +328,7 @@ SamplerCacheKey TextureCacheCommon::GetFramebufferSamplingParams(u16 bufferWidth // Kill any mipmapping settings. key.mipEnable = false; key.mipFilt = false; - key.aniso = 0.0; + key.aniso = 0.0f; key.maxLevel = 0.0f; key.lodBias = 0.0f; @@ -858,7 +858,7 @@ void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c if (doDelete) { ForgetLastTexture(); ReleaseTexture(entry, true); - entry->status &= ~TexCacheEntry::STATUS_IS_SCALED; + entry->status &= ~(TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED | TexCacheEntry::STATUS_TO_REPLACE); } // Mark as hashing, if marked as reliable. @@ -1537,7 +1537,7 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & if (replaced->State() == ReplacementState::ACTIVE) { replaced->GetSize(0, &w, &h); // Consider it already "scaled.". - entry->status |= TexCacheEntry::STATUS_IS_SCALED; + entry->status |= TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED; } // Remove the flag, even if it was invalid. @@ -2073,6 +2073,8 @@ void TextureCacheCommon::ApplyTexture() { // This prevents temporary scaling perf hits on the first second of video. if (IsVideo(entry->addr)) { entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT | TexCacheEntry::STATUS_VIDEO; + } else { + entry->status &= ~TexCacheEntry::STATUS_VIDEO; } if (nextNeedsRehash_) { @@ -2782,7 +2784,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt plan.scaleFactor = 1; } else { entry->status &= ~TexCacheEntry::STATUS_TO_SCALE; - entry->status |= TexCacheEntry::STATUS_IS_SCALED; + entry->status |= TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED; texelsScaledThisFrame_ += plan.w * plan.h; } } @@ -2819,17 +2821,18 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt } if (canReplace) { + // This is the "trigger point" for replacement. plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); - plan.replaceValid = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false; + plan.doReplace = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false; } else { plan.replaced = nullptr; - plan.replaceValid = false; + plan.doReplace = false; } // NOTE! Last chance to change scale factor here! plan.saveTexture = false; - if (plan.replaceValid) { + if (plan.doReplace) { // We're replacing, so we won't scale. plan.scaleFactor = 1; // We're ignoring how many levels were specified - instead we just load all available from the replacer. @@ -2839,7 +2842,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt // But, we still need to create the texture at a larger size. plan.replaced->GetSize(0, &plan.createW, &plan.createH); } else { - if (replacer_.Enabled() && !plan.replaceValid && plan.depth == 1 && canReplace) { + if (replacer_.Enabled() && !plan.doReplace && plan.depth == 1 && canReplace) { ReplacedTextureDecodeInfo replacedInfo; // TODO: Do we handle the race where a replacement becomes valid AFTER this but before we save? replacedInfo.cachekey = entry->CacheKey(); @@ -2889,7 +2892,7 @@ void TextureCacheCommon::LoadTextureLevel(TexCacheEntry &entry, uint8_t *data, s PROFILE_THIS_SCOPE("decodetex"); - if (plan.replaceValid) { + if (plan.doReplace) { plan.replaced->GetSize(srcLevel, &w, &h); double replaceStart = time_now_d(); plan.replaced->CopyLevelTo(srcLevel, data, dataSize, stride); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index b70e1ea1a4..67e78c6f47 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -133,7 +133,7 @@ struct TexCacheEntry { STATUS_CHANGE_FREQUENT = 0x10, // Changes often (less than 6 frames in between.) STATUS_CLUT_RECHECK = 0x20, // Another texture with same addr had a hashfail. STATUS_TO_SCALE = 0x80, // Pending texture scaling in a later frame. - STATUS_IS_SCALED = 0x100, // Has been scaled (can't be replaceImages'd.) + STATUS_IS_SCALED_OR_REPLACED = 0x100, // Has been scaled already (ignored for replacement checks). STATUS_TO_REPLACE = 0x0200, // Pending texture replacement. // When hashing large textures, we optimize 512x512 down to 512x272 by default, since this // is commonly the only part accessed. If access is made above 272, we hash the entire @@ -287,14 +287,14 @@ struct BuildTexturePlan { // The replacement for the texture. ReplacedTexture *replaced; // Need to only check once since it can change during the load! - bool replaceValid; + bool doReplace; bool saveTexture; // TODO: Expand32 should probably also be decided in PrepareBuildTexture. bool decodeToClut8; void GetMipSize(int level, int *w, int *h) const { - if (replaceValid) { + if (doReplace) { replaced->GetSize(level, w, h); return; } diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index d26d48a5fa..aed4f29b07 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -261,7 +261,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { } DXGI_FORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - if (plan.replaceValid) { + if (plan.doReplace) { dstFmt = ToDXGIFormat(plan.replaced->Format()); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM; @@ -298,7 +298,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { int stride = 0; int dataSize; - if (plan.replaceValid) { + if (plan.doReplace) { int blockSize = 0; if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { stride = ((mipWidth + 3) & ~3) * blockSize / 4; // Number of blocks * 4 * Size of a block / 4 @@ -404,7 +404,7 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry) { entry->status &= ~TexCacheEntry::STATUS_NO_MIPS; } - if (plan.replaceValid) { + if (plan.doReplace) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) { diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 3de9c870c1..ef823b3673 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -230,7 +230,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { } D3DFORMAT dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - if (plan.replaceValid) { + if (plan.doReplace) { dstFmt = ToD3D9Format(plan.replaced->Format()); } else if (plan.scaleFactor > 1 || plan.saveTexture) { dstFmt = D3DFMT_A8R8G8B8; @@ -316,7 +316,7 @@ void TextureCacheDX9::BuildTexture(TexCacheEntry *const entry) { entry->status |= TexCacheEntry::STATUS_3D; } - if (plan.replaceValid) { + if (plan.doReplace) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); if (!Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), nullptr)) { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 9445d67421..437144e296 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -246,7 +246,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { int th = plan.createH; Draw::DataFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); - if (plan.replaceValid) { + if (plan.doReplace) { plan.replaced->GetSize(plan.baseLevelSrc, &tw, &th); dstFmt = plan.replaced->Format(); } else if (plan.scaleFactor > 1 || plan.saveTexture) { @@ -296,7 +296,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { bool bc = false; - if (plan.replaceValid) { + if (plan.doReplace) { int blockSize = 0; if (Draw::DataFormatIsBlockCompressed(plan.replaced->Format(), &blockSize)) { stride = mipWidth * 4; @@ -357,7 +357,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) { render_->FinalizeTexture(entry->textureName, 1, false); } - if (plan.replaceValid) { + if (plan.doReplace) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); } } diff --git a/GPU/Vulkan/TextureCacheVulkan.cpp b/GPU/Vulkan/TextureCacheVulkan.cpp index dcbb764a38..5fccb0cf37 100644 --- a/GPU/Vulkan/TextureCacheVulkan.cpp +++ b/GPU/Vulkan/TextureCacheVulkan.cpp @@ -435,7 +435,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { VkFormat dstFmt = GetDestFormat(GETextureFormat(entry->format), gstate.getClutPaletteFormat()); if (plan.scaleFactor > 1) { - _dbg_assert_(!plan.replaceValid); + _dbg_assert_(!plan.doReplace); // Whether hardware or software scaling, this is the dest format. dstFmt = VULKAN_8888_FORMAT; } else if (plan.decodeToClut8) { @@ -445,7 +445,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // We don't generate mipmaps for 512x512 textures because they're almost exclusively used for menu backgrounds // and similar, which don't really need it. // Also, if using replacements, check that we really can generate mips for this format - that's not possible for compressed ones. - if (g_Config.iTexFiltering == TEX_FILTER_AUTO_MAX_QUALITY && plan.w <= 256 && plan.h <= 256 && (!plan.replaceValid || plan.replaced->Format() == Draw::DataFormat::R8G8B8A8_UNORM)) { + if (g_Config.iTexFiltering == TEX_FILTER_AUTO_MAX_QUALITY && plan.w <= 256 && plan.h <= 256 && (!plan.doReplace || plan.replaced->Format() == Draw::DataFormat::R8G8B8A8_UNORM)) { // Boost the number of mipmaps. if (plan.maxPossibleLevels > plan.levelsToCreate) { // TODO: Should check against levelsToLoad, no? // We have to generate mips with a shader. This requires decoding to R8G8B8A8_UNORM format to avoid extra complications. @@ -458,7 +458,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { VkFormat actualFmt = plan.scaleFactor > 1 ? VULKAN_8888_FORMAT : dstFmt; bool bcFormat = false; int bcAlign = 0; - if (plan.replaceValid) { + if (plan.doReplace) { Draw::DataFormat fmt = plan.replaced->Format(); bcFormat = Draw::DataFormatIsBlockCompressed(fmt, &bcAlign); actualFmt = ToVulkanFormat(fmt); @@ -591,7 +591,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { }; bool dataScaled = true; - if (plan.replaceValid) { + if (plan.doReplace) { int rowLength = pixelStride; if (bcFormat) { // For block compressed formats, we just set the upload size to the data size.. @@ -601,7 +601,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { // Directly load the replaced image. data = pushBuffer->Allocate(uploadSize, pushAlignment, &texBuf, &bufferOffset); double replaceStart = time_now_d(); - if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, (uint8_t *)data, uploadSize, byteStride)) { // If plan.replaceValid, this shouldn't fail. + if (!plan.replaced->CopyLevelTo(plan.baseLevelSrc + i, (uint8_t *)data, uploadSize, byteStride)) { // If plan.doReplace, this shouldn't fail. WARN_LOG(G3D, "Failed to copy replaced texture level"); // TODO: Fill with some pattern? } @@ -681,7 +681,7 @@ void TextureCacheVulkan::BuildTexture(TexCacheEntry *const entry) { entry->status |= TexCacheEntry::STATUS_3D; } - if (plan.replaceValid) { + if (plan.doReplace) { entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus())); } } From 97c9b9e4f715eceea0734bdcc740b2c7d65867dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 12:01:24 +0100 Subject: [PATCH 368/424] Break out PollReplacement from TextureCacheCommon::FindReplacement --- GPU/Common/ReplacedTexture.cpp | 2 +- GPU/Common/ReplacedTexture.h | 2 +- GPU/Common/TextureCacheCommon.cpp | 36 ++++++++++++++++++------------- GPU/Common/TextureCacheCommon.h | 8 ++++++- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 293d7c1a76..9461a08141 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -145,7 +145,7 @@ void ReplacedTexture::PurgeIfNotUsedSinceTime(double t) { } // This can only return true if ACTIVE or NOT_FOUND. -bool ReplacedTexture::IsReady(double budget) { +bool ReplacedTexture::Poll(double budget) { _assert_(vfs_ != nullptr); double now = time_now_d(); diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index eaeb5ed230..b4716c8b64 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -161,7 +161,7 @@ public: return (u8)alphaStatus_; } - bool IsReady(double budget); + bool Poll(double budget); bool CopyLevelTo(int level, uint8_t *out, size_t outDataSize, int rowPitch); std::string logId_; diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index e7a4b87012..c2359efa67 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -531,7 +531,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { int w0 = gstate.getTextureWidth(0); int h0 = gstate.getTextureHeight(0); int d0 = 1; - ReplacedTexture *replaced = FindReplacement(entry, w0, h0, d0); + ReplacedTexture *replaced = FindReplacement(entry, &w0, &h0, &d0); if (replaced) { // This texture is pending a replacement load. // So check the replacer if it's reached a conclusion. @@ -1502,8 +1502,8 @@ u32 TextureCacheCommon::EstimateTexMemoryUsage(const TexCacheEntry *entry) { return pixelSize << (dimW + dimH); } -ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d) { - if (d != 1) { +ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int *w, int *h, int *d) { + if (*d != 1) { // We don't yet support replacing 3D textures. return nullptr; } @@ -1519,23 +1519,30 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & return nullptr; } - // Allow some delay to reduce pop-in. - constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0; - double replaceStart = time_now_d(); u64 cachekey = replacer_.Enabled() ? entry->CacheKey() : 0; - ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, w, h); + ReplacedTexture *replaced = replacer_.FindReplacement(cachekey, entry->fullhash, *w, *h); + replacementTimeThisFrame_ += time_now_d() - replaceStart; if (!replaced) { // TODO: Remove the flag here? // entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; - replacementTimeThisFrame_ += time_now_d() - replaceStart; return nullptr; } + entry->replacedTexture = replaced; // we know it's non-null here. + PollReplacement(entry, w, h, d); + return replaced; +} + +void TextureCacheCommon::PollReplacement(TexCacheEntry *entry, int *w, int *h, int *d) { + // Allow some delay to reduce pop-in. + constexpr double MAX_BUDGET_PER_TEX = 0.25 / 60.0; double budget = std::min(MAX_BUDGET_PER_TEX, replacementFrameBudget_ - replacementTimeThisFrame_); - if (replaced->IsReady(budget)) { - if (replaced->State() == ReplacementState::ACTIVE) { - replaced->GetSize(0, &w, &h); + + double replaceStart = time_now_d(); + if (entry->replacedTexture->Poll(budget)) { + if (entry->replacedTexture->State() == ReplacementState::ACTIVE) { + entry->replacedTexture->GetSize(0, w, h); // Consider it already "scaled.". entry->status |= TexCacheEntry::STATUS_IS_SCALED_OR_REPLACED; } @@ -1543,8 +1550,9 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & // Remove the flag, even if it was invalid. entry->status &= ~TexCacheEntry::STATUS_TO_REPLACE; } + replacementTimeThisFrame_ += time_now_d() - replaceStart; - switch (replaced->State()) { + switch (entry->replacedTexture->State()) { case ReplacementState::UNLOADED: case ReplacementState::PENDING: // Make sure we keep polling. @@ -1553,8 +1561,6 @@ ReplacedTexture *TextureCacheCommon::FindReplacement(TexCacheEntry *entry, int & default: break; } - replacementTimeThisFrame_ += time_now_d() - replaceStart; - return replaced; } // This is only used in the GLES backend, where we don't point these to video memory. @@ -2822,7 +2828,7 @@ bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEnt if (canReplace) { // This is the "trigger point" for replacement. - plan.replaced = FindReplacement(entry, plan.w, plan.h, plan.depth); + plan.replaced = FindReplacement(entry, &plan.w, &plan.h, &plan.depth); plan.doReplace = plan.replaced ? plan.replaced->State() == ReplacementState::ACTIVE : false; } else { plan.replaced = nullptr; diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 67e78c6f47..ba97bb135b 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -105,12 +105,18 @@ struct TextureDefinition { GETextureFormat format; }; -// TODO: Shrink this struct. There is some fluff. +// Texture replacement state machine: +// Call FindReplacement during PrepareBuild. +// If replacedTexture gets set: If not found, -> STATUS_TO_REPLACE, otherwise directly -> STATUS_IS_SCALED. +// If replacedTexture is null, leave it at null. +// If replacedTexture is set in SetTexture and STATUS_IS_SCALED is not set, query status. If ready rebuild texture, which will set STATUS_IS_SCALED. // NOTE: These only handle textures loaded directly from PSP memory contents. // Framebuffer textures do not have entries, we bind the framebuffers directly. // At one point we might merge the concepts of framebuffers and textures, but that // moment is far away. + +// TODO: Shrink this struct. There is some fluff. struct TexCacheEntry { ~TexCacheEntry() { if (texturePtr || textureName || vkTex) From 9a228b1f23a76bfe865cc32acd54fb5661bae231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 12:03:32 +0100 Subject: [PATCH 369/424] Avoid calling FindReplacement unnecessarily. --- GPU/Common/TextureCacheCommon.cpp | 6 +++--- GPU/Common/TextureCacheCommon.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index c2359efa67..c1572f0b93 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -531,11 +531,11 @@ TexCacheEntry *TextureCacheCommon::SetTexture() { int w0 = gstate.getTextureWidth(0); int h0 = gstate.getTextureHeight(0); int d0 = 1; - ReplacedTexture *replaced = FindReplacement(entry, &w0, &h0, &d0); - if (replaced) { + if (entry->replacedTexture) { + PollReplacement(entry, &w0, &h0, &d0); // This texture is pending a replacement load. // So check the replacer if it's reached a conclusion. - switch (replaced->State()) { + switch (entry->replacedTexture->State()) { case ReplacementState::NOT_FOUND: // Didn't find a replacement, so stop looking. // DEBUG_LOG(G3D, "No replacement for texture %dx%d", w0, h0); diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index ba97bb135b..6b431184ee 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -389,7 +389,8 @@ protected: CheckAlphaResult DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, TexDecodeFlags flags); void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel); CheckAlphaResult ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool reverseColors, bool expandTo32Bit); - ReplacedTexture *FindReplacement(TexCacheEntry *entry, int &w, int &h, int &d); + ReplacedTexture *FindReplacement(TexCacheEntry *entry, int *w, int *h, int *d); + void PollReplacement(TexCacheEntry *entry, int *w, int *h, int *d); // Return value is mapData normally, but could be another buffer allocated with AllocateAlignedMemory. void LoadTextureLevel(TexCacheEntry &entry, uint8_t *mapData, size_t dataSize, int mapRowPitch, BuildTexturePlan &plan, int srcLevel, Draw::DataFormat dstFmt, TexDecodeFlags texDecFlags); From 3302e6a76bc5b9326f544cac292a5d8b462aa2a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 13:03:05 +0100 Subject: [PATCH 370/424] Lookup filtering overrides at texture load time instead of at runtime. --- GPU/Common/ReplacedTexture.h | 11 +++++++++++ GPU/Common/TextureCacheCommon.cpp | 4 ++-- GPU/Common/TextureReplacer.cpp | 3 +++ GPU/Common/TextureReplacer.h | 3 ++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/GPU/Common/ReplacedTexture.h b/GPU/Common/ReplacedTexture.h index b4716c8b64..4273ffead5 100644 --- a/GPU/Common/ReplacedTexture.h +++ b/GPU/Common/ReplacedTexture.h @@ -23,6 +23,7 @@ #include "Common/File/VFS/VFS.h" #include "Common/GPU/thin3d.h" #include "Common/Log.h" +#include "Core/ConfigValues.h" class TextureReplacer; class LimitedWaitable; @@ -75,6 +76,7 @@ struct ReplacementDesc { uint32_t hash; int w; int h; + TextureFiltering forceFiltering; std::string hashfiles; Path basePath; std::vector filenames; @@ -147,6 +149,15 @@ public: return sz; } + bool ForceFiltering(TextureFiltering *forceFiltering) const { + if (desc_.forceFiltering != (TextureFiltering)0) { + *forceFiltering = desc_.forceFiltering; + return true; + } else { + return false; + } + } + int NumLevels() const { _dbg_assert_(State() == ReplacementState::ACTIVE); return (int)levels_.size(); diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index c1572f0b93..2b5624f47a 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -252,8 +252,8 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac // Filtering overrides from replacements or settings. TextureFiltering forceFiltering = TEX_FILTER_AUTO; - u64 cachekey = replacer_.Enabled() ? (entry ? entry->CacheKey() : 0) : 0; - if (!replacer_.Enabled() || entry == nullptr || !replacer_.FindFiltering(cachekey, entry->fullhash, &forceFiltering)) { + bool useReplacerFiltering = entry && replacer_.Enabled() && entry->replacedTexture && entry->replacedTexture->ForceFiltering(&forceFiltering); + if (!useReplacerFiltering) { switch (g_Config.iTexFiltering) { case TEX_FILTER_AUTO: // Follow what the game wants. We just do a single heuristic change to avoid bleeding of wacky color test colors diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 1dbc82e26a..1628d5fd54 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -501,6 +501,9 @@ ReplacedTexture *TextureReplacer::FindReplacement(u64 cachekey, u32 hash, int w, return nullptr; } + desc.forceFiltering = (TextureFiltering)0; // invalid value + FindFiltering(cachekey, hash, &desc.forceFiltering); + if (!foundAlias) { // We'll just need to generate the names for each level. // By default, we look for png since that's also what's dumped. diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index bd6dd29807..645f26b47c 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -106,7 +106,6 @@ public: // Returns nullptr if not found. ReplacedTexture *FindReplacement(u64 cachekey, u32 hash, int w, int h); - bool FindFiltering(u64 cachekey, u32 hash, TextureFiltering *forceFiltering); // Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.) bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo); @@ -125,6 +124,8 @@ public: static std::string HashName(u64 cachekey, u32 hash, int level); protected: + bool FindFiltering(u64 cachekey, u32 hash, TextureFiltering *forceFiltering); + bool LoadIni(); bool LoadIniValues(IniFile &ini, bool isOverride = false); void ParseHashRange(const std::string &key, const std::string &value); From f5e8d39e42e469c5518288ae5abd998a1f2a24d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 15:01:23 +0100 Subject: [PATCH 371/424] Force mipmapping on when drawing using replacement textures that contain mipmaps. --- GPU/Common/TextureCacheCommon.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 2b5624f47a..16fa289e9b 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -252,7 +252,15 @@ SamplerCacheKey TextureCacheCommon::GetSamplingParams(int maxLevel, const TexCac // Filtering overrides from replacements or settings. TextureFiltering forceFiltering = TEX_FILTER_AUTO; - bool useReplacerFiltering = entry && replacer_.Enabled() && entry->replacedTexture && entry->replacedTexture->ForceFiltering(&forceFiltering); + bool useReplacerFiltering = false; + if (entry && replacer_.Enabled() && entry->replacedTexture && entry->replacedTexture->State() == ReplacementState::ACTIVE) { + // If replacement textures have multiple mip levels, enforce mip filtering. + if (entry->replacedTexture->NumLevels() > 1) { + key.mipFilt = 1; + key.maxLevel = 9 * 256; + } + useReplacerFiltering = entry->replacedTexture->ForceFiltering(&forceFiltering); + } if (!useReplacerFiltering) { switch (g_Config.iTexFiltering) { case TEX_FILTER_AUTO: From baf8cbf27826b1694689cf9775fa0d3108b22a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 18 Mar 2023 15:07:45 +0100 Subject: [PATCH 372/424] Tweaks --- GPU/Common/TextureReplacer.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index 1628d5fd54..b4ccd4cdda 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -909,14 +909,15 @@ bool TextureReplacer::GenerateIni(const std::string &gameID, Path &generatedFile fwrite("\xEF\xBB\xBF", 1, 3, f); // Let's also write some defaults. - fprintf(f, R"(# This file is optional and describes your textures. + fprintf(f, R"(# This describes your textures and set up options for texture replacement. # Documentation about the options and syntax is available here: # https://www.ppsspp.org/docs/reference/texture-replacement + [options] version = 1 hash = quick -ignoreMipmap = false # Set to true to avoid dumping mipmaps. Instead use basisu to generate them, see docs. -reduceHash = false # Usually a good idea to use. +ignoreMipmap = true # Set to true to avoid dumping mipmaps. Instead use basisu to generate them, see docs. +reduceHash = false allowVideo = false [games] @@ -933,9 +934,11 @@ allowVideo = false # Example: 08b31020,512,512 = 480,272 [filtering] -# You can enforce specific filtering modes with this. See the docs. +# You can enforce specific filtering modes with this. Available modes are linear/nearest/auto. See the docs. +# Example: 08d3961000000909ba70b2af = linear [reducehashranges] +# Lets you set regions of memory where reduced hashing applies. See the docs. )", gameID.c_str(), INI_FILENAME.c_str()); fclose(f); } From 0580b09eeb8a9cd2a6ef3d85ec698ec43cd8e832 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Mar 2023 00:00:59 +0100 Subject: [PATCH 373/424] Improve default replacer ini. Various cleanup --- GPU/Common/TextureReplacer.cpp | 27 ++++++++++++++++++--------- GPU/Common/TextureReplacer.h | 2 +- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/GPU/Common/TextureReplacer.cpp b/GPU/Common/TextureReplacer.cpp index b4ccd4cdda..5e369696da 100644 --- a/GPU/Common/TextureReplacer.cpp +++ b/GPU/Common/TextureReplacer.cpp @@ -320,6 +320,11 @@ void TextureReplacer::ParseHashRange(const std::string &key, const std::string & return; } + // Allow addr not starting with 0x, for consistency. TryParse requires 0x to parse as hex. + if (!startsWith(keyParts[0], "0x") && !startsWith(keyParts[0], "0X")) { + keyParts[0] = "0x" + keyParts[0]; + } + u32 addr; u32 fromW; u32 fromH; @@ -869,7 +874,7 @@ bool TextureReplacer::LookupHashRange(u32 addr, int w, int h, int *newW, int *ne } } -float TextureReplacer::LookupReduceHashRange(int& w, int& h) { +float TextureReplacer::LookupReduceHashRange(int w, int h) { const u64 reducerangeKey = ((u64)w << 16) | h; auto range = reducehashranges_.find(reducerangeKey); if (range != reducehashranges_.end()) { @@ -915,10 +920,10 @@ bool TextureReplacer::GenerateIni(const std::string &gameID, Path &generatedFile [options] version = 1 -hash = quick -ignoreMipmap = true # Set to true to avoid dumping mipmaps. Instead use basisu to generate them, see docs. -reduceHash = false -allowVideo = false +hash = quick # options available: "quick", xxh32 - more accurate, but much slower, xxh64 - more accurate and quite fast, but slower than xxh32 on 32 bit cpu's +ignoreMipmap = true # Usually, can just generate them with basisu, no need to dump. +reduceHash = false # Unsafe and can cause glitches in some cases, but allows to skip garbage data in some textures reducing endless duplicates as a side effect speeds up hashing as well, requires stronger hash like xxh32 or xxh64 +ignoreAddress = false # Reduces duplicates at the cost of making hash less reliable, requires stronger hash like xxh32 or xxh64. Basically automatically sets the address to 0 in the dumped filenames. [games] # Used to make it easier to install, and override settings for other regions. @@ -930,15 +935,19 @@ allowVideo = false # See wiki for more info. [hashranges] -# See the documentation. +# This is useful for images that very clearly have smaller dimensions, like 480x272 image. They'll need to be redumped, since the hash will change. See the documentation. # Example: 08b31020,512,512 = 480,272 +# Example: 0x08b31020,512,512 = 480,272 [filtering] -# You can enforce specific filtering modes with this. Available modes are linear/nearest/auto. See the docs. -# Example: 08d3961000000909ba70b2af = linear +# You can enforce specific filtering modes with this. Available modes are linear, nearest, auto. See the docs. +# Example: 08d3961000000909ba70b2af = nearest [reducehashranges] -# Lets you set regions of memory where reduced hashing applies. See the docs. +# Lets you set texture sizes where the hash range is reduced by a factor. See the docs. +# Example: +512,512=0.5 + )", gameID.c_str(), INI_FILENAME.c_str()); fclose(f); } diff --git a/GPU/Common/TextureReplacer.h b/GPU/Common/TextureReplacer.h index 645f26b47c..fdcbfde1f4 100644 --- a/GPU/Common/TextureReplacer.h +++ b/GPU/Common/TextureReplacer.h @@ -132,7 +132,7 @@ protected: void ParseFiltering(const std::string &key, const std::string &value); void ParseReduceHashRange(const std::string& key, const std::string& value); bool LookupHashRange(u32 addr, int w, int h, int *newW, int *newH); - float LookupReduceHashRange(int& w, int& h); + float LookupReduceHashRange(int w, int h); std::string LookupHashFile(u64 cachekey, u32 hash, bool *foundAlias, bool *ignored); bool enabled_ = false; From 6950801e2528526b9815d6f13b2ba647cc6daa9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Fri, 17 Mar 2023 14:06:46 +0100 Subject: [PATCH 374/424] Not much point with a single line cleanup function. Also remove redundant check. --- GPU/Common/ReplacedTexture.cpp | 40 +++++++++++++--------------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/GPU/Common/ReplacedTexture.cpp b/GPU/Common/ReplacedTexture.cpp index 9461a08141..ea63e529f8 100644 --- a/GPU/Common/ReplacedTexture.cpp +++ b/GPU/Common/ReplacedTexture.cpp @@ -404,12 +404,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference ERROR_LOG(G3D, "Could not load texture replacement info: %s - unsupported format %s", filename.c_str(), magic.c_str()); } - // Already populated from cache. TODO: Move this above the first read, and take level.w/h from the cache. - if (!data_[mipLevel].empty()) { - vfs_->CloseFile(openFile); - *pixelFormat = fmt; - return LoadLevelResult::DONE; - } + // TODO: We no longer really need to have a split in this function, the upper and lower parts can be merged now. if (good && mipLevel != 0) { // If loading a low mip directly (through png most likely), check that the mipmap size is correct. @@ -426,10 +421,6 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference return LoadLevelResult::LOAD_ERROR; } - auto cleanup = [&] { - vfs_->CloseFile(openFile); - }; - vfs_->Rewind(openFile); level.fileRef = fileRef; @@ -443,7 +434,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference basist::ktx2_transcoder transcoder; if (!transcoder.init(buffer.data(), (int)buffer.size())) { WARN_LOG(G3D, "Error reading KTX file"); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } @@ -483,7 +474,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference } } else { WARN_LOG(G3D, "PPSSPP currently only supports KTX for basis/UASTC textures. This may change in the future."); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } @@ -523,8 +514,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference levels_.push_back(level); } transcoder.clear(); - cleanup(); - + vfs_->CloseFile(openFile); return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::DDS) { // TODO: Do better with alphaStatus, it's possible. @@ -561,7 +551,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference if (i != 0) level.fileRef = nullptr; // We only provide a fileref on level 0 if we have mipmaps. } - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::DONE; // don't read more levels } else if (imageType == ReplacedImageType::ZIM) { @@ -569,13 +559,13 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference std::unique_ptr zim(new uint8_t[fileSize]); if (!zim) { ERROR_LOG(G3D, "Failed to allocate memory for texture replacement"); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } if (vfs_->Read(openFile, &zim[0], fileSize) != fileSize) { ERROR_LOG(G3D, "Could not load texture replacement: %s - failed to read ZIM", filename.c_str()); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } @@ -586,7 +576,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference if (LoadZIMPtr(&zim[0], fileSize, &w, &h, &f, &image)) { if (w > level.w || h > level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } @@ -609,7 +599,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference good = false; } - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::CONTINUE; } else if (imageType == ReplacedImageType::PNG) { @@ -621,12 +611,12 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference pngdata.resize(vfs_->Read(openFile, &pngdata[0], fileSize)); if (!png_image_begin_read_from_memory(&png, &pngdata[0], pngdata.size())) { ERROR_LOG(G3D, "Could not load texture replacement info: %s - %s (zip)", filename.c_str(), png.message); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } if (png.width > (uint32_t)level.w || png.height > (uint32_t)level.h) { ERROR_LOG(G3D, "Texture replacement changed since header read: %s", filename.c_str()); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::LOAD_ERROR; } @@ -644,7 +634,7 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference out.resize(level.w * level.h * 4); if (!png_image_finish_read(&png, nullptr, &out[0], level.w * 4, nullptr)) { ERROR_LOG(G3D, "Could not load texture replacement: %s - %s", filename.c_str(), png.message); - cleanup(); + vfs_->CloseFile(openFile); out.resize(0); return LoadLevelResult::LOAD_ERROR; } @@ -660,11 +650,11 @@ ReplacedTexture::LoadLevelResult ReplacedTexture::LoadLevelData(VFSFileReference levels_.push_back(level); - cleanup(); + vfs_->CloseFile(openFile); return LoadLevelResult::CONTINUE; } else { WARN_LOG(G3D, "Don't know how to load this image type! %d", (int)imageType); - cleanup(); + vfs_->CloseFile(openFile); } return LoadLevelResult::LOAD_ERROR; } @@ -777,7 +767,7 @@ bool ReplacedTexture::CopyLevelTo(int level, uint8_t *out, size_t outDataSize, i const char *StateString(ReplacementState state) { switch (state) { - case ReplacementState::UNLOADED: return "PREPARED"; + case ReplacementState::UNLOADED: return "UNLOADED"; case ReplacementState::PENDING: return "PENDING"; case ReplacementState::NOT_FOUND: return "NOT_FOUND"; case ReplacementState::ACTIVE: return "ACTIVE"; From 4c67ac8f1293d103bde957e3d547f5a6b86aa140 Mon Sep 17 00:00:00 2001 From: DDinghoya Date: Sun, 19 Mar 2023 17:19:52 +0900 Subject: [PATCH 375/424] Update ko_KR.ini --- assets/lang/ko_KR.ini | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 18f72236d8..d1e7a53a30 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -399,7 +399,6 @@ Warning: Video memory FULL, reducing upscaling and switching to slow caching mod Warning: Video memory FULL, switching to slow caching mode = 비디오 메모리가 가득 찼서, 저속 캐싱 모드로 전환합니다. ZIP file detected (Require UnRAR) = 파일은 (ZIP으로) 압축되어 있습니다.\n먼저 압축을 해제하세요 (UnRAR 시도). ZIP file detected (Require WINRAR) = 파일은 (ZIP으로) 압축되어 있습니다.\n먼저 압축을 해제하세요 (WinRAR 시도). - [Game] Asia = 아시아 Calculate CRC = CRC 계산 @@ -426,7 +425,6 @@ Setting Background = 배경 설정 Show In Folder = 폴더에 표기 USA = 미국 Use UI background = UI 배경 사용 - [Graphics] % of the void = 공백의 % % of viewport = 뷰포트의 % @@ -517,8 +515,8 @@ Must Restart = 이 변경 사항을 적용하려면 PPSSPP를 다시 시작해 Native device resolution = 기본 장치 해상도 Nearest = 근접 필터링 No buffer = 버퍼 없음 -Show Battery % = Show Battery % -Show Speed = Show Speed +Show Battery % = 배터리 % 표시 +Show Speed = 속도 표시 Skip Buffer Effects = 버퍼 효과 건너뛰기(버퍼되지 않음, 더 빠름) None = 없음 Number of Frames = 프레임 수 @@ -545,7 +543,7 @@ Software Rendering = 소프트웨어 렌더링 (느림) Software Skinning = 소프트웨어 스키닝 SoftwareSkinning Tip = 대부분의 게임에서 더 빠르게 CPU에서 스킨 모델 드로우를 결합합니다. Speed = 속도 -Speed Hacks = Speed Hacks (결함을 일으킬 수 있음) +Speed Hacks = 속도 핵 (결함을 일으킬 수 있음) Stereo display shader = 스트레오 디스플레이 쉐이더 Stereo rendering = 스트레오 렌더링 Stretch = 늘이기 @@ -567,7 +565,6 @@ VSync = 수직 동기화 Vulkan = Vulkan Window Size = 창 크기 xBRZ = xBRZ 필터 - [InstallZip] Delete ZIP file = ZIP 파일 삭제 Install = 설치 @@ -615,7 +612,6 @@ SavesAreTemporaryIgnore = 경고 무시 UnpinPath = 고정 해제 UseBrowseOrLoad = 찾아보기를 사용하여 폴더를 선택하거나 불러오기를 사용하여 파일을 선택합니다. www.ppsspp.org = www.ppsspp.org - [MainSettings] Audio = 오디오 Controls = 조작 @@ -624,7 +620,6 @@ Networking = 네트워킹 System = 시스템 Tools = 도구 Search = 검색 - [MappableControls] Alt speed 1 = 대체 속도 1 Alt speed 2 = 대체 속도 2 @@ -707,7 +702,6 @@ Display Landscape = 가로방향 표시 Display Landscape Reversed = 가로방향 반전 표시 Display Portrait = 세로방향 표시 Display Portrait Reversed = 세로방향 반전 표시 - [Networking] AdHoc Server = Ad hoc 서버 AdhocServer Failed to Bind Port = Ad Hoc 서버가 포트를 바인딩하지 못했습니다. @@ -918,7 +912,6 @@ Share Games (Server) = 게임 공유하기 (서버) Share on PPSSPP startup = PPSSPP 시작시 자동으로 공유하기 Stop Sharing = 공유 끝내기 Stopping.. = 중지하는 중... - [Reporting] Bad = 나쁨 FeedbackCRCCalculating = 디스크 CRC: 계산 중... @@ -981,7 +974,7 @@ Failed to load state = 상태를 불러오지 못함 Failed to save state = 상태를 저장하지 못함 fixed = 속도: 대체 GLToolsWarning = 경고: GLTools가 감지되어 문제를 일으킬 수 있습니다. -In menu = 메뉴 +In menu = 메뉴에서 Load savestate failed = 저장 상태 불러오기 실패 Loaded State = 불러온 상태 Loaded. Save in game, restart, and load for less bugs. = 불러왔습니다. 버그를 줄이기 위해 게임을 저장하고 다시 시작하고 불러오세요. @@ -1002,7 +995,6 @@ SpeedCustom2 = Speed: 대체 2 standard = 속도: 표준 State load undone = 상태 불러오기 취소 Untitled PSP game = 제목 없는 PSP 게임 - [Store] Already Installed = 이미 설치됨 Connection Error = 연결 오류 @@ -1012,7 +1004,6 @@ Loading... = 불러오기 중... MB = 메가바이트 Size = 크기 Uninstall = 제거 - [SysInfo] %d (%d per core, %d cores) = %d (코어 당 %d, 코어 %d 개) %d bytes = %d 바이트 @@ -1027,7 +1018,7 @@ Board = 보드 Build Config = 빌드 구성 Build Configuration = 빌드 구성 Built by = 빌더 -Compressed texture formats = Compressed texture formats +Compressed texture formats = 압축된 텍스처 형식 Core Context = 코어 컨텍스트 Cores = 코어 CPU Extensions = CPU 확장 @@ -1078,7 +1069,6 @@ Version Information = 버전 정보 Vulkan Extensions = Vulkan 확장 Vulkan Features = Vulkan 기능 Display Color Formats = 디스플레이 색상 형식 - [System] (broken) = (고장) 12HR = 12시간 @@ -1195,7 +1185,7 @@ Color Saturation = 채도 Show Memory Stick folder = 메모리 스틱 폴더 표시 [Themes] -Dark = Dark +Dark = 어두움 Default = 기본 [TextureShaders] From 858675e43e8121cf9f40fae532aebc7c655d1cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 09:30:43 +0100 Subject: [PATCH 376/424] Update glslang to latest --- ext/glslang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/glslang b/ext/glslang index 77551c429f..b34f619e1c 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit 77551c429f86c0e077f26552b7c1c0f12a9f235e +Subproject commit b34f619e1c85810dcb3c578107d2e48ba4ee2b37 From a9eaa4fdc88d9e07c8f782c23e396709602ecfbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 2 Feb 2023 14:54:50 +0100 Subject: [PATCH 377/424] Get rid of an ifdef --- Common/System/System.h | 1 + Qt/QtMain.cpp | 1 + SDL/SDLMain.cpp | 6 ++++++ UI/GameSettingsScreen.cpp | 14 ++++++-------- UI/GameSettingsScreen.h | 1 - UWP/PPSSPP_UWPMain.cpp | 2 ++ Windows/main.cpp | 1 + android/jni/app-android.cpp | 2 ++ ios/main.mm | 2 ++ 9 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index 6f1524ab03..38482d3e41 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -73,6 +73,7 @@ enum SystemProperty { SYSPROP_HAS_IMAGE_BROWSER, SYSPROP_HAS_BACK_BUTTON, SYSPROP_HAS_KEYBOARD, + SYSPROP_HAS_OPEN_DIRECTORY, // Available as Int: SYSPROP_SYSTEMVERSION, diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 6809e9fec9..10b7f8ca9d 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -235,6 +235,7 @@ bool System_GetPropertyBool(SystemProperty prop) { return true; case SYSPROP_HAS_FILE_BROWSER: case SYSPROP_HAS_FOLDER_BROWSER: + case SYSPROP_HAS_OPEN_DIRECTORY: return true; case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 1acd96e77a..cf77b7e109 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -427,6 +427,12 @@ float System_GetPropertyFloat(SystemProperty prop) { bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { + case SYSPROP_HAS_OPEN_DIRECTORY: +#if PPSSPP_PLATFORM(WINDOWS) + return true; +#elif PPSSPP_PLATFORM(MAC) || (PPSSPP_PLATFORM(LINUX) && !PPSSPP_PLATFORM(ANDROID)) + return true; +#endif case SYSPROP_HAS_BACK_BUTTON: return true; case SYSPROP_APP_GOLD: diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 6d8d0af62e..499765ec7b 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -963,9 +963,12 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { systemSettings->Add(new ItemHeader(sy->T("PSP Memory Stick"))); -#if (defined(USING_QT_UI) || PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(MAC)) && !PPSSPP_PLATFORM(UWP) - systemSettings->Add(new Choice(sy->T("Show Memory Stick folder")))->OnClick.Handle(this, &GameSettingsScreen::OnOpenMemStick); -#endif + if (System_GetPropertyBool(SYSPROP_HAS_OPEN_DIRECTORY)) { + systemSettings->Add(new Choice(sy->T("Show Memory Stick folder")))->OnClick.Add([](UI::EventParams &p) { + OpenDirectory(File::ResolvePath(g_Config.memStickDirectory.ToString()).c_str()); + return UI::EVENT_DONE; + }); + } #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) systemSettings->Add(new Choice(sy->T("Set Memory Stick folder")))->OnClick.Handle(this, &GameSettingsScreen::OnChangeMemStickDir); @@ -1243,11 +1246,6 @@ UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) { return UI::EVENT_DONE; } -UI::EventReturn GameSettingsScreen::OnOpenMemStick(UI::EventParams &e) { - OpenDirectory(File::ResolvePath(g_Config.memStickDirectory.ToString()).c_str()); - return UI::EVENT_DONE; -} - #if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) UI::EventReturn GameSettingsScreen::OnSavePathMydoc(UI::EventParams &e) { diff --git a/UI/GameSettingsScreen.h b/UI/GameSettingsScreen.h index 8471af21d3..89f1ce23ad 100644 --- a/UI/GameSettingsScreen.h +++ b/UI/GameSettingsScreen.h @@ -118,7 +118,6 @@ private: UI::EventReturn OnAudioDevice(UI::EventParams &e); UI::EventReturn OnJitAffectingSetting(UI::EventParams &e); UI::EventReturn OnChangeMemStickDir(UI::EventParams &e); - UI::EventReturn OnOpenMemStick(UI::EventParams &e); #if defined(_WIN32) && !PPSSPP_PLATFORM(UWP) UI::EventReturn OnSavePathMydoc(UI::EventParams &e); UI::EventReturn OnSavePathOther(UI::EventParams &e); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 5fabe3a4e1..dd4ae939e7 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -411,6 +411,8 @@ void System_Toast(const char *str) {} bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { + case SYSPROP_HAS_OPEN_DIRECTORY: + return false; case SYSPROP_HAS_FILE_BROWSER: return true; case SYSPROP_HAS_FOLDER_BROWSER: diff --git a/Windows/main.cpp b/Windows/main.cpp index 973243a070..f1be24ef22 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -346,6 +346,7 @@ bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { case SYSPROP_HAS_FILE_BROWSER: case SYSPROP_HAS_FOLDER_BROWSER: + case SYSPROP_HAS_OPEN_DIRECTORY: return true; case SYSPROP_HAS_IMAGE_BROWSER: return true; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index d7ac20ec4b..e89ec0ec33 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -491,6 +491,8 @@ bool System_GetPropertyBool(SystemProperty prop) { } case SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE: return sustainedPerfSupported; // 7.0 introduced sustained performance mode as an optional feature. + case SYSPROP_HAS_OPEN_DIRECTORY: + return false; case SYSPROP_HAS_ADDITIONAL_STORAGE: return !g_additionalStorageDirs.empty(); case SYSPROP_HAS_BACK_BUTTON: diff --git a/ios/main.mm b/ios/main.mm index 49b35c50b0..3f7e6556d2 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -152,6 +152,8 @@ float System_GetPropertyFloat(SystemProperty prop) { bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { + case SYSPROP_HAS_OPEN_DIRECTORY: + return false; case SYSPROP_HAS_BACK_BUTTON: return false; case SYSPROP_APP_GOLD: From d3955b42bb0e4d18a7d91e4661dc58d2e21dd434 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 10:42:23 +0100 Subject: [PATCH 378/424] Rename some system functions, merge the Launch* ones. android launchurl buildfix --- Common/System/System.h | 33 ++++++++--- Core/HLE/sceUsbCam.cpp | 2 +- Core/HLE/sceUsbMic.cpp | 4 +- Core/Host.h | 1 - Qt/QtHost.h | 7 --- Qt/QtMain.cpp | 6 +- SDL/SDLMain.cpp | 95 +++++++++++++------------------ UI/CwCheatScreen.cpp | 2 +- UI/GameScreen.cpp | 4 +- UI/GameSettingsScreen.cpp | 6 +- UI/GamepadEmu.cpp | 10 ++-- UI/HostTypes.h | 1 - UI/MainScreen.cpp | 18 +++--- UI/MemStickScreen.cpp | 2 +- UI/MiscScreens.cpp | 16 +++--- UI/ReportScreen.cpp | 4 +- UWP/PPSSPP_UWPMain.cpp | 6 +- UWP/UWPHost.cpp | 4 -- UWP/UWPHost.h | 1 - Windows/EmuThread.cpp | 2 +- Windows/GEDebugger/GEDebugger.cpp | 8 +-- Windows/WindowsHost.cpp | 8 --- Windows/WindowsHost.h | 1 - Windows/main.cpp | 6 +- android/jni/app-android.cpp | 28 ++++----- headless/Headless.cpp | 4 +- headless/StubHost.h | 1 - ios/CameraHelper.mm | 2 +- ios/ViewController.mm | 86 ++++++++++++++-------------- ios/main.mm | 4 +- libretro/libretro.cpp | 7 +-- unittest/UnitTest.cpp | 6 +- 32 files changed, 178 insertions(+), 207 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index 38482d3e41..cbb5ad950b 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -4,6 +4,16 @@ #include #include +// Platform integration + +// To run the PPSSPP core, a platform needs to implement all the System_ functions in this file, +// plus derive an object from Host (see Host.h). The latter will be phased out. +// Failure to implement all of these will simply cause linker failures. There are a few that are +// only implemented on specific platforms, but they're also only called on those platforms. + +// The platform then calls the entry points from NativeApp.h as appropriate. That's basically it, +// disregarding build system complexities. + enum SystemPermission { SYSTEM_PERMISSION_STORAGE, }; @@ -18,7 +28,7 @@ enum PermissionStatus { // These APIs must be implemented by every port (for example app-android.cpp, SDLMain.cpp). // Ideally these should be safe to call from any thread. void System_Toast(const char *text); -void ShowKeyboard(); +void System_ShowKeyboard(); // Vibrate either takes a number of milliseconds to vibrate unconditionally, // or you can specify these constants for "standard" feedback. On Android, @@ -30,11 +40,16 @@ enum { HAPTIC_VIRTUAL_KEY = -2, HAPTIC_LONG_PRESS_ACTIVATED = -3, }; -void Vibrate(int length_ms); -void OpenDirectory(const char *path); -void LaunchBrowser(const char *url); -void LaunchMarket(const char *url); -void LaunchEmail(const char *email_address); + +enum class LaunchUrlType { + BROWSER_URL, + MARKET_URL, + EMAIL_ADDRESS, +}; + +void System_Vibrate(int length_ms); +void System_ShowFileInFolder(const char *path); +void System_LaunchUrl(LaunchUrlType urlType, const char *url); void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb); void System_SendMessage(const char *command, const char *parameter); PermissionStatus System_GetPermissionStatus(SystemPermission permission); @@ -123,6 +138,6 @@ int System_GetPropertyInt(SystemProperty prop); float System_GetPropertyFloat(SystemProperty prop); bool System_GetPropertyBool(SystemProperty prop); -std::vector __cameraGetDeviceList(); -bool audioRecording_Available(); -bool audioRecording_State(); +std::vector System_GetCameraDeviceList(); +bool System_AudioRecordingIsAvailable(); +bool System_AudioRecordingState(); diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index c8d43a5027..571f846545 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -332,7 +332,7 @@ std::vector Camera::getDeviceList() { return winCamera->getDeviceList(); } #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) - return __cameraGetDeviceList(); + return System_GetCameraDeviceList(); #elif defined(USING_QT_UI) // Qt:macOS / Qt:Linux return __qt_getDeviceList(); #elif PPSSPP_PLATFORM(LINUX) // SDL:Linux diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 0626f9f4d2..8ab6ff23da 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -103,7 +103,7 @@ void __UsbMicInit() { curChannels = 1; curTargetAddr = 0; readMicDataLength = 0; - micState = 0; + micState = 0; eventMicBlockingResume = CoreTiming::RegisterEvent("MicBlockingResume", &__MicBlockingResume); } @@ -349,7 +349,7 @@ bool Microphone::isHaveDevice() { #ifdef HAVE_WIN32_MICROPHONE return winMic->getDeviceCounts() >= 1; #elif PPSSPP_PLATFORM(ANDROID) - return audioRecording_Available(); + return System_AudioRecordingIsAvailable(); #endif return false; } diff --git a/Core/Host.h b/Core/Host.h index 4a4c739c3d..eba025e428 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -45,7 +45,6 @@ public: //this is sent from EMU thread! Make sure that Host handles it properly! virtual void BootDone() {} - virtual bool IsDebuggingEnabled() {return true;} virtual bool AttemptLoadSymbolMap(); virtual void SaveSymbolMap() {} virtual void NotifySymbolMapUpdated() {} diff --git a/Qt/QtHost.h b/Qt/QtHost.h index d8fa12f1f7..a0327474c1 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -56,13 +56,6 @@ public: mainWindow->Notify(MainWindowMsg::BOOT_DONE); } - bool IsDebuggingEnabled() override { -#ifdef _DEBUG - return true; -#else - return false; -#endif - } bool AttemptLoadSymbolMap() override { auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); return g_symbolMap->LoadSymbolMap(fn); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 10b7f8ca9d..354ea7399b 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -295,18 +295,18 @@ void System_InputBoxGetString(const std::string &title, const std::string &defau } } -void Vibrate(int length_ms) { +void System_Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; else if (length_ms == -2) length_ms = 25; } -void OpenDirectory(const char *path) { +void System_ShowFileInFolder(const char *path) { QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromUtf8(path))); } -void LaunchBrowser(const char *url) +void System_LaunchUrl(LaunchUrlType urlType, const char *url) { QDesktopServices::openUrl(QUrl(url)); } diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index cf77b7e109..c11a50476b 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -158,11 +158,11 @@ void System_Toast(const char *text) { #endif } -void ShowKeyboard() { +void System_ShowKeyboard() { // Irrelevant on PC } -void Vibrate(int length_ms) { +void System_Vibrate(int length_ms) { // Ignore on PC } @@ -194,18 +194,18 @@ void System_SendMessage(const char *command, const char *parameter) { DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { NativeMessageReceived("browse_folder", thePathChosen.c_str()); }; - + DarwinFileSystemServices services; services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectorites = */ true); } #endif - + } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } -void OpenDirectory(const char *path) { +void System_ShowFileInFolder(const char *path) { #if PPSSPP_PLATFORM(WINDOWS) SFGAOF flags; PIDLIST_ABSOLUTE pidl = nullptr; @@ -231,68 +231,53 @@ void OpenDirectory(const char *path) { #endif } -void LaunchBrowser(const char *url) { +void System_LaunchUrl(LaunchUrlType urlType, const char *url) { + switch (urlType) { + case LaunchUrlType::BROWSER_URL: + case LaunchUrlType::MARKET_URL: + { #if PPSSPP_PLATFORM(SWITCH) - Uuid uuid = { 0 }; - WebWifiConfig conf; - webWifiCreate(&conf, NULL, url, uuid, 0); - webWifiShow(&conf, NULL); + Uuid uuid = { 0 }; + WebWifiConfig conf; + webWifiCreate(&conf, NULL, url, uuid, 0); + webWifiShow(&conf, NULL); #elif defined(MOBILE_DEVICE) - INFO_LOG(SYSTEM, "Would have gone to %s but LaunchBrowser is not implemented on this platform", url); + INFO_LOG(SYSTEM, "Would have gone to %s but LaunchBrowser is not implemented on this platform", url); #elif defined(_WIN32) - std::wstring wurl = ConvertUTF8ToWString(url); - ShellExecute(NULL, L"open", wurl.c_str(), NULL, NULL, SW_SHOWNORMAL); + std::wstring wurl = ConvertUTF8ToWString(url); + ShellExecute(NULL, L"open", wurl.c_str(), NULL, NULL, SW_SHOWNORMAL); #elif defined(__APPLE__) - std::string command = std::string("open ") + url; - system(command.c_str()); + std::string command = std::string("open ") + url; + system(command.c_str()); #else - std::string command = std::string("xdg-open ") + url; - int err = system(command.c_str()); - if (err) { - INFO_LOG(SYSTEM, "Would have gone to %s but xdg-utils seems not to be installed", url); - } + std::string command = std::string("xdg-open ") + url; + int err = system(command.c_str()); + if (err) { + INFO_LOG(SYSTEM, "Would have gone to %s but xdg-utils seems not to be installed", url); + } #endif -} - -void LaunchMarket(const char *url) { -#if PPSSPP_PLATFORM(SWITCH) - Uuid uuid = { 0 }; - WebWifiConfig conf; - webWifiCreate(&conf, NULL, url, uuid, 0); - webWifiShow(&conf, NULL); -#elif defined(MOBILE_DEVICE) - INFO_LOG(SYSTEM, "Would have gone to %s but LaunchMarket is not implemented on this platform", url); -#elif defined(_WIN32) - std::wstring wurl = ConvertUTF8ToWString(url); - ShellExecute(NULL, L"open", wurl.c_str(), NULL, NULL, SW_SHOWNORMAL); -#elif defined(__APPLE__) - std::string command = std::string("open ") + url; - system(command.c_str()); -#else - std::string command = std::string("xdg-open ") + url; - int err = system(command.c_str()); - if (err) { - INFO_LOG(SYSTEM, "Would have gone to %s but xdg-utils seems not to be installed", url); + break; } -#endif -} - -void LaunchEmail(const char *email_address) { + case LaunchUrlType::EMAIL_ADDRESS: + { #if defined(MOBILE_DEVICE) - INFO_LOG(SYSTEM, "Would have opened your email client for %s but LaunchEmail is not implemented on this platform", email_address); + INFO_LOG(SYSTEM, "Would have opened your email client for %s but LaunchEmail is not implemented on this platform", url); #elif defined(_WIN32) - std::wstring mailto = std::wstring(L"mailto:") + ConvertUTF8ToWString(email_address); - ShellExecute(NULL, L"open", mailto.c_str(), NULL, NULL, SW_SHOWNORMAL); + std::wstring mailto = std::wstring(L"mailto:") + ConvertUTF8ToWString(url); + ShellExecute(NULL, L"open", mailto.c_str(), NULL, NULL, SW_SHOWNORMAL); #elif defined(__APPLE__) - std::string command = std::string("open mailto:") + email_address; - system(command.c_str()); + std::string command = std::string("open mailto:") + url; + system(command.c_str()); #else - std::string command = std::string("xdg-email ") + email_address; - int err = system(command.c_str()); - if (err) { - INFO_LOG(SYSTEM, "Would have gone to %s but xdg-utils seems not to be installed", email_address); - } + std::string command = std::string("xdg-email ") + url; + int err = system(command.c_str()); + if (err) { + INFO_LOG(SYSTEM, "Would have gone to %s but xdg-utils seems not to be installed", url); + } #endif + break; + } + } } std::string System_GetProperty(SystemProperty prop) { diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index cd6f052ab1..a8f0c9a70f 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -173,7 +173,7 @@ UI::EventReturn CwCheatScreen::OnEditCheatFile(UI::EventParams ¶ms) { } if (engine_) { #if PPSSPP_PLATFORM(UWP) - LaunchBrowser(engine_->CheatFilename().c_str()); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, engine_->CheatFilename().c_str()); #else File::OpenFileInEditor(engine_->CheatFilename()); #endif diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 33773e5adb..3cf6347576 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -140,7 +140,7 @@ void GameScreen::CreateViews() { ViewGroup *rightColumn = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins)); root_->Add(rightColumn); - + LinearLayout *rightColumnItems = new LinearLayout(ORIENT_VERTICAL); rightColumnItems->SetSpacing(0.0f); rightColumn->Add(rightColumnItems); @@ -328,7 +328,7 @@ void GameScreen::render() { } UI::EventReturn GameScreen::OnShowInFolder(UI::EventParams &e) { - OpenDirectory(gamePath_.c_str()); + System_ShowFileInFolder(gamePath_.c_str()); return UI::EVENT_DONE; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 499765ec7b..b368e8114f 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -965,7 +965,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { if (System_GetPropertyBool(SYSPROP_HAS_OPEN_DIRECTORY)) { systemSettings->Add(new Choice(sy->T("Show Memory Stick folder")))->OnClick.Add([](UI::EventParams &p) { - OpenDirectory(File::ResolvePath(g_Config.memStickDirectory.ToString()).c_str()); + System_ShowFileInFolder(File::ResolvePath(g_Config.memStickDirectory.ToString()).c_str()); return UI::EVENT_DONE; }); } @@ -1213,7 +1213,7 @@ void RecreateActivity() { UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) { auto n = GetI18NCategory("Networking"); - LaunchBrowser(n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP")); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP")); return UI::EVENT_DONE; } @@ -1238,7 +1238,7 @@ UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) { DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { DarwinFileSystemServices::setUserPreferredMemoryStickDirectory(thePathChosen); }; - + memoryStickManager.presentDirectoryPanel(callback); #else screenManager()->push(new MemStickScreen(false)); diff --git a/UI/GamepadEmu.cpp b/UI/GamepadEmu.cpp index 5f997fca42..ccd9a1ddde 100644 --- a/UI/GamepadEmu.cpp +++ b/UI/GamepadEmu.cpp @@ -180,7 +180,7 @@ bool PSPButton::Touch(const TouchInput &input) { bool down = pointerDownMask_ != 0; if (down && !lastDown) { if (g_Config.bHapticFeedback) { - Vibrate(HAPTIC_VIRTUAL_KEY); + System_Vibrate(HAPTIC_VIRTUAL_KEY); } __CtrlButtonDown(pspButtonBit_); } else if (lastDown && !down) { @@ -210,7 +210,7 @@ bool ComboKey::Touch(const TouchInput &input) { if (down && !lastDown) { if (g_Config.bHapticFeedback) - Vibrate(HAPTIC_VIRTUAL_KEY); + System_Vibrate(HAPTIC_VIRTUAL_KEY); if (!repeat_) { for (int i = 0; i < ARRAY_SIZE(comboKeyList); i++) { @@ -359,7 +359,7 @@ void PSPDpad::ProcessTouch(float x, float y, bool down) { for (int i = 0; i < 4; i++) { if (pressed & dir[i]) { if (g_Config.bHapticFeedback) { - Vibrate(HAPTIC_VIRTUAL_KEY); + System_Vibrate(HAPTIC_VIRTUAL_KEY); } __CtrlButtonDown(dir[i]); } @@ -829,8 +829,8 @@ UI::ViewGroup *CreatePadLayout(float xres, float yres, bool *pause, bool showPau auto addComboKey = [=](const ConfigCustomButton& cfg, const char *key, const ConfigTouchPos &touch) -> ComboKey * { using namespace CustomKey; if (touch.show) { - auto aux = root->Add(new ComboKey(cfg.key, key, cfg.toggle, cfg.repeat, controllMapper, - g_Config.iTouchButtonStyle == 0 ? comboKeyShapes[cfg.shape].i : comboKeyShapes[cfg.shape].l, comboKeyShapes[cfg.shape].i, + auto aux = root->Add(new ComboKey(cfg.key, key, cfg.toggle, cfg.repeat, controllMapper, + g_Config.iTouchButtonStyle == 0 ? comboKeyShapes[cfg.shape].i : comboKeyShapes[cfg.shape].l, comboKeyShapes[cfg.shape].i, comboKeyImages[cfg.image].i, touch.scale, comboKeyShapes[cfg.shape].d, buttonLayoutParams(touch))); aux->SetAngle(comboKeyImages[cfg.image].r, comboKeyShapes[cfg.shape].r); aux->FlipImageH(comboKeyShapes[cfg.shape].f); diff --git a/UI/HostTypes.h b/UI/HostTypes.h index c801859b07..528ae90f73 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -41,7 +41,6 @@ public: // this is sent from EMU thread! Make sure that Host handles it properly! void BootDone() override {} - bool IsDebuggingEnabled() override {return false;} bool AttemptLoadSymbolMap() override {return false;} void NotifySymbolMapUpdated() override {} void SetWindowTitle(const char *message) override {} diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index ed600b42d3..ba2b3e9276 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -533,7 +533,7 @@ UI::EventReturn GameBrowser::LayoutChange(UI::EventParams &e) { } UI::EventReturn GameBrowser::LastClick(UI::EventParams &e) { - LaunchBrowser(lastLink_.c_str()); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, lastLink_.c_str()); return UI::EVENT_DONE; } @@ -1226,16 +1226,16 @@ UI::EventReturn MainScreen::OnDownloadUpgrade(UI::EventParams &e) { #if PPSSPP_PLATFORM(ANDROID) // Go to app store if (System_GetPropertyBool(SYSPROP_APP_GOLD)) { - LaunchBrowser("market://details?id=org.ppsspp.ppssppgold"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "market://details?id=org.ppsspp.ppssppgold"); } else { - LaunchBrowser("market://details?id=org.ppsspp.ppsspp"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "market://details?id=org.ppsspp.ppsspp"); } #elif PPSSPP_PLATFORM(WINDOWS) - LaunchBrowser("https://www.ppsspp.org/download"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/download"); #else // Go directly to ppsspp.org and let the user sort it out // (for details and in case downloads doesn't have their platform.) - LaunchBrowser("https://www.ppsspp.org/"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/"); #endif return UI::EVENT_DONE; } @@ -1414,20 +1414,20 @@ UI::EventReturn MainScreen::OnCredits(UI::EventParams &e) { UI::EventReturn MainScreen::OnSupport(UI::EventParams &e) { #ifdef __ANDROID__ - LaunchBrowser("market://details?id=org.ppsspp.ppssppgold"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "market://details?id=org.ppsspp.ppssppgold"); #else - LaunchBrowser("https://www.ppsspp.org/buygold"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/buygold"); #endif return UI::EVENT_DONE; } UI::EventReturn MainScreen::OnPPSSPPOrg(UI::EventParams &e) { - LaunchBrowser("https://www.ppsspp.org"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org"); return UI::EVENT_DONE; } UI::EventReturn MainScreen::OnForums(UI::EventParams &e) { - LaunchBrowser("https://forums.ppsspp.org"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://forums.ppsspp.org"); return UI::EVENT_DONE; } diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index e640dd5399..265be6bf68 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -304,7 +304,7 @@ void MemStickScreen::CreateViews() { UI::EventReturn MemStickScreen::OnHelp(UI::EventParams ¶ms) { // I'm letting the old redirect handle this one, as the target is within /docs on the website, // and that structure may change a bit. - LaunchBrowser("https://www.ppsspp.org/guide_storage.html"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/guide_storage.html"); return UI::EVENT_DONE; } diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index b9e93d7ab0..170844f6a4 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -657,7 +657,7 @@ void NewLanguageScreen::OnCompleted(DialogResult result) { g_Config.sLanguageIni = code; bool iniLoadedSuccessfully = false; - // Allow the lang directory to be overridden for testing purposes (e.g. Android, where it's hard to + // Allow the lang directory to be overridden for testing purposes (e.g. Android, where it's hard to // test new languages without recompiling the entire app, which is a hassle). const Path langOverridePath = GetSysDirectory(DIRECTORY_SYSTEM) / "lang"; @@ -840,9 +840,9 @@ void CreditsScreen::CreateViews() { UI::EventReturn CreditsScreen::OnSupport(UI::EventParams &e) { #ifdef __ANDROID__ - LaunchBrowser("market://details?id=org.ppsspp.ppssppgold"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "market://details?id=org.ppsspp.ppssppgold"); #else - LaunchBrowser("https://www.ppsspp.org/buygold"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/buygold"); #endif return UI::EVENT_DONE; } @@ -851,28 +851,28 @@ UI::EventReturn CreditsScreen::OnTwitter(UI::EventParams &e) { #ifdef __ANDROID__ System_SendMessage("showTwitter", "PPSSPP_emu"); #else - LaunchBrowser("https://twitter.com/#!/PPSSPP_emu"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://twitter.com/#!/PPSSPP_emu"); #endif return UI::EVENT_DONE; } UI::EventReturn CreditsScreen::OnPPSSPPOrg(UI::EventParams &e) { - LaunchBrowser("https://www.ppsspp.org"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org"); return UI::EVENT_DONE; } UI::EventReturn CreditsScreen::OnPrivacy(UI::EventParams &e) { - LaunchBrowser("https://www.ppsspp.org/privacy"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.ppsspp.org/privacy"); return UI::EVENT_DONE; } UI::EventReturn CreditsScreen::OnForums(UI::EventParams &e) { - LaunchBrowser("https://forums.ppsspp.org"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://forums.ppsspp.org"); return UI::EVENT_DONE; } UI::EventReturn CreditsScreen::OnDiscord(UI::EventParams &e) { - LaunchBrowser("https://discord.gg/5NJB6dD"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://discord.gg/5NJB6dD"); return UI::EVENT_DONE; } diff --git a/UI/ReportScreen.cpp b/UI/ReportScreen.cpp index 7bd0815de5..44585eb85a 100644 --- a/UI/ReportScreen.cpp +++ b/UI/ReportScreen.cpp @@ -392,7 +392,7 @@ EventReturn ReportScreen::HandleSubmit(EventParams &e) { EventReturn ReportScreen::HandleBrowser(EventParams &e) { const std::string url = "https://" + Reporting::ServerHost() + "/"; - LaunchBrowser(url.c_str()); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, url.c_str()); return EVENT_DONE; } @@ -515,6 +515,6 @@ void ReportFinishScreen::ShowSuggestions() { UI::EventReturn ReportFinishScreen::HandleViewFeedback(UI::EventParams &e) { const std::string url = "https://" + Reporting::ServerHost() + "/game/" + Reporting::CurrentGameID(); - LaunchBrowser(url.c_str()); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, url.c_str()); return EVENT_DONE; } diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index dd4ae939e7..87e7fff4c6 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -476,17 +476,17 @@ void System_SendMessage(const char *command, const char *parameter) { } } -void OpenDirectory(const char *path) { +void System_ShowFileInFolder(const char *path) { // Unsupported } -void LaunchBrowser(const char *url) { +void System_LaunchUrl(LaunchUrlType urlType, const char *url) { auto uri = ref new Windows::Foundation::Uri(ToPlatformString(url)); create_task(Windows::System::Launcher::LaunchUriAsync(uri)).then([](bool b) {}); } -void Vibrate(int length_ms) { +void System_Vibrate(int length_ms) { #if _M_ARM if (length_ms == -1 || length_ms == -3) length_ms = 50; diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index 5e489e161c..977d5ddfc9 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -148,10 +148,6 @@ void UWPHost::NotifySymbolMapUpdated() { g_symbolMap->SortSymbols(); } -bool UWPHost::IsDebuggingEnabled() { - return false; -} - bool UWPHost::CanCreateShortcut() { return false; // Turn on when below function fixed } diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index ee49d0cba5..dea4547aa5 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -26,7 +26,6 @@ public: void UpdateSound() override; void ShutdownSound() override; - bool IsDebuggingEnabled() override; void BootDone() override; bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index c28b59279e..c4225d95d8 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -219,7 +219,7 @@ void MainThreadFunc() { } else { if (g_Config.iGPUBackend == (int)GPUBackend::DIRECT3D9) { // Allow the user to download the DX9 runtime. - LaunchBrowser("https://www.microsoft.com/en-us/download/details.aspx?id=34429"); + System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://www.microsoft.com/en-us/download/details.aspx?id=34429"); } } diff --git a/Windows/GEDebugger/GEDebugger.cpp b/Windows/GEDebugger/GEDebugger.cpp index ae35d85ab6..c96643cc38 100644 --- a/Windows/GEDebugger/GEDebugger.cpp +++ b/Windows/GEDebugger/GEDebugger.cpp @@ -991,7 +991,7 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { tabRect.right = tabRect.left + (width / 2 - tabRect.left * 2); } tabRect.bottom = tabRect.top + (height - tabRect.top - tabRect.left); - + RECT tabRectRight = tabRect; if (tabs && tabsRight_ && tabs->Count() == 0 && tabsRight_->Count() != 0) { tabRect.right = tabRect.left; @@ -1005,7 +1005,7 @@ void CGEDebugger::UpdateSize(WORD width, WORD height) { HWND frameWnd = GetDlgItem(m_hDlg, IDC_GEDBG_FRAME); GetWindowRect(frameWnd, &frameRect); MapWindowPoints(HWND_DESKTOP, m_hDlg, (LPPOINT)&frameRect, 2); - + RECT trRect = { frameRect.right + 10, frameRect.top, tabRectRight.right, tabRectRight.top }; if (tabsTR_ && tabsTR_->Count() == 0) { trRect.right = trRect.left; @@ -1045,7 +1045,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { UpdateSize(LOWORD(lParam), HIWORD(lParam)); SavePosition(); return TRUE; - + case WM_MOVE: SavePosition(); return TRUE; @@ -1213,7 +1213,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) { case IDC_GEDBG_RECORD: GPURecord::SetCallback([](const Path &path) { // Opens a Windows Explorer window with the file. - OpenDirectory(path.c_str()); + System_ShowFileInFolder(path.c_str()); }); GPURecord::Activate(); break; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 5f194bcd88..c92483f0b8 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -304,14 +304,6 @@ void WindowsHost::NotifySymbolMapUpdated() { PostMessage(mainWindow_, WM_USER + 1, 0, 0); } -bool WindowsHost::IsDebuggingEnabled() { -#ifdef _DEBUG - return true; -#else - return false; -#endif -} - // http://msdn.microsoft.com/en-us/library/aa969393.aspx HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathLink, LPCWSTR lpszDesc) { HRESULT hres; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 492d47a9db..6eb659e55e 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -48,7 +48,6 @@ public: void UpdateSound() override; void ShutdownSound() override; - bool IsDebuggingEnabled() override; void BootDone() override; bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; diff --git a/Windows/main.cpp b/Windows/main.cpp index f1be24ef22..b776533ddc 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -110,7 +110,7 @@ int g_activeWindow = 0; static std::thread inputBoxThread; static bool inputBoxRunning = false; -void OpenDirectory(const char *path) { +void System_ShowFileInFolder(const char *path) { // SHParseDisplayName can't handle relative paths, so normalize first. std::string resolved = ReplaceAll(File::ResolvePath(path), "/", "\\"); @@ -125,11 +125,11 @@ void OpenDirectory(const char *path) { } } -void LaunchBrowser(const char *url) { +void System_LaunchUrl(LaunchUrlType urlType, const char *url) { ShellExecute(NULL, L"open", ConvertUTF8ToWString(url).c_str(), NULL, NULL, SW_SHOWNORMAL); } -void Vibrate(int length_ms) { +void System_Vibrate(int length_ms) { // Ignore on PC } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index e89ec0ec33..c67300d53b 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -381,30 +381,26 @@ void System_Toast(const char *text) { PushCommand("toast", text); } -void ShowKeyboard() { +void System_ShowKeyboard() { PushCommand("showKeyboard", ""); } -void Vibrate(int length_ms) { +void System_Vibrate(int length_ms) { char temp[32]; sprintf(temp, "%i", length_ms); PushCommand("vibrate", temp); } -void OpenDirectory(const char *path) { +void System_ShowFileInFolder(const char *path) { // Unsupported } -void LaunchBrowser(const char *url) { - PushCommand("launchBrowser", url); -} - -void LaunchMarket(const char *url) { - PushCommand("launchMarket", url); -} - -void LaunchEmail(const char *email_address) { - PushCommand("launchEmail", email_address); +void System_LaunchUrl(LaunchUrlType urlType, const char *url) { + switch (urlType) { + case LaunchUrlType::BROWSER_URL: PushCommand("launchBrowser", url); break; + case LaunchUrlType::MARKET_URL: PushCommand("launchMarket", url); break; + case LaunchUrlType::EMAIL_ADDRESS: PushCommand("launchEmail", url); break; + } } void System_SendMessage(const char *command, const char *parameter) { @@ -855,11 +851,11 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_audioRecording_1Stop(JNIEnv *, AndroidAudio_Recording_Stop(g_audioState); } -bool audioRecording_Available() { +bool System_AudioRecordingIsAvailable() { return true; } -bool audioRecording_State() { +bool System_AudioRecordingState() { return AndroidAudio_Recording_State(g_audioState); } @@ -1278,7 +1274,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_setDisplayParameters(JN } } -std::vector __cameraGetDeviceList() { +std::vector System_GetCameraDeviceList() { jclass cameraClass = findClass("org/ppsspp/ppsspp/CameraHelper"); jmethodID deviceListMethod = getEnv()->GetStaticMethodID(cameraClass, "getDeviceList", "()Ljava/util/ArrayList;"); jobject deviceListObject = getEnv()->CallStaticObjectMethod(cameraClass, deviceListMethod); diff --git a/headless/Headless.cpp b/headless/Headless.cpp index d6cef79416..8258c58593 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -60,8 +60,8 @@ jclass findClass(const char *name) { return nullptr; } -bool audioRecording_Available() { return false; } -bool audioRecording_State() { return false; } +bool System_AudioRecordingIsAvailable() { return false; } +bool System_AudioRecordingState() { return false; } #endif class PrintfLogger : public LogListener { diff --git a/headless/StubHost.h b/headless/StubHost.h index a77a42424d..5dc0f5a258 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -44,7 +44,6 @@ public: // this is sent from EMU thread! Make sure that Host handles it properly void BootDone() override {} - bool IsDebuggingEnabled() override { return false; } bool AttemptLoadSymbolMap() override { g_symbolMap->Clear(); return false; } void NotifySymbolMapUpdated() override {} diff --git a/ios/CameraHelper.mm b/ios/CameraHelper.mm index ef6a7c305a..86dc9f1aec 100644 --- a/ios/CameraHelper.mm +++ b/ios/CameraHelper.mm @@ -14,7 +14,7 @@ @implementation CameraHelper -std::vector __cameraGetDeviceList() { +std::vector System_GetCameraDeviceList() { std::vector deviceList; for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { deviceList.push_back([device.localizedName UTF8String]); diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 8e30578dec..44de91f4bc 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -178,7 +178,7 @@ static LocationHelper *locationHelper; self.view.frame = [screen bounds]; self.view.multipleTouchEnabled = YES; self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; - + if (!self.context) { self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; } @@ -193,7 +193,7 @@ static LocationHelper *locationHelper; [[DisplayManager shared] updateResolution:[UIScreen mainScreen]]; graphicsContext = new IOSGraphicsContext(); - + graphicsContext->GetDrawContext()->SetErrorCallback([](const char *shortDesc, const char *details, void *userdata) { host->NotifyUserMessage(details, 5.0, 0xFFFFFFFF, "error_callback"); }, nullptr); @@ -202,12 +202,12 @@ static LocationHelper *locationHelper; dp_xscale = (float)g_display.dp_xres / (float)g_display.pixel_xres; dp_yscale = (float)g_display.dp_yres / (float)g_display.pixel_yres; - + /*self.iCadeView = [[iCadeReaderView alloc] init]; [self.view addSubview:self.iCadeView]; self.iCadeView.delegate = self; self.iCadeView.active = YES;*/ - + #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1 if ([GCController class]) { if ([[GCController controllers] count] > 0) { @@ -221,7 +221,7 @@ static LocationHelper *locationHelper; locationHelper = [[LocationHelper alloc] init]; [locationHelper setDelegate:self]; - + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ NativeInitGraphics(graphicsContext); @@ -238,7 +238,7 @@ static LocationHelper *locationHelper; // Also ask the main thread to stop, so it doesn't hang waiting for a new frame. INFO_LOG(SYSTEM, "Emulation thread stopping\n"); graphicsContext->StopThread(); - + threadStopped = true; }); } @@ -317,7 +317,7 @@ static LocationHelper *locationHelper; - (void)touchX:(float)x y:(float)y code:(int)code pointerId:(int)pointerId { float scale = [UIScreen mainScreen].scale; - + if ([[UIScreen mainScreen] respondsToSelector:@selector(nativeScale)]) { scale = [UIScreen mainScreen].nativeScale; } @@ -434,22 +434,22 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axis.axisId = JOYSTICK_AXIS_Y; axis.value = -1.0f; break; - + case iCadeJoystickDown : axis.axisId = JOYSTICK_AXIS_Y; axis.value = 1.0f; break; - + case iCadeJoystickLeft : axis.axisId = JOYSTICK_AXIS_X; axis.value = -1.0f; break; - + case iCadeJoystickRight : axis.axisId = JOYSTICK_AXIS_X; axis.value = 1.0f; break; - + default: break; } @@ -479,7 +479,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { simulateAnalog = !simulateAnalog; lastSelectPress = time_now_d(); } - + if (button == iCadeButtonC) { // Pressing Start twice within 1 second will take to the Emu menu if ((lastStartPress + 1.0f) > time_now_d()) { @@ -492,7 +492,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { } lastStartPress = time_now_d(); } - + if (simulateAnalog && ((button == iCadeJoystickUp) || (button == iCadeJoystickDown) || @@ -504,22 +504,22 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axis.axisId = JOYSTICK_AXIS_Y; axis.value = 0.0f; break; - + case iCadeJoystickDown : axis.axisId = JOYSTICK_AXIS_Y; axis.value = 0.0f; break; - + case iCadeJoystickLeft : axis.axisId = JOYSTICK_AXIS_X; axis.value = 0.0f; break; - + case iCadeJoystickRight : axis.axisId = JOYSTICK_AXIS_X; axis.value = 0.0f; break; - + default: break; } @@ -533,16 +533,16 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { key.deviceId = DEVICE_ID_PAD_0; NativeKey(key); } - + } #if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1 - (void)controllerDidConnect:(NSNotification *)note { if (![[GCController controllers] containsObject:self.gameController]) self.gameController = nil; - + if (self.gameController != nil) return; // already have a connected controller - + [self setupController:(GCController *)note.object]; } @@ -550,7 +550,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { { if (self.gameController == note.object) { self.gameController = nil; - + if ([[GCController controllers] count] > 0) { [self setupController:[[GCController controllers] firstObject]]; } else { @@ -577,15 +577,15 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { - (void)setupController:(GCController *)controller { self.gameController = controller; - + GCGamepad *baseProfile = self.gameController.gamepad; if (baseProfile == nil) { self.gameController = nil; return; } - + [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; // prevent auto-lock - + self.gameController.controllerPausedHandler = ^(GCController *controller) { KeyInput key; key.flags = KEY_DOWN; @@ -593,55 +593,55 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { key.deviceId = DEVICE_ID_KEYBOARD; NativeKey(key); }; - + baseProfile.buttonA.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_2]; // Cross }; - + baseProfile.buttonB.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_3]; // Circle }; - + baseProfile.buttonX.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_4]; // Square }; - + baseProfile.buttonY.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_1]; // Triangle }; - + baseProfile.leftShoulder.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_7]; // LTrigger }; - + baseProfile.rightShoulder.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_8]; // RTrigger }; - + baseProfile.dpad.up.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_DPAD_UP]; }; - + baseProfile.dpad.down.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_DPAD_DOWN]; }; - + baseProfile.dpad.left.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_DPAD_LEFT]; }; - + baseProfile.dpad.right.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_DPAD_RIGHT]; }; - + GCExtendedGamepad *extendedProfile = self.gameController.extendedGamepad; if (extendedProfile == nil) return; // controller doesn't support extendedGamepad profile - + extendedProfile.leftTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_9]; // Select }; - + extendedProfile.rightTrigger.valueChangedHandler = ^(GCControllerButtonInput *button, float value, BOOL pressed) { [self controllerButtonPressed:pressed keyCode:NKCODE_BUTTON_10]; // Start }; @@ -677,7 +677,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { }; } #endif - + extendedProfile.leftThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *axis, float value) { AxisInput axisInput; axisInput.deviceId = DEVICE_ID_PAD_0; @@ -686,7 +686,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.value = value; NativeAxis(axisInput); }; - + extendedProfile.leftThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *axis, float value) { AxisInput axisInput; axisInput.deviceId = DEVICE_ID_PAD_0; @@ -695,7 +695,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.value = -value; NativeAxis(axisInput); }; - + // Map right thumbstick as another analog stick, particularly useful for controllers like the DualShock 3/4 when connected to an iOS device extendedProfile.rightThumbstick.xAxis.valueChangedHandler = ^(GCControllerAxisInput *axis, float value) { AxisInput axisInput; @@ -705,7 +705,7 @@ int ToTouchID(UITouch *uiTouch, bool allowAllocate) { axisInput.value = value; NativeAxis(axisInput); }; - + extendedProfile.rightThumbstick.yAxis.valueChangedHandler = ^(GCControllerAxisInput *axis, float value) { AxisInput axisInput; axisInput.deviceId = DEVICE_ID_PAD_0; @@ -752,11 +752,11 @@ void stopLocation() { @end -void OpenDirectory(const char *path) { +void System_ShowFileInFolder(const char *path) { // Unsupported } -void LaunchBrowser(char const* url) +void System_LaunchUrl(LaunchUrlType urlType, char const* url) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithCString:url encoding:NSStringEncodingConversionAllowLossy]]]; } diff --git a/ios/main.mm b/ios/main.mm index 3f7e6556d2..8ab82e7431 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -208,7 +208,7 @@ void System_SendMessage(const char *command, const char *parameter) { DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { NativeMessageReceived("browse_folder", thePathChosen.c_str()); }; - + DarwinFileSystemServices services; services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectorites = */ true); } @@ -236,7 +236,7 @@ BOOL SupportsTaptic() { return [val intValue] >= 2; } -void Vibrate(int mode) { +void System_Vibrate(int mode) { if (SupportsTaptic()) { PPSSPPUIApplication* app = (PPSSPPUIApplication*)[UIApplication sharedApplication]; if(app.feedbackGenerator == nil) diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 6bc6de0804..11563409fe 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -400,7 +400,6 @@ class LibretroHost : public Host AudioBufferWrite(audio, samples); } void ShutdownSound() override {} - bool IsDebuggingEnabled() override { return false; } bool AttemptLoadSymbolMap() override { return false; } }; @@ -1881,9 +1880,9 @@ void NativeResized() {} void System_Toast(const char *str) {} #if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) -std::vector __cameraGetDeviceList() { return std::vector(); } -bool audioRecording_Available() { return false; } -bool audioRecording_State() { return false; } +std::vector System_GetCameraDeviceList() { return std::vector(); } +bool System_AudioRecordingIsAvailable() { return false; } +bool System_AudioRecordingState() { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } #endif diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index fcbe56f282..457d51727b 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -97,8 +97,8 @@ jclass findClass(const char *name) { return nullptr; } -bool audioRecording_Available() { return false; } -bool audioRecording_State() { return false; } +bool System_AudioRecordingIsAvailable() { return false; } +bool System_AudioRecordingState() { return false; } #endif #ifndef M_PI_2 @@ -694,7 +694,7 @@ static bool TestAndroidContentURI() { EXPECT_TRUE(fileTreeURI.CanNavigateUp()); fileTreeURI.NavigateUp(); EXPECT_FALSE(fileTreeURI.CanNavigateUp()); - + EXPECT_EQ_STR(fileTreeURI.FilePath(), fileTreeURI.RootPath()); EXPECT_EQ_STR(fileTreeURI.ToString(), std::string(directoryURIString)); From ac5855cdf86932a9ed5b9c0f9fe50c0cc98630a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 10:54:43 +0100 Subject: [PATCH 379/424] Remove CanCreateShortcut function --- Common/System/System.h | 2 ++ Core/Host.h | 3 +-- UI/GameScreen.cpp | 12 +++++------- UWP/UWPHost.cpp | 9 --------- UWP/UWPHost.h | 3 --- Windows/WindowsHost.cpp | 4 ---- Windows/WindowsHost.h | 1 - 7 files changed, 8 insertions(+), 26 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index cbb5ad950b..dd2c184918 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -90,6 +90,8 @@ enum SystemProperty { SYSPROP_HAS_KEYBOARD, SYSPROP_HAS_OPEN_DIRECTORY, + SYSPROP_CAN_CREATE_SHORTCUT, + // Available as Int: SYSPROP_SYSTEMVERSION, SYSPROP_DISPLAY_XRES, diff --git a/Core/Host.h b/Core/Host.h index eba025e428..044ad16823 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -18,11 +18,11 @@ #pragma once #include + #include "Common/CommonTypes.h" class GraphicsContext; -// TODO: Whittle this down. Collecting a bunch of random stuff like this isn't good design :P class Host { public: virtual ~Host() {} @@ -50,7 +50,6 @@ public: virtual void NotifySymbolMapUpdated() {} virtual void SetWindowTitle(const char *message) {} - virtual bool CanCreateShortcut() {return false;} virtual bool CreateDesktopShortcut(std::string argumentPath, std::string title) {return false;} virtual void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) {} diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 3cf6347576..767f22d777 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -165,7 +165,7 @@ void GameScreen::CreateViews() { otherChoices_.clear(); rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Delete Game"))))->OnClick.Handle(this, &GameScreen::OnDeleteGame); - if (host->CanCreateShortcut()) { + if (System_GetPropertyBool(SYSPROP_CAN_CREATE_SHORTCUT)) { rightColumnItems->Add(AddOtherChoice(new Choice(ga->T("Create Shortcut"))))->OnClick.Handle(this, &GameScreen::OnCreateShortcut); } if (isRecentGame(gamePath_)) { @@ -443,7 +443,10 @@ UI::EventReturn GameScreen::OnRemoveFromRecent(UI::EventParams &e) { class SetBackgroundPopupScreen : public PopupScreen { public: - SetBackgroundPopupScreen(const std::string &title, const Path &gamePath); + SetBackgroundPopupScreen(const std::string &title, const Path &gamePath) + : PopupScreen(title), gamePath_(gamePath) { + timeStart_ = time_now_d(); + } const char *tag() const override { return "SetBackgroundPopup"; } protected: @@ -465,11 +468,6 @@ private: Status status_ = Status::PENDING; }; -SetBackgroundPopupScreen::SetBackgroundPopupScreen(const std::string &title, const Path &gamePath) - : PopupScreen(title), gamePath_(gamePath) { - timeStart_ = time_now_d(); -} - void SetBackgroundPopupScreen::CreatePopupContents(UI::ViewGroup *parent) { auto ga = GetI18NCategory("Game"); parent->Add(new UI::TextView(ga->T("One moment please..."), ALIGN_LEFT | ALIGN_VCENTER, false, new UI::LinearLayoutParams(UI::Margins(10, 0, 10, 10)))); diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index 977d5ddfc9..b187f4fff5 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -148,15 +148,6 @@ void UWPHost::NotifySymbolMapUpdated() { g_symbolMap->SortSymbols(); } -bool UWPHost::CanCreateShortcut() { - return false; // Turn on when below function fixed -} - -bool UWPHost::CreateDesktopShortcut(std::string argumentPath, std::string gameTitle) { - // TODO: not working correctly - return false; -} - void UWPHost::ToggleDebugConsoleVisibility() { // N/A } diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index dea4547aa5..7913e5964e 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -34,9 +34,6 @@ public: void ToggleDebugConsoleVisibility() override; - bool CanCreateShortcut() override; - bool CreateDesktopShortcut(std::string argumentPath, std::string title) override; - void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override; void NotifySwitchUMDUpdated() override {} diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index c92483f0b8..945526d841 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -339,10 +339,6 @@ HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathL return hres; } -bool WindowsHost::CanCreateShortcut() { - return false; // Turn on when below function fixed -} - bool WindowsHost::CreateDesktopShortcut(std::string argumentPath, std::string gameTitle) { // TODO: not working correctly return false; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 6eb659e55e..a62dc4d1cf 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -56,7 +56,6 @@ public: void ToggleDebugConsoleVisibility() override; - bool CanCreateShortcut() override; bool CreateDesktopShortcut(std::string argumentPath, std::string title) override; void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override; From 06fcc9ccd7b5002f2a6f0b53908534031389b2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 11:10:09 +0100 Subject: [PATCH 380/424] Add System_Notify --- Common/System/System.h | 12 ++++++++++++ Core/Debugger/WebSocket/GameSubscriber.cpp | 3 ++- Core/Host.h | 11 +++-------- Core/SaveState.cpp | 3 ++- Qt/QtHost.h | 9 +-------- Qt/QtMain.cpp | 11 +++++++++++ SDL/SDLMain.cpp | 7 +++++++ UI/EmuScreen.cpp | 5 +++-- UI/HostTypes.h | 3 --- UWP/PPSSPP_UWPMain.cpp | 14 ++++++++++++++ UWP/UWPHost.cpp | 10 +--------- UWP/UWPHost.h | 1 - Windows/WindowsHost.cpp | 8 -------- Windows/WindowsHost.h | 1 - Windows/main.cpp | 19 +++++++++++++++++++ android/jni/app-android.cpp | 5 +++++ headless/Headless.cpp | 4 ++-- headless/StubHost.h | 3 --- ios/main.mm | 5 +++++ libretro/libretro.cpp | 7 +++++++ unittest/UnitTest.cpp | 1 + 21 files changed, 95 insertions(+), 47 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index dd2c184918..a1e3c936a2 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -134,12 +134,24 @@ enum SystemProperty { SYSPROP_KEYBOARD_LAYOUT, }; +enum class SystemNotification { + UI, + MEM_VIEW, + DISASSEMBLY, + DEBUG_MODE, + BOOT_DONE, // this is sent from EMU thread! Make sure that Host handles it properly! + SYMBOL_MAP_UPDATED, + SWITCH_UMD_UPDATED, +}; + std::string System_GetProperty(SystemProperty prop); std::vector System_GetPropertyStringVec(SystemProperty prop); int System_GetPropertyInt(SystemProperty prop); float System_GetPropertyFloat(SystemProperty prop); bool System_GetPropertyBool(SystemProperty prop); +void System_Notify(SystemNotification notification); + std::vector System_GetCameraDeviceList(); bool System_AudioRecordingIsAvailable(); bool System_AudioRecordingState(); diff --git a/Core/Debugger/WebSocket/GameSubscriber.cpp b/Core/Debugger/WebSocket/GameSubscriber.cpp index c48f396bb7..efa8ff2da6 100644 --- a/Core/Debugger/WebSocket/GameSubscriber.cpp +++ b/Core/Debugger/WebSocket/GameSubscriber.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/System/System.h" #include "Core/Config.h" #include "Core/Debugger/WebSocket/GameSubscriber.h" #include "Core/Debugger/WebSocket/WebSocketUtils.h" @@ -54,7 +55,7 @@ void WebSocketGameReset(DebuggerRequest &req) { ERROR_LOG(BOOT, "Error resetting: %s", resetError.c_str()); return req.Fail("Could not reset"); } - host->BootDone(); + System_Notify(SystemNotification::BOOT_DONE); host->UpdateDisassembly(); req.Respond(); diff --git a/Core/Host.h b/Core/Host.h index 044ad16823..ff5179b3e2 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -26,12 +26,13 @@ class GraphicsContext; class Host { public: virtual ~Host() {} - virtual void UpdateUI() {} + virtual void UpdateUI() {} virtual void UpdateMemView() {} virtual void UpdateDisassembly() {} - + virtual void NotifySymbolMapUpdated() {} virtual void SetDebugMode(bool mode) { } + virtual void NotifySwitchUMDUpdated() {} virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; virtual void ShutdownGraphics() = 0; @@ -42,12 +43,8 @@ public: virtual void PollControllers() {} virtual void ToggleDebugConsoleVisibility() {} - //this is sent from EMU thread! Make sure that Host handles it properly! - virtual void BootDone() {} - virtual bool AttemptLoadSymbolMap(); virtual void SaveSymbolMap() {} - virtual void NotifySymbolMapUpdated() {} virtual void SetWindowTitle(const char *message) {} virtual bool CreateDesktopShortcut(std::string argumentPath, std::string title) {return false;} @@ -55,8 +52,6 @@ public: virtual void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) {} virtual void SendUIMessage(const std::string &message, const std::string &value) {} - virtual void NotifySwitchUMDUpdated() {} - // Used for headless. virtual bool ShouldSkipUI() { return false; } virtual void SendDebugOutput(const std::string &output) {} diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 3f51aebbc6..c35d1c9230 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -23,6 +23,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Text/Parsers.h" +#include "Common/System/System.h" #include "Common/File/FileUtil.h" #include "Common/Serialize/Serializer.h" @@ -1078,7 +1079,7 @@ namespace SaveState Core_Stop(); return; } - host->BootDone(); + System_Notify(SystemNotification::BOOT_DONE); host->UpdateDisassembly(); needsRestart = false; } diff --git a/Qt/QtHost.h b/Qt/QtHost.h index a0327474c1..f559265494 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -40,8 +40,7 @@ public: mainWindow->updateMenus(); } - void SetDebugMode(bool mode) override { - } + void SetDebugMode(bool mode) override {} bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} @@ -50,12 +49,6 @@ public: void UpdateSound() override {} void ShutdownSound() override; - // this is sent from EMU thread! Make sure that Host handles it properly! - void BootDone() override { - g_symbolMap->SortSymbols(); - mainWindow->Notify(MainWindowMsg::BOOT_DONE); - } - bool AttemptLoadSymbolMap() override { auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); return g_symbolMap->LoadSymbolMap(fn); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 354ea7399b..1305137ccc 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -254,6 +254,17 @@ bool System_GetPropertyBool(SystemProperty prop) { } } +void System_Notify(SystemNotification notification) { + switch (notification) { + case SystemNotification::BOOT_DONE: + g_symbolMap->SortSymbols(); + mainWindow->Notify(MainWindowMsg::BOOT_DONE); + break; + default: + break; + } +} + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { qApp->exit(0); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index c11a50476b..f59a2dd22a 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -436,6 +436,13 @@ bool System_GetPropertyBool(SystemProperty prop) { } } +void System_Notify(SystemNotification notification) { + switch (notification) { + default: + break; + } +} + // returns -1 on failure static int parseInt(const char *str) { int val; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index a86a460acb..09ee8b2629 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -354,7 +354,8 @@ void EmuScreen::bootGame(const Path &filename) { void EmuScreen::bootComplete() { UpdateUIState(UISTATE_INGAME); - host->BootDone(); + System_Notify(SystemNotification::BOOT_DONE); + host->UpdateDisassembly(); NOTICE_LOG(BOOT, "Loading %s...", PSP_CoreParameter().fileToStart.c_str()); @@ -1300,7 +1301,7 @@ static void DrawFPS(UIContext *ctx, const Bounds &bounds) { snprintf(fpsbuf, sizeof(fpsbuf), "%s Speed: %0.1f%%", fpsbuf, vps / (59.94f / 100.0f)); } } - + #ifdef CAN_DISPLAY_CURRENT_BATTERY_CAPACITY if (g_Config.iShowStatusFlags & (int)ShowStatusFlags::BATTERY_PERCENT) { snprintf(fpsbuf, sizeof(fpsbuf), "%s Battery: %d%%", fpsbuf, getCurrentBatteryCapacity()); diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 528ae90f73..2cdc0a9d84 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -38,9 +38,6 @@ public: void UpdateSound() override {} void ShutdownSound() override; - // this is sent from EMU thread! Make sure that Host handles it properly! - void BootDone() override {} - bool AttemptLoadSymbolMap() override {return false;} void NotifySymbolMapUpdated() override {} void SetWindowTitle(const char *message) override {} diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 87e7fff4c6..a1630b9166 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -436,6 +436,20 @@ bool System_GetPropertyBool(SystemProperty prop) { } } +void System_Notify(SystemNotification notification) { + switch (notification) { + case SystemNotification::BOOT_DONE: + g_symbolMap->SortSymbols(); + + SetDebugMode(false); + Core_EnableStepping(false); + break; + + default: + break; + } +} + void System_SendMessage(const char *command, const char *parameter) { using namespace concurrency; diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index b187f4fff5..f8ddcfc22d 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -85,8 +85,7 @@ void UWPHost::UpdateMemView() { void UWPHost::UpdateDisassembly() { } -void UWPHost::SetDebugMode(bool mode) { -} +void UWPHost::SetDebugMode(bool mode) {} void UWPHost::PollControllers() { for (const auto& device : this->input) @@ -114,13 +113,6 @@ void UWPHost::PollControllers() { */ } -void UWPHost::BootDone() { - g_symbolMap->SortSymbols(); - - SetDebugMode(false); - Core_EnableStepping(false); -} - static Path SymbolMapFilename(const Path ¤tFilename, const char *ext) { File::FileInfo info; // can't fail, definitely exists if it gets this far diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index 7913e5964e..4e604222bb 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -26,7 +26,6 @@ public: void UpdateSound() override; void ShutdownSound() override; - void BootDone() override; bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; void NotifySymbolMapUpdated() override; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 945526d841..d39c172abe 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -264,14 +264,6 @@ void WindowsHost::PollControllers() { HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = g_mouseDeltaY; } -void WindowsHost::BootDone() { - if (g_symbolMap) - g_symbolMap->SortSymbols(); - PostMessage(mainWindow_, WM_USER + 1, 0, 0); - - SetDebugMode(!g_Config.bAutoRun); -} - static Path SymbolMapFilename(const Path ¤tFilename, const char *ext) { File::FileInfo info{}; // can't fail, definitely exists if it gets this far diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index a62dc4d1cf..94436f5479 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -48,7 +48,6 @@ public: void UpdateSound() override; void ShutdownSound() override; - void BootDone() override; bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; void NotifySymbolMapUpdated() override; diff --git a/Windows/main.cpp b/Windows/main.cpp index b776533ddc..af0f555e8d 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -74,6 +74,7 @@ #include "Windows/Debugger/CtrlDisAsmView.h" #include "Windows/Debugger/CtrlMemView.h" #include "Windows/Debugger/CtrlRegisterList.h" +#include "Windows/Debugger/DebuggerShared.h" #include "Windows/InputBox.h" #include "Windows/WindowsHost.h" @@ -369,6 +370,24 @@ bool System_GetPropertyBool(SystemProperty prop) { } } +static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) { + return PostMessage(dialog->GetDlgHandle(), message, wParam, lParam); +} + +void System_Notify(SystemNotification notification) { + switch (notification) { + case SystemNotification::BOOT_DONE: + if (g_symbolMap) + g_symbolMap->SortSymbols(); + PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); + + bool mode = !g_Config.bAutoRun; + if (disasmWindow) + PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)mode); + break; + } +} + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { if (!NativeIsRestarting()) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index c67300d53b..65a483e519 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -540,6 +540,11 @@ bool System_GetPropertyBool(SystemProperty prop) { } } +void System_Notify(SystemNotification notification) { + switch (notification) { + } +} + std::string Android_GetInputDeviceDebugString() { if (!nativeActivity) { return "(N/A)"; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 8258c58593..55316a348a 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -112,7 +112,7 @@ bool System_GetPropertyBool(SystemProperty prop) { return false; } } - +void System_Notify(SystemNotification notification) {} void System_SendMessage(const char *command, const char *parameter) {} void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} @@ -201,7 +201,7 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, const return false; } - host->BootDone(); + System_Notify(SystemNotification::BOOT_DONE); Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops); diff --git a/headless/StubHost.h b/headless/StubHost.h index 5dc0f5a258..585baf4646 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -41,9 +41,6 @@ public: void UpdateSound() override {} void ShutdownSound() override {} - // this is sent from EMU thread! Make sure that Host handles it properly - void BootDone() override {} - bool AttemptLoadSymbolMap() override { g_symbolMap->Clear(); return false; } void NotifySymbolMapUpdated() override {} diff --git a/ios/main.mm b/ios/main.mm index 8ab82e7431..155bf79995 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -170,6 +170,11 @@ bool System_GetPropertyBool(SystemProperty prop) { } } +void System_Notify(SystemNotification notification) { + switch (notification) { + } +} + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { exit(0); diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 11563409fe..726902f31d 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1872,6 +1872,13 @@ bool System_GetPropertyBool(SystemProperty prop) std::string System_GetProperty(SystemProperty prop) { return ""; } std::vector System_GetPropertyStringVec(SystemProperty prop) { return std::vector(); } +void System_Notify(SystemNotification notification) { + switch (notification) { + default: + break; + } +} + void System_SendMessage(const char *command, const char *parameter) {} void NativeUpdate() {} void NativeRender(GraphicsContext *graphicsContext) {} diff --git a/unittest/UnitTest.cpp b/unittest/UnitTest.cpp index 457d51727b..89ce7551c8 100644 --- a/unittest/UnitTest.cpp +++ b/unittest/UnitTest.cpp @@ -87,6 +87,7 @@ bool System_GetPropertyBool(SystemProperty prop) { return false; } } +void System_Notify(SystemNotification notification) {} #if PPSSPP_PLATFORM(ANDROID) JNIEnv *getEnv() { From dda8635c89f2ef2caefa80b7a8ae5d68e8b8db9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 11:21:19 +0100 Subject: [PATCH 381/424] Move three notifications out of Host --- Core/Core.cpp | 10 ++++----- Core/Debugger/Breakpoints.cpp | 3 ++- Core/Debugger/WebSocket/GameSubscriber.cpp | 3 ++- Core/HLE/sceUmd.cpp | 6 +++-- Core/Host.h | 3 --- Core/SaveState.cpp | 2 +- Core/System.cpp | 3 +-- Qt/QtHost.h | 10 --------- UI/EmuScreen.cpp | 9 ++++---- UI/GameSettingsScreen.cpp | 7 +++--- UI/HostTypes.h | 5 ----- UI/MainScreen.cpp | 4 +--- UI/MiscScreens.cpp | 4 +--- UWP/PPSSPP_UWPMain.cpp | 7 ------ UWP/UWPHost.cpp | 10 --------- UWP/UWPHost.h | 3 --- Windows/EmuThread.cpp | 2 +- Windows/WindowsHost.cpp | 20 ----------------- Windows/WindowsHost.h | 4 ---- Windows/main.cpp | 26 ++++++++++++++++++++++ headless/StubHost.h | 5 ----- 21 files changed, 51 insertions(+), 95 deletions(-) diff --git a/Core/Core.cpp b/Core/Core.cpp index 95864b197a..af371a29b6 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -308,8 +308,8 @@ void Core_ProcessStepping() { static int lastSteppingCounter = -1; if (lastSteppingCounter != steppingCounter) { CBreakPoints::ClearTemporaryBreakPoints(); - host->UpdateDisassembly(); - host->UpdateMemView(); + System_Notify(SystemNotification::DISASSEMBLY); + System_Notify(SystemNotification::MEM_VIEW); lastSteppingCounter = steppingCounter; } @@ -320,15 +320,15 @@ void Core_ProcessStepping() { if (doStep && coreState == CORE_STEPPING) { Core_SingleStep(); // Update disasm dialog. - host->UpdateDisassembly(); - host->UpdateMemView(); + System_Notify(SystemNotification::DISASSEMBLY); + System_Notify(SystemNotification::MEM_VIEW); } } // Many platforms, like Android, do not call this function but handle things on their own. // Instead they simply call NativeRender and NativeUpdate directly. bool Core_Run(GraphicsContext *ctx) { - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); while (true) { if (GetUIState() != UISTATE_INGAME) { Core_StateProcessed(); diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 5ce977ec45..cd3df9bf99 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -19,6 +19,7 @@ #include #include +#include "Common/System/System.h" #include "Common/Log.h" #include "Core/Core.h" #include "Core/Debugger/Breakpoints.h" @@ -674,7 +675,7 @@ void CBreakPoints::Update(u32 addr) { } // Redraw in order to show the breakpoint. - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); } bool CBreakPoints::ValidateLogFormat(DebugInterface *cpu, const std::string &fmt) { diff --git a/Core/Debugger/WebSocket/GameSubscriber.cpp b/Core/Debugger/WebSocket/GameSubscriber.cpp index efa8ff2da6..4ca0f3e5cb 100644 --- a/Core/Debugger/WebSocket/GameSubscriber.cpp +++ b/Core/Debugger/WebSocket/GameSubscriber.cpp @@ -55,8 +55,9 @@ void WebSocketGameReset(DebuggerRequest &req) { ERROR_LOG(BOOT, "Error resetting: %s", resetError.c_str()); return req.Fail("Could not reset"); } + System_Notify(SystemNotification::BOOT_DONE); - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); req.Respond(); } diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index 8ad8a5196a..c7591f13d7 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -17,6 +17,7 @@ #include +#include "Common/System/System.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/Serialize/SerializeMap.h" @@ -104,8 +105,9 @@ void __UmdDoState(PointerWrap &p) if (s > 1) { Do(p, UMDReplacePermit); - if (UMDReplacePermit) - host->UpdateUI(); + if (UMDReplacePermit) { + System_Notify(SystemNotification::UI); + } } if (s > 2) { Do(p, umdInsertChangeEvent); diff --git a/Core/Host.h b/Core/Host.h index ff5179b3e2..5fc61c220e 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -27,9 +27,6 @@ class Host { public: virtual ~Host() {} - virtual void UpdateUI() {} - virtual void UpdateMemView() {} - virtual void UpdateDisassembly() {} virtual void NotifySymbolMapUpdated() {} virtual void SetDebugMode(bool mode) { } virtual void NotifySwitchUMDUpdated() {} diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index c35d1c9230..6386ca09ee 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -1080,7 +1080,7 @@ namespace SaveState return; } System_Notify(SystemNotification::BOOT_DONE); - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); needsRestart = false; } } diff --git a/Core/System.cpp b/Core/System.cpp index 8303f08a15..4f6510f07e 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -124,8 +124,7 @@ void UpdateUIState(GlobalUIState newState) { // Never leave the EXIT state. if (globalUIState != newState && globalUIState != UISTATE_EXIT) { globalUIState = newState; - if (host) - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); const char *state = nullptr; switch (globalUIState) { case UISTATE_EXIT: state = "exit"; break; diff --git a/Qt/QtHost.h b/Qt/QtHost.h index f559265494..a9816f7be4 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -30,16 +30,6 @@ public: mainWindow = mainWindow_; } - void UpdateUI() override { - mainWindow->updateMenus(); - } - - void UpdateMemView() override { - } - void UpdateDisassembly() override { - mainWindow->updateMenus(); - } - void SetDebugMode(bool mode) override {} bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 09ee8b2629..e5c03ba69b 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -355,8 +355,7 @@ void EmuScreen::bootGame(const Path &filename) { void EmuScreen::bootComplete() { UpdateUIState(UISTATE_INGAME); System_Notify(SystemNotification::BOOT_DONE); - - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); NOTICE_LOG(BOOT, "Loading %s...", PSP_CoreParameter().fileToStart.c_str()); autoLoad(); @@ -448,7 +447,7 @@ static void AfterSaveStateAction(SaveState::Status status, const std::string &me static void AfterStateBoot(SaveState::Status status, const std::string &message, void *ignored) { AfterSaveStateAction(status, message, ignored); Core_EnableStepping(false); - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); } void EmuScreen::sendMessage(const char *message, const char *value) { @@ -461,12 +460,12 @@ void EmuScreen::sendMessage(const char *message, const char *value) { bootPending_ = false; stopRender_ = true; invalid_ = true; - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); } else if (!strcmp(message, "reset")) { PSP_Shutdown(); bootPending_ = true; invalid_ = true; - host->UpdateDisassembly(); + System_Notify(SystemNotification::DISASSEMBLY); std::string resetError; if (!PSP_InitStart(PSP_CoreParameter(), &resetError)) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index b368e8114f..6556a57193 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -913,8 +913,7 @@ void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) { auto langScreen = new NewLanguageScreen(sy->T("Language")); langScreen->OnChoice.Add([&](UI::EventParams &e) { screenManager()->RecreateAllViews(); - if (host) - host->UpdateUI(); + System_Notify(SystemNotification::UI); return UI::EVENT_DONE; }); if (e.v) @@ -1362,7 +1361,7 @@ void GameSettingsScreen::onFinish(DialogResult result) { g_Config.unloadGameConfig(); } - host->UpdateUI(); + System_Notify(SystemNotification::UI); KeyMap::UpdateNativeMenuKeys(); @@ -1895,7 +1894,7 @@ void GameSettingsScreen::CallbackRestoreDefaults(bool yes) { if (yes) { g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS); } - host->UpdateUI(); + System_Notify(SystemNotification::UI); } UI::EventReturn GameSettingsScreen::OnRestoreDefaultSettings(UI::EventParams &e) { diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 2cdc0a9d84..de5b35fdee 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -24,11 +24,6 @@ class NativeHost : public Host { public: NativeHost() {} - void UpdateUI() override {} - - void UpdateMemView() override {} - void UpdateDisassembly() override {} - void SetDebugMode(bool mode) override { } bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index ba2b3e9276..682fe85074 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -964,9 +964,7 @@ UI::EventReturn GameBrowser::GridSettingsClick(UI::EventParams &e) { UI::EventReturn GameBrowser::OnRecentClear(UI::EventParams &e) { screenManager_->RecreateAllViews(); - if (host) { - host->UpdateUI(); - } + System_Notify(SystemNotification::UI); return UI::EVENT_DONE; } diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index 170844f6a4..c99684bbe0 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -431,9 +431,7 @@ void HandleCommonMessages(const char *message, const char *value, ScreenManager auto langScreen = new NewLanguageScreen(sy->T("Language")); langScreen->OnChoice.Add([](UI::EventParams &) { NativeMessageReceived("recreateviews", ""); - if (host) { - host->UpdateUI(); - } + System_Notify(SystemNotification::UI); return UI::EVENT_DONE; }); manager->push(langScreen); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index a1630b9166..1529a18887 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -438,13 +438,6 @@ bool System_GetPropertyBool(SystemProperty prop) { void System_Notify(SystemNotification notification) { switch (notification) { - case SystemNotification::BOOT_DONE: - g_symbolMap->SortSymbols(); - - SetDebugMode(false); - Core_EnableStepping(false); - break; - default: break; } diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index f8ddcfc22d..58c30f704d 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -64,7 +64,6 @@ void UWPHost::ShutdownGraphics() { } void UWPHost::SetWindowTitle(const char *message) { - // Should really be done differently } void UWPHost::InitSound() { @@ -76,15 +75,6 @@ void UWPHost::UpdateSound() { void UWPHost::ShutdownSound() { } -void UWPHost::UpdateUI() { -} - -void UWPHost::UpdateMemView() { -} - -void UWPHost::UpdateDisassembly() { -} - void UWPHost::SetDebugMode(bool mode) {} void UWPHost::PollControllers() { diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index 4e604222bb..038bf9becb 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -12,9 +12,6 @@ public: UWPHost(); ~UWPHost(); - void UpdateMemView() override; - void UpdateDisassembly() override; - void UpdateUI() override; void SetDebugMode(bool mode) override; // If returns false, will return a null context diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index c4225d95d8..5c3798bc7c 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -161,7 +161,7 @@ void MainThreadFunc() { // Let's continue (and probably crash) just so they have a way to keep trying. } - host->UpdateUI(); + System_Notify(SystemNotification::UI); std::string error_string; bool success = host->InitGraphics(&error_string, &g_graphicsContext); diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index d39c172abe..f270d79c02 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -189,26 +189,6 @@ void WindowsHost::UpdateSound() { void WindowsHost::ShutdownSound() { } -void WindowsHost::UpdateUI() { - PostMessage(mainWindow_, MainWindow::WM_USER_UPDATE_UI, 0, 0); - - int peers = GetInstancePeerCount(); - if (PPSSPP_ID >= 1 && peers != lastNumInstances_) { - lastNumInstances_ = peers; - PostMessage(mainWindow_, MainWindow::WM_USER_WINDOW_TITLE_CHANGED, 0, 0); - } -} - -void WindowsHost::UpdateMemView() { - if (memoryWindow) - PostDialogMessage(memoryWindow, WM_DEB_UPDATE); -} - -void WindowsHost::UpdateDisassembly() { - if (disasmWindow) - PostDialogMessage(disasmWindow, WM_DEB_UPDATE); -} - void WindowsHost::SetDebugMode(bool mode) { if (disasmWindow) PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)mode); diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 94436f5479..42e7e62094 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -34,9 +34,6 @@ public: UpdateConsolePosition(); } - void UpdateMemView() override; - void UpdateDisassembly() override; - void UpdateUI() override; void SetDebugMode(bool mode) override; // If returns false, will return a null context @@ -74,7 +71,6 @@ private: GraphicsContext *gfx_ = nullptr; size_t numDinputDevices_ = 0; std::wstring lastTitle_; - int lastNumInstances_ = 0; std::list> input; }; diff --git a/Windows/main.cpp b/Windows/main.cpp index af0f555e8d..b10e10321e 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -47,6 +47,7 @@ #include "Core/Config.h" #include "Core/ConfigValues.h" #include "Core/SaveState.h" +#include "Core/Instance.h" #include "Windows/EmuThread.h" #include "Windows/WindowsAudio.h" #include "ext/disarm.h" @@ -110,6 +111,7 @@ int g_activeWindow = 0; static std::thread inputBoxThread; static bool inputBoxRunning = false; +int g_lastNumInstances = 0; void System_ShowFileInFolder(const char *path) { // SHParseDisplayName can't handle relative paths, so normalize first. @@ -377,6 +379,7 @@ static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, L void System_Notify(SystemNotification notification) { switch (notification) { case SystemNotification::BOOT_DONE: + { if (g_symbolMap) g_symbolMap->SortSymbols(); PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); @@ -386,6 +389,29 @@ void System_Notify(SystemNotification notification) { PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)mode); break; } + + case SystemNotification::UI: + { + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); + + int peers = GetInstancePeerCount(); + if (PPSSPP_ID >= 1 && peers != g_lastNumInstances) { + g_lastNumInstances = peers; + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_WINDOW_TITLE_CHANGED, 0, 0); + } + break; + } + + case SystemNotification::MEM_VIEW: + if (memoryWindow) + PostDialogMessage(memoryWindow, WM_DEB_UPDATE); + break; + + case SystemNotification::DISASSEMBLY: + if (disasmWindow) + PostDialogMessage(disasmWindow, WM_DEB_UPDATE); + break; + } } void System_SendMessage(const char *command, const char *parameter) { diff --git a/headless/StubHost.h b/headless/StubHost.h index 585baf4646..d952802e73 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -26,11 +26,6 @@ // TODO: Get rid of this junk class HeadlessHost : public Host { public: - void UpdateUI() override {} - - void UpdateMemView() override {} - void UpdateDisassembly() override {} - void SetDebugMode(bool mode) override { } void SetGraphicsCore(GPUCore core) { gpuCore_ = core; } From c92a4acb40afe99e6e3ddeac6cc3cebf6d565b1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 11:28:50 +0100 Subject: [PATCH 382/424] Move NotifySymbolMapUpdated to System_Notify --- Core/HLE/sceKernelModule.cpp | 4 +++- Core/Host.h | 1 - Qt/QtHost.h | 3 --- Qt/QtMain.cpp | 5 +++++ UI/HostTypes.h | 1 - UWP/UWPHost.cpp | 4 ---- UWP/UWPHost.h | 1 - Windows/WindowsHost.cpp | 6 ------ Windows/WindowsHost.h | 1 - Windows/main.cpp | 6 ++++++ headless/StubHost.h | 1 - 11 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index dc4b53032d..7ea2fbf0ab 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -26,6 +26,8 @@ #include "Common/Serialize/SerializeSet.h" #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" +#include "Common/System/System.h" + #include "Core/Config.h" #include "Core/Core.h" #include "Core/HLE/HLE.h" @@ -1829,7 +1831,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str return false; } - host->NotifySymbolMapUpdated(); + System_Notify(SystemNotification::SYMBOL_MAP_UPDATED); char moduleName[29] = { 0 }; int moduleVersion = module->nm.version[0] | (module->nm.version[1] << 8); diff --git a/Core/Host.h b/Core/Host.h index 5fc61c220e..2e9bd64e99 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -27,7 +27,6 @@ class Host { public: virtual ~Host() {} - virtual void NotifySymbolMapUpdated() {} virtual void SetDebugMode(bool mode) { } virtual void NotifySwitchUMDUpdated() {} diff --git a/Qt/QtHost.h b/Qt/QtHost.h index a9816f7be4..00c8af3ac4 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -20,7 +20,6 @@ #include "Core/Host.h" #include "UI/OnScreenDisplay.h" -#include "Core/Debugger/SymbolMap.h" #include "Qt/mainwindow.h" class QtHost : public Host { @@ -44,8 +43,6 @@ public: return g_symbolMap->LoadSymbolMap(fn); } - void NotifySymbolMapUpdated() override { g_symbolMap->SortSymbols(); } - void PrepareShutdown() { auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); g_symbolMap->SaveSymbolMap(fn); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 1305137ccc..8228e33411 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -47,6 +47,7 @@ #include "Core/Config.h" #include "Core/ConfigValues.h" #include "Core/HW/Camera.h" +#include "Core/Debugger/SymbolMap.h" #include #include @@ -260,6 +261,10 @@ void System_Notify(SystemNotification notification) { g_symbolMap->SortSymbols(); mainWindow->Notify(MainWindowMsg::BOOT_DONE); break; + case SystemNotification::SYMBOL_MAP_UPDATED: + if (g_symbolMap) + g_symbolMap->SortSymbols(); + break; default: break; } diff --git a/UI/HostTypes.h b/UI/HostTypes.h index de5b35fdee..9a46df48e1 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -34,7 +34,6 @@ public: void ShutdownSound() override; bool AttemptLoadSymbolMap() override {return false;} - void NotifySymbolMapUpdated() override {} void SetWindowTitle(const char *message) override {} void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override { diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index 58c30f704d..e87c9e970f 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -126,10 +126,6 @@ void UWPHost::SaveSymbolMap() { g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart, ".ppmap")); } -void UWPHost::NotifySymbolMapUpdated() { - g_symbolMap->SortSymbols(); -} - void UWPHost::ToggleDebugConsoleVisibility() { // N/A } diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index 038bf9becb..ba63ce224e 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -25,7 +25,6 @@ public: bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; - void NotifySymbolMapUpdated() override; void SetWindowTitle(const char *message) override; void ToggleDebugConsoleVisibility() override; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index f270d79c02..8a9470d99c 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -270,12 +270,6 @@ void WindowsHost::SaveSymbolMap() { g_symbolMap->SaveSymbolMap(SymbolMapFilename(PSP_CoreParameter().fileToStart, ".ppmap")); } -void WindowsHost::NotifySymbolMapUpdated() { - if (g_symbolMap) - g_symbolMap->SortSymbols(); - PostMessage(mainWindow_, WM_USER + 1, 0, 0); -} - // http://msdn.microsoft.com/en-us/library/aa969393.aspx HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathLink, LPCWSTR lpszDesc) { HRESULT hres; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 42e7e62094..23777953c8 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -47,7 +47,6 @@ public: bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; - void NotifySymbolMapUpdated() override; void SetWindowTitle(const char *message) override; void ToggleDebugConsoleVisibility() override; diff --git a/Windows/main.cpp b/Windows/main.cpp index b10e10321e..3622469976 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -411,6 +411,12 @@ void System_Notify(SystemNotification notification) { if (disasmWindow) PostDialogMessage(disasmWindow, WM_DEB_UPDATE); break; + + case SystemNotification::SYMBOL_MAP_UPDATED: + if (g_symbolMap) + g_symbolMap->SortSymbols(); + PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); + break; } } diff --git a/headless/StubHost.h b/headless/StubHost.h index d952802e73..0a5ebf23f1 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -37,7 +37,6 @@ public: void ShutdownSound() override {} bool AttemptLoadSymbolMap() override { g_symbolMap->Clear(); return false; } - void NotifySymbolMapUpdated() override {} bool ShouldSkipUI() override { return true; } From fc1732cc2256a92e2c758d9973276ee8be5b2348 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 11:31:52 +0100 Subject: [PATCH 383/424] Move NotifySwitchUMDUpdated --- Core/HLE/sceUmd.cpp | 4 ++-- Core/Host.h | 1 - Qt/QtHost.h | 2 -- UI/HostTypes.h | 2 -- UWP/UWPHost.h | 4 +--- Windows/WindowsHost.cpp | 4 ---- Windows/WindowsHost.h | 2 -- Windows/main.cpp | 4 ++++ headless/StubHost.h | 2 -- 9 files changed, 7 insertions(+), 18 deletions(-) diff --git a/Core/HLE/sceUmd.cpp b/Core/HLE/sceUmd.cpp index c7591f13d7..c249b865a4 100644 --- a/Core/HLE/sceUmd.cpp +++ b/Core/HLE/sceUmd.cpp @@ -511,7 +511,7 @@ static u32 sceUmdReplaceProhibit() DEBUG_LOG(SCEIO,"sceUmdReplaceProhibit()"); if (UMDReplacePermit) { UMDReplacePermit = false; - host->NotifySwitchUMDUpdated(); + System_Notify(SystemNotification::SWITCH_UMD_UPDATED); } return 0; } @@ -521,7 +521,7 @@ static u32 sceUmdReplacePermit() DEBUG_LOG(SCEIO,"sceUmdReplacePermit()"); if (!UMDReplacePermit) { UMDReplacePermit = true; - host->NotifySwitchUMDUpdated(); + System_Notify(SystemNotification::SWITCH_UMD_UPDATED); } return 0; } diff --git a/Core/Host.h b/Core/Host.h index 2e9bd64e99..7a298c7a88 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -28,7 +28,6 @@ public: virtual ~Host() {} virtual void SetDebugMode(bool mode) { } - virtual void NotifySwitchUMDUpdated() {} virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; virtual void ShutdownGraphics() = 0; diff --git a/Qt/QtHost.h b/Qt/QtHost.h index 00c8af3ac4..ee782f53d3 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -65,8 +65,6 @@ public: NativeMessageReceived(message.c_str(), value.c_str()); } - void NotifySwitchUMDUpdated() override {} - private: Path SymbolMapFilename(Path currentFilename); MainWindow* mainWindow; diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 9a46df48e1..38d889e4cf 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -43,6 +43,4 @@ public: void SendUIMessage(const std::string &message, const std::string &value) override { NativeMessageReceived(message.c_str(), value.c_str()); } - - void NotifySwitchUMDUpdated() override {} }; diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index ba63ce224e..77e0c94101 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -31,13 +31,11 @@ public: void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override; - void NotifySwitchUMDUpdated() override {} - GraphicsContext *GetGraphicsContext() { return nullptr; } private: void SetConsolePosition(); void UpdateConsolePosition(); - std::list> input; + std::list> input; }; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 8a9470d99c..fd6e743455 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -355,7 +355,3 @@ void WindowsHost::NotifyUserMessage(const std::string &message, float duration, void WindowsHost::SendUIMessage(const std::string &message, const std::string &value) { NativeMessageReceived(message.c_str(), value.c_str()); } - -void WindowsHost::NotifySwitchUMDUpdated() { - PostMessage(mainWindow_, MainWindow::WM_USER_SWITCHUMD_UPDATED, 0, 0); -} diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 23777953c8..086162de4e 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -56,8 +56,6 @@ public: void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override; void SendUIMessage(const std::string &message, const std::string &value) override; - void NotifySwitchUMDUpdated() override; - GraphicsContext *GetGraphicsContext() { return gfx_; } private: diff --git a/Windows/main.cpp b/Windows/main.cpp index 3622469976..6136c3b108 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -417,6 +417,10 @@ void System_Notify(SystemNotification notification) { g_symbolMap->SortSymbols(); PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); break; + + case SystemNotification::SWITCH_UMD_UPDATED: + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_SWITCHUMD_UPDATED, 0, 0); + break; } } diff --git a/headless/StubHost.h b/headless/StubHost.h index 0a5ebf23f1..37586f6e4d 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -68,8 +68,6 @@ public: void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) override; - void NotifySwitchUMDUpdated() override {} - // Unique for HeadlessHost virtual void SwapBuffers() {} From f60f5ccaeadff6a7ccb0553d0aff77bd6632dd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 11:40:48 +0100 Subject: [PATCH 384/424] Move SetDebugMode notification --- Common/System/System.h | 2 +- Core/Core.cpp | 3 +-- Core/Host.h | 2 -- Qt/QtHost.h | 4 ++-- Qt/QtMain.cpp | 11 ++++++++++- UI/HostTypes.h | 2 -- UI/NativeApp.cpp | 8 -------- UWP/UWPHost.cpp | 2 -- UWP/UWPHost.h | 2 -- Windows/WindowsHost.cpp | 5 ----- Windows/WindowsHost.h | 2 -- Windows/main.cpp | 8 ++++++-- headless/StubHost.h | 2 -- 13 files changed, 20 insertions(+), 33 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index a1e3c936a2..aaa49f988e 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -138,7 +138,7 @@ enum class SystemNotification { UI, MEM_VIEW, DISASSEMBLY, - DEBUG_MODE, + DEBUG_MODE_CHANGE, BOOT_DONE, // this is sent from EMU thread! Make sure that Host handles it properly! SYMBOL_MAP_UPDATED, SWITCH_UMD_UPDATED, diff --git a/Core/Core.cpp b/Core/Core.cpp index af371a29b6..3423b714a7 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -368,20 +368,19 @@ bool Core_Run(GraphicsContext *ctx) { void Core_EnableStepping(bool step, const char *reason, u32 relatedAddress) { if (step) { - host->SetDebugMode(true); Core_UpdateState(CORE_STEPPING); steppingCounter++; _assert_msg_(reason != nullptr, "No reason specified for break"); steppingReason = reason; steppingAddress = relatedAddress; } else { - host->SetDebugMode(false); // Clear the exception if we resume. Core_ResetException(); coreState = CORE_RUNNING; coreStatePending = false; m_StepCond.notify_all(); } + System_Notify(SystemNotification::DEBUG_MODE_CHANGE); } bool Core_NextFrame() { diff --git a/Core/Host.h b/Core/Host.h index 7a298c7a88..35800789da 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -27,8 +27,6 @@ class Host { public: virtual ~Host() {} - virtual void SetDebugMode(bool mode) { } - virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; virtual void ShutdownGraphics() = 0; diff --git a/Qt/QtHost.h b/Qt/QtHost.h index ee782f53d3..e3a2c6ab37 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -21,6 +21,8 @@ #include "UI/OnScreenDisplay.h" #include "Qt/mainwindow.h" +#include "Core/Debugger/SymbolMap.h" + class QtHost : public Host { public: @@ -29,8 +31,6 @@ public: mainWindow = mainWindow_; } - void SetDebugMode(bool mode) override {} - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 8228e33411..3571c615ca 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -40,6 +40,8 @@ #include "Common/Profiler/Profiler.h" #include "QtMain.h" +#include "QtHost.h" +#include "Qt/mainwindow.h" #include "Common/Data/Text/I18n.h" #include "Common/Thread/ThreadUtil.h" #include "Common/Data/Encoding/Utf8.h" @@ -57,6 +59,7 @@ static float refreshRate = 60.f; static int browseFileEvent = -1; static int browseFolderEvent = -1; QTCamera *qtcamera = nullptr; +MainWindow *g_mainWindow; #ifdef SDL SDL_AudioSpec g_retFmt; @@ -259,7 +262,7 @@ void System_Notify(SystemNotification notification) { switch (notification) { case SystemNotification::BOOT_DONE: g_symbolMap->SortSymbols(); - mainWindow->Notify(MainWindowMsg::BOOT_DONE); + g_mainWindow->Notify(MainWindowMsg::BOOT_DONE); break; case SystemNotification::SYMBOL_MAP_UPDATED: if (g_symbolMap) @@ -782,6 +785,12 @@ int main(int argc, char *argv[]) NativeInit(argc, (const char **)argv, savegame_dir.c_str(), external_dir.c_str(), nullptr); + g_mainWindow = new MainWindow(nullptr, g_Config.UseFullScreen()); + g_mainWindow->show(); + if (host == nullptr) { + host = new QtHost(g_mainWindow); + } + // TODO: Support other backends than GL, like Vulkan, in the Qt backend. g_Config.iGPUBackend = (int)GPUBackend::OPENGL; diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 38d889e4cf..20c50eb87b 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -24,8 +24,6 @@ class NativeHost : public Host { public: NativeHost() {} - void SetDebugMode(bool mode) override { } - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index e482eca117..ff4010b1fe 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -834,14 +834,6 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch std::string sysName = System_GetProperty(SYSPROP_NAME); isOuya = KeyMap::IsOuya(sysName); -#if !defined(MOBILE_DEVICE) && defined(USING_QT_UI) - MainWindow *mainWindow = new MainWindow(nullptr, g_Config.UseFullScreen()); - mainWindow->show(); - if (host == nullptr) { - host = new QtHost(mainWindow); - } -#endif - // We do this here, instead of in NativeInitGraphics, because the display may be reset. // When it's reset we don't want to forget all our managed things. CheckFailedGPUBackends(); diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index e87c9e970f..3922030448 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -75,8 +75,6 @@ void UWPHost::UpdateSound() { void UWPHost::ShutdownSound() { } -void UWPHost::SetDebugMode(bool mode) {} - void UWPHost::PollControllers() { for (const auto& device : this->input) { diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index 77e0c94101..8f0841c687 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -12,8 +12,6 @@ public: UWPHost(); ~UWPHost(); - void SetDebugMode(bool mode) override; - // If returns false, will return a null context bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; void PollControllers() override; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index fd6e743455..8f1ab5fb92 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -189,11 +189,6 @@ void WindowsHost::UpdateSound() { void WindowsHost::ShutdownSound() { } -void WindowsHost::SetDebugMode(bool mode) { - if (disasmWindow) - PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)mode); -} - void WindowsHost::PollControllers() { static int checkCounter = 0; static const int CHECK_FREQUENCY = 71; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 086162de4e..aedee34cc9 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -34,8 +34,6 @@ public: UpdateConsolePosition(); } - void SetDebugMode(bool mode) override; - // If returns false, will return a null context bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; void PollControllers() override; diff --git a/Windows/main.cpp b/Windows/main.cpp index 6136c3b108..4bf24d4d34 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -384,9 +384,8 @@ void System_Notify(SystemNotification notification) { g_symbolMap->SortSymbols(); PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); - bool mode = !g_Config.bAutoRun; if (disasmWindow) - PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)mode); + PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)Core_IsStepping()); break; } @@ -421,6 +420,11 @@ void System_Notify(SystemNotification notification) { case SystemNotification::SWITCH_UMD_UPDATED: PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_SWITCHUMD_UPDATED, 0, 0); break; + + case SystemNotification::DEBUG_MODE_CHANGE: + if (disasmWindow) + PostDialogMessage(disasmWindow, WM_DEB_SETDEBUGLPARAM, 0, (LPARAM)Core_IsStepping()); + break; } } diff --git a/headless/StubHost.h b/headless/StubHost.h index 37586f6e4d..e8b3463787 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -26,8 +26,6 @@ // TODO: Get rid of this junk class HeadlessHost : public Host { public: - void SetDebugMode(bool mode) override { } - void SetGraphicsCore(GPUCore core) { gpuCore_ = core; } bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override {return false;} void ShutdownGraphics() override {} From 5fae4f36dbbfc742759ae199629181f088e5c8c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 11:42:55 +0100 Subject: [PATCH 385/424] Move SkipUI function --- Common/System/System.h | 2 ++ Core/Host.h | 2 -- Core/Util/PPGeDraw.cpp | 4 +++- headless/Headless.cpp | 2 ++ headless/StubHost.h | 2 -- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index aaa49f988e..8d74f9c270 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -132,6 +132,8 @@ enum SystemProperty { SYSPROP_CAN_JIT, SYSPROP_KEYBOARD_LAYOUT, + + SYSPROP_SKIP_UI, }; enum class SystemNotification { diff --git a/Core/Host.h b/Core/Host.h index 35800789da..aa9267ef4e 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -45,8 +45,6 @@ public: virtual void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) {} virtual void SendUIMessage(const std::string &message, const std::string &value) {} - // Used for headless. - virtual bool ShouldSkipUI() { return false; } virtual void SendDebugOutput(const std::string &output) {} virtual void SendDebugScreenshot(const u8 *pixbuf, u32 w, u32 h) {} }; diff --git a/Core/Util/PPGeDraw.cpp b/Core/Util/PPGeDraw.cpp index 12dc1e86a9..b9124e85c9 100644 --- a/Core/Util/PPGeDraw.cpp +++ b/Core/Util/PPGeDraw.cpp @@ -18,6 +18,8 @@ #include #include "ext/xxhash.h" + +#include "Common/System/System.h" #include "Common/Data/Color/RGBAUtil.h" #include "Common/File/VFS/VFS.h" #include "Common/Data/Format/ZIMLoad.h" @@ -237,7 +239,7 @@ void __PPGeSetupListArgs() void __PPGeInit() { // PPGe isn't really important for headless, and LoadZIM takes a long time. - bool skipZIM = host->ShouldSkipUI(); + bool skipZIM = System_GetPropertyBool(SYSPROP_SKIP_UI); u8 *imageData[12]{}; int width[12]{}; diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 55316a348a..52372f9de0 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -108,6 +108,8 @@ bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { case SYSPROP_CAN_JIT: return true; + case SYSPROP_SKIP_UI: + return true; default: return false; } diff --git a/headless/StubHost.h b/headless/StubHost.h index e8b3463787..1159045f9e 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -36,8 +36,6 @@ public: bool AttemptLoadSymbolMap() override { g_symbolMap->Clear(); return false; } - bool ShouldSkipUI() override { return true; } - void SendDebugOutput(const std::string &output) override { if (output.find('\n') != output.npos) { DoFlushDebugOutput(); From f5472ba0d8977c54e6216ab1297920a89dff54a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 12:08:03 +0100 Subject: [PATCH 386/424] Cleanup up unnecessary audio init functions --- Core/Host.h | 2 -- Core/System.cpp | 25 ------------------ Core/System.h | 4 --- Qt/QtHost.h | 2 -- Qt/mainwindow.h | 2 -- UI/GameSettingsScreen.cpp | 5 ---- UI/HostTypes.h | 2 -- UI/NativeApp.cpp | 18 +------------ UWP/UWPHost.cpp | 6 ----- UWP/UWPHost.h | 2 -- Windows/MainWindowMenu.cpp | 4 --- Windows/WindowsHost.cpp | 6 ----- Windows/WindowsHost.h | 2 -- headless/StubHost.h | 2 -- ios/AppDelegate.mm | 53 +++++++++++++++++++------------------- ios/ViewController.mm | 4 ++- libretro/libretro.cpp | 2 -- 17 files changed, 31 insertions(+), 110 deletions(-) diff --git a/Core/Host.h b/Core/Host.h index aa9267ef4e..920f8f087a 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -30,9 +30,7 @@ public: virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; virtual void ShutdownGraphics() = 0; - virtual void InitSound() = 0; virtual void UpdateSound() {} - virtual void ShutdownSound() = 0; virtual void PollControllers() {} virtual void ToggleDebugConsoleVisibility() {} diff --git a/Core/System.cpp b/Core/System.cpp index 4f6510f07e..71aacc931e 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -156,24 +156,6 @@ std::string GetGPUBackendDevice() { return gpuBackendDevice; } -bool IsAudioInitialised() { - return audioInitialized; -} - -void Audio_Init() { - if (!audioInitialized) { - audioInitialized = true; - host->InitSound(); - } -} - -void Audio_Shutdown() { - if (audioInitialized) { - audioInitialized = false; - host->ShutdownSound(); - } -} - bool CPU_IsReady() { if (coreState == CORE_POWERUP) return false; @@ -302,10 +284,6 @@ bool CPU_Init(std::string *errorString) { host->AttemptLoadSymbolMap(); - if (g_CoreParameter.enableSound) { - Audio_Init(); - } - CoreTiming::Init(); // Init all the HLE modules @@ -353,9 +331,6 @@ void CPU_Shutdown() { CoreTiming::Shutdown(); __KernelShutdown(); HLEShutdown(); - if (g_CoreParameter.enableSound) { - Audio_Shutdown(); - } pspFileSystem.Shutdown(); mipsr4k.Shutdown(); diff --git a/Core/System.h b/Core/System.h index 9a801596ab..c90b84054e 100644 --- a/Core/System.h +++ b/Core/System.h @@ -100,10 +100,6 @@ void Core_UpdateDebugStats(bool collectStats); // Increments or decrements an internal counter. Intended to be used by debuggers. void Core_ForceDebugStats(bool enable); -void Audio_Init(); -void Audio_Shutdown(); -bool IsAudioInitialised(); - void UpdateLoadedFile(FileLoader *fileLoader); // NOTE: These are almost all derived from g_Config.memStickDirectory directly - diff --git a/Qt/QtHost.h b/Qt/QtHost.h index e3a2c6ab37..2b60498d97 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -34,9 +34,7 @@ public: bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} - void InitSound() override; void UpdateSound() override {} - void ShutdownSound() override; bool AttemptLoadSymbolMap() override { auto fn = SymbolMapFilename(PSP_CoreParameter().fileToStart); diff --git a/Qt/mainwindow.h b/Qt/mainwindow.h index 709e903e46..6a492301d6 100644 --- a/Qt/mainwindow.h +++ b/Qt/mainwindow.h @@ -164,8 +164,6 @@ private slots: // Sound void audioAct() { g_Config.bEnableSound = !g_Config.bEnableSound; - if (PSP_IsInited() && !IsAudioInitialised()) - Audio_Init(); } // Cheats diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 6556a57193..ded0d26d52 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1343,11 +1343,6 @@ UI::EventReturn GameSettingsScreen::OnResolutionChange(UI::EventParams &e) { } void GameSettingsScreen::onFinish(DialogResult result) { - if (g_Config.bEnableSound) { - if (PSP_IsInited() && !IsAudioInitialised()) - Audio_Init(); - } - Reporting::Enable(enableReports_, "report.ppsspp.org"); Reporting::UpdateConfig(); if (!g_Config.Save("GameSettingsScreen::onFinish")) { diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 20c50eb87b..c341a993b1 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -27,9 +27,7 @@ public: bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} - void InitSound() override; void UpdateSound() override {} - void ShutdownSound() override; bool AttemptLoadSymbolMap() override {return false;} void SetWindowTitle(const char *message) override {} diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ff4010b1fe..d0d9746f88 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -218,23 +218,6 @@ int Win32Mix(short *buffer, int numSamples, int bits, int rate) { static LogListener *logger = nullptr; Path boot_filename; -void NativeHost::InitSound() { -#if PPSSPP_PLATFORM(IOS) - iOSCoreAudioInit(); -#endif -} - -void NativeHost::ShutdownSound() { -#if PPSSPP_PLATFORM(IOS) - iOSCoreAudioShutdown(); -#endif -} - -#if !defined(MOBILE_DEVICE) && defined(USING_QT_UI) -void QtHost::InitSound() { } -void QtHost::ShutdownSound() { } -#endif - std::string NativeQueryConfig(std::string query) { char temp[128]; if (query == "screenRotation") { @@ -911,6 +894,7 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { } INFO_LOG(SYSTEM, "NativeInitGraphics completed"); + return true; } diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index 3922030448..9b50580a4c 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -66,15 +66,9 @@ void UWPHost::ShutdownGraphics() { void UWPHost::SetWindowTitle(const char *message) { } -void UWPHost::InitSound() { -} - void UWPHost::UpdateSound() { } -void UWPHost::ShutdownSound() { -} - void UWPHost::PollControllers() { for (const auto& device : this->input) { diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index 8f0841c687..14a13b264a 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -17,9 +17,7 @@ public: void PollControllers() override; void ShutdownGraphics() override; - void InitSound() override; void UpdateSound() override; - void ShutdownSound() override; bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 022e1e70cc..7105f390c9 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -917,10 +917,6 @@ namespace MainWindow { case ID_EMULATION_SOUND: g_Config.bEnableSound = !g_Config.bEnableSound; - if (g_Config.bEnableSound) { - if (PSP_IsInited() && !IsAudioInitialised()) - Audio_Init(); - } break; case ID_HELP_OPENWEBSITE: diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 8f1ab5fb92..f12f744344 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -175,9 +175,6 @@ void WindowsHost::SetWindowTitle(const char *message) { PostMessage(mainWindow_, MainWindow::WM_USER_WINDOW_TITLE_CHANGED, 0, 0); } -void WindowsHost::InitSound() { -} - // UGLY! extern WindowsAudioBackend *winAudioBackend; @@ -186,9 +183,6 @@ void WindowsHost::UpdateSound() { winAudioBackend->Update(); } -void WindowsHost::ShutdownSound() { -} - void WindowsHost::PollControllers() { static int checkCounter = 0; static const int CHECK_FREQUENCY = 71; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index aedee34cc9..36682955a2 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -39,9 +39,7 @@ public: void PollControllers() override; void ShutdownGraphics() override; - void InitSound() override; void UpdateSound() override; - void ShutdownSound() override; bool AttemptLoadSymbolMap() override; void SaveSymbolMap() override; diff --git a/headless/StubHost.h b/headless/StubHost.h index 1159045f9e..67c01995f6 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -30,9 +30,7 @@ public: bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override {return false;} void ShutdownGraphics() override {} - void InitSound() override {} void UpdateSound() override {} - void ShutdownSound() override {} bool AttemptLoadSymbolMap() override { g_symbolMap->Clear(); return false; } diff --git a/ios/AppDelegate.mm b/ios/AppDelegate.mm index ba8d4ff6d9..9f543a55f3 100644 --- a/ios/AppDelegate.mm +++ b/ios/AppDelegate.mm @@ -1,5 +1,6 @@ #import "AppDelegate.h" #import "ViewController.h" +#import "iOSCoreAudio.h" #import "Common/System/System.h" #import "Common/System/NativeApp.h" #import "Core/System.h" @@ -16,59 +17,59 @@ // for AVAudioSessionInterruptionNotification -(void) handleAudioSessionInterruption:(NSNotification *)notification { NSNumber *interruptionType = notification.userInfo[AVAudioSessionInterruptionTypeKey]; - + // Sanity check in case it's somehow not an NSNumber if (![interruptionType respondsToSelector:@selector(unsignedIntegerValue)]) { return; // Lets not crash } - + switch ([interruptionType unsignedIntegerValue]) { case AVAudioSessionInterruptionTypeBegan: INFO_LOG(SYSTEM, "ios audio session interruption beginning"); if (g_Config.bEnableSound) { - Audio_Shutdown(); + iOSCoreAudioShutdown(); } break; - + case AVAudioSessionInterruptionTypeEnded: INFO_LOG(SYSTEM, "ios audio session interruption ending"); if (g_Config.bEnableSound) { - /* + /* * Only try to reinit audio if in the foreground, otherwise * it may fail. Instead, trust that applicationDidBecomeActive * will do it later. */ - if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { - Audio_Init(); + if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) { + iOSCoreAudioInit(); } } break; - + default: break; }; } -// This will be called when the iOS's shared media process was reset +// This will be called when the iOS's shared media process was reset // Registered in application:didFinishLaunchingWithOptions: // for AVAudioSessionMediaServicesWereResetNotification -(void) handleMediaServicesWereReset:(NSNotification *)notification { INFO_LOG(SYSTEM, "ios media services were reset - reinitializing audio"); - + /* When media services were reset, Apple recommends: - 1) Dispose of orphaned audio objects (such as players, recorders, + 1) Dispose of orphaned audio objects (such as players, recorders, converters, or audio queues) and create new ones - 2) Reset any internal audio states being tracked, including all + 2) Reset any internal audio states being tracked, including all properties of AVAudioSession - 3) When appropriate, reactivate the AVAudioSession instance using the + 3) When appropriate, reactivate the AVAudioSession instance using the setActive:error: method We accomplish this by shutting down and reinitializing audio */ - + if (g_Config.bEnableSound) { - Audio_Shutdown(); - Audio_Init(); + iOSCoreAudioShutdown(); + iOSCoreAudioInit(); } } @@ -91,14 +92,14 @@ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.viewController = [[ViewController alloc] init]; - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAudioSessionInterruption:) name:AVAudioSessionInterruptionNotification object:[AVAudioSession sharedInstance]]; - + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMediaServicesWereReset:) name:AVAudioSessionMediaServicesWereResetNotification object:nil]; - + self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; - + return YES; } @@ -108,18 +109,18 @@ -(void) applicationWillResignActive:(UIApplication *)application { if (g_Config.bEnableSound) { - Audio_Shutdown(); + iOSCoreAudioShutdown(); } - - NativeMessageReceived("lost_focus", ""); + + NativeMessageReceived("lost_focus", ""); } -(void) applicationDidBecomeActive:(UIApplication *)application { if (g_Config.bEnableSound) { - Audio_Init(); + iOSCoreAudioInit(); } - - NativeMessageReceived("got_focus", ""); + + NativeMessageReceived("got_focus", ""); } - (void)applicationWillTerminate:(UIApplication *)application { diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 44de91f4bc..9c4ff956ff 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -8,6 +8,8 @@ #import "AppDelegate.h" #import "ViewController.h" #import "DisplayManager.h" +#import "iOSCoreAudio.h" + #import #include @@ -254,7 +256,7 @@ static LocationHelper *locationHelper; return; } - Audio_Shutdown(); + iOSCoreAudioShutdown(); if (threadEnabled) { threadEnabled = false; diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 726902f31d..657e79635c 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -388,7 +388,6 @@ class LibretroHost : public Host LibretroHost() {} bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } void ShutdownGraphics() override {} - void InitSound() override {} void UpdateSound() override { int hostAttemptBlockSize = __AudioGetHostAttemptBlockSize(); @@ -399,7 +398,6 @@ class LibretroHost : public Host int samples = __AudioMix(audio, hostAttemptBlockSize, SAMPLERATE); AudioBufferWrite(audio, samples); } - void ShutdownSound() override {} bool AttemptLoadSymbolMap() override { return false; } }; From 2786786c9f65566462cce340985c5b6e09bf2fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 12:36:57 +0100 Subject: [PATCH 387/424] Avoid Host in Windows graphics init --- Core/Host.h | 2 +- UI/NativeApp.cpp | 6 ------ Windows/EmuThread.cpp | 43 +++++++++++++++++++++++++++++++++++++++-- Windows/WindowsHost.cpp | 41 +-------------------------------------- Windows/WindowsHost.h | 3 --- 5 files changed, 43 insertions(+), 52 deletions(-) diff --git a/Core/Host.h b/Core/Host.h index 920f8f087a..c6399370ab 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -30,7 +30,7 @@ public: virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; virtual void ShutdownGraphics() = 0; - virtual void UpdateSound() {} + virtual void UpdateSound() {} // still needed for libretro, will need a proper effort. virtual void PollControllers() {} virtual void ToggleDebugConsoleVisibility() {} diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index d0d9746f88..e2c05d2b31 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1426,12 +1426,6 @@ void NativeShutdown() { screenManager = nullptr; } - if (host) { - host->ShutdownGraphics(); - delete host; - host = nullptr; - } - #if !PPSSPP_PLATFORM(UWP) #endif g_Config.Save("NativeShutdown"); diff --git a/Windows/EmuThread.cpp b/Windows/EmuThread.cpp index 5c3798bc7c..4748557d18 100644 --- a/Windows/EmuThread.cpp +++ b/Windows/EmuThread.cpp @@ -26,6 +26,13 @@ #include "Core/Config.h" #include "Core/ConfigValues.h" +#if PPSSPP_API(ANY_GL) +#include "Windows/GPU/WindowsGLContext.h" +#endif +#include "Windows/GPU/WindowsVulkanContext.h" +#include "Windows/GPU/D3D9Context.h" +#include "Windows/GPU/D3D11Context.h" + enum class EmuThreadState { DISABLED, START_REQUESTED, @@ -112,6 +119,37 @@ static void EmuThreadJoin() { INFO_LOG(SYSTEM, "EmuThreadJoin - joined"); } +bool CreateGraphicsBackend(std::string *error_message, GraphicsContext **ctx) { + WindowsGraphicsContext *graphicsContext = nullptr; + switch (g_Config.iGPUBackend) { +#if PPSSPP_API(ANY_GL) + case (int)GPUBackend::OPENGL: + graphicsContext = new WindowsGLContext(); + break; +#endif + case (int)GPUBackend::DIRECT3D9: + graphicsContext = new D3D9Context(); + break; + case (int)GPUBackend::DIRECT3D11: + graphicsContext = new D3D11Context(); + break; + case (int)GPUBackend::VULKAN: + graphicsContext = new WindowsVulkanContext(); + break; + default: + return false; + } + + if (graphicsContext->Init(MainWindow::GetHInstance(), MainWindow::GetDisplayHWND(), error_message)) { + *ctx = graphicsContext; + return true; + } else { + delete graphicsContext; + *ctx = nullptr; + return false; + } +} + void MainThreadFunc() { if (useEmuThread) { // We'll start up a separate thread we'll call Emu @@ -164,7 +202,7 @@ void MainThreadFunc() { System_Notify(SystemNotification::UI); std::string error_string; - bool success = host->InitGraphics(&error_string, &g_graphicsContext); + bool success = CreateGraphicsBackend(&error_string, &g_graphicsContext); if (success) { // Main thread is the render thread. @@ -299,7 +337,8 @@ shutdown: g_graphicsContext->ThreadEnd(); g_graphicsContext->ShutdownFromRenderThread(); - // NativeShutdown deletes the graphics context through host->ShutdownGraphics(). + g_graphicsContext->Shutdown(); + NativeShutdown(); PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_UPDATE_UI, 0, 0); diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index f12f744344..5c2b09c666 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -53,13 +53,6 @@ #include "Windows/WindowsHost.h" #include "Windows/MainWindow.h" -#if PPSSPP_API(ANY_GL) -#include "Windows/GPU/WindowsGLContext.h" -#endif -#include "Windows/GPU/WindowsVulkanContext.h" -#include "Windows/GPU/D3D9Context.h" -#include "Windows/GPU/D3D11Context.h" - #include "Windows/Debugger/DebuggerShared.h" #include "Windows/Debugger/Debugger_Disasm.h" #include "Windows/Debugger/Debugger_MemoryDlg.h" @@ -117,42 +110,10 @@ void WindowsHost::UpdateConsolePosition() { } bool WindowsHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { - WindowsGraphicsContext *graphicsContext = nullptr; - switch (g_Config.iGPUBackend) { -#if PPSSPP_API(ANY_GL) - case (int)GPUBackend::OPENGL: - graphicsContext = new WindowsGLContext(); - break; -#endif - case (int)GPUBackend::DIRECT3D9: - graphicsContext = new D3D9Context(); - break; - case (int)GPUBackend::DIRECT3D11: - graphicsContext = new D3D11Context(); - break; - case (int)GPUBackend::VULKAN: - graphicsContext = new WindowsVulkanContext(); - break; - default: - return false; - } - - if (graphicsContext->Init(hInstance_, displayWindow_, error_message)) { - *ctx = graphicsContext; - gfx_ = graphicsContext; - return true; - } else { - delete graphicsContext; - *ctx = nullptr; - gfx_ = nullptr; - return false; - } + return true; } void WindowsHost::ShutdownGraphics() { - gfx_->Shutdown(); - delete gfx_; - gfx_ = nullptr; } void WindowsHost::SetWindowTitle(const char *message) { diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 36682955a2..3717bf5291 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -24,8 +24,6 @@ extern float g_mouseDeltaX; extern float g_mouseDeltaY; -class GraphicsContext; - class WindowsHost : public Host { public: WindowsHost(HINSTANCE hInstance, HWND mainWindow, HWND displayWindow); @@ -61,7 +59,6 @@ private: HINSTANCE hInstance_; HWND displayWindow_; HWND mainWindow_; - GraphicsContext *gfx_ = nullptr; size_t numDinputDevices_ = 0; std::wstring lastTitle_; From 47f063550af56a4dec9a8f11458a99fdde477e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 21 Mar 2023 22:19:48 +0100 Subject: [PATCH 388/424] Remove InitGraphics/ShutdownGraphics from Host, except for headless --- Core/Host.h | 3 --- Qt/QtHost.h | 3 --- UI/HostTypes.h | 3 --- UWP/UWPHost.cpp | 9 --------- UWP/UWPHost.h | 3 --- Windows/WindowsHost.cpp | 7 ------- Windows/WindowsHost.h | 5 ----- ext/glslang | 2 +- headless/Headless.cpp | 5 ++--- headless/SDLHeadlessHost.cpp | 2 +- headless/SDLHeadlessHost.h | 2 +- headless/StubHost.h | 6 ++---- headless/WindowsHeadlessHost.cpp | 3 ++- headless/WindowsHeadlessHost.h | 2 +- libretro/libretro.cpp | 2 -- 15 files changed, 10 insertions(+), 47 deletions(-) diff --git a/Core/Host.h b/Core/Host.h index c6399370ab..0fc4746710 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -27,9 +27,6 @@ class Host { public: virtual ~Host() {} - virtual bool InitGraphics(std::string *error_string, GraphicsContext **ctx) = 0; - virtual void ShutdownGraphics() = 0; - virtual void UpdateSound() {} // still needed for libretro, will need a proper effort. virtual void PollControllers() {} virtual void ToggleDebugConsoleVisibility() {} diff --git a/Qt/QtHost.h b/Qt/QtHost.h index 2b60498d97..71278529e5 100644 --- a/Qt/QtHost.h +++ b/Qt/QtHost.h @@ -31,9 +31,6 @@ public: mainWindow = mainWindow_; } - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } - void ShutdownGraphics() override {} - void UpdateSound() override {} bool AttemptLoadSymbolMap() override { diff --git a/UI/HostTypes.h b/UI/HostTypes.h index c341a993b1..ede4580f52 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -24,9 +24,6 @@ class NativeHost : public Host { public: NativeHost() {} - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } - void ShutdownGraphics() override {} - void UpdateSound() override {} bool AttemptLoadSymbolMap() override {return false;} diff --git a/UWP/UWPHost.cpp b/UWP/UWPHost.cpp index 9b50580a4c..d620046e82 100644 --- a/UWP/UWPHost.cpp +++ b/UWP/UWPHost.cpp @@ -54,15 +54,6 @@ void UWPHost::SetConsolePosition() { void UWPHost::UpdateConsolePosition() { } -bool UWPHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { - // Done elsewhere - return true; -} - -void UWPHost::ShutdownGraphics() { - // Done elsewhere -} - void UWPHost::SetWindowTitle(const char *message) { } diff --git a/UWP/UWPHost.h b/UWP/UWPHost.h index 14a13b264a..8e13f6af2a 100644 --- a/UWP/UWPHost.h +++ b/UWP/UWPHost.h @@ -12,10 +12,7 @@ public: UWPHost(); ~UWPHost(); - // If returns false, will return a null context - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; void PollControllers() override; - void ShutdownGraphics() override; void UpdateSound() override; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 5c2b09c666..1ad4edb215 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -109,13 +109,6 @@ void WindowsHost::UpdateConsolePosition() { } } -bool WindowsHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { - return true; -} - -void WindowsHost::ShutdownGraphics() { -} - void WindowsHost::SetWindowTitle(const char *message) { #ifdef GOLD const char *name = "PPSSPP Gold "; diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index 3717bf5291..cae7f5f3ca 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -32,10 +32,7 @@ public: UpdateConsolePosition(); } - // If returns false, will return a null context - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; void PollControllers() override; - void ShutdownGraphics() override; void UpdateSound() override; @@ -50,8 +47,6 @@ public: void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override; void SendUIMessage(const std::string &message, const std::string &value) override; - GraphicsContext *GetGraphicsContext() { return gfx_; } - private: void SetConsolePosition(); void UpdateConsolePosition(); diff --git a/ext/glslang b/ext/glslang index b34f619e1c..77551c429f 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit b34f619e1c85810dcb3c578107d2e48ba4ee2b37 +Subproject commit 77551c429f86c0e077f26552b7c1c0f12a9f235e diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 52372f9de0..27e0508e64 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -409,12 +409,11 @@ int main(int argc, const char* argv[]) g_threadManager.Init(cpu_info.num_cores, cpu_info.logical_cpu_count); HeadlessHost *headlessHost = getHost(gpuCore); - headlessHost->SetGraphicsCore(gpuCore); host = headlessHost; std::string error_string; GraphicsContext *graphicsContext = nullptr; - bool glWorking = host->InitGraphics(&error_string, &graphicsContext); + bool glWorking = ((HeadlessHost *)host)->InitGraphics(&error_string, &graphicsContext, gpuCore); CoreParameter coreParameter; coreParameter.cpuCore = cpuCore; @@ -578,7 +577,7 @@ int main(int argc, const char* argv[]) ShutdownWebServer(); } - host->ShutdownGraphics(); + ((HeadlessHost *)host)->ShutdownGraphics(); delete host; host = nullptr; headlessHost = nullptr; diff --git a/headless/SDLHeadlessHost.cpp b/headless/SDLHeadlessHost.cpp index f26150feeb..8aa0741782 100644 --- a/headless/SDLHeadlessHost.cpp +++ b/headless/SDLHeadlessHost.cpp @@ -165,7 +165,7 @@ bool GLDummyGraphicsContext::InitFromRenderThread(std::string *errorMessage) { return success; } -bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { +bool SDLHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx, GPUCore core) { GraphicsContext *graphicsContext = new GLDummyGraphicsContext(); *ctx = graphicsContext; gfx_ = graphicsContext; diff --git a/headless/SDLHeadlessHost.h b/headless/SDLHeadlessHost.h index 47d92f509c..afcac2e2ac 100644 --- a/headless/SDLHeadlessHost.h +++ b/headless/SDLHeadlessHost.h @@ -30,7 +30,7 @@ typedef void *SDL_GLContext; class SDLHeadlessHost : public HeadlessHost { public: - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; + bool InitGraphics(std::string *error_message, GraphicsContext **ctx, GPUCore core) override; void ShutdownGraphics() override; void SwapBuffers() override; diff --git a/headless/StubHost.h b/headless/StubHost.h index 67c01995f6..280997f4d7 100644 --- a/headless/StubHost.h +++ b/headless/StubHost.h @@ -23,12 +23,10 @@ #include "Core/Host.h" #include "Core/Debugger/SymbolMap.h" -// TODO: Get rid of this junk class HeadlessHost : public Host { public: - void SetGraphicsCore(GPUCore core) { gpuCore_ = core; } - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override {return false;} - void ShutdownGraphics() override {} + virtual bool InitGraphics(std::string *error_message, GraphicsContext **ctx, GPUCore core) {return false;} + virtual void ShutdownGraphics() {} void UpdateSound() override {} diff --git a/headless/WindowsHeadlessHost.cpp b/headless/WindowsHeadlessHost.cpp index c190a8872b..6d7d58da6a 100644 --- a/headless/WindowsHeadlessHost.cpp +++ b/headless/WindowsHeadlessHost.cpp @@ -72,8 +72,9 @@ void WindowsHeadlessHost::SendDebugOutput(const std::string &output) OutputDebugStringUTF8(output.c_str()); } -bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx) { +bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsContext **ctx, GPUCore core) { hWnd = CreateHiddenWindow(); + gpuCore_ = core; if (WINDOW_VISIBLE) { ShowWindow(hWnd, TRUE); diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index b0a3d3901c..3b67fee26a 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -29,7 +29,7 @@ class WindowsHeadlessHost : public HeadlessHost { public: - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override; + bool InitGraphics(std::string *error_message, GraphicsContext **ctx, GPUCore core) override; void ShutdownGraphics() override; void SwapBuffers() override; diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 657e79635c..05b13dcdbf 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -386,8 +386,6 @@ class LibretroHost : public Host { public: LibretroHost() {} - bool InitGraphics(std::string *error_message, GraphicsContext **ctx) override { return true; } - void ShutdownGraphics() override {} void UpdateSound() override { int hostAttemptBlockSize = __AudioGetHostAttemptBlockSize(); From 0584c6f41462bbbe772472f3ba60fb346089d67e Mon Sep 17 00:00:00 2001 From: fp64 <106717720+fp64@users.noreply.github.com> Date: Wed, 22 Mar 2023 01:50:50 -0400 Subject: [PATCH 389/424] Fix RTC failures in autotests on 32 bit Also simplifies code. Note: some uses of (potentially 32-bit) time_t are still left. --- Core/HLE/sceRtc.cpp | 124 ++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 79 deletions(-) diff --git a/Core/HLE/sceRtc.cpp b/Core/HLE/sceRtc.cpp index 1b243dd6fc..7ceca39ce5 100644 --- a/Core/HLE/sceRtc.cpp +++ b/Core/HLE/sceRtc.cpp @@ -220,73 +220,56 @@ static void __RtcPspTimeToTm(tm &val, const ScePspDateTime &pt) val.tm_isdst = 0; } +// Based on http://howardhinnant.github.io/date_algorithms.html +static s64 days_from_civil(s64 y, u32 m, u32 d) +{ + y -= m <= 2; + const s64 era = (y >= 0 ? y : y-399) / 400; + const u32 yoe = static_cast(y - era * 400); // [0, 399] + const u32 doy = (153*(m > 2 ? m-3 : m+9) + 2)/5 + d-1;// [0, 365] + const u32 doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096] + return era * 146097 + static_cast(doe) - 719468; +} + +static void civil_from_days(s64 z, s64 &out_y, u32 &out_m, u32 &out_d) +{ + z += 719468; + const s64 era = (z >= 0 ? z : z - 146096) / 146097; + const u32 doe = static_cast(z - era * 146097); // [0, 146096] + const u32 yoe = (doe - doe/1460 + doe/36524 - doe/146096) / 365; // [0, 399] + const s64 y = static_cast(yoe) + era * 400; + const u32 doy = doe - (365*yoe + yoe/4 - yoe/100); // [0, 365] + const u32 mp = (5*doy + 2)/153; // [0, 11] + out_d = doy - (153*mp+2)/5 + 1; // [1, 31] + out_m = mp < 10 ? mp+3 : mp-9; // [1, 12] + out_y = y + (out_m <= 2); +} + static void __RtcTicksToPspTime(ScePspDateTime &t, u64 ticks) { - int numYearAdd = 0; - if (ticks < 1000000ULL) - { - t.year = 1; - t.month = 1; - t.day = 1; - t.hour = 0; - t.minute = 0; - t.second = 0; - t.microsecond = ticks % 1000000ULL; - return; - } - else if (ticks < rtcMagicOffset) - { - // Need to get a year past 1970 for gmtime - // Add enough 400 year to pass over 1970. - numYearAdd = (int) ((rtcMagicOffset - ticks) / rtc400YearTicks + 1); - ticks += rtc400YearTicks * numYearAdd; - } - - while (ticks >= rtcMagicOffset + rtc400YearTicks) - { - ticks -= rtc400YearTicks; - --numYearAdd; - } - - time_t time = (ticks - rtcMagicOffset) / 1000000ULL; - t.microsecond = ticks % 1000000ULL; - - tm *local = gmtime(&time); - if (!local) - { - ERROR_LOG(SCERTC, "Date is too high/low to handle, pretending to work."); - return; - } - - t.year = local->tm_year + 1900 - numYearAdd * 400; - t.month = local->tm_mon + 1; - t.day = local->tm_mday; - t.hour = local->tm_hour; - t.minute = local->tm_min; - t.second = local->tm_sec; + u64 Day = 24ull * 60ull * 60ull * 1000000ull; + t.microsecond = ticks % 1000000ull; + t.second = ticks / 1000000ull % 60ull; + t.minute = ticks / 1000000ull / 60ull % 60ull; + t.hour = ticks / 1000000ull / 60ull / 60ull % 24ull; + s64 z = s64(ticks / Day) - s64(rtcMagicOffset / Day); + s64 y; + u32 m, d; + civil_from_days(z, y, m, d); + t.day = d; + t.month = m; + t.year = y; } static u64 __RtcPspTimeToTicks(const ScePspDateTime &pt) { - tm local; - __RtcPspTimeToTm(local, pt); - - s64 tickOffset = 0; - while (local.tm_year < 70) - { - tickOffset -= rtc400YearTicks; - local.tm_year += 400; - } - while (local.tm_year >= 470) - { - tickOffset += rtc400YearTicks; - local.tm_year -= 400; - } - - time_t seconds = rtc_timegm(&local); - u64 result = rtcMagicOffset + (u64) seconds * 1000000ULL; - result += pt.microsecond; - return result + tickOffset; + s64 z = days_from_civil(s64(pt.year), pt.month, pt.day); + return rtcMagicOffset + + pt.microsecond + + 1000000ull * (pt.second + + 60ull * (pt.minute + + 60ull * (pt.hour + + 24ull * u64(z)))); } static bool __RtcValidatePspTime(const ScePspDateTime &t) @@ -413,24 +396,7 @@ static u32 sceRtcGetDayOfWeek(u32 year, u32 month, u32 day) month = 12; } - while (year < 1900) - year += 400; - while (year > 2300) - year -= 400; - - tm local; - local.tm_year = year - 1900; - local.tm_mon = month - 1; - local.tm_mday = day; - local.tm_wday = -1; - local.tm_yday = -1; - local.tm_hour = 0; - local.tm_min = 0; - local.tm_sec = 0; - local.tm_isdst = 0; - - mktime(&local); - return local.tm_wday; + return ((days_from_civil(s64(year), month, day) % 7LL) + 11LL) % 7LL; } static bool __RtcIsLeapYear(u32 year) From 94debfbf36410a0cb2c0ff7dcf2e84f916366a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 09:42:31 +0100 Subject: [PATCH 390/424] Rename screenManager to g_screenManager, readme update --- README.md | 12 +++---- UI/NativeApp.cpp | 72 +++++++++++++++++++++--------------------- Windows/MainWindow.cpp | 2 -- 3 files changed, 42 insertions(+), 44 deletions(-) diff --git a/README.md b/README.md index 0aaed77a12..5c0e51a5b1 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,9 @@ Additional code by many contributors, see the Credits screen Originally released under the GPL 2.0 (and later) in November 2012 -Official website: -https://www.ppsspp.org/ +Official website: https://www.ppsspp.org/ -Discord: -https://discord.gg/5NJB6dD +Discord: https://discord.gg/5NJB6dD No BIOS file required to play, PPSSPP is an "HLE" emulator. Default settings balance good compatibility and speed. @@ -19,9 +17,11 @@ To contribute, see [the development page](https://www.ppsspp.org/development.htm For the latest source code, see [our GitHub page](https://github.com/hrydgard/ppsspp). +For documentation of all kinds (usage, reference, development), see the [documentation on the main website](https://www.ppsspp.org/docs) + For build instructions and other development tutorials, see [the wiki](https://github.com/hrydgard/ppsspp/wiki). -If you want to download regularly updated builds for Android, Windows x86 and x64, proceed to this [page](https://buildbot.orphis.net/ppsspp/) +If you want to download regularly updated builds for Android, Windows x86 and x64, [visit Orphis' buildbot](https://buildbot.orphis.net/ppsspp/) For game compatibility, see [community compatibility feedback](https://report.ppsspp.org/games). @@ -412,4 +412,4 @@ Credit goes to: [#16709]: https://github.com/hrydgard/ppsspp/issues/16709 "Correct some shader errors in reporting" [#16708]: https://github.com/hrydgard/ppsspp/issues/16708 "Additional fixes from both our reports and Play reports" [#16703]: https://github.com/hrydgard/ppsspp/issues/16703 "Minor fixes based on the latest Google Play report" -[#16706]: https://github.com/hrydgard/ppsspp/issues/16706 "softgpu: Fix lighting with 0 exp" \ No newline at end of file +[#16706]: https://github.com/hrydgard/ppsspp/issues/16706 "softgpu: Fix lighting with 0 exp" diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index e2c05d2b31..75ab082de1 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -148,7 +148,7 @@ #include -ScreenManager *screenManager; +ScreenManager *g_screenManager; std::string config_filename; // Really need to clean this mess of globals up... but instead I add more :P @@ -789,19 +789,19 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } DEBUG_LOG(SYSTEM, "ScreenManager!"); - screenManager = new ScreenManager(); + g_screenManager = new ScreenManager(); if (g_Config.memStickDirectory.empty()) { INFO_LOG(SYSTEM, "No memstick directory! Asking for one to be configured."); - screenManager->switchScreen(new LogoScreen(AfterLogoScreen::MEMSTICK_SCREEN_INITIAL_SETUP)); + g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::MEMSTICK_SCREEN_INITIAL_SETUP)); } else if (gotoGameSettings) { - screenManager->switchScreen(new LogoScreen(AfterLogoScreen::TO_GAME_SETTINGS)); + g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::TO_GAME_SETTINGS)); } else if (gotoTouchScreenTest) { - screenManager->switchScreen(new MainScreen()); - screenManager->push(new TouchTestScreen(Path())); + g_screenManager->switchScreen(new MainScreen()); + g_screenManager->push(new TouchTestScreen(Path())); } else if (skipLogo) { - screenManager->switchScreen(new EmuScreen(boot_filename)); + g_screenManager->switchScreen(new EmuScreen(boot_filename)); } else { - screenManager->switchScreen(new LogoScreen(AfterLogoScreen::DEFAULT)); + g_screenManager->switchScreen(new LogoScreen(AfterLogoScreen::DEFAULT)); } // Easy testing @@ -833,7 +833,7 @@ bool CreateGlobalPipelines(); bool NativeInitGraphics(GraphicsContext *graphicsContext) { INFO_LOG(SYSTEM, "NativeInitGraphics"); - _assert_(screenManager); + _assert_(g_screenManager); // We set this now so any resize during init is processed later. resized = false; @@ -864,10 +864,10 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) { if (uiContext->Text()) uiContext->Text()->SetFont("Tahoma", 20, 0); - screenManager->setUIContext(uiContext); - screenManager->setDrawContext(g_draw); - screenManager->setPostRenderCallback(&RenderOverlays, nullptr); - screenManager->deviceRestored(); + g_screenManager->setUIContext(uiContext); + g_screenManager->setDrawContext(g_draw); + g_screenManager->setPostRenderCallback(&RenderOverlays, nullptr); + g_screenManager->deviceRestored(); #ifdef _WIN32 winAudioBackend = CreateAudioBackend((AudioBackendType)g_Config.iAudioBackend); @@ -951,8 +951,8 @@ bool CreateGlobalPipelines() { void NativeShutdownGraphics() { INFO_LOG(SYSTEM, "NativeShutdownGraphics"); - if (screenManager) { - screenManager->deviceLost(); + if (g_screenManager) { + g_screenManager->deviceLost(); } if (gpu) @@ -1062,7 +1062,7 @@ void RenderOverlays(UIContext *dc, void *userdata) { void NativeRender(GraphicsContext *graphicsContext) { _dbg_assert_(graphicsContext != nullptr); - _dbg_assert_(screenManager != nullptr); + _dbg_assert_(g_screenManager != nullptr); g_GameManager.Update(); @@ -1108,19 +1108,19 @@ void NativeRender(GraphicsContext *graphicsContext) { ui_draw2d.PushDrawMatrix(ortho); ui_draw2d_front.PushDrawMatrix(ortho); - screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation); + g_screenManager->getUIContext()->SetTintSaturation(g_Config.fUITint, g_Config.fUISaturation); Draw::DebugFlags debugFlags = Draw::DebugFlags::NONE; if (g_Config.bShowGpuProfile) debugFlags |= Draw::DebugFlags::PROFILE_TIMESTAMPS; if (g_Config.bGpuLogProfiler) debugFlags |= Draw::DebugFlags::PROFILE_SCOPES; - screenManager->getDrawContext()->SetDebugFlags(debugFlags); + g_screenManager->getDrawContext()->SetDebugFlags(debugFlags); // All actual rendering happen in here. - screenManager->render(); - if (screenManager->getUIContext()->Text()) { - screenManager->getUIContext()->Text()->OncePerFrame(); + g_screenManager->render(); + if (g_screenManager->getUIContext()->Text()) { + g_screenManager->getUIContext()->Text()->OncePerFrame(); } if (resized) { @@ -1142,7 +1142,7 @@ void NativeRender(GraphicsContext *graphicsContext) { } graphicsContext->Resize(); - screenManager->resized(); + g_screenManager->resized(); // TODO: Move this to the GraphicsContext objects for each backend. #if !PPSSPP_PLATFORM(WINDOWS) && !defined(ANDROID) @@ -1259,14 +1259,14 @@ void NativeUpdate() { for (const auto &item : toProcess) { HandleGlobalMessage(item.msg, item.value); - screenManager->sendMessage(item.msg.c_str(), item.value.c_str()); + g_screenManager->sendMessage(item.msg.c_str(), item.value.c_str()); } for (const auto &item : inputToProcess) { item.cb(item.result, item.value); } g_DownloadManager.Update(); - screenManager->update(); + g_screenManager->update(); g_Discord.Update(); @@ -1275,11 +1275,11 @@ void NativeUpdate() { bool NativeIsAtTopLevel() { // This might need some synchronization? - if (!screenManager) { + if (!g_screenManager) { ERROR_LOG(SYSTEM, "No screen manager active"); return false; } - Screen *currentScreen = screenManager->topScreen(); + Screen *currentScreen = g_screenManager->topScreen(); if (currentScreen) { bool top = currentScreen->isTopLevel(); INFO_LOG(SYSTEM, "Screen toplevel: %i", (int)top); @@ -1291,7 +1291,7 @@ bool NativeIsAtTopLevel() { } void NativeTouch(const TouchInput &touch) { - if (!screenManager) { + if (!g_screenManager) { return; } @@ -1300,7 +1300,7 @@ void NativeTouch(const TouchInput &touch) { if (my_isnan(touch.x) || my_isnan(touch.y)) { return; } - screenManager->touch(touch); + g_screenManager->touch(touch); } bool NativeKey(const KeyInput &key) { @@ -1323,10 +1323,10 @@ bool NativeKey(const KeyInput &key) { } #endif bool retval = false; - if (screenManager) + if (g_screenManager) { HLEPlugins::PluginDataKeys[key.keyCode] = (key.flags & KEY_DOWN) ? 1 : 0; - retval = screenManager->key(key); + retval = g_screenManager->key(key); } return retval; } @@ -1337,7 +1337,7 @@ void NativeAxis(const AxisInput &axis) { return; } - if (!screenManager) { + if (!g_screenManager) { // Too early. return; } @@ -1346,7 +1346,7 @@ void NativeAxis(const AxisInput &axis) { // only do special handling of tilt events if tilt is enabled. HLEPlugins::PluginDataAxis[axis.axisId] = axis.value; - screenManager->axis(axis); + g_screenManager->axis(axis); if (g_Config.iTiltInputType == TILT_NULL) { // if tilt events are disabled, don't do anything special. @@ -1420,10 +1420,10 @@ bool NativeIsRestarting() { } void NativeShutdown() { - if (screenManager) { - screenManager->shutdown(); - delete screenManager; - screenManager = nullptr; + if (g_screenManager) { + g_screenManager->shutdown(); + delete g_screenManager; + g_screenManager = nullptr; } #if !PPSSPP_PLATFORM(UWP) diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index f02d1e4f79..d81d20b121 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -107,7 +107,6 @@ struct VerySleepy_AddrInfo { }; static std::wstring windowTitle; -extern ScreenManager *screenManager; #define TIMER_CURSORUPDATE 1 #define TIMER_CURSORMOVEUPDATE 2 @@ -473,7 +472,6 @@ namespace MainWindow } void UpdateWindowTitle() { - // Seems to be fine to call now since we use a UNICODE build... std::wstring title = windowTitle; if (PPSSPP_ID >= 1 && GetInstancePeerCount() > 1) { title.append(ConvertUTF8ToWString(StringFromFormat(" (instance: %d)", (int)PPSSPP_ID))); From 3852d4f698ec35fafe012da06298d667ab101331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 11:34:48 +0100 Subject: [PATCH 391/424] Make a little system to replace the InputBox message queue with something more generic --- Common/Common.vcxproj | 2 ++ Common/Common.vcxproj.filters | 6 ++++ Common/System/Message.cpp | 55 +++++++++++++++++++++++++++++++++++ Common/System/Message.h | 50 +++++++++++++++++++++++++++++++ Common/System/System.h | 10 +++++++ Windows/main.cpp | 20 +++++++++++++ 6 files changed, 143 insertions(+) create mode 100644 Common/System/Message.cpp create mode 100644 Common/System/Message.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index c066494c66..a28696099b 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -550,6 +550,7 @@ + @@ -1005,6 +1006,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index cce4e7656a..23b138fb39 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -494,6 +494,9 @@ ext\basis_universal + + System + @@ -920,6 +923,9 @@ ext\basis_universal + + System + diff --git a/Common/System/Message.cpp b/Common/System/Message.cpp new file mode 100644 index 0000000000..8a09fc3a04 --- /dev/null +++ b/Common/System/Message.cpp @@ -0,0 +1,55 @@ +#include "Common/System/Message.h" +#include "Common/System/System.h" +#include "Common/Log.h" + +RequestManager g_RequestManager; + +const char *RequestTypeAsString(SystemRequestType type) { + switch (type) { + case SystemRequestType::INPUT_TEXT_MODAL: return "INPUT_TEXT_MODAL"; + default: return "N/A"; + } +} + +bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2) { + int requestId = idCounter_++; + if (!System_MakeRequest(type, requestId, param1, param2)) { + return false; + } + + if (!callback) { + // We don't expect a response, this is a one-directional request. We're thus done. + return true; + } + + std::lock_guard guard(callbackMutex_); + callbackMap_[requestId] = callback; + return true; +} + +void RequestManager::PostSystemResponse(int requestId, const char *responseString, int responseValue) { + std::lock_guard guard(callbackMutex_); + auto iter = callbackMap_.find(requestId); + if (iter == callbackMap_.end()) { + // Unexpected! + ERROR_LOG(SYSTEM, "PostSystemResponse: Unexpected request ID %d for %s (responseString=%s)", requestId, responseString); + return; + } + + std::lock_guard responseGuard(responseMutex_); + PendingResponse response; + response.callback = iter->second; + response.responseString = responseString; + response.responseValue = responseValue; + pendingResponses_.push_back(response); +} + +void RequestManager::ProcessRequests() { + std::lock_guard guard(responseMutex_); + for (auto &iter : pendingResponses_) { + if (iter.callback) { + iter.callback(iter.responseString.c_str(), iter.responseValue); + } + } + pendingResponses_.clear(); +} diff --git a/Common/System/Message.h b/Common/System/Message.h new file mode 100644 index 0000000000..88cd58df41 --- /dev/null +++ b/Common/System/Message.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include + +#include "Common/System/System.h" + +typedef std::function RequestCallback; + +// Platforms often have to process requests asynchronously, on wildly different threads. +// (Especially Android...) +// This acts as bridge and buffer. +class RequestManager { +public: + // These requests are to be handled by platform implementations. + // The callback you pass in will be called on the main thread later. + bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2); + + // Called by the platform implementation, when it's finished with a request. + void PostSystemResponse(int requestId, const char *responseString, int responseValue); + + // This must be called every frame from the beginning of NativeUpdate(). + // This will call the callback of any finished requests. + void ProcessRequests(); + +private: + struct PendingRequest { + SystemRequestType type; + RequestCallback callback; + }; + + std::map callbackMap_; + std::mutex callbackMutex_; + + struct PendingResponse { + std::string responseString; + int responseValue; + RequestCallback callback; + }; + + int idCounter_ = 0; + std::vector pendingResponses_; + std::mutex responseMutex_; +}; + +const char *RequestTypeAsString(SystemRequestType type); + +extern RequestManager g_RequestManager; diff --git a/Common/System/System.h b/Common/System/System.h index 8d74f9c270..c33bac6ed0 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -146,6 +146,16 @@ enum class SystemNotification { SWITCH_UMD_UPDATED, }; +enum class SystemRequestType { + INPUT_TEXT_MODAL, +}; + +// Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). +// This is not to be used directly by applications, instead use the g_RequestManager to make the requests. +// This can return false if it's known that the platform doesn't support the request, the app is supposed to handle +// or ignore that cleanly. +bool System_MakeRequest(SystemRequestType type, int requestId, const char *param1, const char *param2); + std::string System_GetProperty(SystemProperty prop); std::vector System_GetPropertyStringVec(SystemProperty prop); int System_GetPropertyInt(SystemProperty prop); diff --git a/Windows/main.cpp b/Windows/main.cpp index 4bf24d4d34..7db15f7b81 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -513,6 +513,26 @@ void System_InputBoxGetString(const std::string &title, const std::string &defau }); } +bool System_PerformRequest(SystemRequestType type, int requestId, const char *param1, const char *param2) { + switch (type) { + case SystemRequestType::INPUT_TEXT_MODAL: + if (inputBoxRunning) { + inputBoxThread.join(); + } + + inputBoxRunning = true; + inputBoxThread = std::thread([=] { + std::string out; + if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) { + NativeInputBoxReceived(cb, true, out); + } else { + NativeInputBoxReceived(cb, false, ""); + } + }); + } +} + + void System_Toast(const char *text) { // Not-very-good implementation. Will normally not be used on Windows anyway. std::wstring str = ConvertUTF8ToWString(text); From de064e210ed0403116d519e567e5f15c307ae286 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 12:26:14 +0100 Subject: [PATCH 392/424] Replace the inputbox queue with a more generic RequestManager. --- CMakeLists.txt | 4 + Common/Common.vcxproj | 4 +- Common/Common.vcxproj.filters | 4 +- Common/System/NativeApp.h | 3 - Common/System/{Message.cpp => Request.cpp} | 29 +++++-- Common/System/{Message.h => Request.h} | 16 +++- Common/System/System.h | 24 +++--- Core/Dialog/PSPOskDialog.cpp | 6 +- Qt/QtMain.cpp | 2 + SDL/SDLMain.cpp | 2 + UI/ChatScreen.cpp | 10 +-- UI/GameSettingsScreen.cpp | 50 ++++-------- UI/MemStickScreen.cpp | 93 +++++++++++----------- UI/NativeApp.cpp | 28 ++----- UI/RemoteISOScreen.cpp | 6 +- UI/SavedataScreen.cpp | 6 +- UWP/PPSSPP_UWPMain.cpp | 2 + Windows/main.cpp | 74 ++++++++--------- android/jni/app-android.cpp | 32 ++++---- headless/Headless.cpp | 1 + ios/main.mm | 4 + libretro/libretro.cpp | 2 +- unittest/JitHarness.cpp | 1 + 23 files changed, 198 insertions(+), 205 deletions(-) rename Common/System/{Message.cpp => Request.cpp} (59%) rename Common/System/{Message.h => Request.h} (66%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36dbf12c73..a6f2ea7c7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -712,6 +712,10 @@ add_library(Common STATIC Common/Render/Text/draw_text_uwp.h Common/System/Display.cpp Common/System/Display.h + Common/System/System.h + Common/System/NativeApp.h + Common/System/Request.cpp + Common/System/Request.h Common/Thread/Channel.h Common/Thread/ParallelLoop.cpp Common/Thread/ParallelLoop.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index a28696099b..3fabaafa64 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -550,7 +550,7 @@ - + @@ -1006,7 +1006,7 @@ - + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 23b138fb39..879e3495b8 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -494,7 +494,7 @@ ext\basis_universal - + System @@ -923,7 +923,7 @@ ext\basis_universal - + System diff --git a/Common/System/NativeApp.h b/Common/System/NativeApp.h index 6788642eb4..bb0c7af962 100644 --- a/Common/System/NativeApp.h +++ b/Common/System/NativeApp.h @@ -23,9 +23,6 @@ void NativeGetAppInfo(std::string *app_dir_name, std::string *app_nice_name, boo // Generic host->C++ messaging, used for functionality like system-native popup input boxes. void NativeMessageReceived(const char *message, const char *value); -// This is used to communicate back and thread requested input box strings. -void NativeInputBoxReceived(std::function cb, bool result, const std::string &value); - // Easy way for the Java side to ask the C++ side for configuration options, such as // the rotation lock which must be controlled from Java on Android. // It is currently not called on non-Android platforms. diff --git a/Common/System/Message.cpp b/Common/System/Request.cpp similarity index 59% rename from Common/System/Message.cpp rename to Common/System/Request.cpp index 8a09fc3a04..883514d8da 100644 --- a/Common/System/Message.cpp +++ b/Common/System/Request.cpp @@ -1,8 +1,8 @@ -#include "Common/System/Message.h" +#include "Common/System/Request.h" #include "Common/System/System.h" #include "Common/Log.h" -RequestManager g_RequestManager; +RequestManager g_requestManager; const char *RequestTypeAsString(SystemRequestType type) { switch (type) { @@ -11,7 +11,7 @@ const char *RequestTypeAsString(SystemRequestType type) { } } -bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2) { +bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2) { int requestId = idCounter_++; if (!System_MakeRequest(type, requestId, param1, param2)) { return false; @@ -27,12 +27,11 @@ bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback c return true; } -void RequestManager::PostSystemResponse(int requestId, const char *responseString, int responseValue) { +void RequestManager::PostSystemSuccess(int requestId, const char *responseString, int responseValue) { std::lock_guard guard(callbackMutex_); auto iter = callbackMap_.find(requestId); if (iter == callbackMap_.end()) { - // Unexpected! - ERROR_LOG(SYSTEM, "PostSystemResponse: Unexpected request ID %d for %s (responseString=%s)", requestId, responseString); + ERROR_LOG(SYSTEM, "PostSystemSuccess: Unexpected request ID %d (responseString=%s)", requestId, responseString); return; } @@ -44,6 +43,16 @@ void RequestManager::PostSystemResponse(int requestId, const char *responseStrin pendingResponses_.push_back(response); } +void RequestManager::PostSystemFailure(int requestId) { + std::lock_guard guard(callbackMutex_); + auto iter = callbackMap_.find(requestId); + if (iter == callbackMap_.end()) { + ERROR_LOG(SYSTEM, "PostSystemFailure: Unexpected request ID %d", requestId); + return; + } + callbackMap_.erase(iter); +} + void RequestManager::ProcessRequests() { std::lock_guard guard(responseMutex_); for (auto &iter : pendingResponses_) { @@ -53,3 +62,11 @@ void RequestManager::ProcessRequests() { } pendingResponses_.clear(); } + +void RequestManager::Clear() { + std::lock_guard guard(callbackMutex_); + std::lock_guard responseGuard(responseMutex_); + + pendingResponses_.clear(); + callbackMap_.clear(); +} diff --git a/Common/System/Message.h b/Common/System/Request.h similarity index 66% rename from Common/System/Message.h rename to Common/System/Request.h index 88cd58df41..19afe99721 100644 --- a/Common/System/Message.h +++ b/Common/System/Request.h @@ -16,15 +16,19 @@ class RequestManager { public: // These requests are to be handled by platform implementations. // The callback you pass in will be called on the main thread later. - bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const char *param1, const char *param2); + bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2); // Called by the platform implementation, when it's finished with a request. - void PostSystemResponse(int requestId, const char *responseString, int responseValue); + void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0); + void PostSystemFailure(int requestId); // This must be called every frame from the beginning of NativeUpdate(). // This will call the callback of any finished requests. void ProcessRequests(); + // Unclear if we need this... + void Clear(); + private: struct PendingRequest { SystemRequestType type; @@ -47,4 +51,10 @@ private: const char *RequestTypeAsString(SystemRequestType type); -extern RequestManager g_RequestManager; +extern RequestManager g_requestManager; + +// Wrappers for easy requests. +// NOTE: Semantics have changed - this no longer calls the callback on cancellation. +inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback) { + g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue); +} diff --git a/Common/System/System.h b/Common/System/System.h index c33bac6ed0..b0222aeea0 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -50,8 +50,20 @@ enum class LaunchUrlType { void System_Vibrate(int length_ms); void System_ShowFileInFolder(const char *path); void System_LaunchUrl(LaunchUrlType urlType, const char *url); -void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb); + +enum class SystemRequestType { + INPUT_TEXT_MODAL, +}; + +// Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). +// This is not to be used directly by applications, instead use the g_RequestManager to make the requests. +// This can return false if it's known that the platform doesn't support the request, the app is supposed to handle +// or ignore that cleanly. +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2); + +// TODO: To be separated into requests, see Request.h, and a way to post "UI messages". void System_SendMessage(const char *command, const char *parameter); + PermissionStatus System_GetPermissionStatus(SystemPermission permission); void System_AskForPermission(SystemPermission permission); @@ -146,16 +158,6 @@ enum class SystemNotification { SWITCH_UMD_UPDATED, }; -enum class SystemRequestType { - INPUT_TEXT_MODAL, -}; - -// Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). -// This is not to be used directly by applications, instead use the g_RequestManager to make the requests. -// This can return false if it's known that the platform doesn't support the request, the app is supposed to handle -// or ignore that cleanly. -bool System_MakeRequest(SystemRequestType type, int requestId, const char *param1, const char *param2); - std::string System_GetProperty(SystemProperty prop); std::vector System_GetPropertyStringVec(SystemProperty prop); int System_GetPropertyInt(SystemProperty prop); diff --git a/Core/Dialog/PSPOskDialog.cpp b/Core/Dialog/PSPOskDialog.cpp index e6e1ccafc4..bfbc545f67 100755 --- a/Core/Dialog/PSPOskDialog.cpp +++ b/Core/Dialog/PSPOskDialog.cpp @@ -22,7 +22,7 @@ #include "Common/Math/math_util.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/Serialize/SerializeFuncs.h" -#include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Serialize/Serializer.h" #include "Core/Dialog/PSPOskDialog.h" @@ -892,14 +892,14 @@ int PSPOskDialog::NativeKeyboard() { defaultText.assign(u"VALUE"); // There's already ConvertUCS2ToUTF8 in this file. Should we use that instead of the global ones? - System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), [&](bool result, const std::string &value) { + System_InputBoxGetString(::ConvertUCS2ToUTF8(titleText), ::ConvertUCS2ToUTF8(defaultText), [&](const std::string &value, int iValue) { std::lock_guard guard(nativeMutex_); if (nativeStatus_ != PSPOskNativeStatus::WAITING) { return; } nativeValue_ = value; - nativeStatus_ = result ? PSPOskNativeStatus::SUCCESS : PSPOskNativeStatus::FAILURE; + nativeStatus_ = iValue ? PSPOskNativeStatus::SUCCESS : PSPOskNativeStatus::FAILURE; }); } else if (nativeStatus_ == PSPOskNativeStatus::SUCCESS) { inputChars = ConvertUTF8ToUCS2(nativeValue_); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 3571c615ca..65498db322 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -273,6 +273,8 @@ void System_Notify(SystemNotification notification) { } } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { qApp->exit(0); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index f59a2dd22a..3bda836e98 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -166,6 +166,8 @@ void System_Vibrate(int length_ms) { // Ignore on PC } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "toggle_fullscreen")) { g_ToggleFullScreenNextFrame = true; diff --git a/UI/ChatScreen.cpp b/UI/ChatScreen.cpp index 277185b3e5..d62470666e 100644 --- a/UI/ChatScreen.cpp +++ b/UI/ChatScreen.cpp @@ -10,7 +10,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Data/Encoding/Utf8.h" -#include "Common/System/System.h" +#include "Common/System/Request.h" #include "Core/Config.h" #include "Core/System.h" #include "Core/HLE/proAdhoc.h" @@ -97,7 +97,7 @@ UI::EventReturn ChatMenu::OnSubmit(UI::EventParams &e) { sendChat(chat); #elif PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Chat"), "", [](bool result, const std::string &value) { + System_InputBoxGetString(n->T("Chat"), "", [](const std::string &value, int) { sendChat(value); }); #endif @@ -181,10 +181,8 @@ void ChatMenu::Update() { #if defined(USING_WIN_UI) // Could remove the fullscreen check here, it works now. if (promptInput_ && g_Config.bBypassOSKWithKeyboard && !g_Config.UseFullScreen()) { - System_InputBoxGetString(n->T("Chat"), n->T("Chat Here"), [](bool result, const std::string &value) { - if (result) { - sendChat(value); - } + System_InputBoxGetString(n->T("Chat"), n->T("Chat Here"), [](const std::string &value, int) { + sendChat(value); }); promptInput_ = false; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index ded0d26d52..43f7ed44a5 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -30,7 +30,7 @@ #include "Common/VR/PPSSPPVR.h" #include "Common/System/Display.h" // Only to check screen aspect ratio with pixel_yres/pixel_xres -#include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Battery/Battery.h" #include "Common/System/NativeApp.h" #include "Common/Data/Color/RGBAUtil.h" @@ -1564,10 +1564,8 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](bool result, const std::string &value) { - if (result) { - g_Config.sQuickChat0 = value; - } + System_InputBoxGetString(n->T("Enter Quick Chat 1"), g_Config.sQuickChat0, [](const std::string &value, int) { + g_Config.sQuickChat0 = value; }); #endif return UI::EVENT_DONE; @@ -1576,10 +1574,8 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat0(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](bool result, const std::string &value) { - if (result) { - g_Config.sQuickChat1 = value; - } + System_InputBoxGetString(n->T("Enter Quick Chat 2"), g_Config.sQuickChat1, [](const std::string &value, int) { + g_Config.sQuickChat1 = value; }); #endif return UI::EVENT_DONE; @@ -1588,10 +1584,8 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat1(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](bool result, const std::string &value) { - if (result) { - g_Config.sQuickChat2 = value; - } + System_InputBoxGetString(n->T("Enter Quick Chat 3"), g_Config.sQuickChat2, [](const std::string &value, int) { + g_Config.sQuickChat2 = value; }); #endif return UI::EVENT_DONE; @@ -1600,10 +1594,8 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat2(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](bool result, const std::string &value) { - if (result) { - g_Config.sQuickChat3 = value; - } + System_InputBoxGetString(n->T("Enter Quick Chat 4"), g_Config.sQuickChat3, [](const std::string &value, int) { + g_Config.sQuickChat3 = value; }); #endif return UI::EVENT_DONE; @@ -1612,10 +1604,8 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat3(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](bool result, const std::string &value) { - if (result) { - g_Config.sQuickChat4 = value; - } + System_InputBoxGetString(n->T("Enter Quick Chat 5"), g_Config.sQuickChat4, [](const std::string &value, int) { + g_Config.sQuickChat4 = value; }); #endif return UI::EVENT_DONE; @@ -1624,10 +1614,8 @@ UI::EventReturn GameSettingsScreen::OnChangeQuickChat4(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeNickname(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || PPSSPP_PLATFORM(ANDROID) auto n = GetI18NCategory("Networking"); - System_InputBoxGetString(n->T("Enter a new PSP nickname"), g_Config.sNickName, [](bool result, const std::string &value) { - if (result) { - g_Config.sNickName = StripSpaces(value); - } + System_InputBoxGetString(n->T("Enter a new PSP nickname"), g_Config.sNickName, [](const std::string &value, int) { + g_Config.sNickName = StripSpaces(value); }); #endif return UI::EVENT_DONE; @@ -1723,10 +1711,8 @@ UI::EventReturn GameSettingsScreen::OnSysInfo(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeSearchFilter(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) auto se = GetI18NCategory("Search"); - System_InputBoxGetString(se->T("Search term"), searchFilter_, [](bool result, const std::string &value) { - if (result) { - NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str()); - } + System_InputBoxGetString(se->T("Search term"), searchFilter_, [](const std::string &value, int) { + NativeMessageReceived("gameSettings_search", StripSpaces(value).c_str()); }); #else if (!System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) @@ -2098,10 +2084,8 @@ UI::EventReturn HostnameSelectScreen::OnDeleteAllClick(UI::EventParams &e) { UI::EventReturn HostnameSelectScreen::OnEditClick(UI::EventParams& e) { auto n = GetI18NCategory("Networking"); #if PPSSPP_PLATFORM(ANDROID) - System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](bool result, const std::string& value) { - if (result) { - addrView_->SetText(value); - } + System_InputBoxGetString(n->T("proAdhocServer Address:"), addrView_->GetText(), [this](const std::string& value, int) { + addrView_->SetText(value); }); #endif return UI::EVENT_DONE; diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 265be6bf68..5bf8c83d6f 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -26,6 +26,7 @@ #include "Common/StringUtils.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/System/NativeApp.h" #include "Common/System/Display.h" #include "Common/Data/Text/I18n.h" @@ -336,64 +337,62 @@ UI::EventReturn MemStickScreen::SetFolderManually(UI::EventParams ¶ms) { // The old way, from before scoped storage. #if PPSSPP_PLATFORM(ANDROID) auto sy = GetI18NCategory("System"); - System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](bool result, const std::string &value) { + System_InputBoxGetString(sy->T("Memory Stick Folder"), g_Config.memStickDirectory.ToString(), [&](const std::string &value, int) { auto sy = GetI18NCategory("System"); auto di = GetI18NCategory("Dialog"); - if (result) { - std::string newPath = value; - size_t pos = newPath.find_last_not_of("/"); - // Gotta have at least something but a /, and also needs to start with a /. - if (newPath.empty() || pos == newPath.npos || newPath[0] != '/') { - settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr); - return; - } - if (pos != newPath.size() - 1) { - newPath = newPath.substr(0, pos + 1); - } + std::string newPath = value; + size_t pos = newPath.find_last_not_of("/"); + // Gotta have at least something but a /, and also needs to start with a /. + if (newPath.empty() || pos == newPath.npos || newPath[0] != '/') { + settingInfo_->Show(sy->T("ChangingMemstickPathInvalid", "That path couldn't be used to save Memory Stick files."), nullptr); + return; + } + if (pos != newPath.size() - 1) { + newPath = newPath.substr(0, pos + 1); + } - if (newPath.empty()) { - // Reuse below message instead of adding yet another string. - System_Toast(sy->T("Path does not exist!")); - return; - } + if (newPath.empty()) { + // Reuse below message instead of adding yet another string. + System_Toast(sy->T("Path does not exist!")); + return; + } - Path pendingMemStickFolder(newPath); + Path pendingMemStickFolder(newPath); - if (!File::Exists(pendingMemStickFolder)) { - // Try to fix the path string, apparently some users got used to leaving out the /. - if (newPath[0] != '/') { - newPath = "/" + newPath; - } + if (!File::Exists(pendingMemStickFolder)) { + // Try to fix the path string, apparently some users got used to leaving out the /. + if (newPath[0] != '/') { + newPath = "/" + newPath; + } - pendingMemStickFolder = Path(newPath); - } + pendingMemStickFolder = Path(newPath); + } - if (!File::Exists(pendingMemStickFolder) && pendingMemStickFolder.Type() == PathType::NATIVE) { - // Still no path? Try to automatically fix the case. - std::string oldNewPath = newPath; - FixPathCase(Path(""), newPath, FixPathCaseBehavior::FPC_FILE_MUST_EXIST); - if (oldNewPath != newPath) { - NOTICE_LOG(IO, "Fixed path case: %s -> %s", oldNewPath.c_str(), newPath.c_str()); - pendingMemStickFolder = Path(newPath); - } else { - NOTICE_LOG(IO, "Failed to fix case of path %s (result: %s)", newPath.c_str(), oldNewPath.c_str()); - } - } + if (!File::Exists(pendingMemStickFolder) && pendingMemStickFolder.Type() == PathType::NATIVE) { + // Still no path? Try to automatically fix the case. + std::string oldNewPath = newPath; + FixPathCase(Path(""), newPath, FixPathCaseBehavior::FPC_FILE_MUST_EXIST); + if (oldNewPath != newPath) { + NOTICE_LOG(IO, "Fixed path case: %s -> %s", oldNewPath.c_str(), newPath.c_str()); + pendingMemStickFolder = Path(newPath); + } else { + NOTICE_LOG(IO, "Failed to fix case of path %s (result: %s)", newPath.c_str(), oldNewPath.c_str()); + } + } - if (pendingMemStickFolder == g_Config.memStickDirectory) { - // Same directory as before - all good. Nothing to do. - TriggerFinish(DialogResult::DR_OK); - return; - } + if (pendingMemStickFolder == g_Config.memStickDirectory) { + // Same directory as before - all good. Nothing to do. + TriggerFinish(DialogResult::DR_OK); + return; + } - if (!File::Exists(pendingMemStickFolder)) { - System_Toast(sy->T("Path does not exist!")); - return; - } + if (!File::Exists(pendingMemStickFolder)) { + System_Toast(sy->T("Path does not exist!")); + return; + } - screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false)); - } + screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, false)); }); #endif return UI::EVENT_DONE; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 75ab082de1..35503efce0 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -58,8 +58,10 @@ #include "android/jni/app-android.h" #include "Common/System/Display.h" +#include "Common/System/Request.h" #include "Common/System/System.h" #include "Common/System/NativeApp.h" + #include "Common/Data/Text/I18n.h" #include "Common/Input/InputState.h" #include "Common/Math/math_util.h" @@ -164,15 +166,8 @@ struct PendingMessage { std::string value; }; -struct PendingInputBox { - std::function cb; - bool result; - std::string value; -}; - static std::mutex pendingMutex; static std::vector pendingMessages; -static std::vector pendingInputBoxes; static Draw::DrawContext *g_draw; static Draw::Pipeline *colorPipeline; static Draw::Pipeline *texColorPipeline; @@ -443,7 +438,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch setlocale( LC_ALL, "C" ); std::string user_data_path = savegame_dir; pendingMessages.clear(); - pendingInputBoxes.clear(); + g_requestManager.Clear(); // external_dir has all kinds of meanings depending on platform. // on iOS it's even the path to bundled app assets. It's a mess. @@ -1248,22 +1243,18 @@ void NativeUpdate() { PROFILE_END_FRAME(); std::vector toProcess; - std::vector inputToProcess; { std::lock_guard lock(pendingMutex); toProcess = std::move(pendingMessages); - inputToProcess = std::move(pendingInputBoxes); pendingMessages.clear(); - pendingInputBoxes.clear(); } for (const auto &item : toProcess) { HandleGlobalMessage(item.msg, item.value); g_screenManager->sendMessage(item.msg.c_str(), item.value.c_str()); } - for (const auto &item : inputToProcess) { - item.cb(item.result, item.value); - } + + g_requestManager.ProcessRequests(); g_DownloadManager.Update(); g_screenManager->update(); @@ -1396,15 +1387,6 @@ void NativeMessageReceived(const char *message, const char *value) { pendingMessages.push_back(pendingMessage); } -void NativeInputBoxReceived(std::function cb, bool result, const std::string &value) { - std::lock_guard lock(pendingMutex); - PendingInputBox pendingMessage; - pendingMessage.cb = cb; - pendingMessage.result = result; - pendingMessage.value = value; - pendingInputBoxes.push_back(pendingMessage); -} - void NativeResized() { // NativeResized can come from any thread so we just set a flag, then process it later. VERBOSE_LOG(G3D, "NativeResized - setting flag"); diff --git a/UI/RemoteISOScreen.cpp b/UI/RemoteISOScreen.cpp index 98cea5ea85..d14c9999d4 100644 --- a/UI/RemoteISOScreen.cpp +++ b/UI/RemoteISOScreen.cpp @@ -31,6 +31,7 @@ #include "Common/Net/Resolve.h" #include "Common/Net/URL.h" #include "Common/Thread/ThreadUtil.h" +#include "Common/System/Request.h" #include "Common/File/PathBrowser.h" #include "Common/Data/Format/JSONReader.h" @@ -38,7 +39,6 @@ #include "Common/Common.h" #include "Common/Log.h" #include "Common/StringUtils.h" -#include "Common/System/System.h" #include "Common/TimeUtil.h" #include "Core/Config.h" #include "Core/System.h" @@ -643,7 +643,7 @@ void RemoteISOSettingsScreen::CreateViews() { UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteServer(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) auto ri = GetI18NCategory("RemoteISO"); - System_InputBoxGetString(ri->T("Remote Server"), g_Config.sLastRemoteISOServer, [](bool result, const std::string &value) { + System_InputBoxGetString(ri->T("Remote Server"), g_Config.sLastRemoteISOServer, [](const std::string &value, int) { g_Config.sLastRemoteISOServer = value; }); #endif @@ -663,7 +663,7 @@ static void CleanupRemoteISOSubdir() { UI::EventReturn RemoteISOSettingsScreen::OnClickRemoteISOSubdir(UI::EventParams &e) { #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) auto ri = GetI18NCategory("RemoteISO"); - System_InputBoxGetString(ri->T("Remote Subdirectory"), g_Config.sRemoteISOSubdir, [](bool result, const std::string &value) { + System_InputBoxGetString(ri->T("Remote Subdirectory"), g_Config.sRemoteISOSubdir, [](const std::string &value, int) { g_Config.sRemoteISOSubdir = value; // Apply the cleanup logic, too. CleanupRemoteISOSubdir(); diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index 0d04ac02b9..c7ab4b7136 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -24,7 +24,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/Math/curves.h" #include "Common/System/NativeApp.h" -#include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Data/Encoding/Utf8.h" #include "Common/UI/Context.h" #include "Common/UI/View.h" @@ -674,8 +674,8 @@ UI::EventReturn SavedataScreen::OnSortClick(UI::EventParams &e) { UI::EventReturn SavedataScreen::OnSearch(UI::EventParams &e) { auto di = GetI18NCategory("Dialog"); #if PPSSPP_PLATFORM(WINDOWS) || defined(USING_QT_UI) || defined(__ANDROID__) - System_InputBoxGetString(di->T("Filter"), searchFilter_, [](bool result, const std::string &value) { - if (result) { + System_InputBoxGetString(di->T("Filter"), searchFilter_, [](const std::string &value, int ivalue) { + if (ivalue) { NativeMessageReceived("savedatascreen_search", value.c_str()); } }); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 1529a18887..39e27cbf56 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -443,6 +443,8 @@ void System_Notify(SystemNotification notification) { } } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } + void System_SendMessage(const char *command, const char *parameter) { using namespace concurrency; diff --git a/Windows/main.cpp b/Windows/main.cpp index 7db15f7b81..15fd6891d0 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -34,6 +34,7 @@ #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/File/FileUtil.h" #include "Common/File/VFS/VFS.h" #include "Common/File/VFS/DirectoryReader.h" @@ -109,8 +110,8 @@ static std::string restartArgs; int g_activeWindow = 0; -static std::thread inputBoxThread; -static bool inputBoxRunning = false; +static std::thread g_inputBoxThread; +static bool g_inputBoxRunning = false; int g_lastNumInstances = 0; void System_ShowFileInFolder(const char *path) { @@ -376,12 +377,13 @@ static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, L return PostMessage(dialog->GetDlgHandle(), message, wParam, lParam); } +// This can come from any thread, so this mostly uses PostMessage. Can't access most data directly. void System_Notify(SystemNotification notification) { switch (notification) { case SystemNotification::BOOT_DONE: { if (g_symbolMap) - g_symbolMap->SortSymbols(); + g_symbolMap->SortSymbols(); // internal locking is performed here PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); if (disasmWindow) @@ -413,7 +415,7 @@ void System_Notify(SystemNotification notification) { case SystemNotification::SYMBOL_MAP_UPDATED: if (g_symbolMap) - g_symbolMap->SortSymbols(); + g_symbolMap->SortSymbols(); // internal locking is performed here PostMessage(MainWindow::GetHWND(), WM_USER + 1, 0, 0); break; @@ -428,6 +430,28 @@ void System_Notify(SystemNotification notification) { } } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { + switch (type) { + case SystemRequestType::INPUT_TEXT_MODAL: + if (g_inputBoxRunning) { + g_inputBoxThread.join(); + } + + g_inputBoxRunning = true; + g_inputBoxThread = std::thread([=] { + std::string out; + if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), param2, out)) { + g_requestManager.PostSystemSuccess(requestId, out.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }); + return true; + default: + return false; + } +} + void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { if (!NativeIsRestarting()) { @@ -497,42 +521,6 @@ void EnableCrashingOnCrashes() { FreeLibrary(kernel32); } -void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { - if (inputBoxRunning) { - inputBoxThread.join(); - } - - inputBoxRunning = true; - inputBoxThread = std::thread([=] { - std::string out; - if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) { - NativeInputBoxReceived(cb, true, out); - } else { - NativeInputBoxReceived(cb, false, ""); - } - }); -} - -bool System_PerformRequest(SystemRequestType type, int requestId, const char *param1, const char *param2) { - switch (type) { - case SystemRequestType::INPUT_TEXT_MODAL: - if (inputBoxRunning) { - inputBoxThread.join(); - } - - inputBoxRunning = true; - inputBoxThread = std::thread([=] { - std::string out; - if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(title).c_str(), defaultValue, out)) { - NativeInputBoxReceived(cb, true, out); - } else { - NativeInputBoxReceived(cb, false, ""); - } - }); - } -} - - void System_Toast(const char *text) { // Not-very-good implementation. Will normally not be used on Windows anyway. std::wstring str = ConvertUTF8ToWString(text); @@ -639,9 +627,9 @@ static void WinMainInit() { } static void WinMainCleanup() { - if (inputBoxRunning) { - inputBoxThread.join(); - inputBoxRunning = false; + if (g_inputBoxRunning) { + g_inputBoxThread.join(); + g_inputBoxRunning = false; } net::Shutdown(); CoUninitialize(); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 65a483e519..6a9e42a829 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -61,6 +61,7 @@ struct JNIEnv {}; #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Thread/ThreadUtil.h" #include "Common/File/Path.h" #include "Common/File/DirListing.h" @@ -175,9 +176,6 @@ static std::atomic renderLoopRunning; static bool renderer_inited = false; static std::mutex renderLock; -static int inputBoxSequence = 1; -static std::map> inputBoxCallbacks; - static bool sustainedPerfSupported = false; static std::map permissions; @@ -909,7 +907,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { { std::lock_guard guard(renderLock); - inputBoxCallbacks.clear(); NativeShutdown(); g_VFS.Clear(); } @@ -1032,12 +1029,17 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } } -void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { - int seq = inputBoxSequence++; - inputBoxCallbacks[seq] = cb; - - std::string serialized = StringFromFormat("%d:@:%s:@:%s", seq, title.c_str(), defaultValue.c_str()); - System_SendMessage("inputbox", serialized.c_str()); +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { + switch (type) { + case SystemRequestType::INPUT_TEXT_MODAL: + { + std::string serialized = StringFromFormat("%d:@:%s:@:%s", requestId, param1.c_str(), param2.c_str()); + PushCommand("inputbox", serialized.c_str()); + return true; + } + default: + return false; + } } extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendInputBox(JNIEnv *env, jclass, jstring jseqID, jboolean result, jstring jvalue) { @@ -1058,13 +1060,11 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendInputBox(JNIEnv *en return; } - auto entry = inputBoxCallbacks.find(seq); - if (entry == inputBoxCallbacks.end()) { - ERROR_LOG(SYSTEM, "Did not find inputbox callback for %s, shutdown?", seqID.c_str()); - return; + if (result) { + g_requestManager.PostSystemSuccess(seq, value.c_str()); + } else { + g_requestManager.PostSystemFailure(seq); } - - NativeInputBoxReceived(entry->second, result, value); } void LockedNativeUpdateRender() { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 27e0508e64..8d6ae20519 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -116,6 +116,7 @@ bool System_GetPropertyBool(SystemProperty prop) { } void System_Notify(SystemNotification notification) {} void System_SendMessage(const char *command, const char *parameter) {} +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } diff --git a/ios/main.mm b/ios/main.mm index 155bf79995..3caaf93e26 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -219,6 +219,10 @@ void System_SendMessage(const char *command, const char *parameter) { } } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { + return false; +} + void System_Toast(const char *text) {} void System_AskForPermission(SystemPermission permission) {} diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 05b13dcdbf..cdb699bb56 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1874,7 +1874,7 @@ void System_Notify(SystemNotification notification) { break; } } - +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } void System_SendMessage(const char *command, const char *parameter) {} void NativeUpdate() {} void NativeRender(GraphicsContext *graphicsContext) {} diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index ebbcdefa39..f730cc44d6 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -42,6 +42,7 @@ void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } void System_SendMessage(const char *command, const char *parameter) {} +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } From 8bbb9e7c95333b6e4fb5dc9eacaa34e51bb4d933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 13:22:10 +0100 Subject: [PATCH 393/424] Buildfixing --- android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 2 files changed, 2 insertions(+) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 61aaefc181..28775b9b2f 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -214,6 +214,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Common/Net/WebsocketServer.cpp \ $(SRC)/Common/Profiler/Profiler.cpp \ $(SRC)/Common/System/Display.cpp \ + $(SRC)/Common/System/Request.cpp \ $(SRC)/Common/Thread/ThreadUtil.cpp \ $(SRC)/Common/Thread/ThreadManager.cpp \ $(SRC)/Common/Thread/ParallelLoop.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index 3beb711568..83e477f941 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -341,6 +341,7 @@ SOURCES_CXX += \ $(COMMONDIR)/UI/ScrollView.cpp \ $(COMMONDIR)/UI/PopupScreens.cpp \ $(COMMONDIR)/System/Display.cpp \ + $(COMMONDIR)/System/Request.cpp \ $(COMMONDIR)/ArmCPUDetect.cpp \ $(COMMONDIR)/CPUDetect.cpp \ $(COMMONDIR)/Buffer.cpp \ From 9d10417f09a73b912eb73da9b7933df66363ce9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 14:17:19 +0100 Subject: [PATCH 394/424] UWP buildfix --- UWP/CommonUWP/CommonUWP.vcxproj | 2 ++ UWP/CommonUWP/CommonUWP.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index a76a85ef67..f997600744 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -376,6 +376,7 @@ + @@ -510,6 +511,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index 03f9424dfe..67e141a43f 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -429,6 +429,9 @@ ext\basis_universal + + System + @@ -811,6 +814,9 @@ ext\basis_universal + + System + From 604f3b450099dabee5ce95453fe2b6d3ef14d90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 14:25:20 +0100 Subject: [PATCH 395/424] Try to fix Qt. Still broken due to threading issue. --- Qt/QtMain.cpp | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 65498db322..2e2d962c13 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -34,7 +34,7 @@ #endif #include "Common/System/NativeApp.h" -#include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/GPU/OpenGL/GLFeatures.h" #include "Common/Math/math_util.h" #include "Common/Profiler/Profiler.h" @@ -273,7 +273,24 @@ void System_Notify(SystemNotification notification) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { + switch (type) { + case SystemRequestType::INPUT_TEXT_MODAL: + { + // NOTE: This doesn't actually work, we're on the wrong thread! + // Was broken even previously to the conversion to System_MakeRequest. + QString title = QString::fromStdString(param1); + QString defaultValue = QString::fromStdString(param2); + QString text = emugl->InputBoxGetQString(title, defaultValue); + if (text.isEmpty()) { + g_requestManager.PostSystemFailure(requestId); + } else { + g_requestManager.PostSystemSuccess(requestId, text.toStdString().c_str()); + } + break; + } + } +} void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { @@ -307,15 +324,6 @@ void System_Toast(const char *text) {} void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } -void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { - QString text = emugl->InputBoxGetQString(QString::fromStdString(title), QString::fromStdString(defaultValue)); - if (text.isEmpty()) { - NativeInputBoxReceived(cb, false, ""); - } else { - NativeInputBoxReceived(cb, true, text.toStdString()); - } -} - void System_Vibrate(int length_ms) { if (length_ms == -1 || length_ms == -3) length_ms = 50; From cc7b9569f2e0cd0d8d20d1d3dd5a47949305d57a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 14:39:57 +0100 Subject: [PATCH 396/424] Fix InputBox in Qt --- Qt/QtMain.cpp | 76 ++++++++++++++++++++++++++++++++------------------- Qt/QtMain.h | 1 + 2 files changed, 49 insertions(+), 28 deletions(-) diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 2e2d962c13..ba475e5141 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -58,6 +58,8 @@ MainUI *emugl = nullptr; static float refreshRate = 60.f; static int browseFileEvent = -1; static int browseFolderEvent = -1; +static int inputBoxEvent = -1; + QTCamera *qtcamera = nullptr; MainWindow *g_mainWindow; @@ -273,22 +275,54 @@ void System_Notify(SystemNotification notification) { } } +// TODO: Find a better version to pass parameters to HandleCustomEvent. +static std::string g_param1; +static std::string g_param2; +static int g_requestId; + +bool MainUI::HandleCustomEvent(QEvent *e) { + if (e->type() == browseFileEvent) { + QString fileName = QFileDialog::getOpenFileName(nullptr, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)"); + if (QFile::exists(fileName)) { + QDir newPath; + g_Config.currentDirectory = Path(newPath.filePath(fileName).toStdString()); + g_Config.Save("browseFileEvent"); + + NativeMessageReceived("boot", fileName.toStdString().c_str()); + } + } else if (e->type() == browseFolderEvent) { + auto mm = GetI18NCategory("MainMenu"); + QString fileName = QFileDialog::getExistingDirectory(nullptr, mm->T("Choose folder"), g_Config.currentDirectory.c_str()); + if (QDir(fileName).exists()) { + NativeMessageReceived("browse_folderSelect", fileName.toStdString().c_str()); + } + } else if (e->type() == inputBoxEvent) { + QString title = QString::fromStdString(g_param1); + QString defaultValue = QString::fromStdString(g_param2); + QString text = emugl->InputBoxGetQString(title, defaultValue); + if (text.isEmpty()) { + g_requestManager.PostSystemFailure(g_requestId); + } else { + g_requestManager.PostSystemSuccess(g_requestId, text.toStdString().c_str()); + } + } else { + return false; + } + return true; +} + bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: { - // NOTE: This doesn't actually work, we're on the wrong thread! - // Was broken even previously to the conversion to System_MakeRequest. - QString title = QString::fromStdString(param1); - QString defaultValue = QString::fromStdString(param2); - QString text = emugl->InputBoxGetQString(title, defaultValue); - if (text.isEmpty()) { - g_requestManager.PostSystemFailure(requestId); - } else { - g_requestManager.PostSystemSuccess(requestId, text.toStdString().c_str()); - } - break; + g_requestId = requestId; + g_param1 = param1; + g_param2 = param2; + QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)inputBoxEvent)); + return true; } + default: + return false; } } @@ -365,6 +399,7 @@ static int mainInternal(QApplication &a) { browseFileEvent = QEvent::registerEventType(); browseFolderEvent = QEvent::registerEventType(); + inputBoxEvent = QEvent::registerEventType(); int retval = a.exec(); delete emugl; @@ -576,23 +611,8 @@ bool MainUI::event(QEvent *e) { break; default: - if (e->type() == browseFileEvent) { - QString fileName = QFileDialog::getOpenFileName(nullptr, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)"); - if (QFile::exists(fileName)) { - QDir newPath; - g_Config.currentDirectory = Path(newPath.filePath(fileName).toStdString()); - g_Config.Save("browseFileEvent"); - - NativeMessageReceived("boot", fileName.toStdString().c_str()); - } - break; - } else if (e->type() == browseFolderEvent) { - auto mm = GetI18NCategory("MainMenu"); - QString fileName = QFileDialog::getExistingDirectory(nullptr, mm->T("Choose folder"), g_Config.currentDirectory.c_str()); - if (QDir(fileName).exists()) { - NativeMessageReceived("browse_folderSelect", fileName.toStdString().c_str()); - } - } else { + // Can't switch on dynamic event types. + if (!HandleCustomEvent(e)) { return QWidget::event(e); } } diff --git a/Qt/QtMain.h b/Qt/QtMain.h index 639806bcf5..39cce11f77 100644 --- a/Qt/QtMain.h +++ b/Qt/QtMain.h @@ -140,6 +140,7 @@ protected: void EmuThreadJoin(); private: + bool HandleCustomEvent(QEvent *e); QtGLGraphicsContext *graphicsContext; float xscale, yscale; From 0fa134a1eaddc1715c885dc14dba41f6ebcf162c Mon Sep 17 00:00:00 2001 From: fp64 <106717720+fp64@users.noreply.github.com> Date: Wed, 22 Mar 2023 09:51:16 -0400 Subject: [PATCH 397/424] Add -mfpmath=sse to CMakeLists.txt Only affects x86+32bit+gcc combo. --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f2ea7c7e..e1c826ce24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -368,6 +368,10 @@ if(NOT MSVC) if(X86 OR X86_64) # enable sse2 code generation add_definitions(-msse2) + if(NOT X86_64 AND NOT CLANG) + add_definitions(-mfpmath=sse) + # add_definitions(-mstackrealign) + endif() endif() if(IOS) From e9f5394f5922097b6635ad733c903842f83c29cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 13:43:44 +0100 Subject: [PATCH 398/424] Move the Windows open file dialog to the new system, switch the background image selector over. --- Common/System/Request.h | 4 ++++ Common/System/System.h | 1 + UI/GameSettingsScreen.cpp | 15 ++++++++---- UI/NativeApp.cpp | 8 ------- Windows/MainWindow.cpp | 4 ---- Windows/MainWindow.h | 1 - Windows/MainWindowMenu.cpp | 32 ------------------------- Windows/MainWindowMenu.h | 2 -- Windows/main.cpp | 47 ++++++++++++++++++++++++++++--------- android/jni/app-android.cpp | 6 ++--- 10 files changed, 54 insertions(+), 66 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index 19afe99721..99e42eb500 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -58,3 +58,7 @@ extern RequestManager g_requestManager; inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback) { g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue); } + +inline void System_BrowseForImage(const std::string &title, RequestCallback callback) { + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, title, ""); +} diff --git a/Common/System/System.h b/Common/System/System.h index b0222aeea0..dbb79edaab 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -53,6 +53,7 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url); enum class SystemRequestType { INPUT_TEXT_MODAL, + BROWSE_FOR_IMAGE, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 43f7ed44a5..85cb888bf6 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1312,12 +1312,17 @@ UI::EventReturn GameSettingsScreen::OnChangeBackground(UI::EventParams &e) { if (File::Exists(bgPng) || File::Exists(bgJpg)) { File::Delete(bgPng); File::Delete(bgJpg); - - NativeMessageReceived("bgImage_updated", ""); + UIBackgroundShutdown(); } else { - if (System_GetPropertyBool(SYSPROP_HAS_IMAGE_BROWSER)) { - System_SendMessage("bgImage_browse", ""); - } + auto sy = GetI18NCategory("System"); + System_BrowseForImage(sy->T("Set UI background..."), [](const std::string &value, int) { + if (!value.empty()) { + Path dest = GetSysDirectory(DIRECTORY_SYSTEM) / (endsWithNoCase(value, ".jpg") ? "background.jpg" : "background.png"); + File::Copy(Path(value), dest); + } + // It will init again automatically. We can't init outside a frame on Vulkan. + UIBackgroundShutdown(); + }); } // Change to a browse or clear button. diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 35503efce0..ba675e4b29 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1167,14 +1167,6 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) { else if (msg == "inputDeviceConnected") { KeyMap::NotifyPadConnected(nextInputDeviceID, value); } - else if (msg == "bgImage_updated") { - if (!value.empty()) { - Path dest = GetSysDirectory(DIRECTORY_SYSTEM) / (endsWithNoCase(value, ".jpg") ? "background.jpg" : "background.png"); - File::Copy(Path(value), dest); - } - UIBackgroundShutdown(); - // It will init again automatically. We can't init outside a frame on Vulkan. - } else if (msg == "savestate_displayslot") { auto sy = GetI18NCategory("System"); std::string msg = StringFromFormat("%s: %d", sy->T("Savestate Slot"), SaveState::GetCurrentSlot() + 1); diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index d81d20b121..a5ede38046 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -1064,10 +1064,6 @@ namespace MainWindow BrowseAndBootDone(); break; - case WM_USER_BROWSE_BG_DONE: - BrowseBackgroundDone(); - break; - case WM_USER_RESTART_EMUTHREAD: NativeSetRestarting(); InputDevice::StopPolling(); diff --git a/Windows/MainWindow.h b/Windows/MainWindow.h index abf170fb84..e1f51c2b2d 100644 --- a/Windows/MainWindow.h +++ b/Windows/MainWindow.h @@ -15,7 +15,6 @@ namespace MainWindow enum { WM_USER_SAVESTATE_FINISH = WM_USER + 100, WM_USER_UPDATE_UI = WM_USER + 101, - WM_USER_BROWSE_BG_DONE = WM_USER + 102, WM_USER_WINDOW_TITLE_CHANGED = WM_USER + 103, WM_USER_BROWSE_BOOT_DONE = WM_USER + 104, WM_USER_TOGGLE_FULLSCREEN = WM_USER + 105, diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index 7105f390c9..d4bc5ab3dd 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -347,38 +347,6 @@ namespace MainWindow { browseDialog = 0; } - void BrowseBackground() { - static std::wstring filter = L"All supported images (*.jpg *.jpeg *.png)|*.jpg;*.jpeg;*.png|All files (*.*)|*.*||"; - for (size_t i = 0; i < filter.length(); i++) { - if (filter[i] == '|') - filter[i] = '\0'; - } - - W32Util::MakeTopMost(GetHWND(), false); - browseImageDialog = new W32Util::AsyncBrowseDialog(W32Util::AsyncBrowseDialog::OPEN, GetHWND(), WM_USER_BROWSE_BG_DONE, L"LoadFile", L"", filter, L"*.jpg;*.jpeg;*.png;"); - } - - void BrowseBackgroundDone() { - std::string filename; - if (browseImageDialog->GetResult(filename)) { - std::wstring src = ConvertUTF8ToWString(filename); - std::wstring dest; - if (filename.size() >= 5 && (filename.substr(filename.size() - 4) == ".jpg" || filename.substr(filename.size() - 5) == ".jpeg")) { - dest = (GetSysDirectory(DIRECTORY_SYSTEM) / "background.jpg").ToWString(); - } else { - dest = (GetSysDirectory(DIRECTORY_SYSTEM) / "background.png").ToWString(); - } - - CopyFileW(src.c_str(), dest.c_str(), FALSE); - NativeMessageReceived("bgImage_updated", ""); - } - - W32Util::MakeTopMost(GetHWND(), g_Config.bTopMost); - - delete browseImageDialog; - browseImageDialog = nullptr; - } - static void UmdSwitchAction() { std::string fn; std::string filter = "PSP ROMs (*.iso *.cso *.pbp *.elf)|*.pbp;*.elf;*.iso;*.cso;*.prx|All files (*.*)|*.*||"; diff --git a/Windows/MainWindowMenu.h b/Windows/MainWindowMenu.h index 5669335c22..dc194855e0 100644 --- a/Windows/MainWindowMenu.h +++ b/Windows/MainWindowMenu.h @@ -9,8 +9,6 @@ namespace MainWindow { void TranslateMenus(HWND hWnd, HMENU menu); void BrowseAndBoot(std::string defaultPath, bool browseDirectory = false); void BrowseAndBootDone(); - void BrowseBackground(); - void BrowseBackgroundDone(); void setTexScalingMultiplier(int level); void SetIngameMenuItemStates(HMENU menu, const GlobalUIState state); } diff --git a/Windows/main.cpp b/Windows/main.cpp index 15fd6891d0..4314acda19 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -44,6 +44,7 @@ #include "Common/Data/Encoding/Utf8.h" #include "Common/Net/Resolve.h" #include "W32Util/DarkMode.h" +#include "W32Util/ShellUtil.h" #include "Core/Config.h" #include "Core/ConfigValues.h" @@ -110,8 +111,10 @@ static std::string restartArgs; int g_activeWindow = 0; -static std::thread g_inputBoxThread; -static bool g_inputBoxRunning = false; +// Used for all the system dialogs. +static std::thread g_dialogThread; +static bool g_dialogRunning = false; + int g_lastNumInstances = 0; void System_ShowFileInFolder(const char *path) { @@ -430,15 +433,23 @@ void System_Notify(SystemNotification notification) { } } +std::wstring MakeFilter(std::wstring filter) { + for (size_t i = 0; i < filter.length(); i++) { + if (filter[i] == '|') + filter[i] = '\0'; + } + return filter; +} + bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: - if (g_inputBoxRunning) { - g_inputBoxThread.join(); + if (g_dialogRunning) { + g_dialogThread.join(); } - g_inputBoxRunning = true; - g_inputBoxThread = std::thread([=] { + g_dialogRunning = true; + g_dialogThread = std::thread([=] { std::string out; if (InputBox_GetString(MainWindow::GetHInstance(), MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), param2, out)) { g_requestManager.PostSystemSuccess(requestId, out.c_str()); @@ -447,6 +458,22 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } }); return true; + case SystemRequestType::BROWSE_FOR_IMAGE: + if (g_dialogRunning) { + g_dialogThread.join(); + } + + g_dialogRunning = true; + g_dialogThread = std::thread([=] { + std::string out; + if (W32Util::BrowseForFileName(true, MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), nullptr, + MakeFilter(L"All supported images (*.jpg *.jpeg *.png)|*.jpg;*.jpeg;*.png|All files (*.*)|*.*||").c_str(), L"jpg", out)) { + g_requestManager.PostSystemSuccess(requestId, out.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }); + return true; default: return false; } @@ -483,8 +510,6 @@ void System_SendMessage(const char *command, const char *parameter) { std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), mm->T("Choose folder")); if (folder.size()) NativeMessageReceived("browse_folderSelect", folder.c_str()); - } else if (!strcmp(command, "bgImage_browse")) { - MainWindow::BrowseBackground(); } else if (!strcmp(command, "toggle_fullscreen")) { bool flag = !MainWindow::IsFullscreen(); if (strcmp(parameter, "0") == 0) { @@ -627,9 +652,9 @@ static void WinMainInit() { } static void WinMainCleanup() { - if (g_inputBoxRunning) { - g_inputBoxThread.join(); - g_inputBoxRunning = false; + if (g_dialogRunning) { + g_dialogThread.join(); + g_dialogRunning = false; } net::Shutdown(); CoUninitialize(); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 6a9e42a829..ceb39ddf85 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1037,6 +1037,8 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string PushCommand("inputbox", serialized.c_str()); return true; } + case SystemRequestType::BROWSE_FOR_IMAGE: + return false; default: return false; } @@ -1316,9 +1318,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_setSatInfoAndroid(JNIEn GPS::setSatInfo(index, id, elevation, azimuth, snr, good); } -extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_pushCameraImageAndroid(JNIEnv *env, jclass, - jbyteArray image) { - +extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_pushCameraImageAndroid(JNIEnv *env, jclass, jbyteArray image) { if (image != NULL) { jlong size = env->GetArrayLength(image); jbyte* buffer = env->GetByteArrayElements(image, NULL); From 0403bbf084a8ee681eefb992a651ac66f31d8af3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 14:14:15 +0100 Subject: [PATCH 399/424] Make the new image selection path work on Android as well. --- Common/System/Request.cpp | 5 +++ UI/GameScreen.cpp | 2 +- android/jni/app-android.cpp | 28 +++++------- .../src/org/ppsspp/ppsspp/NativeActivity.java | 44 ++++++++++++------- android/src/org/ppsspp/ppsspp/NativeApp.java | 3 +- 5 files changed, 46 insertions(+), 36 deletions(-) diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index 883514d8da..0effd87f1c 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -7,12 +7,14 @@ RequestManager g_requestManager; const char *RequestTypeAsString(SystemRequestType type) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: return "INPUT_TEXT_MODAL"; + case SystemRequestType::BROWSE_FOR_IMAGE: return "BROWSE_FOR_IMAGE"; default: return "N/A"; } } bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2) { int requestId = idCounter_++; + INFO_LOG(SYSTEM, "Making system request %s: id %d, callback_valid %d", RequestTypeAsString(type), requestId, callback != nullptr); if (!System_MakeRequest(type, requestId, param1, param2)) { return false; } @@ -23,6 +25,7 @@ bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback c } std::lock_guard guard(callbackMutex_); + INFO_LOG(SYSTEM, "Registering pending callback %d", requestId); callbackMap_[requestId] = callback; return true; } @@ -41,6 +44,7 @@ void RequestManager::PostSystemSuccess(int requestId, const char *responseString response.responseString = responseString; response.responseValue = responseValue; pendingResponses_.push_back(response); + INFO_LOG(SYSTEM, "PostSystemSuccess: Request %d (%s, %d)", requestId, responseString, responseValue); } void RequestManager::PostSystemFailure(int requestId) { @@ -50,6 +54,7 @@ void RequestManager::PostSystemFailure(int requestId) { ERROR_LOG(SYSTEM, "PostSystemFailure: Unexpected request ID %d", requestId); return; } + INFO_LOG(SYSTEM, "PostSystemFailure: Request %d failed", requestId); callbackMap_.erase(iter); } diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index 767f22d777..0b2781419d 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -490,7 +490,7 @@ void SetBackgroundPopupScreen::update() { File::WriteStringToFile(false, pic->data, bgPng); } - NativeMessageReceived("bgImage_updated", ""); + UIBackgroundShutdown(); // It's worse if it flickers, stay open for at least 1s. timeDone_ = timeStart_ + 1.0; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index ceb39ddf85..60a4aa46d7 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -539,8 +539,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } void System_Notify(SystemNotification notification) { - switch (notification) { - } } std::string Android_GetInputDeviceDebugString() { @@ -1038,34 +1036,28 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return true; } case SystemRequestType::BROWSE_FOR_IMAGE: - return false; + PushCommand("browse_image", StringFromFormat("%d", requestId)); + return true; default: return false; } } -extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendInputBox(JNIEnv *env, jclass, jstring jseqID, jboolean result, jstring jvalue) { - std::string seqID = GetJavaString(env, jseqID); +extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendRequestResult(JNIEnv *env, jclass, jint jrequestID, jboolean result, jstring jvalue, jint jintValue) { std::string value = GetJavaString(env, jvalue); - static std::string lastSeqID = ""; - if (lastSeqID == seqID) { + static jint lastSeqID = -1; + if (lastSeqID == jrequestID) { // We send this on dismiss, so twice in many cases. - DEBUG_LOG(SYSTEM, "Ignoring duplicate sendInputBox"); - return; - } - lastSeqID = seqID; - - int seq = 0; - if (!TryParse(seqID, &seq)) { - ERROR_LOG(SYSTEM, "Invalid inputbox seqID value: %s", seqID.c_str()); + WARN_LOG(SYSTEM, "Ignoring duplicate sendInputBox"); return; } + lastSeqID = jrequestID; if (result) { - g_requestManager.PostSystemSuccess(seq, value.c_str()); + g_requestManager.PostSystemSuccess(jrequestID, value.c_str()); } else { - g_requestManager.PostSystemFailure(seq); + g_requestManager.PostSystemFailure(jrequestID); } } @@ -1227,7 +1219,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env } else if (msg == "sustained_perf_supported") { sustainedPerfSupported = true; } else if (msg == "safe_insets") { - INFO_LOG(SYSTEM, "Got insets: %s", prm.c_str()); + // INFO_LOG(SYSTEM, "Got insets: %s", prm.c_str()); // We don't bother with supporting exact rectangular regions. Safe insets are good enough. int left, right, top, bottom; if (4 == sscanf(prm.c_str(), "%d:%d:%d:%d", &left, &right, &top, &bottom)) { diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 2a40786d35..5a249cc702 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -105,6 +105,8 @@ public abstract class NativeActivity extends Activity { private static final int RESULT_OPEN_DOCUMENT = 2; private static final int RESULT_OPEN_DOCUMENT_TREE = 3; + private int imageRequestId = -1; + // Allow for multiple connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. private ArrayList inputPlayers = new ArrayList(); @@ -1130,15 +1132,16 @@ public abstract class NativeActivity extends Activity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (resultCode != RESULT_OK || data == null) { - return; - } if (requestCode == RESULT_LOAD_IMAGE) { + if (resultCode != RESULT_OK || data == null) { + NativeApp.sendRequestResult(imageRequestId, false, "", 0); + return; + } try { Uri selectedImage = data.getData(); if (selectedImage != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - NativeApp.sendMessage("bgImage_updated", selectedImage.toString()); + NativeApp.sendRequestResult(imageRequestId, true, selectedImage.toString(), 0); } else { String[] filePathColumn = {MediaStore.Images.Media.DATA}; Cursor cursor = getContentResolver().query(selectedImage, filePathColumn, null, null, null); @@ -1147,14 +1150,20 @@ public abstract class NativeActivity extends Activity { int columnIndex = cursor.getColumnIndex(filePathColumn[0]); String picturePath = cursor.getString(columnIndex); cursor.close(); - NativeApp.sendMessage("bgImage_updated", picturePath); + NativeApp.sendRequestResult(imageRequestId, true, picturePath, 0); } } + } else { + NativeApp.sendRequestResult(imageRequestId, false, "", 0); } } catch (Exception e) { Log.w(TAG, "Exception receiving image: " + e); } + imageRequestId = -1; } else if (requestCode == RESULT_OPEN_DOCUMENT) { + if (resultCode != RESULT_OK || data == null) { + return; + } Uri selectedFile = data.getData(); if (selectedFile != null) { try { @@ -1171,6 +1180,9 @@ public abstract class NativeActivity extends Activity { NativeApp.sendMessage("browse_fileSelect", selectedFile.toString()); } } else if (requestCode == RESULT_OPEN_DOCUMENT_TREE) { + if (resultCode != RESULT_OK || data == null) { + return; + } Uri selectedDirectoryUri = data.getData(); if (selectedDirectoryUri != null) { String path = selectedDirectoryUri.toString(); @@ -1230,11 +1242,11 @@ public abstract class NativeActivity extends Activity { return bld; } - // The return value is sent to C++ via seqID. - public void inputBox(final String seqID, final String title, String defaultText, String defaultAction) { + // The return value is sent to C++ via requestID. + public void inputBox(final int requestId, final String title, String defaultText, String defaultAction) { // Workaround for issue #13363 to fix Split/Second game start if (isVRDevice()) { - NativeApp.sendInputBox(seqID, false, defaultText); + NativeApp.sendRequestResult(requestId, false, defaultText, 0); return; } @@ -1269,14 +1281,14 @@ public abstract class NativeActivity extends Activity { .setPositiveButton(defaultAction, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int which) { - NativeApp.sendInputBox(seqID, true, input.getText().toString()); + NativeApp.sendRequestResult(requestId, true, input.getText().toString(), 0); d.dismiss(); } }) .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface d, int which) { - NativeApp.sendInputBox(seqID, false, ""); + NativeApp.sendRequestResult(requestId, false, "", 0); d.cancel(); } }); @@ -1284,7 +1296,7 @@ public abstract class NativeActivity extends Activity { builder.setOnDismissListener(new DialogInterface.OnDismissListener() { @Override public void onDismiss(DialogInterface d) { - NativeApp.sendInputBox(seqID, false, ""); + NativeApp.sendRequestResult(requestId, false, "", 0); updateSystemUiVisibility(); } }); @@ -1321,8 +1333,10 @@ public abstract class NativeActivity extends Activity { Log.e(TAG, e.toString()); return false; } - } else if (command.equals("bgImage_browse")) { + } else if (command.equals("browse_image")) { try { + imageRequestId = Integer.parseInt(params); + Log.i(TAG, "image request ID: " + imageRequestId); Intent i = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(i, RESULT_LOAD_IMAGE); return true; @@ -1419,13 +1433,13 @@ public abstract class NativeActivity extends Activity { String title = "Input"; String defString = ""; String[] param = params.split(":@:", 3); - String seqID = param[0]; + int requestID = Integer.parseInt(param[0]); if (param.length > 1 && param[1].length() > 0) title = param[1]; if (param.length > 2) defString = param[2]; - Log.i(TAG, "Launching inputbox: #" + seqID + " " + title + " " + defString); - inputBox(seqID, title, defString, "OK"); + Log.i(TAG, "Launching inputbox: #" + requestID + " " + title + " " + defString); + inputBox(requestID, title, defString, "OK"); return true; } else if (command.equals("vibrate")) { int milliseconds = -1; diff --git a/android/src/org/ppsspp/ppsspp/NativeApp.java b/android/src/org/ppsspp/ppsspp/NativeApp.java index 65fa15500f..00ee71d57a 100644 --- a/android/src/org/ppsspp/ppsspp/NativeApp.java +++ b/android/src/org/ppsspp/ppsspp/NativeApp.java @@ -51,8 +51,7 @@ public class NativeApp { public static native void accelerometer(float x, float y, float z); public static native void sendMessage(String msg, String arg); - public static native void sendInputBox(String seqID, boolean result, String value); - + public static native void sendRequestResult(int seqID, boolean result, String value, int iValue); public static native String queryConfig(String queryName); public static native int getSelectedCamera(); From 47ae31e29314795be0a513d31c3a5c5b32b92f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 15:05:54 +0100 Subject: [PATCH 400/424] Minor cleanups, drive-by fix for folder browser on iOS --- Windows/MainWindowMenu.cpp | 33 ++++++++++----------------------- ios/main.mm | 2 +- 2 files changed, 11 insertions(+), 24 deletions(-) diff --git a/Windows/MainWindowMenu.cpp b/Windows/MainWindowMenu.cpp index d4bc5ab3dd..924ad60ecd 100644 --- a/Windows/MainWindowMenu.cpp +++ b/Windows/MainWindowMenu.cpp @@ -56,7 +56,6 @@ namespace MainWindow { extern HINSTANCE hInst; extern bool noFocusPause; static W32Util::AsyncBrowseDialog *browseDialog; - static W32Util::AsyncBrowseDialog *browseImageDialog; static bool browsePauseAfter; static std::unordered_map initialMenuKeys; @@ -361,10 +360,6 @@ namespace MainWindow { } } - static void setScreenRotation(int rotation) { - g_Config.iInternalScreenRotation = rotation; - } - static void SaveStateActionFinished(SaveState::Status status, const std::string &message, void *userdata) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { osm.Show(message, status == SaveState::Status::SUCCESS ? 2.0 : 5.0); @@ -378,14 +373,6 @@ namespace MainWindow { NativeMessageReceived("gpu_configChanged", ""); } - static void setTexFiltering(int type) { - g_Config.iTexFiltering = type; - } - - static void setBufFilter(int type) { - g_Config.iBufFilter = type; - } - static void setTexScalingType(int type) { g_Config.iTexScalingType = type; NativeMessageReceived("gpu_configChanged", ""); @@ -517,10 +504,10 @@ namespace MainWindow { UmdSwitchAction(); break; - case ID_EMULATION_ROTATION_H: setScreenRotation(ROTATION_LOCKED_HORIZONTAL); break; - case ID_EMULATION_ROTATION_V: setScreenRotation(ROTATION_LOCKED_VERTICAL); break; - case ID_EMULATION_ROTATION_H_R: setScreenRotation(ROTATION_LOCKED_HORIZONTAL180); break; - case ID_EMULATION_ROTATION_V_R: setScreenRotation(ROTATION_LOCKED_VERTICAL180); break; + case ID_EMULATION_ROTATION_H: g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL; break; + case ID_EMULATION_ROTATION_V: g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL; break; + case ID_EMULATION_ROTATION_H_R: g_Config.iInternalScreenRotation = ROTATION_LOCKED_HORIZONTAL180; break; + case ID_EMULATION_ROTATION_V_R: g_Config.iInternalScreenRotation = ROTATION_LOCKED_VERTICAL180; break; case ID_EMULATION_CHEATS: g_Config.bEnableCheats = !g_Config.bEnableCheats; @@ -858,13 +845,13 @@ namespace MainWindow { case ID_OPTIONS_VERTEXCACHE: g_Config.bVertexCache = !g_Config.bVertexCache; break; - case ID_OPTIONS_TEXTUREFILTERING_AUTO: setTexFiltering(TEX_FILTER_AUTO); break; - case ID_OPTIONS_NEARESTFILTERING: setTexFiltering(TEX_FILTER_FORCE_NEAREST); break; - case ID_OPTIONS_LINEARFILTERING: setTexFiltering(TEX_FILTER_FORCE_LINEAR); break; - case ID_OPTIONS_AUTOMAXQUALITYFILTERING: setTexFiltering(TEX_FILTER_AUTO_MAX_QUALITY); break; + case ID_OPTIONS_TEXTUREFILTERING_AUTO: g_Config.iTexFiltering = TEX_FILTER_AUTO; break; + case ID_OPTIONS_NEARESTFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_NEAREST; break; + case ID_OPTIONS_LINEARFILTERING: g_Config.iTexFiltering = TEX_FILTER_FORCE_LINEAR; break; + case ID_OPTIONS_AUTOMAXQUALITYFILTERING: g_Config.iTexFiltering = TEX_FILTER_AUTO_MAX_QUALITY; break; - case ID_OPTIONS_BUFLINEARFILTER: setBufFilter(SCALE_LINEAR); break; - case ID_OPTIONS_BUFNEARESTFILTER: setBufFilter(SCALE_NEAREST); break; + case ID_OPTIONS_BUFLINEARFILTER: g_Config.iBufFilter = SCALE_LINEAR; break; + case ID_OPTIONS_BUFNEARESTFILTER: g_Config.iBufFilter = SCALE_NEAREST; break; case ID_OPTIONS_TOPMOST: g_Config.bTopMost = !g_Config.bTopMost; diff --git a/ios/main.mm b/ios/main.mm index 3caaf93e26..d1c56fc537 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -211,7 +211,7 @@ void System_SendMessage(const char *command, const char *parameter) { } } else if (!strcmp(command, "browse_folder")) { DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { - NativeMessageReceived("browse_folder", thePathChosen.c_str()); + NativeMessageReceived("browse_folderSelect", thePathChosen.c_str()); }; DarwinFileSystemServices services; From 70f0ac04af43f0cb71db1a55e9d8d65ebb8f014b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 15:21:03 +0100 Subject: [PATCH 401/424] Port the file browser spawned by the Load button to the new request stuff --- Common/System/Request.cpp | 4 ++-- Common/System/Request.h | 16 +++++++++++++--- Common/System/System.h | 3 ++- Qt/QtMain.cpp | 2 +- SDL/SDLMain.cpp | 2 +- UI/MainScreen.cpp | 7 ++++++- UWP/PPSSPP_UWPMain.cpp | 2 +- Windows/main.cpp | 36 +++++++++++++++++++++++++++++++++--- android/jni/app-android.cpp | 2 +- headless/Headless.cpp | 2 +- libretro/libretro.cpp | 2 +- unittest/JitHarness.cpp | 2 +- 12 files changed, 63 insertions(+), 17 deletions(-) diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index 0effd87f1c..0e4e53b97b 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -12,10 +12,10 @@ const char *RequestTypeAsString(SystemRequestType type) { } } -bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2) { +bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2, int param3) { int requestId = idCounter_++; INFO_LOG(SYSTEM, "Making system request %s: id %d, callback_valid %d", RequestTypeAsString(type), requestId, callback != nullptr); - if (!System_MakeRequest(type, requestId, param1, param2)) { + if (!System_MakeRequest(type, requestId, param1, param2, param3)) { return false; } diff --git a/Common/System/Request.h b/Common/System/Request.h index 99e42eb500..b0797e4ff8 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -16,7 +16,7 @@ class RequestManager { public: // These requests are to be handled by platform implementations. // The callback you pass in will be called on the main thread later. - bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2); + bool MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2, int param3); // Called by the platform implementation, when it's finished with a request. void PostSystemSuccess(int requestId, const char *responseString, int responseValue = 0); @@ -56,9 +56,19 @@ extern RequestManager g_requestManager; // Wrappers for easy requests. // NOTE: Semantics have changed - this no longer calls the callback on cancellation. inline void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, RequestCallback callback) { - g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue); + g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue, 0); } inline void System_BrowseForImage(const std::string &title, RequestCallback callback) { - g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, title, ""); + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, title, "", 0); +} + +enum class BrowseFileType { + BOOTABLE, + INI, + ANY, +}; + +inline void System_BrowseForFile(const std::string &title, BrowseFileType type, RequestCallback callback) { + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, callback, title, "", (int)type); } diff --git a/Common/System/System.h b/Common/System/System.h index dbb79edaab..1e1c04ea4a 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -54,13 +54,14 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url); enum class SystemRequestType { INPUT_TEXT_MODAL, BROWSE_FOR_IMAGE, + BROWSE_FOR_FILE, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). // This is not to be used directly by applications, instead use the g_RequestManager to make the requests. // This can return false if it's known that the platform doesn't support the request, the app is supposed to handle // or ignore that cleanly. -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2); +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3); // TODO: To be separated into requests, see Request.h, and a way to post "UI messages". void System_SendMessage(const char *command, const char *parameter); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index ba475e5141..e52a563915 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -311,7 +311,7 @@ bool MainUI::HandleCustomEvent(QEvent *e) { return true; } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: { diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 3bda836e98..daf41c79d2 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -166,7 +166,7 @@ void System_Vibrate(int length_ms) { // Ignore on PC } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "toggle_fullscreen")) { diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 682fe85074..78015eadfc 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -23,6 +23,8 @@ #include "Common/System/Display.h" #include "Common/System/System.h" +#include "Common/System/Request.h" +#include "Common/System/NativeApp.h" #include "Common/Render/TextureAtlas.h" #include "Common/Render/DrawBuffer.h" #include "Common/UI/Root.h" @@ -1278,7 +1280,10 @@ void MainScreen::update() { UI::EventReturn MainScreen::OnLoadFile(UI::EventParams &e) { if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) { - System_SendMessage("browse_file", ""); + auto mm = GetI18NCategory("MainMenu"); + System_BrowseForFile(mm->T("Load"), BrowseFileType::BOOTABLE, [](const std::string &value, int) { + NativeMessageReceived("boot", value.c_str()); + }); } return UI::EVENT_DONE; } diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 39e27cbf56..7811986fa0 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -443,7 +443,7 @@ void System_Notify(SystemNotification notification) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_SendMessage(const char *command, const char *parameter) { using namespace concurrency; diff --git a/Windows/main.cpp b/Windows/main.cpp index 4314acda19..b5ebb2dadb 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -441,7 +441,7 @@ std::wstring MakeFilter(std::wstring filter) { return filter; } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: if (g_dialogRunning) { @@ -474,6 +474,38 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } }); return true; + case SystemRequestType::BROWSE_FOR_FILE: + { + BrowseFileType type = (BrowseFileType)param3; + std::wstring filter; + switch (type) { + case BrowseFileType::BOOTABLE: + filter = MakeFilter(L"All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip *.ppdmp)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip;*.ppdmp|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*||"); + break; + case BrowseFileType::INI: + filter = MakeFilter(L"Ini files (*.ini)|*.ini|All files (*.*)|*.*||"); + break; + case BrowseFileType::ANY: + filter = MakeFilter(L"All files (*.*)|*.*||"); + break; + default: + return false; + } + if (g_dialogRunning) { + g_dialogThread.join(); + } + + g_dialogRunning = true; + g_dialogThread = std::thread([=] { + std::string out; + if (W32Util::BrowseForFileName(true, MainWindow::GetHWND(), ConvertUTF8ToWString(param1).c_str(), nullptr, filter.c_str(), L"", out)) { + g_requestManager.PostSystemSuccess(requestId, out.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }); + return true; + } default: return false; } @@ -503,8 +535,6 @@ void System_SendMessage(const char *command, const char *parameter) { } else if (!strcmp(command, "setclipboardtext")) { std::wstring data = ConvertUTF8ToWString(parameter); W32Util::CopyTextToClipboard(MainWindow::GetDisplayHWND(), data); - } else if (!strcmp(command, "browse_file")) { - MainWindow::BrowseAndBoot(""); } else if (!strcmp(command, "browse_folder")) { auto mm = GetI18NCategory("MainMenu"); std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), mm->T("Choose folder")); diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 60a4aa46d7..730671b2f0 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1027,7 +1027,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: { diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 8d6ae20519..137b3ae1f3 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -116,7 +116,7 @@ bool System_GetPropertyBool(SystemProperty prop) { } void System_Notify(SystemNotification notification) {} void System_SendMessage(const char *command, const char *parameter) {} -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index cdb699bb56..2289b1fb97 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1874,7 +1874,7 @@ void System_Notify(SystemNotification notification) { break; } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_SendMessage(const char *command, const char *parameter) {} void NativeUpdate() {} void NativeRender(GraphicsContext *graphicsContext) {} diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index f730cc44d6..d578c0af13 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -42,7 +42,7 @@ void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } void System_SendMessage(const char *command, const char *parameter) {} -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } From 7718c06dd13c384ab4c66ac332b53bb8b473aad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 15:35:21 +0100 Subject: [PATCH 402/424] Port UWP file browser, fix UWP image browser --- UI/MainScreen.cpp | 4 - UWP/PPSSPP_UWPMain.cpp | 76 ++++++++++++------- android/jni/app-android.cpp | 3 + .../src/org/ppsspp/ppsspp/NativeActivity.java | 8 +- 4 files changed, 59 insertions(+), 32 deletions(-) diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 78015eadfc..9a19fe37f2 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -1254,10 +1254,6 @@ void MainScreen::sendMessage(const char *message, const char *value) { if (!strcmp(message, "boot")) { LaunchFile(screenManager(), Path(std::string(value))); } - if (!strcmp(message, "browse_fileSelect")) { - INFO_LOG(SYSTEM, "Attempting to launch: '%s'", value); - LaunchFile(screenManager(), Path(std::string(value))); - } if (!strcmp(message, "browse_folderSelect")) { std::string filename = value; INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str()); diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 7811986fa0..d174437aee 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -22,7 +22,7 @@ #include "Common/StringUtils.h" #include "Common/System/Display.h" #include "Common/System/NativeApp.h" -#include "Common/System/System.h" +#include "Common/System/Request.h" #include "Core/System.h" #include "Core/Loaders.h" @@ -418,7 +418,7 @@ bool System_GetPropertyBool(SystemProperty prop) { case SYSPROP_HAS_FOLDER_BROWSER: return false; // at least I don't know a usable one case SYSPROP_HAS_IMAGE_BROWSER: - return false; + return true; // we just use the file browser case SYSPROP_HAS_BACK_BUTTON: return true; case SYSPROP_APP_GOLD: @@ -443,32 +443,59 @@ void System_Notify(SystemNotification notification) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { + switch (type) { + case SystemRequestType::BROWSE_FOR_IMAGE: + case SystemRequestType::BROWSE_FOR_FILE: + { + auto picker = ref new Windows::Storage::Pickers::FileOpenPicker(); + picker->ViewMode = Pickers::PickerViewMode::List; + + if (type == SystemRequestType::BROWSE_FOR_IMAGE) { + picker->FileTypeFilter->Append(".jpg"); + picker->FileTypeFilter->Append(".png"); + } else { + switch ((BrowseFileType)param3) { + case BrowseFileType::BOOTABLE: + // These are single files that can be loaded directly using StorageFileLoader. + picker->FileTypeFilter->Append(".cso"); + picker->FileTypeFilter->Append(".iso"); + + // Can't load these this way currently, they require mounting the underlying folder. + picker->FileTypeFilter->Append(".bin"); + picker->FileTypeFilter->Append(".elf"); + break; + case BrowseFileType::INI: + picker->FileTypeFilter->Append(".ini"); + break; + case BrowseFileType::ANY: + picker->FileTypeFilter->Append("*"); + break; + } + } + + picker->SuggestedStartLocation = Pickers::PickerLocationId::DocumentsLibrary; + + create_task(picker->PickSingleFileAsync()).then([requestId](StorageFile ^file) { + if (file) { + std::string path = FromPlatformString(file->Path); + g_requestManager.PostSystemSuccess(requestId, path.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }); + return true; + } + } + + return false; +} void System_SendMessage(const char *command, const char *parameter) { using namespace concurrency; if (!strcmp(command, "finish")) { // Not really supposed to support this under UWP. - } else if (!strcmp(command, "browse_file")) { - auto picker = ref new Windows::Storage::Pickers::FileOpenPicker(); - picker->ViewMode = Pickers::PickerViewMode::List; - - // These are single files that can be loaded directly using StorageFileLoader. - picker->FileTypeFilter->Append(".cso"); - picker->FileTypeFilter->Append(".iso"); - - // Can't load these this way currently, they require mounting the underlying folder. - picker->FileTypeFilter->Append(".bin"); - picker->FileTypeFilter->Append(".elf"); - picker->SuggestedStartLocation = Pickers::PickerLocationId::DocumentsLibrary; - - create_task(picker->PickSingleFileAsync()).then([](StorageFile ^file){ - if (file) { - std::string path = FromPlatformString(file->Path); - NativeMessageReceived("boot", path.c_str()); - } - }); } else if (!strcmp(command, "toggle_fullscreen")) { auto view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView(); bool flag = !view->IsFullScreenMode; @@ -519,11 +546,6 @@ PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } -void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { - // TODO - cb(false, ""); -} - std::string GetCPUBrandString() { Platform::String^ cpu_id = nullptr; Platform::String^ cpu_name = nullptr; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 730671b2f0..0674c6728d 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1038,6 +1038,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::BROWSE_FOR_IMAGE: PushCommand("browse_image", StringFromFormat("%d", requestId)); return true; + case SystemRequestType::BROWSE_FOR_FILE: + PushCommand("browse_file", StringFromFormat("%d", requestId)); + return true; default: return false; } diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 5a249cc702..288087aaec 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -105,7 +105,9 @@ public abstract class NativeActivity extends Activity { private static final int RESULT_OPEN_DOCUMENT = 2; private static final int RESULT_OPEN_DOCUMENT_TREE = 3; + // These can probably be merged, but conceptually nice to have them separate. private int imageRequestId = -1; + private int fileRequestId = -1; // Allow for multiple connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. @@ -1173,12 +1175,15 @@ public abstract class NativeActivity extends Activity { } } catch (Exception e) { Log.w(TAG, "Exception getting permissions for document: " + e.toString()); + NativeApp.sendRequestResult(fileRequestId, false, "", 0); + return; } // Even if we got an exception getting permissions, try to pass along the file. Maybe this version of Android // doesn't need it. Log.i(TAG, "Browse file finished:" + selectedFile.toString()); - NativeApp.sendMessage("browse_fileSelect", selectedFile.toString()); + NativeApp.sendRequestResult(fileRequestId, true, selectedFile.toString(), 0); } + fileRequestId = -1; } else if (requestCode == RESULT_OPEN_DOCUMENT_TREE) { if (resultCode != RESULT_OK || data == null) { return; @@ -1346,6 +1351,7 @@ public abstract class NativeActivity extends Activity { } } else if (command.equals("browse_file")) { try { + fileRequestId = Integer.parseInt(params); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); intent.addCategory(Intent.CATEGORY_OPENABLE); intent.setType("*/*"); From 1c79fd8cf4e476590999a8145466bd7e42f97372 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 15:52:11 +0100 Subject: [PATCH 403/424] Fix Qt file browser, use to implement image browser --- Common/System/Request.h | 3 +++ Qt/QtMain.cpp | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index b0797e4ff8..bd61104926 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -59,12 +59,15 @@ inline void System_InputBoxGetString(const std::string &title, const std::string g_requestManager.MakeSystemRequest(SystemRequestType::INPUT_TEXT_MODAL, callback, title, defaultValue, 0); } +// This one will pop up a special image brwoser if available. You can also pick +// images with the file browser below. inline void System_BrowseForImage(const std::string &title, RequestCallback callback) { g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_IMAGE, callback, title, "", 0); } enum class BrowseFileType { BOOTABLE, + IMAGE, INI, ANY, }; diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index e52a563915..e05ef5e3ad 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -239,6 +239,7 @@ bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { case SYSPROP_HAS_BACK_BUTTON: return true; + case SYSPROP_HAS_IMAGE_BROWSER: case SYSPROP_HAS_FILE_BROWSER: case SYSPROP_HAS_FOLDER_BROWSER: case SYSPROP_HAS_OPEN_DIRECTORY: @@ -278,17 +279,32 @@ void System_Notify(SystemNotification notification) { // TODO: Find a better version to pass parameters to HandleCustomEvent. static std::string g_param1; static std::string g_param2; +static int g_param3; static int g_requestId; bool MainUI::HandleCustomEvent(QEvent *e) { if (e->type() == browseFileEvent) { - QString fileName = QFileDialog::getOpenFileName(nullptr, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)"); - if (QFile::exists(fileName)) { - QDir newPath; - g_Config.currentDirectory = Path(newPath.filePath(fileName).toStdString()); - g_Config.Save("browseFileEvent"); + BrowseFileType fileType = (BrowseFileType)g_param3; + const char *filter = "All files (*.*)"; + switch (fileType) { + case BrowseFileType::BOOTABLE: + filter = "PSP ROMs (*.iso *.cso *.pbp *.elf *.zip *.ppdmp)"; + break; + case BrowseFileType::IMAGE: + filter = "Pictures (*.jpg *.png)"; + break; + case BrowseFileType::INI: + filter = "INI files (*.ini)"; + break; + case BrowseFileType::ANY: + break; + } - NativeMessageReceived("boot", fileName.toStdString().c_str()); + QString fileName = QFileDialog::getOpenFileName(nullptr, g_param1.c_str(), g_Config.currentDirectory.c_str(), filter); + if (QFile::exists(fileName)) { + g_requestManager.PostSystemSuccess(g_requestId, fileName.toStdString().c_str()); + } else { + g_requestManager.PostSystemFailure(g_requestId); } } else if (e->type() == browseFolderEvent) { auto mm = GetI18NCategory("MainMenu"); @@ -318,9 +334,20 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string g_requestId = requestId; g_param1 = param1; g_param2 = param2; + g_param3 = param3; QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)inputBoxEvent)); return true; } + case SystemRequestType::BROWSE_FOR_IMAGE: + // Fall back to file browser. + return System_MakeRequest(SystemRequestType::BROWSE_FOR_FILE, requestId, param1, param2, (int)BrowseFileType::IMAGE); + case SystemRequestType::BROWSE_FOR_FILE: + g_requestId = requestId; + g_param1 = param1; + g_param2 = param2; + g_param3 = param3; + QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFileEvent)); + return true; default: return false; } @@ -329,8 +356,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { qApp->exit(0); - } else if (!strcmp(command, "browse_file")) { - QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFileEvent)); } else if (!strcmp(command, "browse_folder")) { QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent)); } else if (!strcmp(command, "graphics_restart")) { From 376cd341821d0cd630b023b6b8e567d8802eae20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 16:58:32 +0100 Subject: [PATCH 404/424] iOS buildfix --- ios/main.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/main.mm b/ios/main.mm index d1c56fc537..ca0684c074 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -219,7 +219,7 @@ void System_SendMessage(const char *command, const char *parameter) { } } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2) { +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } From 9508ef467eaea20d5f0be726f8f39973cfc13c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 16:09:33 +0100 Subject: [PATCH 405/424] Port folder browser too, now this time start with Qt --- Common/System/Request.cpp | 2 ++ Common/System/Request.h | 4 ++++ Common/System/System.h | 1 + Qt/QtMain.cpp | 14 +++++++++++--- UI/MainScreen.cpp | 15 +++++---------- UI/MemStickScreen.cpp | 38 +++++++++++++++----------------------- UI/MemStickScreen.h | 1 - 7 files changed, 38 insertions(+), 37 deletions(-) diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index 0e4e53b97b..7ec0a872f2 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -8,6 +8,8 @@ const char *RequestTypeAsString(SystemRequestType type) { switch (type) { case SystemRequestType::INPUT_TEXT_MODAL: return "INPUT_TEXT_MODAL"; case SystemRequestType::BROWSE_FOR_IMAGE: return "BROWSE_FOR_IMAGE"; + case SystemRequestType::BROWSE_FOR_FILE: return "BROWSE_FOR_FILE"; + case SystemRequestType::BROWSE_FOR_FOLDER: return "BROWSE_FOR_FOLDER"; default: return "N/A"; } } diff --git a/Common/System/Request.h b/Common/System/Request.h index bd61104926..856fbb9e41 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -75,3 +75,7 @@ enum class BrowseFileType { inline void System_BrowseForFile(const std::string &title, BrowseFileType type, RequestCallback callback) { g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FILE, callback, title, "", (int)type); } + +inline void System_BrowseForFolder(const std::string &title, RequestCallback callback) { + g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, title, "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index 1e1c04ea4a..1b05cf4960 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -55,6 +55,7 @@ enum class SystemRequestType { INPUT_TEXT_MODAL, BROWSE_FOR_IMAGE, BROWSE_FOR_FILE, + BROWSE_FOR_FOLDER, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index e05ef5e3ad..966af70b77 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -307,10 +307,12 @@ bool MainUI::HandleCustomEvent(QEvent *e) { g_requestManager.PostSystemFailure(g_requestId); } } else if (e->type() == browseFolderEvent) { - auto mm = GetI18NCategory("MainMenu"); - QString fileName = QFileDialog::getExistingDirectory(nullptr, mm->T("Choose folder"), g_Config.currentDirectory.c_str()); + QString title = QString::fromStdString(g_param1); + QString fileName = QFileDialog::getExistingDirectory(nullptr, title, g_Config.currentDirectory.c_str()); if (QDir(fileName).exists()) { - NativeMessageReceived("browse_folderSelect", fileName.toStdString().c_str()); + g_requestManager.PostSystemSuccess(g_requestId, fileName.toStdString().c_str()); + } else { + g_requestManager.PostSystemFailure(g_requestId); } } else if (e->type() == inputBoxEvent) { QString title = QString::fromStdString(g_param1); @@ -348,6 +350,12 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string g_param3 = param3; QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFileEvent)); return true; + case SystemRequestType::BROWSE_FOR_FOLDER: + g_requestId = requestId; + g_param1 = param1; + g_param2 = param2; + QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent)); + return true; default: return false; } diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 9a19fe37f2..768b3c4f21 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -540,7 +540,11 @@ UI::EventReturn GameBrowser::LastClick(UI::EventParams &e) { } UI::EventReturn GameBrowser::BrowseClick(UI::EventParams &e) { - System_SendMessage("browse_folder", ""); + auto mm = GetI18NCategory("MainMenu"); + System_BrowseForFolder(mm->T("Choose folder"), [this](const std::string &value, int) { + std::string filename = value; + this->SetPath(Path(filename)); + }); return UI::EVENT_DONE; } @@ -1254,15 +1258,6 @@ void MainScreen::sendMessage(const char *message, const char *value) { if (!strcmp(message, "boot")) { LaunchFile(screenManager(), Path(std::string(value))); } - if (!strcmp(message, "browse_folderSelect")) { - std::string filename = value; - INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str()); - int tab = tabHolder_->GetCurrentTab(); - // Don't allow browsing in the other tabs (I don't think it's possible to reach the option though) - if (tab == 1) { - gameBrowsers_[tab]->SetPath(Path(filename)); - } - } } if (!strcmp(message, "permission_granted") && !strcmp(value, "storage")) { RecreateViews(); diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 5bf8c83d6f..9b3def0b61 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -445,32 +445,24 @@ UI::EventReturn MemStickScreen::UseStorageRoot(UI::EventParams ¶ms) { } UI::EventReturn MemStickScreen::Browse(UI::EventParams ¶ms) { - System_SendMessage("browse_folder", ""); - return UI::EVENT_DONE; -} + auto mm = GetI18NCategory("MainMenu"); + System_BrowseForFolder(mm->T("Choose folder"), [=](const std::string &value, int) { + std::string filename; + filename = value; + INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str()); -void MemStickScreen::sendMessage(const char *message, const char *value) { - // Always call the base class method first to handle the most common messages. - UIDialogScreenWithBackground::sendMessage(message, value); + // Browse finished. Let's pop up the confirmation dialog. + Path pendingMemStickFolder = Path(filename); - if (screenManager()->topScreen() == this) { - if (!strcmp(message, "browse_folderSelect")) { - std::string filename; - filename = value; - INFO_LOG(SYSTEM, "Got folder: '%s'", filename.c_str()); - - // Browse finished. Let's pop up the confirmation dialog. - Path pendingMemStickFolder = Path(filename); - - if (pendingMemStickFolder == g_Config.memStickDirectory) { - auto iz = GetI18NCategory("MemStick"); - return; - } - - bool existingFiles = FolderSeemsToBeUsed(pendingMemStickFolder); - screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, initialSetup_)); + if (pendingMemStickFolder == g_Config.memStickDirectory) { + auto iz = GetI18NCategory("MemStick"); + return; } - } + + bool existingFiles = FolderSeemsToBeUsed(pendingMemStickFolder); + screenManager()->push(new ConfirmMemstickMoveScreen(pendingMemStickFolder, initialSetup_)); + }); + return UI::EVENT_DONE; } void MemStickScreen::dialogFinished(const Screen *dialog, DialogResult result) { diff --git a/UI/MemStickScreen.h b/UI/MemStickScreen.h index 378f4f3ed0..3912e095bc 100644 --- a/UI/MemStickScreen.h +++ b/UI/MemStickScreen.h @@ -48,7 +48,6 @@ public: protected: void CreateViews() override; - void sendMessage(const char *message, const char *value) override; void dialogFinished(const Screen *dialog, DialogResult result) override; void update() override; void render() override { From 49efa4499e459d971ab2a1a1d6c0a23a4ff877aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 16:20:30 +0100 Subject: [PATCH 406/424] Blind convert iOS to the new folder picking path --- UI/DarwinFileSystemServices.h | 2 +- UI/DarwinFileSystemServices.mm | 11 ++++++++--- ios/main.mm | 24 +++++++++++++++++------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/UI/DarwinFileSystemServices.h b/UI/DarwinFileSystemServices.h index f49d053d42..85a61a80c3 100644 --- a/UI/DarwinFileSystemServices.h +++ b/UI/DarwinFileSystemServices.h @@ -12,7 +12,7 @@ #define PreferredMemoryStickUserDefaultsKey "UserPreferredMemoryStickDirectoryPath" -typedef std::function DarwinDirectoryPanelCallback; +typedef std::function DarwinDirectoryPanelCallback; /// A Class providing help functions to work with the FileSystem /// on Darwin platforms. diff --git a/UI/DarwinFileSystemServices.mm b/UI/DarwinFileSystemServices.mm index 50d9f94ec6..c89d039c15 100644 --- a/UI/DarwinFileSystemServices.mm +++ b/UI/DarwinFileSystemServices.mm @@ -33,7 +33,9 @@ - (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray *)urls { if (urls.count >= 1) - self.callback(Path(urls[0].path.UTF8String)); + self.callback(true, Path(urls[0].path.UTF8String)); + else + self.callback)false, Path()); } @end @@ -55,8 +57,11 @@ void DarwinFileSystemServices::presentDirectoryPanel(DarwinDirectoryPanelCallbac // panel.allowedFileTypes = @[(__bridge NSString *)kUTTypeFolder]; NSModalResponse modalResponse = [panel runModal]; - if (modalResponse == NSModalResponseOK && panel.URLs.firstObject) - callback(Path(panel.URLs.firstObject.path.UTF8String)); + if (modalResponse == NSModalResponseOK && panel.URLs.firstObject) { + callback(true, Path(panel.URLs.firstObject.path.UTF8String)); + } else if (modalResponse == NSModalReponseCancel) { + callback(false, Path()); + } #elif PPSSPP_PLATFORM(IOS) UIViewController *rootViewController = UIApplication.sharedApplication .keyWindow diff --git a/ios/main.mm b/ios/main.mm index ca0684c074..a96ed3f49a 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -18,6 +18,7 @@ #include "Common/MemoryUtil.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/StringUtils.h" #include "Common/Profiler/Profiler.h" #include "UI/DarwinFileSystemServices.h" @@ -209,17 +210,26 @@ void System_SendMessage(const char *command, const char *parameter) { g_safeInsetTop = top; g_safeInsetBottom = bottom; } - } else if (!strcmp(command, "browse_folder")) { - DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { - NativeMessageReceived("browse_folderSelect", thePathChosen.c_str()); - }; - - DarwinFileSystemServices services; - services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectorites = */ true); } } bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { + switch (type) { + case SystemRequestType::BROWSE_FOR_FOLDER: + { + DarwinDirectoryPanelCallback callback = [] (bool success, Path thePathChosen) { + if (success) { + g_requestManager.PostSystemSuccess(requestId, thePathChosen.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }; + DarwinFileSystemServices services; + services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ true); + } + break; + } + } return false; } From b7350f3cbf485f4f658de645a518e1731e35be30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 17:39:45 +0100 Subject: [PATCH 407/424] Fix folder browser on Android and Windows --- Common/System/Request.cpp | 19 ++++++----- Qt/QtMain.cpp | 2 -- SDL/SDLMain.cpp | 32 ++++++++++++------- UI/NativeApp.cpp | 12 +------ Windows/main.cpp | 15 ++++++--- android/jni/app-android.cpp | 3 ++ .../src/org/ppsspp/ppsspp/NativeActivity.java | 10 +++++- 7 files changed, 54 insertions(+), 39 deletions(-) diff --git a/Common/System/Request.cpp b/Common/System/Request.cpp index 7ec0a872f2..13e12f1502 100644 --- a/Common/System/Request.cpp +++ b/Common/System/Request.cpp @@ -16,19 +16,22 @@ const char *RequestTypeAsString(SystemRequestType type) { bool RequestManager::MakeSystemRequest(SystemRequestType type, RequestCallback callback, const std::string ¶m1, const std::string ¶m2, int param3) { int requestId = idCounter_++; + + // NOTE: We need to register immediately, in order to support synchronous implementations. + { + std::lock_guard guard(callbackMutex_); + callbackMap_[requestId] = callback; + } + INFO_LOG(SYSTEM, "Making system request %s: id %d, callback_valid %d", RequestTypeAsString(type), requestId, callback != nullptr); if (!System_MakeRequest(type, requestId, param1, param2, param3)) { + { + std::lock_guard guard(callbackMutex_); + callbackMap_.erase(requestId); + } return false; } - if (!callback) { - // We don't expect a response, this is a one-directional request. We're thus done. - return true; - } - - std::lock_guard guard(callbackMutex_); - INFO_LOG(SYSTEM, "Registering pending callback %d", requestId); - callbackMap_[requestId] = callback; return true; } diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 966af70b77..28ca9d75ef 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -364,8 +364,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "finish")) { qApp->exit(0); - } else if (!strcmp(command, "browse_folder")) { - QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent)); } else if (!strcmp(command, "graphics_restart")) { // Should find a way to properly restart the app. qApp->exit(0); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index daf41c79d2..7ac7ae1868 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -166,7 +166,26 @@ void System_Vibrate(int length_ms) { // Ignore on PC } -bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } +bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { + switch (type) { + case SystemRequestType::BROWSE_FOR_FOLDER: +#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) + DarwinDirectoryPanelCallback callback = [](bool success, Path thePathChosen) { + if (success) { + g_requestManager.PostSystemSuccess(requestId, thePathChosen.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }; + DarwinFileSystemServices services; + services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ true); + return true; +#else + return false; +#endif + } + return false; +} void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "toggle_fullscreen")) { @@ -191,17 +210,6 @@ void System_SendMessage(const char *command, const char *parameter) { StopSDLAudioDevice(); InitSDLAudioDevice(); } -#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - else if (!strcmp(command, "browse_folder")) { - DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { - NativeMessageReceived("browse_folder", thePathChosen.c_str()); - }; - - DarwinFileSystemServices services; - services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectorites = */ true); - } -#endif - } void System_AskForPermission(SystemPermission permission) {} diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index ba675e4b29..6ff7dd17fb 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1215,19 +1215,9 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) { g_Config.Reload(); PostLoadConfig(); g_Config.iGPUBackend = gpuBackend; - } - else if (msg == "app_resumed" || msg == "got_focus") { + } else if (msg == "app_resumed" || msg == "got_focus") { // Assume that the user may have modified things. MemoryStick_NotifyWrite(); - } else if (msg == "browse_folder") { - Path thePath = Path(value); - File::FileInfo info; - if (!File::GetFileInfo(thePath, &info)) - return; - if (info.isDirectory) - NativeMessageReceived("browse_folderSelect", thePath.c_str()); - else - NativeMessageReceived("browse_fileSelect", thePath.c_str()); } } diff --git a/Windows/main.cpp b/Windows/main.cpp index b5ebb2dadb..59e83a0722 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -506,6 +506,16 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string }); return true; } + case SystemRequestType::BROWSE_FOR_FOLDER: + { + std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), param1.c_str()); + if (folder.size()) { + g_requestManager.PostSystemSuccess(requestId, folder.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + return true; + } default: return false; } @@ -535,11 +545,6 @@ void System_SendMessage(const char *command, const char *parameter) { } else if (!strcmp(command, "setclipboardtext")) { std::wstring data = ConvertUTF8ToWString(parameter); W32Util::CopyTextToClipboard(MainWindow::GetDisplayHWND(), data); - } else if (!strcmp(command, "browse_folder")) { - auto mm = GetI18NCategory("MainMenu"); - std::string folder = W32Util::BrowseForFolder(MainWindow::GetHWND(), mm->T("Choose folder")); - if (folder.size()) - NativeMessageReceived("browse_folderSelect", folder.c_str()); } else if (!strcmp(command, "toggle_fullscreen")) { bool flag = !MainWindow::IsFullscreen(); if (strcmp(parameter, "0") == 0) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 0674c6728d..b5e8ac937f 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1041,6 +1041,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::BROWSE_FOR_FILE: PushCommand("browse_file", StringFromFormat("%d", requestId)); return true; + case SystemRequestType::BROWSE_FOR_FOLDER: + PushCommand("browse_folder", StringFromFormat("%d", requestId)); + return true; default: return false; } diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 288087aaec..bd6857bef4 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -108,6 +108,7 @@ public abstract class NativeActivity extends Activity { // These can probably be merged, but conceptually nice to have them separate. private int imageRequestId = -1; private int fileRequestId = -1; + private int folderRequestId = -1; // Allow for multiple connected gamepads but just consider them the same for now. // Actually this is not entirely true, see the code. @@ -1164,6 +1165,7 @@ public abstract class NativeActivity extends Activity { imageRequestId = -1; } else if (requestCode == RESULT_OPEN_DOCUMENT) { if (resultCode != RESULT_OK || data == null) { + NativeApp.sendRequestResult(fileRequestId, false, "", 0); return; } Uri selectedFile = data.getData(); @@ -1186,6 +1188,7 @@ public abstract class NativeActivity extends Activity { fileRequestId = -1; } else if (requestCode == RESULT_OPEN_DOCUMENT_TREE) { if (resultCode != RESULT_OK || data == null) { + NativeApp.sendRequestResult(folderRequestId, false, "", 0); return; } Uri selectedDirectoryUri = data.getData(); @@ -1208,8 +1211,9 @@ public abstract class NativeActivity extends Activity { Log.i(TAG, "Child: " + child.getUri() + " " + child.getName()); } */ - NativeApp.sendMessage("browse_folderSelect", documentFile.getUri().toString()); + NativeApp.sendRequestResult(folderRequestId, true, documentFile.getUri().toString(), 0); } + folderRequestId = -1; } } @@ -1346,6 +1350,7 @@ public abstract class NativeActivity extends Activity { startActivityForResult(i, RESULT_LOAD_IMAGE); return true; } catch (Exception e) { // For example, android.content.ActivityNotFoundException + imageRequestId = -1; Log.e(TAG, e.toString()); return false; } @@ -1362,11 +1367,13 @@ public abstract class NativeActivity extends Activity { startActivityForResult(intent, RESULT_OPEN_DOCUMENT); // intent.putExtra(DocumentsContract.EXTRA_INITIAL_URI, pickerInitialUri); } catch (Exception e) { + fileRequestId = -1; Log.e(TAG, e.toString()); return false; } } else if (command.equals("browse_folder")) { try { + folderRequestId = Integer.parseInt(params); Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION); @@ -1375,6 +1382,7 @@ public abstract class NativeActivity extends Activity { startActivityForResult(intent, RESULT_OPEN_DOCUMENT_TREE); return true; } catch (Exception e) { + folderRequestId = -1; Log.e(TAG, e.toString()); return false; } From dfa06c4e777b30bd97e09a13c6f2f940e3438d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 17:57:28 +0100 Subject: [PATCH 408/424] SDL buildfix, fix file/folder browsers on Darwin --- Common/File/Path.h | 2 +- SDL/SDLMain.cpp | 33 ++++++++++++++++++++++++++------- UI/DarwinFileSystemServices.mm | 2 +- UI/GameSettingsScreen.cpp | 9 +++------ ios/main.mm | 22 +++++++++++++++++----- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/Common/File/Path.h b/Common/File/Path.h index aded7b5bde..b66471c53e 100644 --- a/Common/File/Path.h +++ b/Common/File/Path.h @@ -81,9 +81,9 @@ public: Path WithReplacedExtension(const std::string &oldExtension, const std::string &newExtension) const; Path WithReplacedExtension(const std::string &newExtension) const; - // Removes the last component. std::string GetFilename() const; // Really, GetLastComponent. Could be a file or directory. Includes the extension. std::string GetFileExtension() const; // Always lowercase return. Includes the dot. + // Removes the last component. std::string GetDirectory() const; const std::string &ToString() const; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 7ac7ae1868..ad80509a44 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -24,10 +24,12 @@ SDLJoystick *joystick = NULL; #include "Common/System/Display.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/System/NativeApp.h" #include "ext/glslang/glslang/Public/ShaderLang.h" #include "Common/Data/Format/PNGLoad.h" #include "Common/Net/Resolve.h" +#include "Common/File/FileUtil.h" #include "NKCodeFromSDL.h" #include "Common/Math/math_util.h" #include "Common/GPU/OpenGL/GLRenderManager.h" @@ -168,20 +170,33 @@ void System_Vibrate(int length_ms) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { - case SystemRequestType::BROWSE_FOR_FOLDER: #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - DarwinDirectoryPanelCallback callback = [](bool success, Path thePathChosen) { + case SystemRequestType::BROWSE_FOR_FILE: + { + DarwinDirectoryPanelCallback callback = [requestId] (bool success, Path path) { if (success) { - g_requestManager.PostSystemSuccess(requestId, thePathChosen.c_str()); + g_requestManager.PostSystemSuccess(requestId, path.c_str()); } else { g_requestManager.PostSystemFailure(requestId); } }; DarwinFileSystemServices services; - services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ true); + services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ false); return true; -#else - return false; + } + case SystemRequestType::BROWSE_FOR_FOLDER: + { + DarwinDirectoryPanelCallback callback = [requestId] (bool success, Path path) { + if (success) { + g_requestManager.PostSystemSuccess(requestId, path.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }; + DarwinFileSystemServices services; + services.presentDirectoryPanel(callback, /* allowFiles = */ false, /* allowDirectories = */ true); + return true; + } #endif } return false; @@ -440,7 +455,11 @@ bool System_GetPropertyBool(SystemProperty prop) { return true; case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR: return true; // FileUtil.cpp: OpenFileInEditor - +#if PPSSPP_PLATFORM(MAC) + case SYSPROP_HAS_FOLDER_BROWSER: + case SYSPROP_HAS_FILE_BROWSER: + return true; +#endif default: return false; } diff --git a/UI/DarwinFileSystemServices.mm b/UI/DarwinFileSystemServices.mm index c89d039c15..b5006351db 100644 --- a/UI/DarwinFileSystemServices.mm +++ b/UI/DarwinFileSystemServices.mm @@ -59,7 +59,7 @@ void DarwinFileSystemServices::presentDirectoryPanel(DarwinDirectoryPanelCallbac NSModalResponse modalResponse = [panel runModal]; if (modalResponse == NSModalResponseOK && panel.URLs.firstObject) { callback(true, Path(panel.URLs.firstObject.path.UTF8String)); - } else if (modalResponse == NSModalReponseCancel) { + } else if (modalResponse == NSModalResponseCancel) { callback(false, Path()); } #elif PPSSPP_PLATFORM(IOS) diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 85cb888bf6..470efbca15 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1233,12 +1233,9 @@ UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) { #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) - DarwinFileSystemServices memoryStickManager; - DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) { - DarwinFileSystemServices::setUserPreferredMemoryStickDirectory(thePathChosen); - }; - - memoryStickManager.presentDirectoryPanel(callback); + System_BrowseForFolder("", [](const std::string &value, int) { + DarwinFileSystemServices::setUserPreferredMemoryStickDirectory(Path(value)); + }); #else screenManager()->push(new MemStickScreen(false)); #endif diff --git a/ios/main.mm b/ios/main.mm index a96ed3f49a..c879c0793d 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -215,19 +215,31 @@ void System_SendMessage(const char *command, const char *parameter) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { - case SystemRequestType::BROWSE_FOR_FOLDER: + case SystemRequestType::BROWSE_FOR_FILE: { - DarwinDirectoryPanelCallback callback = [] (bool success, Path thePathChosen) { + DarwinDirectoryPanelCallback callback = [requestId] (bool success, Path path) { if (success) { - g_requestManager.PostSystemSuccess(requestId, thePathChosen.c_str()); + g_requestManager.PostSystemSuccess(requestId, path.c_str()); } else { g_requestManager.PostSystemFailure(requestId); } }; DarwinFileSystemServices services; - services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ true); + services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectories = */ false); + return true; } - break; + case SystemRequestType::BROWSE_FOR_FOLDER: + { + DarwinDirectoryPanelCallback callback = [requestId] (bool success, Path path) { + if (success) { + g_requestManager.PostSystemSuccess(requestId, path.c_str()); + } else { + g_requestManager.PostSystemFailure(requestId); + } + }; + DarwinFileSystemServices services; + services.presentDirectoryPanel(callback, /* allowFiles = */ false, /* allowDirectories = */ true); + return true; } } return false; From 49af6b97311eef3b4d7d8b69a7fef7a8a1f17fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 19:36:50 +0100 Subject: [PATCH 409/424] Single-character iOS buildfix, sigh --- UI/DarwinFileSystemServices.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UI/DarwinFileSystemServices.mm b/UI/DarwinFileSystemServices.mm index b5006351db..5f710b89ec 100644 --- a/UI/DarwinFileSystemServices.mm +++ b/UI/DarwinFileSystemServices.mm @@ -35,7 +35,7 @@ if (urls.count >= 1) self.callback(true, Path(urls[0].path.UTF8String)); else - self.callback)false, Path()); + self.callback(false, Path()); } @end From 410b35fba3db1a889757981c418ff3a519462ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 22:07:29 +0100 Subject: [PATCH 410/424] Get rid of "finish" and "setclipboardtext" messages, replace with requests. --- Common/System/Request.h | 8 ++++++++ Common/System/System.h | 8 ++++++++ Common/UI/View.cpp | 3 ++- Qt/QtMain.cpp | 12 +++++++----- SDL/SDLMain.cpp | 12 +++++++----- UI/GameSettingsScreen.cpp | 4 ++-- UI/MainScreen.cpp | 2 +- UI/NativeApp.cpp | 12 ++++++++---- UI/PauseScreen.cpp | 3 ++- UWP/PPSSPP_UWPMain.cpp | 4 +--- Windows/main.cpp | 20 ++++++++++++-------- android/jni/app-android.cpp | 4 ++++ ios/main.mm | 17 +++++++++-------- 13 files changed, 71 insertions(+), 38 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index 856fbb9e41..0d32e8c491 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -79,3 +79,11 @@ inline void System_BrowseForFile(const std::string &title, BrowseFileType type, inline void System_BrowseForFolder(const std::string &title, RequestCallback callback) { g_requestManager.MakeSystemRequest(SystemRequestType::BROWSE_FOR_FOLDER, callback, title, "", 0); } + +inline void System_CopyStringToClipboard(const std::string &string) { + g_requestManager.MakeSystemRequest(SystemRequestType::COPY_TO_CLIPBOARD, nullptr, string, "", 0); +} + +inline void System_ExitApp() { + g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, "", "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index 1b05cf4960..f4f8a5c294 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -51,17 +51,25 @@ void System_Vibrate(int length_ms); void System_ShowFileInFolder(const char *path); void System_LaunchUrl(LaunchUrlType urlType, const char *url); +// It's sometimes a little unclear what should be a request, and what should be a separate function. +// Going forward, "optional" things (PPSSPP will still function alright without it) will be requests, +// to make implementations simpler in the default case. + enum class SystemRequestType { INPUT_TEXT_MODAL, BROWSE_FOR_IMAGE, BROWSE_FOR_FILE, BROWSE_FOR_FOLDER, + + EXIT_APP, + COPY_TO_CLIPBOARD, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). // This is not to be used directly by applications, instead use the g_RequestManager to make the requests. // This can return false if it's known that the platform doesn't support the request, the app is supposed to handle // or ignore that cleanly. +// Some requests don't use responses. bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3); // TODO: To be separated into requests, see Request.h, and a way to post "UI messages". diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index c48e7eca16..5a3f53c68f 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -13,6 +13,7 @@ #include "Common/UI/Tween.h" #include "Common/UI/Root.h" #include "Common/GPU/thin3d.h" +#include "Common/System/Request.h" #include "Common/System/System.h" #include "Common/TimeUtil.h" #include "Common/StringUtils.h" @@ -1195,7 +1196,7 @@ bool TextEdit::Key(const KeyInput &input) { switch (input.keyCode) { case NKCODE_C: // Just copy the entire text contents, until we get selection support. - System_SendMessage("setclipboardtext", text_.c_str()); + System_CopyStringToClipboard(text_.c_str()); break; case NKCODE_V: { diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 28ca9d75ef..2b4ba23a66 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -331,6 +331,12 @@ bool MainUI::HandleCustomEvent(QEvent *e) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + qApp->exit(0); + return true; + case SystemRequestType::COPY_TO_CLIPBOARD: + QApplication::clipboard()->setText(parameter); + return true; case SystemRequestType::INPUT_TEXT_MODAL: { g_requestId = requestId; @@ -362,9 +368,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { - qApp->exit(0); - } else if (!strcmp(command, "graphics_restart")) { + if (!strcmp(command, "graphics_restart")) { // Should find a way to properly restart the app. qApp->exit(0); } else if (!strcmp(command, "camera_command")) { @@ -375,8 +379,6 @@ void System_SendMessage(const char *command, const char *parameter) { } else if (!strcmp(parameter, "stopVideo")) { emit(qtcamera->onStopCamera()); } - } else if (!strcmp(command, "setclipboardtext")) { - QApplication::clipboard()->setText(parameter); #if defined(SDL) } else if (!strcmp(command, "audio_resetDevice")) { StopSDLAudioDevice(); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index ad80509a44..c998f79c9b 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -170,6 +170,13 @@ void System_Vibrate(int length_ms) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + // Do a clean exit + g_QuitRequested = true; + break; + case SystemRequestType::COPY_TO_CLIPBOARD: + SDL_SetClipboardText(param1.c_str()); + break; #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) case SystemRequestType::BROWSE_FOR_FILE: { @@ -213,14 +220,9 @@ void System_SendMessage(const char *command, const char *parameter) { // Just toggle. g_ToggleFullScreenType = -1; } - } else if (!strcmp(command, "finish")) { - // Do a clean exit - g_QuitRequested = true; } else if (!strcmp(command, "graphics_restart")) { // Not sure how we best do this, but do a clean exit, better than being stuck in a bad state. g_QuitRequested = true; - } else if (!strcmp(command, "setclipboardtext")) { - SDL_SetClipboardText(parameter); } else if (!strcmp(command, "audio_resetDevice")) { StopSDLAudioDevice(); InitSDLAudioDevice(); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 470efbca15..e3b571aa4e 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -2107,8 +2107,8 @@ UI::EventReturn HostnameSelectScreen::OnIPClick(UI::EventParams& e) { std::string text = e.v ? e.v->Tag() : ""; if (text.length() > 0) { addrView_->SetText(text); - // TODO: Copy the IP to clipboard for the host to easily share their IP through chatting apps. - System_SendMessage("setclipboardtext", text.c_str()); // Doesn't seems to be working on windows (yet?) + // Copy the IP to clipboard for the host to easily share their IP through chatting apps. + System_CopyStringToClipboard(text); } return UI::EVENT_DONE; } diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 768b3c4f21..69e9486621 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -1432,7 +1432,7 @@ UI::EventReturn MainScreen::OnExit(UI::EventParams &e) { } // Request the framework to exit cleanly. - System_SendMessage("finish", ""); + System_ExitApp(); UpdateUIState(UISTATE_EXIT); return UI::EVENT_DONE; diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index 6ff7dd17fb..babf0e1b6d 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -1289,7 +1289,7 @@ bool NativeKey(const KeyInput &key) { pspKeys.clear(); if (KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &pspKeys)) { if (std::find(pspKeys.begin(), pspKeys.end(), VIRTKEY_PAUSE) != pspKeys.end()) { - System_SendMessage("finish", ""); + System_ExitApp(); return true; } } @@ -1390,8 +1390,6 @@ void NativeShutdown() { g_screenManager = nullptr; } -#if !PPSSPP_PLATFORM(UWP) -#endif g_Config.Save("NativeShutdown"); INFO_LOG(SYSTEM, "NativeShutdown called"); @@ -1404,7 +1402,9 @@ void NativeShutdown() { ShutdownWebServer(); - System_SendMessage("finish", ""); +#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) + System_ExitApp(); +#endif net::Shutdown(); @@ -1423,6 +1423,10 @@ void NativeShutdown() { g_threadManager.Teardown(); +#if !(PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS)) + System_ExitApp(); +#endif + // Previously we did exit() here on Android but that makes it hard to do things like restart on backend change. // I think we handle most globals correctly or correct-enough now. } diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 4738e425d9..f3405fdc89 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -28,6 +28,7 @@ #include "Common/Data/Text/I18n.h" #include "Common/StringUtils.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/VR/PPSSPPVR.h" #include "Common/UI/AsyncImageFileView.h" @@ -392,7 +393,7 @@ UI::EventReturn GamePauseScreen::OnScreenshotClicked(UI::EventParams &e) { UI::EventReturn GamePauseScreen::OnExitToMenu(UI::EventParams &e) { if (g_Config.bPauseMenuExitsEmulator) { - System_SendMessage("finish", ""); + System_ExitApp(); } else { TriggerFinish(DR_OK); } diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index d174437aee..9e27c82f1a 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -494,9 +494,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string void System_SendMessage(const char *command, const char *parameter) { using namespace concurrency; - if (!strcmp(command, "finish")) { - // Not really supposed to support this under UWP. - } else if (!strcmp(command, "toggle_fullscreen")) { + if (!strcmp(command, "toggle_fullscreen")) { auto view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView(); bool flag = !view->IsFullScreenMode; if (strcmp(parameter, "0") == 0) { diff --git a/Windows/main.cpp b/Windows/main.cpp index 59e83a0722..1dd21cbc74 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -443,6 +443,17 @@ std::wstring MakeFilter(std::wstring filter) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + if (!NativeIsRestarting()) { + PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + } + return true; + case SystemRequestType::COPY_TO_CLIPBOARD: + { + std::wstring data = ConvertUTF8ToWString(param1); + W32Util::CopyTextToClipboard(MainWindow::GetDisplayHWND(), data); + return true; + } case SystemRequestType::INPUT_TEXT_MODAL: if (g_dialogRunning) { g_dialogThread.join(); @@ -522,11 +533,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { - if (!NativeIsRestarting()) { - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); - } - } else if (!strcmp(command, "graphics_restart")) { + if (!strcmp(command, "graphics_restart")) { restartArgs = parameter == nullptr ? "" : parameter; if (!restartArgs.empty()) AddDebugRestartArgs(); @@ -542,9 +549,6 @@ void System_SendMessage(const char *command, const char *parameter) { std::wstring full_error = ConvertUTF8ToWString(StringFromFormat("%s %s", backendSwitchError, parameter)); std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); MessageBox(MainWindow::GetHWND(), full_error.c_str(), title.c_str(), MB_OK); - } else if (!strcmp(command, "setclipboardtext")) { - std::wstring data = ConvertUTF8ToWString(parameter); - W32Util::CopyTextToClipboard(MainWindow::GetDisplayHWND(), data); } else if (!strcmp(command, "toggle_fullscreen")) { bool flag = !MainWindow::IsFullscreen(); if (strcmp(parameter, "0") == 0) { diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index b5e8ac937f..1b0e18af77 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -402,6 +402,7 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url) { } void System_SendMessage(const char *command, const char *parameter) { + // TODO: Using sendmessage this way is deprecated. PushCommand(command, parameter); } @@ -1029,6 +1030,9 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + PushCommand("finish", ""); + return true; case SystemRequestType::INPUT_TEXT_MODAL: { std::string serialized = StringFromFormat("%d:@:%s:@:%s", requestId, param1.c_str(), param2.c_str()); diff --git a/ios/main.mm b/ios/main.mm index c879c0793d..b63b475b2e 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -177,14 +177,7 @@ void System_Notify(SystemNotification notification) { } void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "finish")) { - exit(0); - // The below seems right, but causes hangs. See #12140. - // dispatch_async(dispatch_get_main_queue(), ^{ - // [sharedViewController shutdown]; - // exit(0); - // }); - } else if (!strcmp(command, "sharetext")) { + if (!strcmp(command, "sharetext")) { NSString *text = [NSString stringWithUTF8String:parameter]; [sharedViewController shareText:text]; } else if (!strcmp(command, "camera_command")) { @@ -215,6 +208,14 @@ void System_SendMessage(const char *command, const char *parameter) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { + case SystemRequestType::EXIT_APP: + exit(0); + // The below seems right, but causes hangs. See #12140. + // dispatch_async(dispatch_get_main_queue(), ^{ + // [sharedViewController shutdown]; + // exit(0); + // }); + break; case SystemRequestType::BROWSE_FOR_FILE: { DarwinDirectoryPanelCallback callback = [requestId] (bool success, Path path) { From 5a55fd5fd395bd6a385ff8f982a9df5835759703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 22:17:53 +0100 Subject: [PATCH 411/424] And replace "graphics_restart", "toggle_fullscreen", etc --- Common/System/Request.h | 13 ++++++++ Common/System/System.h | 3 ++ Qt/QtMain.cpp | 9 +++--- SDL/SDLMain.cpp | 28 ++++++++--------- UI/ControlMappingScreen.cpp | 3 +- UI/EmuScreen.cpp | 3 +- UI/GameSettingsScreen.cpp | 6 ++-- UI/MainScreen.cpp | 2 +- UI/MemStickScreen.cpp | 2 +- UI/NativeApp.cpp | 6 ++-- UWP/PPSSPP_UWPMain.cpp | 21 ++++++------- Windows/main.cpp | 61 +++++++++++++++++++++---------------- android/jni/app-android.cpp | 3 ++ 13 files changed, 94 insertions(+), 66 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index 0d32e8c491..1b801e962a 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -87,3 +87,16 @@ inline void System_CopyStringToClipboard(const std::string &string) { inline void System_ExitApp() { g_requestManager.MakeSystemRequest(SystemRequestType::EXIT_APP, nullptr, "", "", 0); } + +inline void System_RestartApp(const std::string ¶ms) { + g_requestManager.MakeSystemRequest(SystemRequestType::RESTART_APP, nullptr, params, "", 0); +} + +// The design is a little weird, just a holdover from the old message. Can either toggle or set to on or off. +inline void System_ToggleFullscreenState(const std::string ¶m) { + g_requestManager.MakeSystemRequest(SystemRequestType::TOGGLE_FULLSCREEN_STATE, nullptr, param, "", 0); +} + +inline void System_GraphicsBackendFailedAlert(const std::string ¶m) { + g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, param, "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index f4f8a5c294..e4e00b53f7 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -62,7 +62,10 @@ enum class SystemRequestType { BROWSE_FOR_FOLDER, EXIT_APP, + RESTART_APP, // For graphics backend changes COPY_TO_CLIPBOARD, + TOGGLE_FULLSCREEN_STATE, + GRAPHICS_BACKEND_FAILED_ALERT, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 2b4ba23a66..293ea67056 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -334,6 +334,10 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::EXIT_APP: qApp->exit(0); return true; + case SystemRequestType::RESTART_APP: + // Should find a way to properly restart the app. + qApp->exit(0); + return true; case SystemRequestType::COPY_TO_CLIPBOARD: QApplication::clipboard()->setText(parameter); return true; @@ -368,10 +372,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "graphics_restart")) { - // Should find a way to properly restart the app. - qApp->exit(0); - } else if (!strcmp(command, "camera_command")) { + if (!strcmp(command, "camera_command")) { if (!strncmp(parameter, "startVideo", 10)) { int width = 0, height = 0; sscanf(parameter, "startVideo_%dx%d", &width, &height); diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index c998f79c9b..f6defed98f 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -171,12 +171,13 @@ void System_Vibrate(int length_ms) { bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::EXIT_APP: + case SystemRequestType::RESTART_APP: // Not sure how we best do this, but do a clean exit, better than being stuck in a bad state. // Do a clean exit g_QuitRequested = true; - break; + return true; case SystemRequestType::COPY_TO_CLIPBOARD: SDL_SetClipboardText(param1.c_str()); - break; + return true; #if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) case SystemRequestType::BROWSE_FOR_FILE: { @@ -205,25 +206,24 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return true; } #endif - } - return false; -} - -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "toggle_fullscreen")) { + case SystemRequestType::TOGGLE_FULLSCREEN_STATE: g_ToggleFullScreenNextFrame = true; - if (strcmp(parameter, "1") == 0) { + if (param1 == "1") { g_ToggleFullScreenType = 1; - } else if (strcmp(parameter, "0") == 0) { + } else if (param1 == "0") { g_ToggleFullScreenType = 0; } else { // Just toggle. g_ToggleFullScreenType = -1; } - } else if (!strcmp(command, "graphics_restart")) { - // Not sure how we best do this, but do a clean exit, better than being stuck in a bad state. - g_QuitRequested = true; - } else if (!strcmp(command, "audio_resetDevice")) { + return true; + default: + return false; + } +} + +void System_SendMessage(const char *command, const char *parameter) { + if (!strcmp(command, "audio_resetDevice")) { StopSDLAudioDevice(); InitSDLAudioDevice(); } diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index bfcb9e662c..de04aef59a 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -37,6 +37,7 @@ #include "Common/StringUtils.h" #include "Common/System/Display.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/TimeUtil.h" #include "Core/KeyMap.h" #include "Core/Host.h" @@ -726,7 +727,7 @@ UI::EventReturn TouchTestScreen::OnImmersiveModeChange(UI::EventParams &e) { UI::EventReturn TouchTestScreen::OnRenderingBackend(UI::EventParams &e) { g_Config.Save("GameSettingsScreen::RenderingBackend"); - System_SendMessage("graphics_restart", "--touchscreentest"); + System_RestartApp("--touchscreentest"); return UI::EVENT_DONE; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index e5c03ba69b..b367e3b067 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -41,6 +41,7 @@ using namespace std::placeholders; #include "Common/System/Display.h" #include "Common/System/System.h" #include "Common/System/NativeApp.h" +#include "Common/System/Request.h" #include "Common/Profiler/Profiler.h" #include "Common/Math/curves.h" #include "Common/TimeUtil.h" @@ -676,7 +677,7 @@ void EmuScreen::onVKeyDown(int virtualKeyCode) { NativeMessageReceived("savestate_displayslot", ""); break; case VIRTKEY_TOGGLE_FULLSCREEN: - System_SendMessage("toggle_fullscreen", ""); + System_ToggleFullscreenState(""); break; case VIRTKEY_SCREENSHOT: diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index e3b571aa4e..50b47a5677 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1329,12 +1329,12 @@ UI::EventReturn GameSettingsScreen::OnChangeBackground(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnFullscreenChange(UI::EventParams &e) { g_Config.iForceFullScreen = -1; - System_SendMessage("toggle_fullscreen", g_Config.UseFullScreen() ? "1" : "0"); + System_ToggleFullscreenState(g_Config.UseFullScreen() ? "1" : "0"); return UI::EVENT_DONE; } UI::EventReturn GameSettingsScreen::OnFullscreenMultiChange(UI::EventParams &e) { - System_SendMessage("toggle_fullscreen", g_Config.UseFullScreen() ? "1" : "0"); + System_ToggleFullscreenState(g_Config.UseFullScreen() ? "1" : "0"); return UI::EVENT_DONE; } @@ -1477,7 +1477,7 @@ void GameSettingsScreen::TriggerRestart(const char *why) { } // Make sure the new instance is considered the first. ShutdownInstanceCounter(); - System_SendMessage("graphics_restart", param.c_str()); + System_RestartApp(param); } void GameSettingsScreen::CallbackRenderingBackend(bool yes) { diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 69e9486621..875d9c07b8 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -1287,7 +1287,7 @@ UI::EventReturn MainScreen::OnFullScreenToggle(UI::EventParams &e) { } #if !defined(MOBILE_DEVICE) g_Config.bFullScreen = !g_Config.bFullScreen; - System_SendMessage("toggle_fullscreen", ""); + System_ToggleFullscreenState(""); #endif return UI::EVENT_DONE; } diff --git a/UI/MemStickScreen.cpp b/UI/MemStickScreen.cpp index 9b3def0b61..d5812885ad 100644 --- a/UI/MemStickScreen.cpp +++ b/UI/MemStickScreen.cpp @@ -771,7 +771,7 @@ void ConfirmMemstickMoveScreen::FinishFolderMove() { if (!initialSetup_) { // We restart the app here, to get the new settings. - System_SendMessage("graphics_restart", ""); + System_RestartApp(""); } else { // This is initial setup, we now switch to the main screen, if we were successful // (which we better have been...) diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index babf0e1b6d..b42c9a037d 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -387,7 +387,7 @@ static void CheckFailedGPUBackends() { g_Config.iGPUBackend = g_Config.NextValidBackend(); if (lastBackend != g_Config.iGPUBackend) { std::string param = GPUBackendToString((GPUBackend)lastBackend) + " -> " + GPUBackendToString((GPUBackend)g_Config.iGPUBackend); - System_SendMessage("graphics_failedBackend", param.c_str()); + System_GraphicsBackendFailedAlert(param); WARN_LOG(LOADER, "Failed graphics backend switched from %s (%d to %d)", param.c_str(), lastBackend, g_Config.iGPUBackend); } // And then let's - for now - add the current to the failed list. @@ -640,11 +640,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_Config.bPauseMenuExitsEmulator = true; if (!strcmp(argv[i], "--fullscreen")) { g_Config.iForceFullScreen = 1; - System_SendMessage("toggle_fullscreen", "1"); + System_ToggleFullscreenState("1"); } if (!strcmp(argv[i], "--windowed")) { g_Config.iForceFullScreen = 0; - System_SendMessage("toggle_fullscreen", "0"); + System_ToggleFullscreenState("0"); } if (!strcmp(argv[i], "--touchscreentest")) gotoTouchScreenTest = true; diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 9e27c82f1a..0af1409d3d 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -486,20 +486,13 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string }); return true; } - } - - return false; -} - -void System_SendMessage(const char *command, const char *parameter) { - using namespace concurrency; - - if (!strcmp(command, "toggle_fullscreen")) { + case SystemRequestType::TOGGLE_FULLSCREEN_STATE: + { auto view = Windows::UI::ViewManagement::ApplicationView::GetForCurrentView(); bool flag = !view->IsFullScreenMode; - if (strcmp(parameter, "0") == 0) { + if (param1 == "0") { flag = false; - } else if (strcmp(parameter, "1") == 0){ + } else if (param1 == "1"){ flag = true; } if (flag) { @@ -507,9 +500,15 @@ void System_SendMessage(const char *command, const char *parameter) { } else { view->ExitFullScreenMode(); } + return true; + } + default: + return false; } } +void System_SendMessage(const char *command, const char *parameter) {} + void System_ShowFileInFolder(const char *path) { // Unsupported } diff --git a/Windows/main.cpp b/Windows/main.cpp index 1dd21cbc74..057522fc68 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -448,6 +448,19 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); } return true; + case SystemRequestType::RESTART_APP: + { + restartArgs = param1; + if (!restartArgs.empty()) + AddDebugRestartArgs(); + if (IsDebuggerPresent()) { + PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); + } else { + g_Config.bRestartRequired = true; + PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); + } + return true; + } case SystemRequestType::COPY_TO_CLIPBOARD: { std::wstring data = ConvertUTF8ToWString(param1); @@ -527,38 +540,32 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } return true; } + case SystemRequestType::TOGGLE_FULLSCREEN_STATE: + { + bool flag = !MainWindow::IsFullscreen(); + if (param1 == "0") { + flag = false; + } else if (param1 == "1") { + flag = true; + } + MainWindow::SendToggleFullscreen(flag); + return true; + } + case SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT: + { + auto err = GetI18NCategory("Error"); + const char *backendSwitchError = err->T("GenericBackendSwitchCrash", "PPSSPP crashed while starting. This usually means a graphics driver problem. Try upgrading your graphics drivers.\n\nGraphics backend has been switched:"); + std::wstring full_error = ConvertUTF8ToWString(StringFromFormat("%s %s", backendSwitchError, param1.c_str())); + std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); + MessageBox(MainWindow::GetHWND(), full_error.c_str(), title.c_str(), MB_OK); + return true; + } default: return false; } } -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "graphics_restart")) { - restartArgs = parameter == nullptr ? "" : parameter; - if (!restartArgs.empty()) - AddDebugRestartArgs(); - if (IsDebuggerPresent()) { - PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); - } else { - g_Config.bRestartRequired = true; - PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0); - } - } else if (!strcmp(command, "graphics_failedBackend")) { - auto err = GetI18NCategory("Error"); - const char *backendSwitchError = err->T("GenericBackendSwitchCrash", "PPSSPP crashed while starting. This usually means a graphics driver problem. Try upgrading your graphics drivers.\n\nGraphics backend has been switched:"); - std::wstring full_error = ConvertUTF8ToWString(StringFromFormat("%s %s", backendSwitchError, parameter)); - std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); - MessageBox(MainWindow::GetHWND(), full_error.c_str(), title.c_str(), MB_OK); - } else if (!strcmp(command, "toggle_fullscreen")) { - bool flag = !MainWindow::IsFullscreen(); - if (strcmp(parameter, "0") == 0) { - flag = false; - } else if (strcmp(parameter, "1") == 0) { - flag = true; - } - MainWindow::SendToggleFullscreen(flag); - } -} +void System_SendMessage(const char *command, const char *parameter) {} void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 1b0e18af77..dec8285fe1 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1033,6 +1033,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::EXIT_APP: PushCommand("finish", ""); return true; + case SystemRequestType::RESTART_APP: + PushCommand("graphics_restart", param1); + return true; case SystemRequestType::INPUT_TEXT_MODAL: { std::string serialized = StringFromFormat("%d:@:%s:@:%s", requestId, param1.c_str(), param2.c_str()); From 2c9787643dbbf4582c8bfecde8f4a0ad0f61aecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 22:40:13 +0100 Subject: [PATCH 412/424] Move the twitter special-case URL handling to java --- UI/MiscScreens.cpp | 4 -- .../src/org/ppsspp/ppsspp/NativeActivity.java | 46 ++++++++++--------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index c99684bbe0..d6a5c4fecc 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -846,11 +846,7 @@ UI::EventReturn CreditsScreen::OnSupport(UI::EventParams &e) { } UI::EventReturn CreditsScreen::OnTwitter(UI::EventParams &e) { -#ifdef __ANDROID__ - System_SendMessage("showTwitter", "PPSSPP_emu"); -#else System_LaunchUrl(LaunchUrlType::BROWSER_URL, "https://twitter.com/#!/PPSSPP_emu"); -#endif return UI::EVENT_DONE; } diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index bd6857bef4..439f8a2b7a 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -1319,14 +1319,31 @@ public abstract class NativeActivity extends Activity { public boolean processCommand(String command, String params) { SurfaceView surfView = javaGL ? mGLSurfaceView : mSurfaceView; if (command.equals("launchBrowser")) { - try { - Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); - startActivity(i); - return true; - } catch (Exception e) { - // No browser? - Log.e(TAG, e.toString()); - return false; + // Special case for twitter + if (params.startsWith("https://twitter.com/#!/")) { + try { + String twitter_user_name = params.replaceFirst("https://twitter.com/#!/", ""); + try { + Log.i(TAG, "Launching twitter directly: " + twitter_user_name); + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitter_user_name))); + } catch (Exception e) { + startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/#!/" + twitter_user_name))); + } + return true; + } catch (Exception e) { // For example, android.content.ActivityNotFoundException + Log.e(TAG, e.toString()); + return false; + } + } else { + try { + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(params)); + startActivity(i); + return true; + } catch (Exception e) { + // No browser? + Log.e(TAG, e.toString()); + return false; + } } } else if (command.equals("launchEmail")) { try { @@ -1410,19 +1427,6 @@ public abstract class NativeActivity extends Activity { Log.e(TAG, e.toString()); return false; } - } else if (command.equals("showTwitter")) { - try { - String twitter_user_name = params; - try { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("twitter://user?screen_name=" + twitter_user_name))); - } catch (Exception e) { - startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/#!/" + twitter_user_name))); - } - return true; - } catch (Exception e) { // For example, android.content.ActivityNotFoundException - Log.e(TAG, e.toString()); - return false; - } } else if (command.equals("launchMarket")) { // Don't need this, can just use launchBrowser with a market: // http://stackoverflow.com/questions/3442366/android-link-to-market-from-inside-another-app From 87d0c21f14dc52c1c18f54b6bcf77042d8d1dbe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 22:49:38 +0100 Subject: [PATCH 413/424] Make proper requests for the external hardware commands (gps, microphone, camera) --- Common/System/Request.h | 12 ++++++++++++ Common/System/System.h | 5 +++++ Core/HLE/sceUsbCam.cpp | 5 +++-- Core/HLE/sceUsbGps.cpp | 7 ++++--- Core/HLE/sceUsbMic.cpp | 5 +++-- Qt/QtMain.cpp | 19 ++++++++++--------- android/jni/app-android.cpp | 10 ++++++++++ ios/main.mm | 35 +++++++++++++++++++---------------- 8 files changed, 66 insertions(+), 32 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index 1b801e962a..4860588854 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -100,3 +100,15 @@ inline void System_ToggleFullscreenState(const std::string ¶m) { inline void System_GraphicsBackendFailedAlert(const std::string ¶m) { g_requestManager.MakeSystemRequest(SystemRequestType::GRAPHICS_BACKEND_FAILED_ALERT, nullptr, param, "", 0); } + +inline void System_CameraCommand(const std::string &command) { + g_requestManager.MakeSystemRequest(SystemRequestType::CAMERA_COMMAND, nullptr, command, "", 0); +} + +inline void System_GPSCommand(const std::string &command) { + g_requestManager.MakeSystemRequest(SystemRequestType::GPS_COMMAND, nullptr, command, "", 0); +} + +inline void System_MicrophoneCommand(const std::string &command) { + g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, command, "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index e4e00b53f7..3f4c8e3f84 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -66,6 +66,11 @@ enum class SystemRequestType { COPY_TO_CLIPBOARD, TOGGLE_FULLSCREEN_STATE, GRAPHICS_BACKEND_FAILED_ALERT, + + // High-level hardware control + CAMERA_COMMAND, + GPS_COMMAND, + MICROPHONE_COMMAND, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). diff --git a/Core/HLE/sceUsbCam.cpp b/Core/HLE/sceUsbCam.cpp index 571f846545..512bcfe15d 100644 --- a/Core/HLE/sceUsbCam.cpp +++ b/Core/HLE/sceUsbCam.cpp @@ -21,6 +21,7 @@ #include "ppsspp_config.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Core/HLE/HLE.h" @@ -360,7 +361,7 @@ int Camera::startCapture() { #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) || defined(USING_QT_UI) char command[40] = {0}; snprintf(command, sizeof(command), "startVideo_%dx%d", width, height); - System_SendMessage("camera_command", command); + System_CameraCommand(command); #elif PPSSPP_PLATFORM(LINUX) __v4l_startCapture(width, height); #else @@ -376,7 +377,7 @@ int Camera::stopCapture() { winCamera->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr }); } #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS) || defined(USING_QT_UI) - System_SendMessage("camera_command", "stopVideo"); + System_CameraCommand("stopVideo"); #elif PPSSPP_PLATFORM(LINUX) __v4l_stopCapture(); #else diff --git a/Core/HLE/sceUsbGps.cpp b/Core/HLE/sceUsbGps.cpp index 020339fe10..fe9fdf66d5 100644 --- a/Core/HLE/sceUsbGps.cpp +++ b/Core/HLE/sceUsbGps.cpp @@ -21,6 +21,7 @@ #include #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Core/HLE/HLE.h" @@ -51,7 +52,7 @@ void __UsbGpsDoState(PointerWrap &p) { void __UsbGpsShutdown() { gpsStatus = GPS_STATE_OFF; - System_SendMessage("gps_command", "close"); + System_GPSCommand("close"); }; static int sceUsbGpsGetInitDataLocation(u32 addr) { @@ -69,14 +70,14 @@ static int sceUsbGpsOpen() { ERROR_LOG(HLE, "UNIMPL sceUsbGpsOpen"); GPS::init(); gpsStatus = GPS_STATE_ON; - System_SendMessage("gps_command", "open"); + System_GPSCommand("open"); return 0; } static int sceUsbGpsClose() { ERROR_LOG(HLE, "UNIMPL sceUsbGpsClose"); gpsStatus = GPS_STATE_OFF; - System_SendMessage("gps_command", "close"); + System_GPSCommand("close"); return 0; } diff --git a/Core/HLE/sceUsbMic.cpp b/Core/HLE/sceUsbMic.cpp index 8ab6ff23da..2d46b5e6a2 100644 --- a/Core/HLE/sceUsbMic.cpp +++ b/Core/HLE/sceUsbMic.cpp @@ -22,6 +22,7 @@ #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Core/HLE/HLE.h" #include "Core/HLE/FunctionWrappers.h" #include "Core/HLE/sceKernelThread.h" @@ -328,7 +329,7 @@ int Microphone::startMic(void *param) { int sampleRate = micParam->at(0); int channels = micParam->at(1); INFO_LOG(HLE, "microphone_command : sr = %d", sampleRate); - System_SendMessage("microphone_command", ("startRecording:" + std::to_string(sampleRate)).c_str()); + System_MicrophoneCommand("startRecording:" + std::to_string(sampleRate)); #endif micState = 1; return 0; @@ -339,7 +340,7 @@ int Microphone::stopMic() { if (winMic) winMic->sendMessage({ CAPTUREDEVIDE_COMMAND::STOP, nullptr }); #elif PPSSPP_PLATFORM(ANDROID) - System_SendMessage("microphone_command", "stopRecording"); + System_MicrophoneCommand("stopRecording"); #endif micState = 0; return 0; diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 293ea67056..b01acce6ba 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -366,13 +366,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string g_param2 = param2; QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent)); return true; - default: - return false; - } -} - -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "camera_command")) { + case SystemRequestType::CAMERA_COMMAND: if (!strncmp(parameter, "startVideo", 10)) { int width = 0, height = 0; sscanf(parameter, "startVideo_%dx%d", &width, &height); @@ -380,12 +374,19 @@ void System_SendMessage(const char *command, const char *parameter) { } else if (!strcmp(parameter, "stopVideo")) { emit(qtcamera->onStopCamera()); } + return true; + default: + return false; + } +} + +void System_SendMessage(const char *command, const char *parameter) { #if defined(SDL) - } else if (!strcmp(command, "audio_resetDevice")) { + if (!strcmp(command, "audio_resetDevice")) { StopSDLAudioDevice(); InitSDLAudioDevice(); -#endif } +#endif } void System_Toast(const char *text) {} diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index dec8285fe1..8af62f0988 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1051,6 +1051,16 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::BROWSE_FOR_FOLDER: PushCommand("browse_folder", StringFromFormat("%d", requestId)); return true; + + case SystemRequestType::CAMERA_COMMAND: + PushCommand("camera_command", param1); + break; + case SystemRequestType::GPS_COMMAND: + PushCommand("gps_command", param1); + break; + case SystemRequestType::MICROPHONE_COMMAND: + PushCommand("microphone_command", param1); + break; default: return false; } diff --git a/ios/main.mm b/ios/main.mm index b63b475b2e..44cd031cc0 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -180,21 +180,6 @@ void System_SendMessage(const char *command, const char *parameter) { if (!strcmp(command, "sharetext")) { NSString *text = [NSString stringWithUTF8String:parameter]; [sharedViewController shareText:text]; - } else if (!strcmp(command, "camera_command")) { - if (!strncmp(parameter, "startVideo", 10)) { - int width = 0, height = 0; - sscanf(parameter, "startVideo_%dx%d", &width, &height); - setCameraSize(width, height); - startVideo(); - } else if (!strcmp(parameter, "stopVideo")) { - stopVideo(); - } - } else if (!strcmp(command, "gps_command")) { - if (!strcmp(parameter, "open")) { - startLocation(); - } else if (!strcmp(parameter, "close")) { - stopLocation(); - } } else if (!strcmp(command, "safe_insets")) { float left, right, top, bottom; if (4 == sscanf(parameter, "%f:%f:%f:%f", &left, &right, &top, &bottom)) { @@ -242,8 +227,26 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string services.presentDirectoryPanel(callback, /* allowFiles = */ false, /* allowDirectories = */ true); return true; } + case SystemRequestType::CAMERA_COMMAND: + if (!strncmp(param1.c_str(), "startVideo", 10)) { + int width = 0, height = 0; + sscanf(param1.c_str(), "startVideo_%dx%d", &width, &height); + setCameraSize(width, height); + startVideo(); + } else if (!strcmp(param1.c_str(), "stopVideo")) { + stopVideo(); + } + return true; + case SystemRequestType::GPS_COMMAND: + if (param1 == "open") { + startLocation(); + } else if (param1 == "close")) { + stopLocation(); + } + return true; + default: + return false; } - return false; } void System_Toast(const char *text) {} From ac47476253d44e8660e4cb543f1168ae543f3846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 22:55:53 +0100 Subject: [PATCH 414/424] And share_text, toast, recreate --- Common/System/Request.h | 4 ++++ Common/System/System.h | 4 ++++ UI/ControlMappingScreen.cpp | 12 ++++++++++- UI/GameSettingsScreen.cpp | 16 ++------------ UI/MainScreen.cpp | 2 +- UI/MiscScreens.cpp | 3 ++- android/jni/app-android.cpp | 19 +++++++++++++---- .../src/org/ppsspp/ppsspp/NativeActivity.java | 13 +----------- ios/ViewController.mm | 8 +++---- ios/main.mm | 21 +++++++------------ 10 files changed, 51 insertions(+), 51 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index 4860588854..b42c96fc9e 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -112,3 +112,7 @@ inline void System_GPSCommand(const std::string &command) { inline void System_MicrophoneCommand(const std::string &command) { g_requestManager.MakeSystemRequest(SystemRequestType::MICROPHONE_COMMAND, nullptr, command, "", 0); } + +inline void System_ShareText(const std::string &text) { + g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, text, "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index 3f4c8e3f84..8c3774c342 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -71,6 +71,8 @@ enum class SystemRequestType { CAMERA_COMMAND, GPS_COMMAND, MICROPHONE_COMMAND, + + SHARE_TEXT, }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). @@ -175,6 +177,8 @@ enum class SystemNotification { BOOT_DONE, // this is sent from EMU thread! Make sure that Host handles it properly! SYMBOL_MAP_UPDATED, SWITCH_UMD_UPDATED, + ROTATE_UPDATED, + FORCE_RECREATE_ACTIVITY, }; std::string System_GetProperty(SystemProperty prop); diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index de04aef59a..5dbe5c4db6 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -718,7 +718,17 @@ void TouchTestScreen::render() { ui_context->Flush(); } -void RecreateActivity(); +void RecreateActivity() { + const int SYSTEM_JELLYBEAN = 16; + if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) { + INFO_LOG(SYSTEM, "Sending recreate"); + System_Notify(SystemNotification::FORCE_RECREATE_ACTIVITY); + INFO_LOG(SYSTEM, "Got back from recreate"); + } else { + auto gr = GetI18NCategory("Graphics"); + System_Toast(gr->T("Must Restart", "You must restart PPSSPP for this change to take effect")); + } +} UI::EventReturn TouchTestScreen::OnImmersiveModeChange(UI::EventParams &e) { System_SendMessage("immersive", ""); diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 50b47a5677..6d3004fe3a 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1193,23 +1193,11 @@ UI::EventReturn GameSettingsScreen::OnAutoFrameskip(UI::EventParams &e) { UI::EventReturn GameSettingsScreen::OnScreenRotation(UI::EventParams &e) { INFO_LOG(SYSTEM, "New display rotation: %d", g_Config.iScreenRotation); INFO_LOG(SYSTEM, "Sending rotate"); - System_SendMessage("rotate", ""); + System_Notify(SystemNotification::ROTATE_UPDATED); INFO_LOG(SYSTEM, "Got back from rotate"); return UI::EVENT_DONE; } -void RecreateActivity() { - const int SYSTEM_JELLYBEAN = 16; - if (System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= SYSTEM_JELLYBEAN) { - INFO_LOG(SYSTEM, "Sending recreate"); - System_SendMessage("recreate", ""); - INFO_LOG(SYSTEM, "Got back from recreate"); - } else { - auto gr = GetI18NCategory("Graphics"); - System_SendMessage("toast", gr->T("Must Restart", "You must restart PPSSPP for this change to take effect")); - } -} - UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) { auto n = GetI18NCategory("Networking"); System_LaunchUrl(LaunchUrlType::BROWSER_URL, n->T("MultiplayerHowToURL", "https://github.com/hrydgard/ppsspp/wiki/How-to-play-multiplayer-games-with-PPSSPP")); @@ -1348,7 +1336,7 @@ void GameSettingsScreen::onFinish(DialogResult result) { Reporting::Enable(enableReports_, "report.ppsspp.org"); Reporting::UpdateConfig(); if (!g_Config.Save("GameSettingsScreen::onFinish")) { - System_SendMessage("toast", "Failed to save settings!\nCheck permissions, or try to restart the device."); + System_Toast("Failed to save settings!\nCheck permissions, or try to restart the device."); } if (editThenRestore_) { diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 875d9c07b8..2fa799e9b7 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -1428,7 +1428,7 @@ UI::EventReturn MainScreen::OnForums(UI::EventParams &e) { UI::EventReturn MainScreen::OnExit(UI::EventParams &e) { // Let's make sure the config was saved, since it may not have been. if (!g_Config.Save("MainScreen::OnExit")) { - System_SendMessage("toast", "Failed to save settings!\nCheck permissions, or try to restart the device."); + System_Toast("Failed to save settings!\nCheck permissions, or try to restart the device."); } // Request the framework to exit cleanly. diff --git a/UI/MiscScreens.cpp b/UI/MiscScreens.cpp index d6a5c4fecc..84dbbbe80f 100644 --- a/UI/MiscScreens.cpp +++ b/UI/MiscScreens.cpp @@ -29,6 +29,7 @@ #include "Common/System/Display.h" #include "Common/System/NativeApp.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/Math/curves.h" #include "Common/File/VFS/VFS.h" @@ -872,7 +873,7 @@ UI::EventReturn CreditsScreen::OnDiscord(UI::EventParams &e) { UI::EventReturn CreditsScreen::OnShare(UI::EventParams &e) { auto cr = GetI18NCategory("PSPCredits"); - System_SendMessage("sharetext", cr->T("CheckOutPPSSPP", "Check out PPSSPP, the awesome PSP emulator: https://www.ppsspp.org/")); + System_ShareText(cr->T("CheckOutPPSSPP", "Check out PPSSPP, the awesome PSP emulator: https://www.ppsspp.org/")); return UI::EVENT_DONE; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 8af62f0988..a7e3747553 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -539,9 +539,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } } -void System_Notify(SystemNotification notification) { -} - std::string Android_GetInputDeviceDebugString() { if (!nativeActivity) { return "(N/A)"; @@ -1028,6 +1025,17 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_backbufferResize(JNIEnv } } +void System_Notify(SystemNotification notification) { + switch (notification) { + case SystemNotification::ROTATE_UPDATED: + PushCommand("rotate", ""); + break; + case SystemNotification::FORCE_RECREATE_ACTIVITY: + PushCommand("recreate", ""); + break; + } +} + bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::EXIT_APP: @@ -1061,6 +1069,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::MICROPHONE_COMMAND: PushCommand("microphone_command", param1); break; + case SystemRequestType::SHARE_TEXT: + PushCommand("share_text", param1); + break; default: return false; } @@ -1226,7 +1237,7 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessage(JNIEnv *env std::string msg = GetJavaString(env, message); std::string prm = GetJavaString(env, param); - // Some messages are caught by app-android. + // Some messages are caught by app-android. TODO: Should be all. if (msg == "moga") { mogaVersion = prm; } else if (msg == "permission_pending") { diff --git a/android/src/org/ppsspp/ppsspp/NativeActivity.java b/android/src/org/ppsspp/ppsspp/NativeActivity.java index 439f8a2b7a..d8e4622950 100644 --- a/android/src/org/ppsspp/ppsspp/NativeActivity.java +++ b/android/src/org/ppsspp/ppsspp/NativeActivity.java @@ -1403,18 +1403,7 @@ public abstract class NativeActivity extends Activity { Log.e(TAG, e.toString()); return false; } - } else if (command.equals("sharejpeg")) { - try { - Intent share = new Intent(Intent.ACTION_SEND); - share.setType("image/jpeg"); - share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + params)); - startActivity(Intent.createChooser(share, "Share Picture")); - return true; - } catch (Exception e) { // For example, android.content.ActivityNotFoundException - Log.e(TAG, e.toString()); - return false; - } - } else if (command.equals("sharetext")) { + } else if (command.equals("share_text")) { try { Intent sendIntent = new Intent(); sendIntent.setType("text/plain"); diff --git a/ios/ViewController.mm b/ios/ViewController.mm index 9c4ff956ff..a693dd771c 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -165,10 +165,10 @@ static LocationHelper *locationHelper; [super viewSafeAreaInsetsDidChange]; char safeArea[100]; // we use 0.0f instead of safeAreaInsets.bottom because the bottom overlay isn't disturbing (for now) - snprintf(safeArea, sizeof(safeArea), "%f:%f:%f:%f", - self.view.safeAreaInsets.left, self.view.safeAreaInsets.right, - self.view.safeAreaInsets.top, 0.0f); - System_SendMessage("safe_insets", safeArea); + g_safeInsetLeft = self.view.safeAreaInsets.left; + g_safeInsetRight = self.view.safeAreaInsets.right; + g_safeInsetTop = self.view.safeAreaInsets.top; + g_safeInsetBottom = 0.0f; } } diff --git a/ios/main.mm b/ios/main.mm index 44cd031cc0..a6a5ec4bf3 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -176,20 +176,7 @@ void System_Notify(SystemNotification notification) { } } -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "sharetext")) { - NSString *text = [NSString stringWithUTF8String:parameter]; - [sharedViewController shareText:text]; - } else if (!strcmp(command, "safe_insets")) { - float left, right, top, bottom; - if (4 == sscanf(parameter, "%f:%f:%f:%f", &left, &right, &top, &bottom)) { - g_safeInsetLeft = left; - g_safeInsetRight = right; - g_safeInsetTop = top; - g_safeInsetBottom = bottom; - } - } -} +void System_SendMessage(const char *command, const char *parameter) {} bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { @@ -244,6 +231,12 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string stopLocation(); } return true; + case SystemRequestType::SHARE_TEXT: + { + NSString *text = [NSString stringWithUTF8String:param1.c_str()]; + [sharedViewController shareText:text]; + return true; + } default: return false; } From 4c99712b6011f64689e803ffb5e550a29c9b2bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 23:15:08 +0100 Subject: [PATCH 415/424] And "immersive", "audio_resetDevice" --- Common/System/System.h | 2 ++ Qt/QtMain.cpp | 13 +++++-------- SDL/SDLMain.cpp | 12 ++++++------ UI/ControlMappingScreen.cpp | 2 +- UI/GameSettingsScreen.cpp | 4 ++-- android/jni/AndroidVulkanContext.cpp | 2 +- android/jni/app-android.cpp | 11 +++++++---- 7 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Common/System/System.h b/Common/System/System.h index 8c3774c342..4187358187 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -179,6 +179,8 @@ enum class SystemNotification { SWITCH_UMD_UPDATED, ROTATE_UPDATED, FORCE_RECREATE_ACTIVITY, + IMMERSIVE_MODE_CHANGE, + AUDIO_RESET_DEVICE, }; std::string System_GetProperty(SystemProperty prop); diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index b01acce6ba..0b256e3f19 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -271,6 +271,10 @@ void System_Notify(SystemNotification notification) { if (g_symbolMap) g_symbolMap->SortSymbols(); break; + case SystemNotification::AUDIO_RESET_DEVICE: + StopSDLAudioDevice(); + InitSDLAudioDevice(); + break; default: break; } @@ -380,14 +384,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } } -void System_SendMessage(const char *command, const char *parameter) { -#if defined(SDL) - if (!strcmp(command, "audio_resetDevice")) { - StopSDLAudioDevice(); - InitSDLAudioDevice(); - } -#endif -} +void System_SendMessage(const char *command, const char *parameter) {} void System_Toast(const char *text) {} void System_AskForPermission(SystemPermission permission) {} diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index f6defed98f..4042e77232 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -222,12 +222,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } } -void System_SendMessage(const char *command, const char *parameter) { - if (!strcmp(command, "audio_resetDevice")) { - StopSDLAudioDevice(); - InitSDLAudioDevice(); - } -} +void System_SendMessage(const char *command, const char *parameter) {} void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } @@ -469,6 +464,11 @@ bool System_GetPropertyBool(SystemProperty prop) { void System_Notify(SystemNotification notification) { switch (notification) { + case SystemNotification::AUDIO_RESET_DEVICE: + StopSDLAudioDevice(); + InitSDLAudioDevice(); + break; + default: break; } diff --git a/UI/ControlMappingScreen.cpp b/UI/ControlMappingScreen.cpp index 5dbe5c4db6..eba85e37bf 100644 --- a/UI/ControlMappingScreen.cpp +++ b/UI/ControlMappingScreen.cpp @@ -731,7 +731,7 @@ void RecreateActivity() { } UI::EventReturn TouchTestScreen::OnImmersiveModeChange(UI::EventParams &e) { - System_SendMessage("immersive", ""); + System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE); return UI::EVENT_DONE; } diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 6d3004fe3a..58eb2c68bd 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1205,7 +1205,7 @@ UI::EventReturn GameSettingsScreen::OnAdhocGuides(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnImmersiveModeChange(UI::EventParams &e) { - System_SendMessage("immersive", ""); + System_Notify(SystemNotification::IMMERSIVE_MODE_CHANGE); return UI::EVENT_DONE; } @@ -1547,7 +1547,7 @@ UI::EventReturn GameSettingsScreen::OnAudioDevice(UI::EventParams &e) { if (g_Config.sAudioDevice == a->T("Auto")) { g_Config.sAudioDevice.clear(); } - System_SendMessage("audio_resetDevice", ""); + System_Notify(SystemNotification::AUDIO_RESET_DEVICE); return UI::EVENT_DONE; } diff --git a/android/jni/AndroidVulkanContext.cpp b/android/jni/AndroidVulkanContext.cpp index 6d5693273e..d12832a7fe 100644 --- a/android/jni/AndroidVulkanContext.cpp +++ b/android/jni/AndroidVulkanContext.cpp @@ -85,7 +85,7 @@ bool AndroidVulkanContext::InitAPI() { INFO_LOG(G3D, "Creating Vulkan device"); if (g_Vulkan->CreateDevice() != VK_SUCCESS) { INFO_LOG(G3D, "Failed to create vulkan device: %s", g_Vulkan->InitError().c_str()); - System_SendMessage("toast", "No Vulkan driver found. Using OpenGL instead."); + System_Toast("No Vulkan driver found. Using OpenGL instead."); g_Vulkan->DestroyInstance(); delete g_Vulkan; g_Vulkan = nullptr; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index a7e3747553..b4f5892b03 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -1033,6 +1033,9 @@ void System_Notify(SystemNotification notification) { case SystemNotification::FORCE_RECREATE_ACTIVITY: PushCommand("recreate", ""); break; + case SystemNotification::IMMERSIVE_MODE_CHANGE: + PushCommand("immersive", ""); + break; } } @@ -1062,16 +1065,16 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::CAMERA_COMMAND: PushCommand("camera_command", param1); - break; + return true; case SystemRequestType::GPS_COMMAND: PushCommand("gps_command", param1); - break; + return true; case SystemRequestType::MICROPHONE_COMMAND: PushCommand("microphone_command", param1); - break; + return true; case SystemRequestType::SHARE_TEXT: PushCommand("share_text", param1); - break; + return true; default: return false; } From b440e28e3803a4b55044c759671f8683cfd0cee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 22 Mar 2023 23:25:00 +0100 Subject: [PATCH 416/424] Remove System_SendMessage! iOS, Qt buildfixes --- Common/System/Request.h | 4 ++++ Common/System/System.h | 5 ++--- Core/System.cpp | 3 ++- Qt/QtMain.cpp | 9 ++++----- SDL/SDLMain.cpp | 2 -- UI/EmuScreen.cpp | 7 ------- UI/GameSettingsScreen.cpp | 2 +- UI/MainScreen.cpp | 1 - UWP/PPSSPP_UWPMain.cpp | 2 -- Windows/main.cpp | 2 -- android/jni/app-android.cpp | 11 ++++++----- headless/Headless.cpp | 1 - ios/ViewController.mm | 5 +++++ ios/main.mm | 12 +++++------- libretro/libretro.cpp | 1 - unittest/JitHarness.cpp | 1 - 16 files changed, 29 insertions(+), 39 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index b42c96fc9e..9972ee4205 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -116,3 +116,7 @@ inline void System_MicrophoneCommand(const std::string &command) { inline void System_ShareText(const std::string &text) { g_requestManager.MakeSystemRequest(SystemRequestType::SHARE_TEXT, nullptr, text, "", 0); } + +inline void System_NotifyUIState(const std::string &state) { + g_requestManager.MakeSystemRequest(SystemRequestType::NOTIFY_UI_STATE, nullptr, state, "", 0); +} diff --git a/Common/System/System.h b/Common/System/System.h index 4187358187..795493ae44 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -73,6 +73,7 @@ enum class SystemRequestType { MICROPHONE_COMMAND, SHARE_TEXT, + NOTIFY_UI_STATE, // Used on Android only. Not a SystemNotification since it takes a parameter. }; // Implementations are supposed to process the request, and post the response to the g_RequestManager (see Message.h). @@ -82,9 +83,6 @@ enum class SystemRequestType { // Some requests don't use responses. bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3); -// TODO: To be separated into requests, see Request.h, and a way to post "UI messages". -void System_SendMessage(const char *command, const char *parameter); - PermissionStatus System_GetPermissionStatus(SystemPermission permission); void System_AskForPermission(SystemPermission permission); @@ -181,6 +179,7 @@ enum class SystemNotification { FORCE_RECREATE_ACTIVITY, IMMERSIVE_MODE_CHANGE, AUDIO_RESET_DEVICE, + SUSTAINED_PERF_CHANGE, }; std::string System_GetProperty(SystemProperty prop); diff --git a/Core/System.cpp b/Core/System.cpp index 71aacc931e..5a1c26b338 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -33,6 +33,7 @@ #include #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Common/File/Path.h" #include "Common/Math/math_util.h" #include "Common/Thread/ThreadUtil.h" @@ -134,7 +135,7 @@ void UpdateUIState(GlobalUIState newState) { case UISTATE_EXCEPTION: state = "exception"; break; } if (state) { - System_SendMessage("uistate", state); + System_NotifyUIState(state); } } } diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index 0b256e3f19..c165914bba 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -343,7 +343,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string qApp->exit(0); return true; case SystemRequestType::COPY_TO_CLIPBOARD: - QApplication::clipboard()->setText(parameter); + QApplication::clipboard()->setText(param1.c_str()); return true; case SystemRequestType::INPUT_TEXT_MODAL: { @@ -371,11 +371,11 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string QCoreApplication::postEvent(emugl, new QEvent((QEvent::Type)browseFolderEvent)); return true; case SystemRequestType::CAMERA_COMMAND: - if (!strncmp(parameter, "startVideo", 10)) { + if (!strncmp(param1.c_str(), "startVideo", 10)) { int width = 0, height = 0; - sscanf(parameter, "startVideo_%dx%d", &width, &height); + sscanf(param1.c_str(), "startVideo_%dx%d", &width, &height); emit(qtcamera->onStartCamera(width, height)); - } else if (!strcmp(parameter, "stopVideo")) { + } else if (param1 == "stopVideo") { emit(qtcamera->onStopCamera()); } return true; @@ -384,7 +384,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } } -void System_SendMessage(const char *command, const char *parameter) {} void System_Toast(const char *text) {} void System_AskForPermission(SystemPermission permission) {} diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 4042e77232..8aadab0be5 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -222,8 +222,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } } -void System_SendMessage(const char *command, const char *parameter) {} - void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index b367e3b067..19b17a7a46 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -211,7 +211,6 @@ bool EmuScreen::bootAllowStorage(const Path &filename) { case PERMISSION_STATUS_DENIED: stopRender_ = true; screenManager()->switchScreen(new MainScreen()); - System_SendMessage("event", "failstartgame"); return false; case PERMISSION_STATUS_PENDING: @@ -244,7 +243,6 @@ void EmuScreen::bootGame(const Path &filename) { if (invalid_) { errorMessage_ = error_string; ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); - System_SendMessage("event", "failstartgame"); return; } bootComplete(); @@ -329,7 +327,6 @@ void EmuScreen::bootGame(const Path &filename) { invalid_ = true; errorMessage_ = error_string; ERROR_LOG(BOOT, "%s", errorMessage_.c_str()); - System_SendMessage("event", "failstartgame"); } if (PSP_CoreParameter().compat.flags().RequireBufferedRendering && g_Config.bSkipBufferEffects) { @@ -393,8 +390,6 @@ void EmuScreen::bootComplete() { #endif } - System_SendMessage("event", "startgame"); - saveStateSlot_ = SaveState::GetCurrentSlot(); loadingViewColor_->Divert(0x00FFFFFF, 0.2f); @@ -430,7 +425,6 @@ void EmuScreen::dialogFinished(const Screen *dialog, DialogResult result) { // DR_YES means a message sent to PauseMenu by NativeMessageReceived. if (result == DR_OK || quit_) { screenManager()->switchScreen(new MainScreen()); - System_SendMessage("event", "exitgame"); quit_ = false; } // Returning to the PauseScreen, unless we're stepping, means we should go back to controls. @@ -473,7 +467,6 @@ void EmuScreen::sendMessage(const char *message, const char *value) { ERROR_LOG(LOADER, "Error resetting: %s", resetError.c_str()); stopRender_ = true; screenManager()->switchScreen(new MainScreen()); - System_SendMessage("event", "failstartgame"); return; } } else if (!strcmp(message, "boot")) { diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 58eb2c68bd..eba83997d1 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1210,7 +1210,7 @@ UI::EventReturn GameSettingsScreen::OnImmersiveModeChange(UI::EventParams &e) { } UI::EventReturn GameSettingsScreen::OnSustainedPerformanceModeChange(UI::EventParams &e) { - System_SendMessage("sustainedPerfMode", ""); + System_Notify(SystemNotification::SUSTAINED_PERF_CHANGE); return UI::EVENT_DONE; } diff --git a/UI/MainScreen.cpp b/UI/MainScreen.cpp index 2fa799e9b7..d5baa80ef1 100644 --- a/UI/MainScreen.cpp +++ b/UI/MainScreen.cpp @@ -980,7 +980,6 @@ UI::EventReturn GameBrowser::OnHomebrewStore(UI::EventParams &e) { } MainScreen::MainScreen() { - System_SendMessage("event", "mainscreen"); g_BackgroundAudio.SetGame(Path()); } diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index 0af1409d3d..f78a8e0787 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -507,8 +507,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } } -void System_SendMessage(const char *command, const char *parameter) {} - void System_ShowFileInFolder(const char *path) { // Unsupported } diff --git a/Windows/main.cpp b/Windows/main.cpp index 057522fc68..9b6f19df4f 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -565,8 +565,6 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string } } -void System_SendMessage(const char *command, const char *parameter) {} - void System_AskForPermission(SystemPermission permission) {} PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; } diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index b4f5892b03..dc114d850c 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -401,11 +401,6 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url) { } } -void System_SendMessage(const char *command, const char *parameter) { - // TODO: Using sendmessage this way is deprecated. - PushCommand(command, parameter); -} - std::string System_GetProperty(SystemProperty prop) { switch (prop) { case SYSPROP_NAME: @@ -1036,6 +1031,9 @@ void System_Notify(SystemNotification notification) { case SystemNotification::IMMERSIVE_MODE_CHANGE: PushCommand("immersive", ""); break; + case SystemNotification::SUSTAINED_PERF_CHANGE: + PushCommand("sustainedPerfMode", ""); + break; } } @@ -1075,6 +1073,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::SHARE_TEXT: PushCommand("share_text", param1); return true; + case SystemRequestType::NOTIFY_UI_STATE: + PushCommand("uistate", param1); + return true; default: return false; } diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 137b3ae1f3..c085bab344 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -115,7 +115,6 @@ bool System_GetPropertyBool(SystemProperty prop) { } } void System_Notify(SystemNotification notification) {} -void System_SendMessage(const char *command, const char *parameter) {} bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} diff --git a/ios/ViewController.mm b/ios/ViewController.mm index a693dd771c..49f8a011dd 100644 --- a/ios/ViewController.mm +++ b/ios/ViewController.mm @@ -160,6 +160,11 @@ static LocationHelper *locationHelper; }); } +extern float g_safeInsetLeft; +extern float g_safeInsetRight; +extern float g_safeInsetTop; +extern float g_safeInsetBottom; + - (void)viewSafeAreaInsetsDidChange { if (@available(iOS 11.0, *)) { [super viewSafeAreaInsetsDidChange]; diff --git a/ios/main.mm b/ios/main.mm index a6a5ec4bf3..e90b60e8a1 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -89,10 +89,10 @@ void *exception_handler(void *argument) { return NULL; } -static float g_safeInsetLeft = 0.0; -static float g_safeInsetRight = 0.0; -static float g_safeInsetTop = 0.0; -static float g_safeInsetBottom = 0.0; +float g_safeInsetLeft = 0.0; +float g_safeInsetRight = 0.0; +float g_safeInsetTop = 0.0; +float g_safeInsetBottom = 0.0; // We no longer need to judge if jit is usable or not by according to the ios version. /* @@ -176,8 +176,6 @@ void System_Notify(SystemNotification notification) { } } -void System_SendMessage(const char *command, const char *parameter) {} - bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { switch (type) { case SystemRequestType::EXIT_APP: @@ -227,7 +225,7 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case SystemRequestType::GPS_COMMAND: if (param1 == "open") { startLocation(); - } else if (param1 == "close")) { + } else if (param1 == "close") { stopLocation(); } return true; diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp index 2289b1fb97..dea29a92a9 100644 --- a/libretro/libretro.cpp +++ b/libretro/libretro.cpp @@ -1875,7 +1875,6 @@ void System_Notify(SystemNotification notification) { } } bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } -void System_SendMessage(const char *command, const char *parameter) {} void NativeUpdate() {} void NativeRender(GraphicsContext *graphicsContext) {} void NativeResized() {} diff --git a/unittest/JitHarness.cpp b/unittest/JitHarness.cpp index d578c0af13..18518360f6 100644 --- a/unittest/JitHarness.cpp +++ b/unittest/JitHarness.cpp @@ -41,7 +41,6 @@ void NativeUpdate() { } void NativeRender(GraphicsContext *graphicsContext) { } void NativeResized() { } -void System_SendMessage(const char *command, const char *parameter) {} bool System_MakeRequest(SystemRequestType type, int requestId, const std::string ¶m1, const std::string ¶m2, int param3) { return false; } void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function cb) { cb(false, ""); } void System_AskForPermission(SystemPermission permission) {} From d8986af3673248cfd7a48931564db9551fb048dd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 22 Mar 2023 22:51:00 -0700 Subject: [PATCH 417/424] headless: Avoid ugly casts. --- headless/Headless.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/headless/Headless.cpp b/headless/Headless.cpp index 27e0508e64..f84034af76 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -413,7 +413,7 @@ int main(int argc, const char* argv[]) std::string error_string; GraphicsContext *graphicsContext = nullptr; - bool glWorking = ((HeadlessHost *)host)->InitGraphics(&error_string, &graphicsContext, gpuCore); + bool glWorking = headlessHost->InitGraphics(&error_string, &graphicsContext, gpuCore); CoreParameter coreParameter; coreParameter.cpuCore = cpuCore; @@ -577,7 +577,7 @@ int main(int argc, const char* argv[]) ShutdownWebServer(); } - ((HeadlessHost *)host)->ShutdownGraphics(); + headlessHost->ShutdownGraphics(); delete host; host = nullptr; headlessHost = nullptr; From 3a9e66ab604084b878e165e261de345160c72fbd Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Wed, 22 Mar 2023 22:54:24 -0700 Subject: [PATCH 418/424] Build: Unrevert glslang update. Revert unintentional rollback in 47f06355, reapplying 858675e4. --- ext/glslang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/glslang b/ext/glslang index 77551c429f..b34f619e1c 160000 --- a/ext/glslang +++ b/ext/glslang @@ -1 +1 @@ -Subproject commit 77551c429f86c0e077f26552b7c1c0f12a9f235e +Subproject commit b34f619e1c85810dcb3c578107d2e48ba4ee2b37 From ac66deeb25e03e562f17d475c59d9fad2f336e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 16 Feb 2023 19:01:13 +0100 Subject: [PATCH 419/424] Improve cheats UX --- Common/UI/View.h | 8 +++--- UI/CwCheatScreen.cpp | 66 ++++++++++++++++++++++++++++++++++---------- UI/CwCheatScreen.h | 8 +++++- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/Common/UI/View.h b/Common/UI/View.h index c50a335151..f857d837ae 100644 --- a/Common/UI/View.h +++ b/Common/UI/View.h @@ -741,10 +741,10 @@ protected: std::string smallText_; ImageID image_; // Centered if no text, on the left if text. ImageID rightIconImage_ = ImageID::invalid(); // Shows in the right. - float rightIconScale_; - float rightIconRot_; - bool rightIconFlipH_; - bool rightIconKeepColor_; + float rightIconScale_ = 0.0f; + float rightIconRot_ = 0.0f; + bool rightIconFlipH_ = false; + bool rightIconKeepColor_ = false; Padding textPadding_; bool centered_ = false; float imgScale_ = 1.0f; diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index a8f0c9a70f..184a7233a0 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -34,6 +34,10 @@ static const int FILE_CHECK_FRAME_INTERVAL = 53; +static Path GetGlobalCheatFile() { + return GetSysDirectory(DIRECTORY_CHEATS) / "cheat.db"; +} + CwCheatScreen::CwCheatScreen(const Path &gamePath) : UIDialogScreenWithGameBackground(gamePath) { } @@ -53,7 +57,7 @@ void CwCheatScreen::LoadCheatInfo() { gameID = g_paramSFO.GenerateFakeID(gamePath_.ToString()); } - if (engine_ == nullptr || gameID != gameID_) { + if (!engine_ || gameID != gameID_) { gameID_ = gameID; delete engine_; engine_ = new CWCheatEngine(gameID_); @@ -77,6 +81,7 @@ void CwCheatScreen::CreateViews() { using namespace UI; auto cw = GetI18NCategory("CwCheats"); auto di = GetI18NCategory("Dialog"); + auto mm = GetI18NCategory("MainMenu"); root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT)); @@ -84,9 +89,15 @@ void CwCheatScreen::CreateViews() { Margins actionMenuMargins(50, -15, 15, 0); LinearLayout *leftColumn = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(400, FILL_PARENT)); - leftColumn->Add(new ItemHeader(cw->T("Options"))); //leftColumn->Add(new Choice(cw->T("Add Cheat")))->OnClick.Handle(this, &CwCheatScreen::OnAddCheat); - leftColumn->Add(new Choice(cw->T("Import Cheats")))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat); + leftColumn->Add(new ItemHeader(cw->T("Import Cheats"))); + + Path cheatPath = GetGlobalCheatFile(); + + leftColumn->Add(new Choice(cheatPath.ToVisualString()))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat); + leftColumn->Add(new Choice(mm->T("Browse"), ImageID("I_FOLDER_OPEN")))->OnClick.Handle(this, &CwCheatScreen::OnImportBrowse); + + leftColumn->Add(new ItemHeader(cw->T("Options"))); #if !defined(MOBILE_DEVICE) leftColumn->Add(new Choice(cw->T("Edit Cheat File")))->OnClick.Handle(this, &CwCheatScreen::OnEditCheatFile); #endif @@ -141,6 +152,21 @@ void CwCheatScreen::onFinish(DialogResult result) { } } +void CwCheatScreen::sendMessage(const char *message, const char *value) { + // Always call the base class method first to handle the most common messages. + UIDialogScreenWithGameBackground::sendMessage(message, value); + if (!strcmp(message, "browse_fileSelect")) { + Path path(value); + INFO_LOG(SYSTEM, "Attempting to load cheats from: '%s'", path.ToVisualString().c_str()); + if (ImportCheats(path)) { + g_Config.bReloadCheats = true; + } else { + // Show an error message? + } + RecreateViews(); + } +} + UI::EventReturn CwCheatScreen::OnEnableAll(UI::EventParams ¶ms) { enableAllFlag_ = !enableAllFlag_; @@ -193,24 +219,39 @@ static char *GetLineNoNewline(char *temp, int sz, FILE *fp) { return line; } +UI::EventReturn CwCheatScreen::OnImportBrowse(UI::EventParams ¶ms) { + System_SendMessage("browse_file", ""); + return UI::EVENT_DONE; +} + UI::EventReturn CwCheatScreen::OnImportCheat(UI::EventParams ¶ms) { - if (gameID_.length() != 9 || !engine_) { - WARN_LOG(COMMON, "CWCHEAT: Incorrect ID(%s) - can't import cheats.", gameID_.c_str()); + if (!ImportCheats(GetGlobalCheatFile())) { + // Show an error message? return UI::EVENT_DONE; } - std::vector title; - std::vector newList; - Path cheatFile = GetSysDirectory(DIRECTORY_CHEATS) / "cheat.db"; + g_Config.bReloadCheats = true; + RecreateViews(); + return UI::EVENT_DONE; +} + +bool CwCheatScreen::ImportCheats(const Path & cheatFile) { + if (gameID_.length() != 9 || !engine_) { + WARN_LOG(COMMON, "CWCHEAT: Incorrect ID(%s) - can't import cheats.", gameID_.c_str()); + return false; + } + std::string gameID = StringFromFormat("_S %s-%s", gameID_.substr(0, 4).c_str(), gameID_.substr(4).c_str()); FILE *in = File::OpenCFile(cheatFile, "rt"); - if (!in) { WARN_LOG(COMMON, "Unable to open %s\n", cheatFile.c_str()); - return UI::EVENT_SKIPPED; + return false; } + std::vector title; + std::vector newList; + char linebuf[2048]{}; bool parseGameEntry = false; bool parseCheatEntry = false; @@ -281,10 +322,7 @@ UI::EventReturn CwCheatScreen::OnImportCheat(UI::EventParams ¶ms) { } } fclose(append); - - g_Config.bReloadCheats = true; - RecreateViews(); - return UI::EVENT_DONE; + return true; } UI::EventReturn CwCheatScreen::OnCheckBox(int index) { diff --git a/UI/CwCheatScreen.h b/UI/CwCheatScreen.h index b343cbd818..d29961a2e6 100644 --- a/UI/CwCheatScreen.h +++ b/UI/CwCheatScreen.h @@ -35,9 +35,12 @@ public: UI::EventReturn OnAddCheat(UI::EventParams ¶ms); UI::EventReturn OnImportCheat(UI::EventParams ¶ms); + UI::EventReturn OnImportBrowse(UI::EventParams ¶ms); UI::EventReturn OnEditCheatFile(UI::EventParams ¶ms); UI::EventReturn OnEnableAll(UI::EventParams ¶ms); + void sendMessage(const char *message, const char *value) override; + void update() override; void onFinish(DialogResult result) override; @@ -48,16 +51,19 @@ protected: private: UI::EventReturn OnCheckBox(int index); + bool ImportCheats(const Path &cheatFile); enum { INDEX_ALL = -1 }; bool HasCheatWithName(const std::string &name); bool RebuildCheatFile(int index); UI::ScrollView *rightScroll_ = nullptr; + UI::TextView *errorMessageView_ = nullptr; + CWCheatEngine *engine_ = nullptr; std::vector fileInfo_; std::string gameID_; int fileCheckCounter_ = 0; - uint64_t fileCheckHash_; + uint64_t fileCheckHash_ = 0; bool enableAllFlag_ = false; }; From e21867315b7a07287aaf12edeaf75d3f5ad207e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Mar 2023 01:16:12 +0100 Subject: [PATCH 420/424] Fix browsing for Cheat DB files. Easy now after the refactor! --- Common/System/Request.h | 1 + Qt/QtMain.cpp | 3 +++ UI/CwCheatScreen.cpp | 28 ++++++++++++---------------- UI/CwCheatScreen.h | 2 -- UWP/PPSSPP_UWPMain.cpp | 3 +++ Windows/main.cpp | 3 +++ 6 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Common/System/Request.h b/Common/System/Request.h index 9972ee4205..745f4eb555 100644 --- a/Common/System/Request.h +++ b/Common/System/Request.h @@ -69,6 +69,7 @@ enum class BrowseFileType { BOOTABLE, IMAGE, INI, + DB, ANY, }; diff --git a/Qt/QtMain.cpp b/Qt/QtMain.cpp index c165914bba..02f2e91fc4 100644 --- a/Qt/QtMain.cpp +++ b/Qt/QtMain.cpp @@ -300,6 +300,9 @@ bool MainUI::HandleCustomEvent(QEvent *e) { case BrowseFileType::INI: filter = "INI files (*.ini)"; break; + case BrowseFileType::DB: + filter = "DB files (*.db)"; + break; case BrowseFileType::ANY: break; } diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index 184a7233a0..c84f320ba4 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -24,6 +24,7 @@ #include "Common/File/FileUtil.h" #include "Common/StringUtils.h" #include "Common/System/System.h" +#include "Common/System/Request.h" #include "Core/Core.h" #include "Core/Config.h" #include "Core/CwCheat.h" @@ -152,21 +153,6 @@ void CwCheatScreen::onFinish(DialogResult result) { } } -void CwCheatScreen::sendMessage(const char *message, const char *value) { - // Always call the base class method first to handle the most common messages. - UIDialogScreenWithGameBackground::sendMessage(message, value); - if (!strcmp(message, "browse_fileSelect")) { - Path path(value); - INFO_LOG(SYSTEM, "Attempting to load cheats from: '%s'", path.ToVisualString().c_str()); - if (ImportCheats(path)) { - g_Config.bReloadCheats = true; - } else { - // Show an error message? - } - RecreateViews(); - } -} - UI::EventReturn CwCheatScreen::OnEnableAll(UI::EventParams ¶ms) { enableAllFlag_ = !enableAllFlag_; @@ -220,7 +206,17 @@ static char *GetLineNoNewline(char *temp, int sz, FILE *fp) { } UI::EventReturn CwCheatScreen::OnImportBrowse(UI::EventParams ¶ms) { - System_SendMessage("browse_file", ""); + System_BrowseForFile("Open cheat DB file", BrowseFileType::DB, [&](const std::string &value, int) { + Path path(value); + INFO_LOG(SYSTEM, "Attempting to load cheats from: '%s'", path.ToVisualString().c_str()); + if (ImportCheats(path)) { + g_Config.bReloadCheats = true; + } else { + // Show an error message? + } + RecreateViews(); + // Chose a cheat file. + }); return UI::EVENT_DONE; } diff --git a/UI/CwCheatScreen.h b/UI/CwCheatScreen.h index d29961a2e6..fd82040993 100644 --- a/UI/CwCheatScreen.h +++ b/UI/CwCheatScreen.h @@ -39,8 +39,6 @@ public: UI::EventReturn OnEditCheatFile(UI::EventParams ¶ms); UI::EventReturn OnEnableAll(UI::EventParams ¶ms); - void sendMessage(const char *message, const char *value) override; - void update() override; void onFinish(DialogResult result) override; diff --git a/UWP/PPSSPP_UWPMain.cpp b/UWP/PPSSPP_UWPMain.cpp index f78a8e0787..c469029c76 100644 --- a/UWP/PPSSPP_UWPMain.cpp +++ b/UWP/PPSSPP_UWPMain.cpp @@ -468,6 +468,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case BrowseFileType::INI: picker->FileTypeFilter->Append(".ini"); break; + case BrowseFileType::DB: + picker->FileTypeFilter->Append(".db"); + break; case BrowseFileType::ANY: picker->FileTypeFilter->Append("*"); break; diff --git a/Windows/main.cpp b/Windows/main.cpp index 9b6f19df4f..929abafdc8 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -509,6 +509,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string case BrowseFileType::INI: filter = MakeFilter(L"Ini files (*.ini)|*.ini|All files (*.*)|*.*||"); break; + case BrowseFileType::DB: + filter = MakeFilter(L"Cheat db files (*.db)|*.db|All files (*.*)|*.*||"); + break; case BrowseFileType::ANY: filter = MakeFilter(L"All files (*.*)|*.*||"); break; From f5afc91f2312e82687b7652fbe625717340dea31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Mar 2023 10:32:11 +0100 Subject: [PATCH 421/424] Change Enable/Disable All to just a Disable All button. --- Common/File/Path.cpp | 26 ++++++++++++++++++++++++-- Common/File/Path.h | 3 ++- UI/CwCheatScreen.cpp | 26 ++++++++++++++------------ UI/CwCheatScreen.h | 2 +- 4 files changed, 41 insertions(+), 16 deletions(-) diff --git a/Common/File/Path.cpp b/Common/File/Path.cpp index 489ab692b4..71a795d683 100644 --- a/Common/File/Path.cpp +++ b/Common/File/Path.cpp @@ -255,12 +255,34 @@ std::wstring Path::ToWString() const { } #endif -std::string Path::ToVisualString() const { +std::string Path::ToVisualString(const char *relativeRoot) const { if (type_ == PathType::CONTENT_URI) { return AndroidContentURI(path_).ToVisualString(); #if PPSSPP_PLATFORM(WINDOWS) } else if (type_ == PathType::NATIVE) { - return ReplaceAll(path_, "/", "\\"); + // It can be useful to show the path as relative to the memstick + if (relativeRoot) { + std::string root = ReplaceAll(relativeRoot, "/", "\\"); + std::string path = ReplaceAll(path_, "/", "\\"); + if (startsWithNoCase(path, root)) { + return path.substr(root.size()); + } else { + return path; + } + } else { + return ReplaceAll(path_, "/", "\\"); + } +#else + if (relativeRoot) { + std::string root = relativeRoot; + if (startsWithNoCase(path_, root)) { + return path_.substr(root.size()); + } else { + return path_; + } + } else { + return path_; + } #endif } else { return path_; diff --git a/Common/File/Path.h b/Common/File/Path.h index b66471c53e..ac93f9a9b8 100644 --- a/Common/File/Path.h +++ b/Common/File/Path.h @@ -92,7 +92,8 @@ public: std::wstring ToWString() const; #endif - std::string ToVisualString() const; + // Pass in a relative root to turn the path into a relative path - if it is one! + std::string ToVisualString(const char *relativeRoot = nullptr) const; bool CanNavigateUp() const; Path NavigateUp() const; diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index c84f320ba4..d6d3636bd7 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -35,7 +35,7 @@ static const int FILE_CHECK_FRAME_INTERVAL = 53; -static Path GetGlobalCheatFile() { +static Path GetGlobalCheatFilePath() { return GetSysDirectory(DIRECTORY_CHEATS) / "cheat.db"; } @@ -93,16 +93,20 @@ void CwCheatScreen::CreateViews() { //leftColumn->Add(new Choice(cw->T("Add Cheat")))->OnClick.Handle(this, &CwCheatScreen::OnAddCheat); leftColumn->Add(new ItemHeader(cw->T("Import Cheats"))); - Path cheatPath = GetGlobalCheatFile(); + Path cheatPath = GetGlobalCheatFilePath(); - leftColumn->Add(new Choice(cheatPath.ToVisualString()))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat); + std::string root = GetSysDirectory(DIRECTORY_MEMSTICK_ROOT).ToString(); + + leftColumn->Add(new Choice(cheatPath.ToVisualString(root.c_str())))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat); leftColumn->Add(new Choice(mm->T("Browse"), ImageID("I_FOLDER_OPEN")))->OnClick.Handle(this, &CwCheatScreen::OnImportBrowse); + errorMessageView_ = leftColumn->Add(new TextView(di->T("LoadingFailed"))); + errorMessageView_->SetVisibility(V_GONE); - leftColumn->Add(new ItemHeader(cw->T("Options"))); + leftColumn->Add(new ItemHeader(di->T("Options"))); #if !defined(MOBILE_DEVICE) leftColumn->Add(new Choice(cw->T("Edit Cheat File")))->OnClick.Handle(this, &CwCheatScreen::OnEditCheatFile); #endif - leftColumn->Add(new Choice(cw->T("Enable/Disable All")))->OnClick.Handle(this, &CwCheatScreen::OnEnableAll); + leftColumn->Add(new Choice(di->T("Disable All")))->OnClick.Handle(this, &CwCheatScreen::OnDisableAll); leftColumn->Add(new PopupSliderChoice(&g_Config.iCwCheatRefreshRate, 1, 1000, cw->T("Refresh Rate"), 1, screenManager())); rightScroll_ = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT, 0.5f)); @@ -153,12 +157,10 @@ void CwCheatScreen::onFinish(DialogResult result) { } } -UI::EventReturn CwCheatScreen::OnEnableAll(UI::EventParams ¶ms) { - enableAllFlag_ = !enableAllFlag_; - - // Flip all the switches. +UI::EventReturn CwCheatScreen::OnDisableAll(UI::EventParams ¶ms) { + // Disable all the switches. for (auto &info : fileInfo_) { - info.enabled = enableAllFlag_; + info.enabled = false; } if (!RebuildCheatFile(INDEX_ALL)) { @@ -215,14 +217,14 @@ UI::EventReturn CwCheatScreen::OnImportBrowse(UI::EventParams ¶ms) { // Show an error message? } RecreateViews(); - // Chose a cheat file. }); return UI::EVENT_DONE; } UI::EventReturn CwCheatScreen::OnImportCheat(UI::EventParams ¶ms) { - if (!ImportCheats(GetGlobalCheatFile())) { + if (!ImportCheats(GetGlobalCheatFilePath())) { // Show an error message? + errorMessageView_->SetVisibility(UI::V_VISIBLE); return UI::EVENT_DONE; } diff --git a/UI/CwCheatScreen.h b/UI/CwCheatScreen.h index fd82040993..7a7578c76e 100644 --- a/UI/CwCheatScreen.h +++ b/UI/CwCheatScreen.h @@ -37,7 +37,7 @@ public: UI::EventReturn OnImportCheat(UI::EventParams ¶ms); UI::EventReturn OnImportBrowse(UI::EventParams ¶ms); UI::EventReturn OnEditCheatFile(UI::EventParams ¶ms); - UI::EventReturn OnEnableAll(UI::EventParams ¶ms); + UI::EventReturn OnDisableAll(UI::EventParams ¶ms); void update() override; void onFinish(DialogResult result) override; From 4475533c0b159b05922fc0b3f35d26e1c0c4b198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Mar 2023 10:32:27 +0100 Subject: [PATCH 422/424] Remove redundant translation strings --- assets/lang/ar_AE.ini | 2 -- assets/lang/az_AZ.ini | 2 -- assets/lang/bg_BG.ini | 2 -- assets/lang/ca_ES.ini | 2 -- assets/lang/cz_CZ.ini | 2 -- assets/lang/da_DK.ini | 2 -- assets/lang/de_DE.ini | 2 -- assets/lang/dr_ID.ini | 2 -- assets/lang/en_US.ini | 2 -- assets/lang/es_ES.ini | 2 -- assets/lang/es_LA.ini | 2 -- assets/lang/fa_IR.ini | 2 -- assets/lang/fi_FI.ini | 2 -- assets/lang/fr_FR.ini | 2 -- assets/lang/gl_ES.ini | 2 -- assets/lang/gr_EL.ini | 2 -- assets/lang/he_IL.ini | 2 -- assets/lang/he_IL_invert.ini | 2 -- assets/lang/hr_HR.ini | 2 -- assets/lang/hu_HU.ini | 2 -- assets/lang/id_ID.ini | 2 -- assets/lang/it_IT.ini | 2 -- assets/lang/ja_JP.ini | 2 -- assets/lang/jv_ID.ini | 2 -- assets/lang/ko_KR.ini | 2 -- assets/lang/lo_LA.ini | 2 -- assets/lang/lt-LT.ini | 2 -- assets/lang/ms_MY.ini | 2 -- assets/lang/nl_NL.ini | 2 -- assets/lang/no_NO.ini | 2 -- assets/lang/pl_PL.ini | 2 -- assets/lang/pt_BR.ini | 2 -- assets/lang/pt_PT.ini | 2 -- assets/lang/ro_RO.ini | 2 -- assets/lang/ru_RU.ini | 2 -- assets/lang/sv_SE.ini | 2 -- assets/lang/tg_PH.ini | 2 -- assets/lang/th_TH.ini | 2 -- assets/lang/tr_TR.ini | 2 -- assets/lang/uk_UA.ini | 2 -- assets/lang/vi_VN.ini | 2 -- assets/lang/zh_CN.ini | 2 -- assets/lang/zh_TW.ini | 2 -- 43 files changed, 86 deletions(-) diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index 461295a85a..c360e6eb11 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -116,9 +116,7 @@ Y = Y [CwCheats] Cheats = ‎الشفرات Edit Cheat File = ‎عدل ملف الشفرة -Enable/Disable All = ‎تمكين/تعطيل كل الشفرات Import Cheats = ‎إستورد من cheat.db -Options = ‎إعدادات Refresh Rate = ‎معدل التحديث [DesktopUI] diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index e8a197072a..2648673730 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Edit cheat file -Enable/Disable All = Enable/Disable all Cheats Import Cheats = Import from cheat.db -Options = Options Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index 35774afa64..c68fac507b 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Чийтове Edit Cheat File = Edit cheat file -Enable/Disable All = Включи/Изключи всички чийтове Import Cheats = Внеси от cheat.db -Options = Опции Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 03bf12572d..ebdbcae8b5 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Trucs Edit Cheat File = Editar el fitxer de trucs -Enable/Disable All = Activar/desactivar tots els trucs Import Cheats = Importar «cheat.db» -Options = Opcions Refresh Rate = Freqüència de refrescament [DesktopUI] diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 6052de0562..89bd7f46a5 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheaty Edit Cheat File = Upravit soubor s cheaty -Enable/Disable All = Povolit/Zakázat všechny cheaty Import Cheats = Importovat z cheat.db -Options = Nastavení Refresh Rate = Frekvence obnoveni [DesktopUI] diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 6fa8bf2e34..8a69c7578b 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Snyd Edit Cheat File = Editer snydefil -Enable/Disable All = Aktiver/Deaktiver alle snyd Import Cheats = Importer fra cheat.db -Options = Optioner Refresh Rate = Opdateringsrate [DesktopUI] diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index cf78feb4b9..5fed08040e 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Cheatdatei ändern -Enable/Disable All = Alle de- oder aktivieren Import Cheats = Cheats importieren (aus cheat.db) -Options = Optionen Refresh Rate = Wiederholfrequenz [DesktopUI] diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 4226051826..848585f5fa 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheat Edit Cheat File = Edit cheat file -Enable/Disable All = Pajalan/Bosian nasan Cheat Import Cheats = Patamanni cheat.db -Options = Pangpillean Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 8b2c8715d0..2718fbdb3c 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -132,9 +132,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Edit cheat file -Enable/Disable All = Enable/Disable all Cheats Import Cheats = Import from cheat.db -Options = Options Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 7dffaf6552..c3212ec6f6 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Trucos Edit Cheat File = Editar archivo de trucos -Enable/Disable All = Activar/desactivar todos los trucos Import Cheats = Importar archivo cheat.db -Options = Opciones Refresh Rate = Frecuencia de actualización [DesktopUI] diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index c537e9566c..129b2e5175 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = trucos Edit Cheat File = Editar archivo de trucos -Enable/Disable All = Activar/desactivar todos los trucos Import Cheats = Importar archivo cheat.db -Options = Opciones Refresh Rate = Frecuencia de actualización [DesktopUI] diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 92ff1b406c..1656074114 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = ‎کد های تقلب Edit Cheat File = ‎ویرایش فایل کد ها -Enable/Disable All = ‎فعال/غیرفعال کردن همه ی کدهای تقلب Import Cheats = ‎cheat.db وارد کردن از -Options = ‎تنظیمات Refresh Rate = بازیابی نرخ [DesktopUI] diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 5c62718b08..15c8360a4f 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Huijaukset Edit Cheat File = Muokkaa huijaus tiedostoa -Enable/Disable All = Ota/Poista käytöstä kaikki huijaukset Import Cheats = Tuo huijauksia -Options = Asetukset Refresh Rate = Ruudunpäivitysnopeus [DesktopUI] diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index e2eb49f59b..ccc4ffad56 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -108,9 +108,7 @@ Y = Axe Y [CwCheats] Cheats = Codes de triche Edit Cheat File = Modifier le fichier de triche -Enable/Disable All = Tout activer/désactiver Import Cheats = Importer des codes de triche -Options = Options Refresh Rate = Taux de rafraîchissement [DesktopUI] diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 11ef02432c..a733b6a84e 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Trucos Edit Cheat File = Editar arquivo de trucos -Enable/Disable All = Activar/desactivar tódolos trucos Import Cheats = Importar cheat.db -Options = Opcións Refresh Rate = Frecuencia de actualización [DesktopUI] diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index aa9dde34a7..e7189a93c7 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Κωδικοί Edit Cheat File = Επεξεργασία αρχείου κωδικών -Enable/Disable All = Ενεργοπ./Απενεργοπ. Όλων Import Cheats = Εισαγωγή από cheat.db -Options = Ρυθμίσεις Refresh Rate = Ρυθμός ανανέωσης [DesktopUI] diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index 32013364f8..ffc818b432 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Edit cheat file -Enable/Disable All = Enable/Disable all Cheats Import Cheats = Import from cheat.db -Options = Options Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 240da1cdd2..33b0ab6189 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Edit cheat file -Enable/Disable All = Enable/Disable all Cheats Import Cheats = Import from cheat.db -Options = Options Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index b873743723..c28612e300 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Šifre Edit Cheat File = Izmijeni cheat datoteku -Enable/Disable All = Upali/Izgasi sve Šifre Import Cheats = Uvezi iz cheat.db -Options = Opcije Refresh Rate = Brzina osvježavanja [DesktopUI] diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 8920fb5b9a..ec2ac4b493 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Csalások Edit Cheat File = Csalás fájl szerkesztése -Enable/Disable All = Összes csalás engedélyezése/tiltása Import Cheats = Importálás cheat.db-ből -Options = Beállítások Refresh Rate = Frissítési gyakoriság [DesktopUI] diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 75bc24cc01..cf52c4f9a4 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Pengecoh Edit Cheat File = Edit berkas pengecoh -Enable/Disable All = Hidupkan/matikan semua pengecoh Import Cheats = Impor dari cheat.db -Options = Pilihan Refresh Rate = Perbarui penyegaran [DesktopUI] diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index ec58a24f29..dcf507b8ba 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Trucchi Edit Cheat File = Modifica file Trucchi -Enable/Disable All = Attiva/Disattiva Trucchi Import Cheats = Importa da cheat.db -Options = Opzioni Refresh Rate = Frequenza di Aggiornamento [DesktopUI] diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index f3e0658528..24e677302f 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = チート Edit Cheat File = チートファイルを編集する -Enable/Disable All = 全て有効/無効にする Import Cheats = cheat.dbからインポートする -Options = オプション Refresh Rate = リフレッシュレート [DesktopUI] diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 15f3ae2248..abb2406761 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Mbeling Edit Cheat File = Sunting berkas mbeling -Enable/Disable All = Ngatifke/Pateni Kabeh mbeling Import Cheats = Njokot soko cheat.db -Options = Pilian Refresh Rate = Restar rate [DesktopUI] diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index d1e7a53a30..7001fd30cb 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = 치트 Edit Cheat File = 치트 파일 수정 -Enable/Disable All = 모든 치트 활성화/비활성화 Import Cheats = cheat.db에서 가져오기 -Options = 옵션 Refresh Rate = 주사율 [DesktopUI] diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index c4fb69568c..12dc20f7e6 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = ການໃຊ້ສູດໂກງ Edit Cheat File = ປັບແຕ່ງໄຟລ໌ສູດໂກງ -Enable/Disable All = ເປີດ/ປິດ ສູດທັງໝົດ Import Cheats = ນຳເຂົ້າຈາກໄຟລ໌ສູດໂກງ -Options = ໂຕເລືອກ Refresh Rate = ອັດຕາການຟື້ນຟູ [DesktopUI] diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 7708f8fdc2..f9d6d1d9aa 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Kodai Edit Cheat File = Redaguoti kodų failą -Enable/Disable All = Įjungti/Išjungti visus Kodus Import Cheats = Importuoti iš cheat.db -Options = Parametrai Refresh Rate = Atsinaujinimo dažnis [DesktopUI] diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 072affd878..91866aee34 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheat Edit Cheat File = Ubah cheat file -Enable/Disable All = Upayakan/Lumpuhkan semua Cheat Import Cheats = Import dari cheat.db -Options = Pilihan Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 03730e79fe..d520703262 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Cheatbestand bewerken -Enable/Disable All = Alle cheats aan-/uitzetten Import Cheats = Importeren van cheat.db -Options = Opties Refresh Rate = Vernieuwingsfrequentie [DesktopUI] diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 85ad21d76d..7075b66bf4 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Edit cheat file -Enable/Disable All = Enable/Disable all Cheats Import Cheats = Import from cheat.db -Options = Options Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 5af4c6c860..b63b0cc1fe 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Kody Edit Cheat File = Edytuj plik kodów -Enable/Disable All = Wł./wył. wszystkie kody Import Cheats = Importuj z pliku cheat.db -Options = Opcje Refresh Rate = Szybkość odświeżania [DesktopUI] diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 25dfb9755a..583f4575da 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -132,9 +132,7 @@ Y = Y [CwCheats] Cheats = Trapaças Edit Cheat File = Editar arquivo de trapaças -Enable/Disable All = Ativar/Desativar todas as trapaças Import Cheats = Importar do cheat.db -Options = Opções Refresh Rate = Taxa de atualização [DesktopUI] diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index eccd69ecae..80e4aaeada 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -132,9 +132,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Editar ficheiro de Cheats -Enable/Disable All = Ativar/Desativar todas os Cheats Import Cheats = Importar de cheat.db -Options = Opções Refresh Rate = Taxa de refrescamento [DesktopUI] diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index b262ed7d21..1e553bdd08 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Trișare Edit Cheat File = Editare fișier trișare -Enable/Disable All = Activează/Dezactivează tot trișatul Import Cheats = Importă din cheat.db -Options = Opțiuni Refresh Rate = Rată de împrospatare [DesktopUI] diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index b61e7c5fc0..e34f841ff5 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Читы Edit Cheat File = Изменить файл чита -Enable/Disable All = Включить/выключить все Import Cheats = Импортировать из cheat.db -Options = Настройки Refresh Rate = Частота обновления [DesktopUI] diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 7570246282..d40917596c 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Fusk Edit Cheat File = Redigera fusk-fil -Enable/Disable All = Slå av eller på alla Import Cheats = Importera från cheat.db -Options = Inställningar Refresh Rate = Uppdateringsfrekvens [DesktopUI] diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index aa3dcbab93..14473f78ff 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Mga Daya Edit Cheat File = Edit Cheat File -Enable/Disable All = Paganahin/Wag paganahin ang mga daya Import Cheats = Import ang mga daya mula sa cheat.db -Options = Ayos Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 9bb3fdac31..cd18ed6ba4 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -108,9 +108,7 @@ Y = แกน Y [CwCheats] Cheats = การใช้สูตรโกง Edit Cheat File = ปรับแต่งไฟล์สูตรโกง -Enable/Disable All = เปิด/ปิด ใช้งานสูตรทั้งหมด Import Cheats = นำเข้าจากไฟล์สูตรโกง -Options = ตัวเลือก Refresh Rate = อัตรารีเฟรช [DesktopUI] diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index cf9583ace4..e921f961db 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Hileler Edit Cheat File = Hile dosyasını düzenle -Enable/Disable All = Bütün hileleri Aç/Kapat Import Cheats = cheat.db'den hile al -Options = Ayarlar Refresh Rate = Yenileme Hızı [DesktopUI] diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index f03c6bd823..e4cc24f436 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Чит-коди Edit Cheat File = Змінити файл чит-коду -Enable/Disable All = Ввімкнути/Вимкнути все Import Cheats = Імпортувати з cheat.db -Options = Налаштування Refresh Rate = Частота оновлення [DesktopUI] diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index 1c2d60e972..eb715014a3 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = Cheats Edit Cheat File = Sửa mục cheat -Enable/Disable All = Bật/Tắt tất cả các mã cheat Import Cheats = Nhập mã từ cheat.db -Options = Thiết lập Refresh Rate = Tần số làm mới [DesktopUI] diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 91d76768ab..2a1c7b180f 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = 金手指 Edit Cheat File = 编辑金手指文件 -Enable/Disable All = 启用/禁用全部 Import Cheats = 从cheat.db导入 -Options = 选项 Refresh Rate = 刷新率 [DesktopUI] diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 5e165dbe8b..c0810c024c 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -108,9 +108,7 @@ Y = Y [CwCheats] Cheats = 密技 Edit Cheat File = 編輯密技檔案 -Enable/Disable All = 啟用/停用所有密技 Import Cheats = 從 cheat.db 匯入 -Options = 選項 Refresh Rate = 重新整理速率 [DesktopUI] From 84f33d9346ed811c1bb15f0afc9b7594e4365812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Mar 2023 13:46:07 +0100 Subject: [PATCH 423/424] Button text fix, required adding a new translation line. --- UI/CwCheatScreen.cpp | 4 +++- assets/lang/ar_AE.ini | 1 + assets/lang/az_AZ.ini | 1 + assets/lang/bg_BG.ini | 1 + assets/lang/ca_ES.ini | 1 + assets/lang/cz_CZ.ini | 1 + assets/lang/da_DK.ini | 2 +- assets/lang/dr_ID.ini | 1 + assets/lang/en_US.ini | 1 + assets/lang/fi_FI.ini | 1 + assets/lang/fr_FR.ini | 1 + assets/lang/gl_ES.ini | 1 + assets/lang/gr_EL.ini | 1 + assets/lang/he_IL.ini | 1 + assets/lang/he_IL_invert.ini | 1 + assets/lang/hr_HR.ini | 1 + assets/lang/hu_HU.ini | 1 + assets/lang/id_ID.ini | 1 + assets/lang/it_IT.ini | 1 + assets/lang/ja_JP.ini | 1 + assets/lang/jv_ID.ini | 2 +- assets/lang/lo_LA.ini | 2 +- assets/lang/lt-LT.ini | 1 + assets/lang/ms_MY.ini | 1 + assets/lang/nl_NL.ini | 1 + assets/lang/no_NO.ini | 1 + assets/lang/pl_PL.ini | 1 + assets/lang/pt_BR.ini | 11 ++++++----- assets/lang/pt_PT.ini | 1 + assets/lang/ro_RO.ini | 1 + assets/lang/ru_RU.ini | 1 + assets/lang/sv_SE.ini | 1 + assets/lang/tg_PH.ini | 2 +- assets/lang/tr_TR.ini | 1 + assets/lang/uk_UA.ini | 1 + assets/lang/vi_VN.ini | 1 + assets/lang/zh_CN.ini | 1 + assets/lang/zh_TW.ini | 1 + 38 files changed, 45 insertions(+), 10 deletions(-) diff --git a/UI/CwCheatScreen.cpp b/UI/CwCheatScreen.cpp index d6d3636bd7..15e45207f8 100644 --- a/UI/CwCheatScreen.cpp +++ b/UI/CwCheatScreen.cpp @@ -97,7 +97,9 @@ void CwCheatScreen::CreateViews() { std::string root = GetSysDirectory(DIRECTORY_MEMSTICK_ROOT).ToString(); - leftColumn->Add(new Choice(cheatPath.ToVisualString(root.c_str())))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat); + std::string title = StringFromFormat(cw->T("Import from %s"), "PSP/Cheats/cheat.db"); + + leftColumn->Add(new Choice(title.c_str()))->OnClick.Handle(this, &CwCheatScreen::OnImportCheat); leftColumn->Add(new Choice(mm->T("Browse"), ImageID("I_FOLDER_OPEN")))->OnClick.Handle(this, &CwCheatScreen::OnImportBrowse); errorMessageView_ = leftColumn->Add(new TextView(di->T("LoadingFailed"))); errorMessageView_->SetVisibility(V_GONE); diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index c360e6eb11..03851d3694 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -117,6 +117,7 @@ Y = Y Cheats = ‎الشفرات Edit Cheat File = ‎عدل ملف الشفرة Import Cheats = ‎إستورد من cheat.db +Import from %s = ‎إستورد من %s Refresh Rate = ‎معدل التحديث [DesktopUI] diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index 2648673730..ca7c57a8a7 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Edit cheat file Import Cheats = Import from cheat.db +Import from %s = Import from %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index c68fac507b..0ee29c2fa1 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Чийтове Edit Cheat File = Edit cheat file Import Cheats = Внеси от cheat.db +Import from %s = Внеси от %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index ebdbcae8b5..fc0eff76bd 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Trucs Edit Cheat File = Editar el fitxer de trucs Import Cheats = Importar «cheat.db» +Import from %s = Importar %s Refresh Rate = Freqüència de refrescament [DesktopUI] diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index 89bd7f46a5..0850a50a82 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheaty Edit Cheat File = Upravit soubor s cheaty Import Cheats = Importovat z cheat.db +Import from %s = Importovat z %s Refresh Rate = Frekvence obnoveni [DesktopUI] diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index 8a69c7578b..0deb860f5e 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -108,7 +108,7 @@ Y = Y [CwCheats] Cheats = Snyd Edit Cheat File = Editer snydefil -Import Cheats = Importer fra cheat.db +Import from %s = Importer fra %s Refresh Rate = Opdateringsrate [DesktopUI] diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 848585f5fa..95041f345c 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheat Edit Cheat File = Edit cheat file Import Cheats = Patamanni cheat.db +Import from %s = Patamanni %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 2718fbdb3c..cb75ad6227 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -133,6 +133,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Edit cheat file Import Cheats = Import from cheat.db +Import from %s = Import from %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index 15c8360a4f..68991bc328 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Huijaukset Edit Cheat File = Muokkaa huijaus tiedostoa Import Cheats = Tuo huijauksia +Import from %s = %s Refresh Rate = Ruudunpäivitysnopeus [DesktopUI] diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index ccc4ffad56..49a7288770 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -109,6 +109,7 @@ Y = Axe Y Cheats = Codes de triche Edit Cheat File = Modifier le fichier de triche Import Cheats = Importer des codes de triche +Import from %s = Importer de %s Refresh Rate = Taux de rafraîchissement [DesktopUI] diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index a733b6a84e..911e94a099 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Trucos Edit Cheat File = Editar arquivo de trucos Import Cheats = Importar cheat.db +Import from %s = Importar %s Refresh Rate = Frecuencia de actualización [DesktopUI] diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index e7189a93c7..5abcded47c 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Κωδικοί Edit Cheat File = Επεξεργασία αρχείου κωδικών Import Cheats = Εισαγωγή από cheat.db +Import from %s = Εισαγωγή από %s Refresh Rate = Ρυθμός ανανέωσης [DesktopUI] diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index ffc818b432..b53230ac96 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Edit cheat file Import Cheats = Import from cheat.db +Import from %s = Import from %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 33b0ab6189..498dcdad0d 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Edit cheat file Import Cheats = Import from cheat.db +Import from %s = Import from %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index c28612e300..0b04b28661 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Šifre Edit Cheat File = Izmijeni cheat datoteku Import Cheats = Uvezi iz cheat.db +Import from %s = Uvezi iz %s Refresh Rate = Brzina osvježavanja [DesktopUI] diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index ec2ac4b493..70126bd913 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Csalások Edit Cheat File = Csalás fájl szerkesztése Import Cheats = Importálás cheat.db-ből +Import from %s = Importálás %s-ből Refresh Rate = Frissítési gyakoriság [DesktopUI] diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index cf52c4f9a4..d43ba497a0 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Pengecoh Edit Cheat File = Edit berkas pengecoh Import Cheats = Impor dari cheat.db +Import from %s = Impor dari %s Refresh Rate = Perbarui penyegaran [DesktopUI] diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index dcf507b8ba..e78f9b2092 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Trucchi Edit Cheat File = Modifica file Trucchi Import Cheats = Importa da cheat.db +Import from %s = Importa da %s Refresh Rate = Frequenza di Aggiornamento [DesktopUI] diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 24e677302f..affe890a4b 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -109,6 +109,7 @@ Y = Y Cheats = チート Edit Cheat File = チートファイルを編集する Import Cheats = cheat.dbからインポートする +Import from %s = %sからインポートする Refresh Rate = リフレッシュレート [DesktopUI] diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index abb2406761..8931f65f45 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -108,7 +108,7 @@ Y = Y [CwCheats] Cheats = Mbeling Edit Cheat File = Sunting berkas mbeling -Import Cheats = Njokot soko cheat.db +Import from %s = Njokot soko %s Refresh Rate = Restar rate [DesktopUI] diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index 12dc20f7e6..2bf159d9bc 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -108,7 +108,7 @@ Y = Y [CwCheats] Cheats = ການໃຊ້ສູດໂກງ Edit Cheat File = ປັບແຕ່ງໄຟລ໌ສູດໂກງ -Import Cheats = ນຳເຂົ້າຈາກໄຟລ໌ສູດໂກງ +Import from %s = ນຳເຂົ້າຈາກໄຟລ໌ສູດໂກງ %s Refresh Rate = ອັດຕາການຟື້ນຟູ [DesktopUI] diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index f9d6d1d9aa..d5e1f78adb 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Kodai Edit Cheat File = Redaguoti kodų failą Import Cheats = Importuoti iš cheat.db +Import from %s = Importuoti iš %s Refresh Rate = Atsinaujinimo dažnis [DesktopUI] diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index 91866aee34..ed9e286f62 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheat Edit Cheat File = Ubah cheat file Import Cheats = Import dari cheat.db +Import from %s = Import dari %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index d520703262..73f3bfd964 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Cheatbestand bewerken Import Cheats = Importeren van cheat.db +Import from %s = Importeren van %s Refresh Rate = Vernieuwingsfrequentie [DesktopUI] diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 7075b66bf4..715516d893 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Edit cheat file Import Cheats = Import from cheat.db +Import from %s = Import from %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index b63b0cc1fe..93230b473e 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Kody Edit Cheat File = Edytuj plik kodów Import Cheats = Importuj z pliku cheat.db +Import from %s = Importuj z pliku %s Refresh Rate = Szybkość odświeżania [DesktopUI] diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index 583f4575da..c93a14a39b 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -133,6 +133,7 @@ Y = Y Cheats = Trapaças Edit Cheat File = Editar arquivo de trapaças Import Cheats = Importar do cheat.db +Import from %s = Importar do %s Refresh Rate = Taxa de atualização [DesktopUI] @@ -515,7 +516,7 @@ Frame Skipping = Pulo dos frames Frame Skipping Type = Tipo de pulo dos frames FullScreen = Tela cheia Geometry shader culling = Abate do shader da geometria -Hack Settings = Configurações dos hacks (pode causar erros gráficos) +Hack Settings = Configurações dos hacks (pode causar erros gráficos) Hardware Tessellation = Tesselação por hardware Hardware Transform = Transformação por hardware hardware transform error - falling back to software = Erro de transformação pelo hardware, retrocedendo pro software. @@ -884,10 +885,10 @@ tools = Ferramentas grátis usadas: # Leave extra lines blank. 4 contributors per line seems to look best. translators1 = Papel, gabrielmop, Efraim Lopes, AkiraJkr translators2 = Felipe -translators3 = -translators4 = -translators5 = -translators6 = +translators3 = +translators4 = +translators5 = +translators6 = Twitter @PPSSPP_emu = Twitter @PPSSPP_emu website = Verifique o site da web: written = Escrito em C++ pela velocidade e portabilidade diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 80e4aaeada..d88325d86e 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -133,6 +133,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Editar ficheiro de Cheats Import Cheats = Importar de cheat.db +Import from %s = Importar de %s Refresh Rate = Taxa de refrescamento [DesktopUI] diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 1e553bdd08..bc30e4bed2 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Trișare Edit Cheat File = Editare fișier trișare Import Cheats = Importă din cheat.db +Import %s = Importă din %s Refresh Rate = Rată de împrospatare [DesktopUI] diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index e34f841ff5..3f4f820d66 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Читы Edit Cheat File = Изменить файл чита Import Cheats = Импортировать из cheat.db +Import from %s = Импортировать из %s Refresh Rate = Частота обновления [DesktopUI] diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index d40917596c..9bc12b9f16 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Fusk Edit Cheat File = Redigera fusk-fil Import Cheats = Importera från cheat.db +Import from %s = Importera från %s Refresh Rate = Uppdateringsfrekvens [DesktopUI] diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index 14473f78ff..207a5ad4bc 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -108,7 +108,7 @@ Y = Y [CwCheats] Cheats = Mga Daya Edit Cheat File = Edit Cheat File -Import Cheats = Import ang mga daya mula sa cheat.db +Import from %s = Import ang mga daya mula sa %s Refresh Rate = Refresh rate [DesktopUI] diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index e921f961db..c7d2ad7a90 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Hileler Edit Cheat File = Hile dosyasını düzenle Import Cheats = cheat.db'den hile al +Import from %s = %s'den hile al Refresh Rate = Yenileme Hızı [DesktopUI] diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index e4cc24f436..d4420858a0 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Чит-коди Edit Cheat File = Змінити файл чит-коду Import Cheats = Імпортувати з cheat.db +Import from %s = Імпортувати з %s Refresh Rate = Частота оновлення [DesktopUI] diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index eb715014a3..a4a89a1734 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -109,6 +109,7 @@ Y = Y Cheats = Cheats Edit Cheat File = Sửa mục cheat Import Cheats = Nhập mã từ cheat.db +Import from %s = Nhập mã từ %s Refresh Rate = Tần số làm mới [DesktopUI] diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 2a1c7b180f..9816ad0076 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -109,6 +109,7 @@ Y = Y Cheats = 金手指 Edit Cheat File = 编辑金手指文件 Import Cheats = 从cheat.db导入 +Import from %s = 从%s导入 Refresh Rate = 刷新率 [DesktopUI] diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index c0810c024c..f91808f864 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -109,6 +109,7 @@ Y = Y Cheats = 密技 Edit Cheat File = 編輯密技檔案 Import Cheats = 從 cheat.db 匯入 +Import Cheats = 從 %s 匯入 Refresh Rate = 重新整理速率 [DesktopUI] From 451ee14ebc0414681107f502e620d38f566afba4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 23 Mar 2023 17:14:12 +0100 Subject: [PATCH 424/424] Don't forget to call CheckDepthUsage when using imm draws. Fixes #17169 --- GPU/GPUCommon.cpp | 6 +++++- GPU/GPUCommon.h | 1 + GPU/GPUCommonHW.h | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 802219472c..d90cde535a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1350,14 +1350,18 @@ void GPUCommon::FlushImm() { return; SetDrawType(DRAW_PRIM, immPrim_); + VirtualFramebuffer *vfb = nullptr; if (framebufferManager_) - framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); + vfb = framebufferManager_->SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // No idea how many cycles to skip, heh. immCount_ = 0; return; } UpdateUVScaleOffset(); + if (vfb) { + CheckDepthUsage(vfb); + } bool antialias = (immFlags_ & GE_IMM_ANTIALIAS) != 0; bool prevAntialias = gstate.isAntiAliasEnabled(); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 367da7c85b..e8dc1abd99 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -250,6 +250,7 @@ protected: void BeginFrame() override; void UpdateVsyncInterval(bool force); + virtual void CheckDepthUsage(VirtualFramebuffer *vfb) {} virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); diff --git a/GPU/GPUCommonHW.h b/GPU/GPUCommonHW.h index 000993be79..c1928de99e 100644 --- a/GPU/GPUCommonHW.h +++ b/GPU/GPUCommonHW.h @@ -68,7 +68,7 @@ public: void ExecuteOp(u32 op, u32 diff) override; private: - void CheckDepthUsage(VirtualFramebuffer *vfb); + void CheckDepthUsage(VirtualFramebuffer *vfb) override; void CheckFlushOp(int cmd, u32 diff); protected:

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 z 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 z%0A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

7(9XJ8raRxOgx~w=N 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

5^37YWIErY(dzv0D#!pj`M$V&=@ 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 ZemU#=>{A+Yzl~Z3<6XG@XDlTTyE3q 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

8Xi{?|mkMSNm+B{S7JkIJ@ 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 iGM_Q4O?RpR`J6j|bvE#N;&#QIinV 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