diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java index 2462b5958..ed6ec32ce 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/BaseActivity.java @@ -26,16 +26,16 @@ protected void onResume() { private void applyTheme(){ switch (GlobalConfig.get(GlobalConfig.KEY_APP_THEME)){ - case GlobalConfig.VALUE_THEME_ANDROID: + case GlobalConfig.THEME_ANDROID: setTheme(R.style.Theme_Pandroid); break; - case GlobalConfig.VALUE_THEME_LIGHT: + case GlobalConfig.THEME_LIGHT: setTheme(R.style.Theme_Pandroid_Light); break; - case GlobalConfig.VALUE_THEME_DARK: + case GlobalConfig.THEME_DARK: setTheme(R.style.Theme_Pandroid_Dark); break; - case GlobalConfig.VALUE_THEME_BLACK: + case GlobalConfig.THEME_BLACK: setTheme(R.style.Theme_Pandroid_Black); break; } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/SMDH.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/SMDH.java index ae61cf4bf..2401a4039 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/SMDH.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/SMDH.java @@ -1,6 +1,7 @@ package com.panda3ds.pandroid.data; import android.graphics.Bitmap; +import android.graphics.Color; import com.panda3ds.pandroid.data.game.GameRegion; @@ -8,12 +9,26 @@ import java.nio.charset.StandardCharsets; public class SMDH { + + public static final int LANGUAGE_ENGLISH = 1; + public static final int LANGUAGE_JAPANESE = 0; + public static final int LANGUAGE_CHINESE = 6; + public static final int LANGUAGE_KOREAN = 7; + + public static final int REGION_JAPAN_MASK = 0x1; + public static final int REGION_NORTH_AMERICAN_MASK = 0x2; + public static final int REGION_EUROPE_MASK = 0x4; + public static final int REGION_AUSTRALIA_MASK = 0x8; + public static final int REGION_CHINA_MASK = 0x10; + public static final int REGION_KOREAN_MASK = 0x20; + public static final int REGION_TAIWAN_MASK = 0x40; + private static final int ICON_SIZE = 48; - private static final int META_OFFSET = 0x8 ; + private static final int META_OFFSET = 0x8; private static final int META_REGION_OFFSET = 0x2018; private static final int IMAGE_OFFSET = 0x24C0; - private int metaIndex = 1; + private int metaLanguage = LANGUAGE_ENGLISH; private final ByteBuffer smdh; private final String[] title = new String[12]; private final String[] publisher = new String[12]; @@ -21,7 +36,7 @@ public class SMDH { private final GameRegion region; - public SMDH(byte[] source){ + public SMDH(byte[] source) { smdh = ByteBuffer.allocate(source.length); smdh.position(0); smdh.put(source); @@ -32,20 +47,20 @@ public SMDH(byte[] source){ parseMeta(); } - private GameRegion parseRegion(){ + private GameRegion parseRegion() { GameRegion region; smdh.position(META_REGION_OFFSET); int regionMasks = smdh.get() & 0xFF; - final boolean japan = (regionMasks & 0x1) != 0; - final boolean northAmerica = (regionMasks & 0x2) != 0; - final boolean europe = (regionMasks & 0x4) != 0; - final boolean australia = (regionMasks & 0x8) != 0; - final boolean china = (regionMasks & 0x10) != 0; - final boolean korea = (regionMasks & 0x20) != 0; + final boolean japan = (regionMasks & REGION_JAPAN_MASK) != 0; + final boolean northAmerica = (regionMasks & REGION_NORTH_AMERICAN_MASK) != 0; + final boolean europe = (regionMasks & REGION_EUROPE_MASK) != 0; + final boolean australia = (regionMasks & REGION_AUSTRALIA_MASK) != 0; + final boolean china = (regionMasks & REGION_CHINA_MASK) != 0; + final boolean korea = (regionMasks & REGION_KOREAN_MASK) != 0; + final boolean taiwan = (regionMasks & REGION_TAIWAN_MASK) != 0; - final boolean taiwan = (regionMasks & 0x40) != 0; if (northAmerica) { region = GameRegion.NorthAmerican; } else if (europe) { @@ -54,15 +69,15 @@ private GameRegion parseRegion(){ region = GameRegion.Australia; } else if (japan) { region = GameRegion.Japan; - metaIndex = 0; + metaLanguage = LANGUAGE_JAPANESE; } else if (korea) { - metaIndex = 7; + metaLanguage = LANGUAGE_KOREAN; region = GameRegion.Korean; } else if (china) { - metaIndex = 6; + metaLanguage = LANGUAGE_CHINESE; region = GameRegion.China; } else if (taiwan) { - metaIndex = 6; + metaLanguage = LANGUAGE_CHINESE; region = GameRegion.Taiwan; } else { region = GameRegion.None; @@ -71,50 +86,52 @@ private GameRegion parseRegion(){ return region; } - private void parseMeta(){ - - for (int i = 0; i < 12; i++){ - smdh.position(META_OFFSET + (512*i) + 0x80); - byte[] data = new byte[0x100]; + private void parseMeta() { + byte[] data; + for (int i = 0; i < 12; i++) { + smdh.position(META_OFFSET + (512 * i) + 0x80); + data = new byte[0x100]; smdh.get(data); title[i] = convertString(data).replaceAll("\n", " "); - } - for (int i = 0; i < 12; i++){ smdh.position(META_OFFSET + (512 * i) + 0x180); - byte[] data = new byte[0x80]; + data = new byte[0x80]; smdh.get(data); publisher[i] = convertString(data); } } + // The icons are stored in RGB562 but android need RGB888 private int[] parseIcon() { - int[] icon = new int[ICON_SIZE*ICON_SIZE]; + int[] icon = new int[ICON_SIZE * ICON_SIZE]; smdh.position(0); for (int x = 0; x < ICON_SIZE; x++) { for (int y = 0; y < ICON_SIZE; y++) { - int curseY = y & ~7; - int curseX = x & ~7; + int indexY = y & ~7; + int indexX = x & ~7; int i = mortonInterleave(x, y); - int offset = (i + (curseX * 8)) * 2; + int offset = (i + (indexX * 8)) * 2; - offset = offset + curseY * 48 * 2; + offset = offset + indexY * ICON_SIZE * 2; smdh.position(offset + IMAGE_OFFSET); - int bit1 = smdh.get() & 0xFF; - int bit2 = smdh.get() & 0xFF; + int byte1 = smdh.get() & 0xFF; + int byte2 = smdh.get() & 0xFF; + + int texel = byte1 | (byte2 << 8); - int pixel = bit1 + (bit2 << 8); + int r = (texel >> 11) & 0x1f; + int g = (texel >> 5) & 0x3f; + int b = texel & 0x1f; - int r = (((pixel & 0xF800) >> 11) << 3); - int g = (((pixel & 0x7E0) >> 5) << 2); - int b = (((pixel & 0x1F)) << 3); + b = (b << 3) | (b >> 2); + g = (g << 2) | (g >> 4); + r = (r << 3) | (r >> 2); - //Convert to ARGB8888 - icon[x + 48 * y] = 255 << 24 | (r & 255) << 16 | (g & 255) << 8 | (b & 255); + icon[x + ICON_SIZE * y] = Color.rgb(r, g, b); } } return icon; @@ -125,9 +142,9 @@ public GameRegion getRegion() { return region; } - public Bitmap getBitmapIcon(){ + public Bitmap getBitmapIcon() { Bitmap bitmap = Bitmap.createBitmap(ICON_SIZE, ICON_SIZE, Bitmap.Config.RGB_565); - bitmap.setPixels(icon,0,ICON_SIZE,0,0,ICON_SIZE,ICON_SIZE); + bitmap.setPixels(icon, 0, ICON_SIZE, 0, 0, ICON_SIZE, ICON_SIZE); return bitmap; } @@ -135,30 +152,25 @@ public int[] getIcon() { return icon; } - public String getTitle(){ - return title[metaIndex]; + public String getTitle() { + return title[metaLanguage]; } - public String getPublisher(){ - return publisher[metaIndex]; + public String getPublisher() { + return publisher[metaLanguage]; } // SMDH stores string in UTF-16LE format - private static String convertString(byte[] buffer){ + private static String convertString(byte[] buffer) { try { - return new String(buffer,0, buffer.length, StandardCharsets.UTF_16LE) - .replaceAll("\0",""); - } catch (Exception e){ + return new String(buffer, 0, buffer.length, StandardCharsets.UTF_16LE) + .replaceAll("\0", ""); + } catch (Exception e) { return ""; } } - // u and v are the UVs of the relevant texel - // Texture data is stored interleaved in Morton order, ie in a Z - order curve as shown here - // https://en.wikipedia.org/wiki/Z-order_curve - // Textures are split into 8x8 tiles.This function returns the in - tile offset depending on the u & v of the texel - // The in - tile offset is the sum of 2 offsets, one depending on the value of u % 8 and the other on the value of y % 8 - // As documented in this picture https ://en.wikipedia.org/wiki/File:Moser%E2%80%93de_Bruijn_addition.svg + // Reference: https://github.com/wheremyfoodat/Panda3DS/blob/master/src/core/renderer_gl/textures.cpp#L88 private static int mortonInterleave(int u, int v) { int[] xlut = {0, 1, 4, 5, 16, 17, 20, 21}; int[] ylut = {0, 2, 8, 10, 32, 34, 40, 42}; diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java index 0ee41ddef..038c27ced 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java @@ -10,14 +10,14 @@ public class GlobalConfig { private static final GsonConfigParser parser = new GsonConfigParser(Constants.PREF_GLOBAL_CONFIG); - public static final int VALUE_THEME_ANDROID = 0; - public static final int VALUE_THEME_LIGHT = 1; - public static final int VALUE_THEME_DARK = 2; - public static final int VALUE_THEME_BLACK = 3; + public static final int THEME_ANDROID = 0; + public static final int THEME_LIGHT = 1; + public static final int THEME_DARK = 2; + public static final int THEME_BLACK = 3; public static DataModel data; - public static final Key KEY_APP_THEME = new Key<>("app.theme", VALUE_THEME_ANDROID); + public static final Key KEY_APP_THEME = new Key<>("app.theme", THEME_ANDROID); public static void initialize() { data = parser.load(DataModel.class); diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/SearchAgent.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/SearchAgent.java index 212c1a1da..b4ea2152d 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/SearchAgent.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/SearchAgent.java @@ -9,10 +9,8 @@ public class SearchAgent { - /** - * Store all possibles results in map - * id->words - */ + // Store all possibles results in map + // id->words private final HashMap searchBuffer = new HashMap<>(); // Add search item to list