mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-10 13:33:24 -05:00
feat: add thirty emulator profiles and their data
Thirty profiles from the ES-DE batch, each source-verified by the session that wrote it and passing the schema and semantic checks. Five declare no files at all and say why in notes referenced to the code: NGP.emu, openbor, Plastic, Swan.emu and XeniOS. Twenty-eight files come with them, every one declared by the profile that needs it and matching the hash it declares, with no duplicate of anything already held: the NetherSX2 Turnip Classic assets, the Speccy machine ROMs, the Virtual Boy homebrew the app bundles, Snes9x EX+'s bundled game, and sixtyforce's Overrides.plist, which carries a size and no hash because the binary never checks one. supermodel gains the four data files it reads from its install tree, hakux marks its controller map unsourceable now that the asset manager is known to read inside the package, and nethersx2 sheds the two core aliases that belong to the Turnip profiles.
This commit is contained in:
1 parent
87ff398f9a
commit
e42d0815c1
61 files changed
+154724
-7
No files matched your search
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,107 @@
|
|||||||
|
//#version 420 // Keep it for editor detection
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Common Interface Definition
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER
|
||||||
|
|
||||||
|
#if !pGL_ES
|
||||||
|
out gl_PerVertex {
|
||||||
|
vec4 gl_Position;
|
||||||
|
float gl_PointSize;
|
||||||
|
#if !pGL_ES
|
||||||
|
float gl_ClipDistance[1];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef GEOMETRY_SHADER
|
||||||
|
|
||||||
|
#if !pGL_ES
|
||||||
|
in gl_PerVertex {
|
||||||
|
vec4 gl_Position;
|
||||||
|
float gl_PointSize;
|
||||||
|
#if !pGL_ES
|
||||||
|
float gl_ClipDistance[1];
|
||||||
|
#endif
|
||||||
|
} gl_in[];
|
||||||
|
|
||||||
|
out gl_PerVertex {
|
||||||
|
vec4 gl_Position;
|
||||||
|
float gl_PointSize;
|
||||||
|
#if !pGL_ES
|
||||||
|
float gl_ClipDistance[1];
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Constant Buffer Definition
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Performance note, some drivers (nouveau) will validate all Constant Buffers
|
||||||
|
// even if only one was updated.
|
||||||
|
|
||||||
|
#if defined(VERTEX_SHADER) || defined(GEOMETRY_SHADER)
|
||||||
|
layout(std140, binding = 1) uniform cb20
|
||||||
|
{
|
||||||
|
vec2 VertexScale;
|
||||||
|
vec2 VertexOffset;
|
||||||
|
|
||||||
|
vec2 TextureScale;
|
||||||
|
vec2 TextureOffset;
|
||||||
|
|
||||||
|
vec2 PointSize;
|
||||||
|
uint MaxDepth;
|
||||||
|
uint pad_cb20;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(VERTEX_SHADER) || defined(FRAGMENT_SHADER)
|
||||||
|
layout(std140, binding = 0) uniform cb21
|
||||||
|
{
|
||||||
|
vec3 FogColor;
|
||||||
|
float AREF;
|
||||||
|
|
||||||
|
vec4 WH;
|
||||||
|
|
||||||
|
vec2 TA;
|
||||||
|
float MaxDepthPS;
|
||||||
|
float Af;
|
||||||
|
|
||||||
|
uvec4 MskFix;
|
||||||
|
|
||||||
|
uvec4 FbMask;
|
||||||
|
|
||||||
|
vec4 HalfTexel;
|
||||||
|
|
||||||
|
vec4 MinMax;
|
||||||
|
|
||||||
|
ivec4 ChannelShuffle;
|
||||||
|
|
||||||
|
vec2 TC_OffsetHack;
|
||||||
|
vec2 STScale;
|
||||||
|
|
||||||
|
mat4 DitherMatrix;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//layout(std140, binding = 22) uniform cb22
|
||||||
|
//{
|
||||||
|
// vec4 rt_size;
|
||||||
|
//};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Default Sampler
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
#ifdef FRAGMENT_SHADER
|
||||||
|
|
||||||
|
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,387 @@
|
|||||||
|
//#version 420 // Keep it for editor detection
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 POSITION;
|
||||||
|
layout(location = 1) in vec2 TEXCOORD0;
|
||||||
|
layout(location = 7) in vec4 COLOR;
|
||||||
|
|
||||||
|
// FIXME set the interpolation (don't know what dx do)
|
||||||
|
// flat means that there is no interpolation. The value given to the fragment shader is based on the provoking vertex conventions.
|
||||||
|
//
|
||||||
|
// noperspective means that there will be linear interpolation in window-space. This is usually not what you want, but it can have its uses.
|
||||||
|
//
|
||||||
|
// smooth, the default, means to do perspective-correct interpolation.
|
||||||
|
//
|
||||||
|
// The centroid qualifier only matters when multisampling. If this qualifier is not present, then the value is interpolated to the pixel's center, anywhere in the pixel, or to one of the pixel's samples. This sample may lie outside of the actual primitive being rendered, since a primitive can cover only part of a pixel's area. The centroid qualifier is used to prevent this; the interpolation point must fall within both the pixel's area and the primitive's area.
|
||||||
|
out vec4 PSin_p;
|
||||||
|
out vec2 PSin_t;
|
||||||
|
out vec4 PSin_c;
|
||||||
|
|
||||||
|
void vs_main()
|
||||||
|
{
|
||||||
|
PSin_p = vec4(POSITION, 0.5f, 1.0f);
|
||||||
|
PSin_t = TEXCOORD0;
|
||||||
|
PSin_c = COLOR;
|
||||||
|
gl_Position = vec4(POSITION, 0.5f, 1.0f); // NOTE I don't know if it is possible to merge POSITION_OUT and gl_Position
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FRAGMENT_SHADER
|
||||||
|
|
||||||
|
in vec4 PSin_p;
|
||||||
|
in vec2 PSin_t;
|
||||||
|
in vec4 PSin_c;
|
||||||
|
|
||||||
|
// Give a different name so I remember there is a special case!
|
||||||
|
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||||
|
layout(location = 0) out uint SV_Target1;
|
||||||
|
#else
|
||||||
|
layout(location = 0) out vec4 SV_Target0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 sample_c()
|
||||||
|
{
|
||||||
|
return texture(TextureSampler, PSin_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ps_copy
|
||||||
|
void ps_copy()
|
||||||
|
{
|
||||||
|
SV_Target0 = sample_c();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_depth_copy
|
||||||
|
void ps_depth_copy()
|
||||||
|
{
|
||||||
|
gl_FragDepth = sample_c().r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_16bits
|
||||||
|
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||||
|
void ps_convert_rgba8_16bits()
|
||||||
|
{
|
||||||
|
highp uvec4 i = uvec4(sample_c() * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||||
|
|
||||||
|
SV_Target1 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_float32_32bits
|
||||||
|
void ps_convert_float32_32bits()
|
||||||
|
{
|
||||||
|
// Convert a GL_FLOAT32 depth texture into a 32 bits UINT texture
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
SV_Target1 = uint(exp2(32.0f) * sample_c().r);
|
||||||
|
#else
|
||||||
|
SV_Target1 = uint(exp2(24.0f) * sample_c().r);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_float32_rgba8
|
||||||
|
void ps_convert_float32_rgba8()
|
||||||
|
{
|
||||||
|
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
uint d = uint(sample_c().r * exp2(32.0f));
|
||||||
|
#else
|
||||||
|
uint d = uint(sample_c().r * exp2(24.0f));
|
||||||
|
#endif
|
||||||
|
SV_Target0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_float16_rgb5a1
|
||||||
|
void ps_convert_float16_rgb5a1()
|
||||||
|
{
|
||||||
|
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
uint d = uint(sample_c().r * exp2(32.0f));
|
||||||
|
#else
|
||||||
|
uint d = uint(sample_c().r * exp2(24.0f));
|
||||||
|
#endif
|
||||||
|
SV_Target0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float rgba8_to_depth32(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||||
|
#else
|
||||||
|
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-24.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
float rgba8_to_depth24(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||||
|
#else
|
||||||
|
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-24.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
float rgba8_to_depth16(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||||
|
#else
|
||||||
|
return float(c.r | (c.g << 8)) * exp2(-24.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
float rgb5a1_to_depth16(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||||
|
#else
|
||||||
|
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-24.0f);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float32
|
||||||
|
void ps_convert_rgba8_float32()
|
||||||
|
{
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
gl_FragDepth = rgba8_to_depth32(sample_c());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float24
|
||||||
|
void ps_convert_rgba8_float24()
|
||||||
|
{
|
||||||
|
// Same as above but without the alpha channel (24 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
gl_FragDepth = rgba8_to_depth24(sample_c());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float16
|
||||||
|
void ps_convert_rgba8_float16()
|
||||||
|
{
|
||||||
|
// Same as above but without the A/B channels (16 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
gl_FragDepth = rgba8_to_depth16(sample_c());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgb5a1_float16
|
||||||
|
void ps_convert_rgb5a1_float16()
|
||||||
|
{
|
||||||
|
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||||
|
gl_FragDepth = rgb5a1_to_depth16(sample_c());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||||
|
ivec2 dims = textureSize(TextureSampler, 0); \
|
||||||
|
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
|
||||||
|
ivec2 top_left = ivec2(floor(top_left_f)); \
|
||||||
|
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
|
||||||
|
vec2 mix_vals = fract(top_left_f); \
|
||||||
|
float depthTL = CONVERT_FN(texelFetch(TextureSampler, coords.xy, 0)); \
|
||||||
|
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
|
||||||
|
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
|
||||||
|
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
|
||||||
|
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float32_biln
|
||||||
|
void ps_convert_rgba8_float32_biln()
|
||||||
|
{
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float24_biln
|
||||||
|
void ps_convert_rgba8_float24_biln()
|
||||||
|
{
|
||||||
|
// Same as above but without the alpha channel (24 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float16_biln
|
||||||
|
void ps_convert_rgba8_float16_biln()
|
||||||
|
{
|
||||||
|
// Same as above but without the A/B channels (16 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgb5a1_float16_biln
|
||||||
|
void ps_convert_rgb5a1_float16_biln()
|
||||||
|
{
|
||||||
|
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba_8i
|
||||||
|
void ps_convert_rgba_8i()
|
||||||
|
{
|
||||||
|
// Convert a RGBA texture into a 8 bits packed texture
|
||||||
|
// Input column: 8x2 RGBA pixels
|
||||||
|
// 0: 8 RGBA
|
||||||
|
// 1: 8 RGBA
|
||||||
|
// Output column: 16x4 Index pixels
|
||||||
|
// 0: 8 R | 8 B
|
||||||
|
// 1: 8 R | 8 B
|
||||||
|
// 2: 8 G | 8 A
|
||||||
|
// 3: 8 G | 8 A
|
||||||
|
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||||
|
|
||||||
|
// Collapse separate R G B A areas into their base pixel
|
||||||
|
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||||
|
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||||
|
uvec2 coord = block | subblock;
|
||||||
|
|
||||||
|
// Apply offset to cols 1 and 2
|
||||||
|
uint is_col23 = pos.y & 4u;
|
||||||
|
uint is_col13 = pos.y & 2u;
|
||||||
|
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||||
|
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||||
|
|
||||||
|
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||||
|
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
|
||||||
|
else
|
||||||
|
coord *= uvec2(PS_SCALE_FACTOR);
|
||||||
|
|
||||||
|
vec4 pixel = texelFetch(TextureSampler, ivec2(coord), 0);
|
||||||
|
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||||
|
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||||
|
SV_Target0 = vec4(sel1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_filter_transparency
|
||||||
|
void ps_filter_transparency()
|
||||||
|
{
|
||||||
|
vec4 c = sample_c();
|
||||||
|
SV_Target0 = vec4(c.rgb, 1.0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Used for DATE (stencil)
|
||||||
|
// DATM == 1
|
||||||
|
#ifdef ps_datm1
|
||||||
|
void ps_datm1()
|
||||||
|
{
|
||||||
|
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Used for DATE (stencil)
|
||||||
|
// DATM == 0
|
||||||
|
#ifdef ps_datm0
|
||||||
|
void ps_datm0()
|
||||||
|
{
|
||||||
|
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_hdr_init
|
||||||
|
void ps_hdr_init()
|
||||||
|
{
|
||||||
|
vec4 value = sample_c();
|
||||||
|
SV_Target0 = vec4(round(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_hdr_resolve
|
||||||
|
void ps_hdr_resolve()
|
||||||
|
{
|
||||||
|
vec4 value = sample_c();
|
||||||
|
SV_Target0 = vec4(vec3(uvec3(value.rgb * 65535.0f) & 255u) / 255.0f, value.a);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_yuv
|
||||||
|
uniform ivec2 EMOD;
|
||||||
|
|
||||||
|
void ps_yuv()
|
||||||
|
{
|
||||||
|
vec4 i = sample_c();
|
||||||
|
vec4 o;
|
||||||
|
|
||||||
|
mat3 rgb2yuv; // Value from GS manual
|
||||||
|
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||||
|
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
|
||||||
|
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
|
||||||
|
|
||||||
|
vec3 yuv = rgb2yuv * i.gbr;
|
||||||
|
|
||||||
|
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
|
||||||
|
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||||
|
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||||
|
|
||||||
|
switch(EMOD.x) {
|
||||||
|
case 0:
|
||||||
|
o.a = i.a;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
o.a = Y;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
o.a = Y/2.0f;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
o.a = 0.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(EMOD.y) {
|
||||||
|
case 0:
|
||||||
|
o.rgb = i.rgb;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
o.rgb = vec3(Y);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
o.rgb = vec3(Y, Cb, Cr);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
o.rgb = vec3(i.a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SV_Target0 = o;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
SV_Target0 = vec4(0x7FFFFFFF);
|
||||||
|
|
||||||
|
#ifdef ps_stencil_image_init_0
|
||||||
|
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
|
||||||
|
SV_Target0 = vec4(-1);
|
||||||
|
#endif
|
||||||
|
#ifdef ps_stencil_image_init_1
|
||||||
|
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||||
|
SV_Target0 = vec4(-1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,993 @@
|
|||||||
|
//#version 420 // Keep it for text editor detection
|
||||||
|
|
||||||
|
// Require for bit operation
|
||||||
|
//#extension GL_ARB_gpu_shader5 : enable
|
||||||
|
|
||||||
|
#define FMT_32 0
|
||||||
|
#define FMT_24 1
|
||||||
|
#define FMT_16 2
|
||||||
|
|
||||||
|
// APITRACE_DEBUG enables forced pixel output to easily detect
|
||||||
|
// the fragment computed by primitive
|
||||||
|
#define APITRACE_DEBUG 0
|
||||||
|
// TEX_COORD_DEBUG output the uv coordinate as color. It is useful
|
||||||
|
// to detect bad sampling due to upscaling
|
||||||
|
//#define TEX_COORD_DEBUG
|
||||||
|
// Just copy directly the texture coordinate
|
||||||
|
#ifdef TEX_COORD_DEBUG
|
||||||
|
#define PS_TFX 1
|
||||||
|
#define PS_TCC 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||||
|
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
|
||||||
|
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_CLR_HW > 3)
|
||||||
|
#define PS_PRIMID_INIT (PS_DATE == 1 || PS_DATE == 2)
|
||||||
|
#define NEEDS_RT_EARLY (PS_TEX_IS_FB == 1 || PS_DATE >= 5)
|
||||||
|
#define NEEDS_RT (NEEDS_RT_EARLY || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)))
|
||||||
|
|
||||||
|
#ifdef FRAGMENT_SHADER
|
||||||
|
|
||||||
|
#if !defined(BROKEN_DRIVER) && (pGL_ES || defined(GL_ARB_enhanced_layouts) && GL_ARB_enhanced_layouts)
|
||||||
|
layout(location = 0)
|
||||||
|
#endif
|
||||||
|
in SHADER
|
||||||
|
{
|
||||||
|
vec4 t_float;
|
||||||
|
vec4 t_int;
|
||||||
|
|
||||||
|
#if PS_IIP != 0
|
||||||
|
vec4 c;
|
||||||
|
#else
|
||||||
|
flat vec4 c;
|
||||||
|
#endif
|
||||||
|
} PSin;
|
||||||
|
|
||||||
|
#define TARGET_0_QUALIFIER out
|
||||||
|
|
||||||
|
// Only enable framebuffer fetch when we actually need it.
|
||||||
|
#if HAS_FRAMEBUFFER_FETCH && NEEDS_RT
|
||||||
|
// We need to force the colour to be defined here, to read from it.
|
||||||
|
// Basically the only scenario where this'll happen is RGBA masked and DATE is active.
|
||||||
|
#undef PS_NO_COLOR
|
||||||
|
#define PS_NO_COLOR 0
|
||||||
|
#if defined(GL_EXT_shader_framebuffer_fetch)
|
||||||
|
#undef TARGET_0_QUALIFIER
|
||||||
|
#define TARGET_0_QUALIFIER inout
|
||||||
|
#define LAST_FRAG_COLOR SV_Target0
|
||||||
|
#elif defined(GL_ARM_shader_framebuffer_fetch)
|
||||||
|
#define LAST_FRAG_COLOR gl_LastFragColorARM
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAS_DEPTH_FETCH && PS_TEX_IS_DS == 1
|
||||||
|
#if defined(GL_ARM_shader_framebuffer_fetch_depth_stencil)
|
||||||
|
#define LAST_FRAG_DEPTH gl_LastFragDepthARM
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !PS_NO_COLOR
|
||||||
|
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
|
||||||
|
// Same buffer but 2 colors for dual source blending
|
||||||
|
layout(location = 0, index = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||||
|
layout(location = 0, index = 1) out vec4 SV_Target1;
|
||||||
|
#else
|
||||||
|
layout(location = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
layout(binding = 1) uniform sampler2D PaletteSampler;
|
||||||
|
|
||||||
|
#if !HAS_FRAMEBUFFER_FETCH && NEEDS_RT
|
||||||
|
layout(binding = 2) uniform sampler2D RtSampler; // note 2 already use by the image below
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_DATE == 3
|
||||||
|
layout(binding = 3) uniform sampler2D img_prim_min;
|
||||||
|
|
||||||
|
// I don't remember why I set this parameter but it is surely useless
|
||||||
|
//layout(pixel_center_integer) in vec4 gl_FragCoord;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 fetch_rt()
|
||||||
|
{
|
||||||
|
#if !NEEDS_RT
|
||||||
|
return vec4(0.0);
|
||||||
|
#elif HAS_FRAMEBUFFER_FETCH
|
||||||
|
return LAST_FRAG_COLOR;
|
||||||
|
#else
|
||||||
|
return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sample_c(vec2 uv)
|
||||||
|
{
|
||||||
|
#if PS_TEX_IS_FB == 1
|
||||||
|
return fetch_rt();
|
||||||
|
#elif PS_TEX_IS_DS == 1
|
||||||
|
return vec4(LAST_FRAG_DEPTH, 0.0f, 0.0f, 0.0f);
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if PS_POINT_SAMPLER
|
||||||
|
// Weird issue with ATI/AMD cards,
|
||||||
|
// it looks like they add 127/128 of a texel to sampling coordinates
|
||||||
|
// occasionally causing point sampling to erroneously round up.
|
||||||
|
// I'm manually adjusting coordinates to the centre of texels here,
|
||||||
|
// though the centre is just paranoia, the top left corner works fine.
|
||||||
|
// As of 2018 this issue is still present.
|
||||||
|
uv = (trunc(uv * WH.zw) + vec2(0.5, 0.5)) / WH.zw;
|
||||||
|
#endif
|
||||||
|
uv *= STScale;
|
||||||
|
|
||||||
|
#if PS_AUTOMATIC_LOD == 1
|
||||||
|
return texture(TextureSampler, uv);
|
||||||
|
#elif PS_MANUAL_LOD == 1
|
||||||
|
// FIXME add LOD: K - ( LOG2(Q) * (1 << L))
|
||||||
|
float K = MinMax.x;
|
||||||
|
float L = MinMax.y;
|
||||||
|
float bias = MinMax.z;
|
||||||
|
float max_lod = MinMax.w;
|
||||||
|
|
||||||
|
float gs_lod = K - log2(abs(PSin.t_float.w)) * L;
|
||||||
|
// FIXME max useful ?
|
||||||
|
//float lod = max(min(gs_lod, max_lod) - bias, 0.0f);
|
||||||
|
float lod = min(gs_lod, max_lod) - bias;
|
||||||
|
|
||||||
|
return textureLod(TextureSampler, uv, lod);
|
||||||
|
#else
|
||||||
|
return textureLod(TextureSampler, uv, 0.0f); // No lod
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sample_p(float idx)
|
||||||
|
{
|
||||||
|
return texture(PaletteSampler, vec2(idx, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 clamp_wrap_uv(vec4 uv)
|
||||||
|
{
|
||||||
|
vec4 uv_out = uv;
|
||||||
|
#if PS_INVALID_TEX0 == 1
|
||||||
|
vec4 tex_size = WH.zwzw;
|
||||||
|
#else
|
||||||
|
vec4 tex_size = WH.xyxy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_WMS == PS_WMT
|
||||||
|
|
||||||
|
#if PS_WMS == 2
|
||||||
|
uv_out = clamp(uv, MinMax.xyxy, MinMax.zwzw);
|
||||||
|
#elif PS_WMS == 3
|
||||||
|
#if PS_FST == 0
|
||||||
|
// wrap negative uv coords to avoid an off by one error that shifted
|
||||||
|
// textures. Fixes Xenosaga's hair issue.
|
||||||
|
uv = fract(uv);
|
||||||
|
#endif
|
||||||
|
uv_out = vec4((uvec4(uv * tex_size) & MskFix.xyxy) | MskFix.zwzw) / tex_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // PS_WMS != PS_WMT
|
||||||
|
|
||||||
|
#if PS_WMS == 2
|
||||||
|
uv_out.xz = clamp(uv.xz, MinMax.xx, MinMax.zz);
|
||||||
|
|
||||||
|
#elif PS_WMS == 3
|
||||||
|
#if PS_FST == 0
|
||||||
|
uv.xz = fract(uv.xz);
|
||||||
|
#endif
|
||||||
|
uv_out.xz = vec2((uvec2(uv.xz * tex_size.xx) & MskFix.xx) | MskFix.zz) / tex_size.xx;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_WMT == 2
|
||||||
|
uv_out.yw = clamp(uv.yw, MinMax.yy, MinMax.ww);
|
||||||
|
|
||||||
|
#elif PS_WMT == 3
|
||||||
|
#if PS_FST == 0
|
||||||
|
uv.yw = fract(uv.yw);
|
||||||
|
#endif
|
||||||
|
uv_out.yw = vec2((uvec2(uv.yw * tex_size.yy) & MskFix.yy) | MskFix.ww) / tex_size.yy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return uv_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 sample_4c(vec4 uv)
|
||||||
|
{
|
||||||
|
mat4 c;
|
||||||
|
|
||||||
|
// Note: texture gather can't be used because of special clamping/wrapping
|
||||||
|
// Also it doesn't support lod
|
||||||
|
c[0] = sample_c(uv.xy);
|
||||||
|
c[1] = sample_c(uv.zy);
|
||||||
|
c[2] = sample_c(uv.xw);
|
||||||
|
c[3] = sample_c(uv.zw);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sample_4_index(vec4 uv)
|
||||||
|
{
|
||||||
|
vec4 c;
|
||||||
|
|
||||||
|
// Either GS will send a texture that contains a single channel
|
||||||
|
// in this case the red channel is remapped as alpha channel
|
||||||
|
//
|
||||||
|
// Or we have an old RT (ie RGBA8) that contains index (4/8) in the alpha channel
|
||||||
|
|
||||||
|
// Note: texture gather can't be used because of special clamping/wrapping
|
||||||
|
// Also it doesn't support lod
|
||||||
|
c.x = sample_c(uv.xy).a;
|
||||||
|
c.y = sample_c(uv.zy).a;
|
||||||
|
c.z = sample_c(uv.xw).a;
|
||||||
|
c.w = sample_c(uv.zw).a;
|
||||||
|
|
||||||
|
uvec4 i = uvec4(c * 255.0f + 0.5f); // Denormalize value
|
||||||
|
|
||||||
|
#if PS_PAL_FMT == 1
|
||||||
|
// 4HL
|
||||||
|
return vec4(i & 0xFu) / 255.0f;
|
||||||
|
|
||||||
|
#elif PS_PAL_FMT == 2
|
||||||
|
// 4HH
|
||||||
|
return vec4(i >> 4u) / 255.0f;
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Most of texture will hit this code so keep normalized float value
|
||||||
|
|
||||||
|
// 8 bits
|
||||||
|
return c;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
mat4 sample_4p(vec4 u)
|
||||||
|
{
|
||||||
|
mat4 c;
|
||||||
|
|
||||||
|
c[0] = sample_p(u.x);
|
||||||
|
c[1] = sample_p(u.y);
|
||||||
|
c[2] = sample_p(u.z);
|
||||||
|
c[3] = sample_p(u.w);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fetch_raw_depth()
|
||||||
|
{
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
float multiplier = exp2(32.0f);
|
||||||
|
#else
|
||||||
|
float multiplier = exp2(24.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_TEX_IS_FB == 1
|
||||||
|
return int(fetch_rt().r * multiplier);
|
||||||
|
#elif PS_TEX_IS_DS == 1
|
||||||
|
return int(LAST_FRAG_DEPTH * multiplier);
|
||||||
|
#else
|
||||||
|
return int(texelFetch(TextureSampler, ivec2(gl_FragCoord.xy), 0).r * multiplier);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_raw_color()
|
||||||
|
{
|
||||||
|
#if PS_TEX_IS_FB == 1
|
||||||
|
return fetch_rt();
|
||||||
|
#elif PS_TEX_IS_DS == 1
|
||||||
|
return vec4(LAST_FRAG_DEPTH, 0.0f, 0.0f, 0.0f);
|
||||||
|
#else
|
||||||
|
return texelFetch(TextureSampler, ivec2(gl_FragCoord.xy), 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_c(ivec2 uv)
|
||||||
|
{
|
||||||
|
#if PS_TEX_IS_DS == 1
|
||||||
|
return vec4(LAST_FRAG_DEPTH, 0.0f, 0.0f, 0.0f);
|
||||||
|
#else
|
||||||
|
return texelFetch(TextureSampler, ivec2(uv), 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Depth sampling
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
ivec2 clamp_wrap_uv_depth(ivec2 uv)
|
||||||
|
{
|
||||||
|
ivec2 uv_out = uv;
|
||||||
|
|
||||||
|
// Keep the full precision
|
||||||
|
// It allow to multiply the ScalingFactor before the 1/16 coeff
|
||||||
|
ivec4 mask = ivec4(MskFix) << 4;
|
||||||
|
|
||||||
|
#if PS_WMS == PS_WMT
|
||||||
|
|
||||||
|
#if PS_WMS == 2
|
||||||
|
uv_out = clamp(uv, mask.xy, mask.zw);
|
||||||
|
#elif PS_WMS == 3
|
||||||
|
uv_out = (uv & mask.xy) | mask.zw;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else // PS_WMS != PS_WMT
|
||||||
|
|
||||||
|
#if PS_WMS == 2
|
||||||
|
uv_out.x = clamp(uv.x, mask.x, mask.z);
|
||||||
|
#elif PS_WMS == 3
|
||||||
|
uv_out.x = (uv.x & mask.x) | mask.z;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_WMT == 2
|
||||||
|
uv_out.y = clamp(uv.y, mask.y, mask.w);
|
||||||
|
#elif PS_WMT == 3
|
||||||
|
uv_out.y = (uv.y & mask.y) | mask.w;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return uv_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 sample_depth(vec2 st)
|
||||||
|
{
|
||||||
|
vec2 uv_f = vec2(clamp_wrap_uv_depth(ivec2(st))) * vec2(float(PS_SCALE_FACTOR)) * vec2(1.0f/16.0f);
|
||||||
|
ivec2 uv = ivec2(uv_f);
|
||||||
|
|
||||||
|
vec4 t = vec4(0.0f);
|
||||||
|
#if PS_TALES_OF_ABYSS_HLE == 1
|
||||||
|
// Warning: UV can't be used in channel effect
|
||||||
|
int depth = fetch_raw_depth();
|
||||||
|
|
||||||
|
// Convert msb based on the palette
|
||||||
|
t = texelFetch(PaletteSampler, ivec2((depth >> 8) & 0xFF, 0), 0) * 255.0f;
|
||||||
|
|
||||||
|
#elif PS_URBAN_CHAOS_HLE == 1
|
||||||
|
// Depth buffer is read as a RGB5A1 texture. The game try to extract the green channel.
|
||||||
|
// So it will do a first channel trick to extract lsb, value is right-shifted.
|
||||||
|
// Then a new channel trick to extract msb which will shifted to the left.
|
||||||
|
// OpenGL uses a FLOAT32 format for the depth so it requires a couple of conversion.
|
||||||
|
// To be faster both steps (msb&lsb) are done in a single pass.
|
||||||
|
|
||||||
|
// Warning: UV can't be used in channel effect
|
||||||
|
int depth = fetch_raw_depth();
|
||||||
|
|
||||||
|
// Convert lsb based on the palette
|
||||||
|
t = texelFetch(PaletteSampler, ivec2((depth & 0xFF), 0), 0) * 255.0f;
|
||||||
|
|
||||||
|
// Msb is easier
|
||||||
|
float green = float((depth >> 8) & 0xFF) * 36.0f;
|
||||||
|
green = min(green, 255.0f);
|
||||||
|
|
||||||
|
t.g += green;
|
||||||
|
|
||||||
|
|
||||||
|
#elif PS_DEPTH_FMT == 1
|
||||||
|
// Based on ps_convert_float32_rgba8 of convert
|
||||||
|
// Convert a GL_FLOAT32 depth texture into a RGBA color texture
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||||
|
#else
|
||||||
|
uint d = uint(fetch_c(uv).r * exp2(24.0f));
|
||||||
|
#endif
|
||||||
|
t = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24)));
|
||||||
|
|
||||||
|
#elif PS_DEPTH_FMT == 2
|
||||||
|
// Based on ps_convert_float16_rgb5a1 of convert
|
||||||
|
// Convert a GL_FLOAT32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||||
|
#if HAS_CLIP_CONTROL
|
||||||
|
uint d = uint(fetch_c(uv).r * exp2(32.0f));
|
||||||
|
#else
|
||||||
|
uint d = uint(fetch_c(uv).r * exp2(24.0f));
|
||||||
|
#endif
|
||||||
|
t = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) * vec4(8.0f, 8.0f, 8.0f, 128.0f);
|
||||||
|
|
||||||
|
#elif PS_DEPTH_FMT == 3
|
||||||
|
// Convert a RGBA/RGB5A1 color texture into a RGBA/RGB5A1 color texture
|
||||||
|
t = fetch_c(uv) * 255.0f;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// warning t ranges from 0 to 255
|
||||||
|
#if (PS_AEM_FMT == FMT_24)
|
||||||
|
t.a = ( (PS_AEM == 0) || any(bvec3(t.rgb)) ) ? 255.0f * TA.x : 0.0f;
|
||||||
|
#elif (PS_AEM_FMT == FMT_16)
|
||||||
|
t.a = t.a >= 128.0f ? 255.0f * TA.y : ( (PS_AEM == 0) || any(bvec3(t.rgb)) ) ? 255.0f * TA.x : 0.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Fetch a Single Channel
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
vec4 fetch_red()
|
||||||
|
{
|
||||||
|
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||||
|
int depth = (fetch_raw_depth()) & 0xFF;
|
||||||
|
vec4 rt = vec4(depth) / 255.0f;
|
||||||
|
#else
|
||||||
|
vec4 rt = fetch_raw_color();
|
||||||
|
#endif
|
||||||
|
return sample_p(rt.r) * 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_green()
|
||||||
|
{
|
||||||
|
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||||
|
int depth = (fetch_raw_depth() >> 8) & 0xFF;
|
||||||
|
vec4 rt = vec4(depth) / 255.0f;
|
||||||
|
#else
|
||||||
|
vec4 rt = fetch_raw_color();
|
||||||
|
#endif
|
||||||
|
return sample_p(rt.g) * 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_blue()
|
||||||
|
{
|
||||||
|
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||||
|
int depth = (fetch_raw_depth() >> 16) & 0xFF;
|
||||||
|
vec4 rt = vec4(depth) / 255.0f;
|
||||||
|
#else
|
||||||
|
vec4 rt = fetch_raw_color();
|
||||||
|
#endif
|
||||||
|
return sample_p(rt.b) * 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_alpha()
|
||||||
|
{
|
||||||
|
vec4 rt = fetch_raw_color();
|
||||||
|
return sample_p(rt.a) * 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_rgb()
|
||||||
|
{
|
||||||
|
vec4 rt = fetch_raw_color();
|
||||||
|
vec4 c = vec4(sample_p(rt.r).r, sample_p(rt.g).g, sample_p(rt.b).b, 1.0f);
|
||||||
|
return c * 255.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 fetch_gXbY()
|
||||||
|
{
|
||||||
|
#if PS_DEPTH_FMT == 1 || PS_DEPTH_FMT == 2
|
||||||
|
int depth = fetch_raw_depth();
|
||||||
|
int bg = (depth >> (8 + ChannelShuffle.w)) & 0xFF;
|
||||||
|
return vec4(bg);
|
||||||
|
#else
|
||||||
|
ivec4 rt = ivec4(fetch_raw_color() * 255.0f);
|
||||||
|
int green = (rt.g >> ChannelShuffle.w) & ChannelShuffle.z;
|
||||||
|
int blue = (rt.b << ChannelShuffle.y) & ChannelShuffle.x;
|
||||||
|
return vec4(green | blue);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
vec4 sample_color(vec2 st)
|
||||||
|
{
|
||||||
|
#if (PS_TCOFFSETHACK == 1)
|
||||||
|
st += TC_OffsetHack.xy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 t;
|
||||||
|
mat4 c;
|
||||||
|
vec2 dd;
|
||||||
|
|
||||||
|
// FIXME I'm not sure this condition is useful (I think code will be optimized)
|
||||||
|
#if (PS_LTF == 0 && PS_AEM_FMT == FMT_32 && PS_PAL_FMT == 0 && PS_WMS < 2 && PS_WMT < 2)
|
||||||
|
// No software LTF and pure 32 bits RGBA texure without special texture wrapping
|
||||||
|
c[0] = sample_c(st);
|
||||||
|
#ifdef TEX_COORD_DEBUG
|
||||||
|
c[0].rg = st.xy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
vec4 uv;
|
||||||
|
|
||||||
|
if(PS_LTF != 0)
|
||||||
|
{
|
||||||
|
uv = st.xyxy + HalfTexel;
|
||||||
|
dd = fract(uv.xy * WH.zw);
|
||||||
|
#if (PS_FST == 0)
|
||||||
|
// Background in Shin Megami Tensei Lucifers
|
||||||
|
// I suspect that uv isn't a standard number, so fract is outside of the [0;1] range
|
||||||
|
// Note: it is free on GPU but let's do it only for float coordinate
|
||||||
|
dd = clamp(dd, vec2(0.0f), vec2(1.0f));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uv = st.xyxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
uv = clamp_wrap_uv(uv);
|
||||||
|
|
||||||
|
#if PS_PAL_FMT != 0
|
||||||
|
c = sample_4p(sample_4_index(uv));
|
||||||
|
#else
|
||||||
|
c = sample_4c(uv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TEX_COORD_DEBUG
|
||||||
|
c[0].rg = uv.xy;
|
||||||
|
c[1].rg = uv.xy;
|
||||||
|
c[2].rg = uv.xy;
|
||||||
|
c[3].rg = uv.xy;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// PERF note: using dot product reduces by 1 the number of instruction
|
||||||
|
// but I'm not sure it is equivalent neither faster.
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
//float sum = dot(c[i].rgb, vec3(1.0f));
|
||||||
|
#if (PS_AEM_FMT == FMT_24)
|
||||||
|
c[i].a = ( (PS_AEM == 0) || any(bvec3(c[i].rgb)) ) ? TA.x : 0.0f;
|
||||||
|
//c[i].a = ( (PS_AEM == 0) || (sum > 0.0f) ) ? TA.x : 0.0f;
|
||||||
|
#elif (PS_AEM_FMT == FMT_16)
|
||||||
|
c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || any(bvec3(c[i].rgb)) ) ? TA.x : 0.0f;
|
||||||
|
//c[i].a = c[i].a >= 0.5 ? TA.y : ( (PS_AEM == 0) || (sum > 0.0f) ) ? TA.x : 0.0f;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if(PS_LTF != 0)
|
||||||
|
t = mix(mix(c[0], c[1], dd.x), mix(c[2], c[3], dd.x), dd.y);
|
||||||
|
#else
|
||||||
|
t = c[0];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// The 0.05f helps to fix the overbloom of sotc
|
||||||
|
// I think the issue is related to the rounding of texture coodinate. The linear (from fixed unit)
|
||||||
|
// interpolation could be slightly below the correct one.
|
||||||
|
return trunc(t * 255.0f + 0.05f);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 tfx(vec4 T, vec4 C)
|
||||||
|
{
|
||||||
|
vec4 C_out;
|
||||||
|
vec4 FxT = trunc(trunc(C) * T / 128.0f);
|
||||||
|
|
||||||
|
#if (PS_TFX == 0)
|
||||||
|
C_out = FxT;
|
||||||
|
#elif (PS_TFX == 1)
|
||||||
|
C_out = T;
|
||||||
|
#elif (PS_TFX == 2)
|
||||||
|
C_out.rgb = FxT.rgb + C.a;
|
||||||
|
C_out.a = T.a + C.a;
|
||||||
|
#elif (PS_TFX == 3)
|
||||||
|
C_out.rgb = FxT.rgb + C.a;
|
||||||
|
C_out.a = T.a;
|
||||||
|
#else
|
||||||
|
C_out = C;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (PS_TCC == 0)
|
||||||
|
C_out.a = C.a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (PS_TFX == 0) || (PS_TFX == 2) || (PS_TFX == 3)
|
||||||
|
// Clamp only when it is useful
|
||||||
|
C_out = min(C_out, 255.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return C_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void atst(vec4 C)
|
||||||
|
{
|
||||||
|
float a = C.a;
|
||||||
|
|
||||||
|
#if (PS_ATST == 0)
|
||||||
|
// nothing to do
|
||||||
|
#elif (PS_ATST == 1)
|
||||||
|
if (a > AREF) discard;
|
||||||
|
#elif (PS_ATST == 2)
|
||||||
|
if (a < AREF) discard;
|
||||||
|
#elif (PS_ATST == 3)
|
||||||
|
if (abs(a - AREF) > 0.5f) discard;
|
||||||
|
#elif (PS_ATST == 4)
|
||||||
|
if (abs(a - AREF) < 0.5f) discard;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void fog(inout vec4 C, float f)
|
||||||
|
{
|
||||||
|
#if PS_FOG != 0
|
||||||
|
C.rgb = trunc(mix(FogColor, C.rgb, f));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 ps_color()
|
||||||
|
{
|
||||||
|
//FIXME: maybe we can set gl_Position.w = q in VS
|
||||||
|
#if (PS_FST == 0) && (PS_INVALID_TEX0 == 1)
|
||||||
|
// Re-normalize coordinate from invalid GS to corrected texture size
|
||||||
|
vec2 st = (PSin.t_float.xy * WH.xy) / (vec2(PSin.t_float.w) * WH.zw);
|
||||||
|
vec2 st_int = (PSin.t_int.zw * WH.xy) / (vec2(PSin.t_float.w) * WH.zw);
|
||||||
|
#elif (PS_FST == 0)
|
||||||
|
vec2 st = PSin.t_float.xy / vec2(PSin.t_float.w);
|
||||||
|
vec2 st_int = PSin.t_int.zw / vec2(PSin.t_float.w);
|
||||||
|
#else
|
||||||
|
// Note xy are normalized coordinate
|
||||||
|
vec2 st = PSin.t_int.xy;
|
||||||
|
vec2 st_int = PSin.t_int.zw;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_CHANNEL_FETCH == 1
|
||||||
|
vec4 T = fetch_red();
|
||||||
|
#elif PS_CHANNEL_FETCH == 2
|
||||||
|
vec4 T = fetch_green();
|
||||||
|
#elif PS_CHANNEL_FETCH == 3
|
||||||
|
vec4 T = fetch_blue();
|
||||||
|
#elif PS_CHANNEL_FETCH == 4
|
||||||
|
vec4 T = fetch_alpha();
|
||||||
|
#elif PS_CHANNEL_FETCH == 5
|
||||||
|
vec4 T = fetch_rgb();
|
||||||
|
#elif PS_CHANNEL_FETCH == 6
|
||||||
|
vec4 T = fetch_gXbY();
|
||||||
|
#elif PS_DEPTH_FMT > 0
|
||||||
|
// Integral coordinate
|
||||||
|
vec4 T = sample_depth(st_int);
|
||||||
|
#else
|
||||||
|
vec4 T = sample_color(st);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 C = tfx(T, PSin.c);
|
||||||
|
|
||||||
|
atst(C);
|
||||||
|
|
||||||
|
fog(C, PSin.t_float.z);
|
||||||
|
|
||||||
|
return C;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ps_fbmask(inout vec4 C)
|
||||||
|
{
|
||||||
|
// FIXME do I need special case for 16 bits
|
||||||
|
#if PS_FBMASK
|
||||||
|
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||||
|
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ps_dither(inout vec3 C)
|
||||||
|
{
|
||||||
|
#if PS_DITHER
|
||||||
|
#if PS_DITHER == 2
|
||||||
|
ivec2 fpos = ivec2(gl_FragCoord.xy);
|
||||||
|
#else
|
||||||
|
ivec2 fpos = ivec2(gl_FragCoord.xy / float(PS_SCALE_FACTOR));
|
||||||
|
#endif
|
||||||
|
C += DitherMatrix[fpos.y&3][fpos.x&3];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ps_color_clamp_wrap(inout vec3 C)
|
||||||
|
{
|
||||||
|
// When dithering the bottom 3 bits become meaningless and cause lines in the picture
|
||||||
|
// so we need to limit the color depth on dithered items
|
||||||
|
#if SW_BLEND || PS_DITHER || PS_FBMASK
|
||||||
|
|
||||||
|
// Correct the Color value based on the output format
|
||||||
|
#if PS_COLCLIP == 0 && PS_HDR == 0
|
||||||
|
// Standard Clamp
|
||||||
|
C = clamp(C, vec3(0.0f), vec3(255.0f));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// FIXME rouding of negative float?
|
||||||
|
// compiler uses trunc but it might need floor
|
||||||
|
|
||||||
|
// Warning: normally blending equation is mult(A, B) = A * B >> 7. GPU have the full accuracy
|
||||||
|
// GS: Color = 1, Alpha = 255 => output 1
|
||||||
|
// GPU: Color = 1/255, Alpha = 255/255 * 255/128 => output 1.9921875
|
||||||
|
#if PS_DFMT == FMT_16 && PS_BLEND_MIX == 0
|
||||||
|
// In 16 bits format, only 5 bits of colors are used. It impacts shadows computation of Castlevania
|
||||||
|
C = vec3(ivec3(C) & ivec3(0xF8));
|
||||||
|
#elif PS_COLCLIP == 1 || PS_HDR == 1
|
||||||
|
C = vec3(ivec3(C) & ivec3(0xFF));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ps_blend(inout vec4 Color, inout float As)
|
||||||
|
{
|
||||||
|
#if SW_BLEND
|
||||||
|
|
||||||
|
// PABE
|
||||||
|
#if PS_PABE
|
||||||
|
// No blending so early exit
|
||||||
|
if (As < 1.0f)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec3 Cs = Color.rgb;
|
||||||
|
|
||||||
|
#if SW_BLEND_NEEDS_RT
|
||||||
|
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||||
|
// FIXME FMT_16 case
|
||||||
|
// FIXME Ad or Ad * 2?
|
||||||
|
float Ad = RT.a / 128.0f;
|
||||||
|
|
||||||
|
// Let the compiler do its jobs !
|
||||||
|
vec3 Cd = RT.rgb;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_BLEND_A == 0
|
||||||
|
vec3 A = Cs;
|
||||||
|
#elif PS_BLEND_A == 1
|
||||||
|
vec3 A = Cd;
|
||||||
|
#else
|
||||||
|
vec3 A = vec3(0.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_BLEND_B == 0
|
||||||
|
vec3 B = Cs;
|
||||||
|
#elif PS_BLEND_B == 1
|
||||||
|
vec3 B = Cd;
|
||||||
|
#else
|
||||||
|
vec3 B = vec3(0.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_BLEND_C == 0
|
||||||
|
float C = As;
|
||||||
|
#elif PS_BLEND_C == 1
|
||||||
|
float C = Ad;
|
||||||
|
#else
|
||||||
|
float C = Af;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_BLEND_D == 0
|
||||||
|
vec3 D = Cs;
|
||||||
|
#elif PS_BLEND_D == 1
|
||||||
|
vec3 D = Cd;
|
||||||
|
#else
|
||||||
|
vec3 D = vec3(0.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// As/Af clamp alpha for Blend mix
|
||||||
|
// We shouldn't clamp blend mix with clr1 as we want alpha higher
|
||||||
|
float C_clamped = C;
|
||||||
|
#if PS_BLEND_MIX > 0 && PS_CLR_HW != 1
|
||||||
|
C_clamped = min(C_clamped, 1.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_BLEND_A == PS_BLEND_B
|
||||||
|
Color.rgb = D;
|
||||||
|
// In blend_mix, HW adds on some alpha factor * dst.
|
||||||
|
// Truncating here wouldn't quite get the right result because it prevents the <1 bit here from combining with a <1 bit in dst to form a ≥1 amount that pushes over the truncation.
|
||||||
|
// Instead, apply an offset to convert HW's round to a floor.
|
||||||
|
// Since alpha is in 1/128 increments, subtracting (0.5 - 0.5/128 == 127/256) would get us what we want if GPUs blended in full precision.
|
||||||
|
// But they don't. Details here: https://github.com/PCSX2/pcsx2/pull/6809#issuecomment-1211473399
|
||||||
|
// Based on the scripts at the above link, the ideal choice for Intel GPUs is 126/256, AMD 120/256. Nvidia is a lost cause.
|
||||||
|
// 124/256 seems like a reasonable compromise, providing the correct answer 99.3% of the time on Intel (vs 99.6% for 126/256), and 97% of the time on AMD (vs 97.4% for 120/256).
|
||||||
|
#elif PS_BLEND_MIX == 2
|
||||||
|
Color.rgb = ((A - B) * C_clamped + D) + (124.0f/256.0f);
|
||||||
|
#elif PS_BLEND_MIX == 1
|
||||||
|
Color.rgb = ((A - B) * C_clamped + D) - (124.0f/256.0f);
|
||||||
|
#else
|
||||||
|
Color.rgb = trunc((A - B) * C + D);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_CLR_HW == 1
|
||||||
|
// Replace Af with As so we can do proper compensation for Alpha.
|
||||||
|
#if PS_BLEND_C == 2
|
||||||
|
As = Af;
|
||||||
|
#endif
|
||||||
|
// Subtract 1 for alpha to compensate for the changed equation,
|
||||||
|
// if c.rgb > 255.0f then we further need to adjust alpha accordingly,
|
||||||
|
// we pick the lowest overflow from all colors because it's the safest,
|
||||||
|
// we divide by 255 the color because we don't know Cd value,
|
||||||
|
// changed alpha should only be done for hw blend.
|
||||||
|
float min_color = min(min(Color.r, Color.g), Color.b);
|
||||||
|
float alpha_compensate = max(1.0f, min_color / 255.0f);
|
||||||
|
As -= alpha_compensate;
|
||||||
|
#elif PS_CLR_HW == 2
|
||||||
|
// Compensate slightly for Cd*(As + 1) - Cs*As.
|
||||||
|
// The initial factor we chose is 1 (0.00392)
|
||||||
|
// as that is the minimum color Cd can be,
|
||||||
|
// then we multiply by alpha to get the minimum
|
||||||
|
// blended value it can be.
|
||||||
|
float color_compensate = 1.0f * (C + 1.0f);
|
||||||
|
Color.rgb -= vec3(color_compensate);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
// Needed for Cd * (As/Ad/F + 1) blending modes
|
||||||
|
#if PS_CLR_HW == 1 || PS_CLR_HW == 5
|
||||||
|
Color.rgb = vec3(255.0f);
|
||||||
|
#elif PS_CLR_HW == 2 || PS_CLR_HW == 4
|
||||||
|
// Cd*As,Cd*Ad or Cd*F
|
||||||
|
|
||||||
|
#if PS_BLEND_C == 2
|
||||||
|
float Alpha = Af;
|
||||||
|
#else
|
||||||
|
float Alpha = As;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Color.rgb = max(vec3(0.0f), (Alpha - vec3(1.0f)));
|
||||||
|
Color.rgb *= vec3(255.0f);
|
||||||
|
#elif PS_CLR_HW == 3
|
||||||
|
// Needed for Cs*Ad, Cs*Ad + Cd, Cd - Cs*Ad
|
||||||
|
// Multiply Color.rgb by (255/128) to compensate for wrong Ad/255 value
|
||||||
|
|
||||||
|
Color.rgb *= (255.0f / 128.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void ps_main()
|
||||||
|
{
|
||||||
|
#if PS_SCANMSK & 2
|
||||||
|
// fail depth test on prohibited lines
|
||||||
|
if ((int(gl_FragCoord.y) & 1) == (PS_SCANMSK & 1))
|
||||||
|
discard;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_DATE >= 5
|
||||||
|
|
||||||
|
#if PS_WRITE_RG == 1
|
||||||
|
// Pseudo 16 bits access.
|
||||||
|
float rt_a = fetch_rt().g;
|
||||||
|
#else
|
||||||
|
float rt_a = fetch_rt().a;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (PS_DATE & 3) == 1
|
||||||
|
// DATM == 0: Pixel with alpha equal to 1 will failed
|
||||||
|
bool bad = (127.5f / 255.0f) < rt_a;
|
||||||
|
#elif (PS_DATE & 3) == 2
|
||||||
|
// DATM == 1: Pixel with alpha equal to 0 will failed
|
||||||
|
bool bad = rt_a < (127.5f / 255.0f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (bad) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_DATE == 3
|
||||||
|
int stencil_ceil = int(texelFetch(img_prim_min, ivec2(gl_FragCoord.xy), 0).r);
|
||||||
|
// Note gl_PrimitiveID == stencil_ceil will be the primitive that will update
|
||||||
|
// the bad alpha value so we must keep it.
|
||||||
|
|
||||||
|
if (gl_PrimitiveID > stencil_ceil) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 C = ps_color();
|
||||||
|
#if (APITRACE_DEBUG & 1) == 1
|
||||||
|
C.r = 255.0f;
|
||||||
|
#endif
|
||||||
|
#if (APITRACE_DEBUG & 2) == 2
|
||||||
|
C.g = 255.0f;
|
||||||
|
#endif
|
||||||
|
#if (APITRACE_DEBUG & 4) == 4
|
||||||
|
C.b = 255.0f;
|
||||||
|
#endif
|
||||||
|
#if (APITRACE_DEBUG & 8) == 8
|
||||||
|
C.a = 128.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_SHUFFLE
|
||||||
|
uvec4 denorm_c = uvec4(C);
|
||||||
|
uvec2 denorm_TA = uvec2(vec2(TA.xy) * 255.0f + 0.5f);
|
||||||
|
|
||||||
|
// Write RB part. Mask will take care of the correct destination
|
||||||
|
#if PS_READ_BA
|
||||||
|
C.rb = C.bb;
|
||||||
|
#else
|
||||||
|
C.rb = C.rr;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// FIXME precompute my_TA & 0x80
|
||||||
|
|
||||||
|
// Write GA part. Mask will take care of the correct destination
|
||||||
|
// Note: GLSL 4.50/GL_EXT_shader_integer_mix support a mix instruction to select a component\n"
|
||||||
|
// However Nvidia emulate it with an if (at least on kepler arch) ...\n"
|
||||||
|
#if PS_READ_BA
|
||||||
|
// bit field operation requires GL4 HW. Could be nice to merge it with step/mix below
|
||||||
|
// uint my_ta = (bool(bitfieldExtract(denorm_c.a, 7, 1))) ? denorm_TA.y : denorm_TA.x;
|
||||||
|
// denorm_c.a = bitfieldInsert(denorm_c.a, bitfieldExtract(my_ta, 7, 1), 7, 1);
|
||||||
|
// c.ga = vec2(float(denorm_c.a));
|
||||||
|
|
||||||
|
if (bool(denorm_c.a & 0x80u))
|
||||||
|
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||||
|
else
|
||||||
|
C.ga = vec2(float((denorm_c.a & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||||
|
|
||||||
|
#else
|
||||||
|
if (bool(denorm_c.g & 0x80u))
|
||||||
|
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.y & 0x80u)));
|
||||||
|
else
|
||||||
|
C.ga = vec2(float((denorm_c.g & 0x7Fu) | (denorm_TA.x & 0x80u)));
|
||||||
|
|
||||||
|
// Nice idea but step/mix requires 4 instructions
|
||||||
|
// set / trunc / I2F / Mad
|
||||||
|
//
|
||||||
|
// float sel = step(128.0f, c.g);
|
||||||
|
// vec2 c_shuffle = vec2((denorm_c.gg & 0x7Fu) | (denorm_TA & 0x80u));
|
||||||
|
// c.ga = mix(c_shuffle.xx, c_shuffle.yy, sel);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Must be done before alpha correction
|
||||||
|
|
||||||
|
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||||
|
#if PS_FIXED_ONE_A
|
||||||
|
C.a = 128.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SW_AD_TO_HW
|
||||||
|
vec4 RT = trunc(fetch_rt() * 255.0f + 0.1f);
|
||||||
|
float alpha_blend = RT.a / 128.0f;
|
||||||
|
#else
|
||||||
|
float alpha_blend = C.a / 128.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Correct the ALPHA value based on the output format
|
||||||
|
#if (PS_DFMT == FMT_16)
|
||||||
|
float A_one = 128.0f; // alpha output will be 0x80
|
||||||
|
C.a = (PS_FBA != 0) ? A_one : step(128.0f, C.a) * A_one;
|
||||||
|
#elif (PS_DFMT == FMT_32) && (PS_FBA != 0)
|
||||||
|
if(C.a < 128.0f) C.a += 128.0f;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Get first primitive that will write a failling alpha value
|
||||||
|
#if PS_DATE == 1
|
||||||
|
// DATM == 0
|
||||||
|
// Pixel with alpha equal to 1 will failed (128-255)
|
||||||
|
SV_Target0 = (C.a > 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||||
|
return;
|
||||||
|
#elif PS_DATE == 2
|
||||||
|
// DATM == 1
|
||||||
|
// Pixel with alpha equal to 0 will failed (0-127)
|
||||||
|
SV_Target0 = (C.a < 127.5f) ? vec4(gl_PrimitiveID) : vec4(0x7FFFFFFF);
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ps_blend(C, alpha_blend);
|
||||||
|
|
||||||
|
ps_dither(C.rgb);
|
||||||
|
|
||||||
|
// Color clamp/wrap needs to be done after sw blending and dithering
|
||||||
|
ps_color_clamp_wrap(C.rgb);
|
||||||
|
|
||||||
|
ps_fbmask(C);
|
||||||
|
|
||||||
|
#if !PS_NO_COLOR
|
||||||
|
#if PS_HDR == 1
|
||||||
|
SV_Target0 = vec4(C.rgb / 65535.0f, C.a / 255.0f);
|
||||||
|
#else
|
||||||
|
SV_Target0 = C / 255.0f;
|
||||||
|
#endif
|
||||||
|
#if !defined(DISABLE_DUAL_SOURCE) && !PS_NO_COLOR1
|
||||||
|
SV_Target1 = vec4(alpha_blend);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_NO_ABLEND
|
||||||
|
// write alpha blend factor into col0
|
||||||
|
SV_Target0.a = alpha_blend;
|
||||||
|
#endif
|
||||||
|
#if PS_ONLY_ALPHA
|
||||||
|
// rgb isn't used
|
||||||
|
SV_Target0.rgb = vec3(0.0f);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PS_ZCLAMP
|
||||||
|
gl_FragDepth = min(gl_FragCoord.z, MaxDepthPS);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
#ifndef PS_SCALE_FACTOR
|
||||||
|
#define PS_SCALE_FACTOR 1.0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef VERTEX_SHADER
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 a_pos;
|
||||||
|
layout(location = 1) in vec2 a_tex;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 v_tex;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(a_pos.x, -a_pos.y, a_pos.z, a_pos.w);
|
||||||
|
v_tex = a_tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FRAGMENT_SHADER
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 v_tex;
|
||||||
|
|
||||||
|
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||||
|
layout(location = 0) out uint o_col0;
|
||||||
|
#else
|
||||||
|
layout(location = 0) out vec4 o_col0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D samp0;
|
||||||
|
|
||||||
|
vec4 sample_c(vec2 uv)
|
||||||
|
{
|
||||||
|
return texture(samp0, uv);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ps_copy
|
||||||
|
void ps_copy()
|
||||||
|
{
|
||||||
|
o_col0 = sample_c(v_tex);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_depth_copy
|
||||||
|
void ps_depth_copy()
|
||||||
|
{
|
||||||
|
gl_FragDepth = sample_c(v_tex).r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_filter_transparency
|
||||||
|
void ps_filter_transparency()
|
||||||
|
{
|
||||||
|
vec4 c = sample_c(v_tex);
|
||||||
|
o_col0 = vec4(c.rgb, 1.0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_16bits
|
||||||
|
// Need to be careful with precision here, it can break games like Spider-Man 3 and Dogs Life
|
||||||
|
void ps_convert_rgba8_16bits()
|
||||||
|
{
|
||||||
|
uvec4 i = uvec4(sample_c(v_tex) * vec4(255.5f, 255.5f, 255.5f, 255.5f));
|
||||||
|
|
||||||
|
o_col0 = ((i.x & 0x00F8u) >> 3) | ((i.y & 0x00F8u) << 2) | ((i.z & 0x00f8u) << 7) | ((i.w & 0x80u) << 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_datm1
|
||||||
|
void ps_datm1()
|
||||||
|
{
|
||||||
|
o_col0 = vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||||
|
discard;
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_datm0
|
||||||
|
void ps_datm0()
|
||||||
|
{
|
||||||
|
o_col0 = vec4(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_hdr_init
|
||||||
|
void ps_hdr_init()
|
||||||
|
{
|
||||||
|
vec4 value = sample_c(v_tex);
|
||||||
|
o_col0 = vec4(roundEven(value.rgb * 255.0f) / 65535.0f, value.a);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_hdr_resolve
|
||||||
|
void ps_hdr_resolve()
|
||||||
|
{
|
||||||
|
vec4 value = sample_c(v_tex);
|
||||||
|
o_col0 = vec4(vec3(uvec3(value.rgb * 65535.5f) & 255u) / 255.0f, value.a);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_float32_32bits
|
||||||
|
void ps_convert_float32_32bits()
|
||||||
|
{
|
||||||
|
// Convert a vec32 depth texture into a 32 bits UINT texture
|
||||||
|
o_col0 = uint(exp2(32.0f) * sample_c(v_tex).r);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_float32_rgba8
|
||||||
|
void ps_convert_float32_rgba8()
|
||||||
|
{
|
||||||
|
// Convert a vec32 depth texture into a RGBA color texture
|
||||||
|
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||||
|
o_col0 = vec4(uvec4((d & 0xFFu), ((d >> 8) & 0xFFu), ((d >> 16) & 0xFFu), (d >> 24))) / vec4(255.0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_float16_rgb5a1
|
||||||
|
void ps_convert_float16_rgb5a1()
|
||||||
|
{
|
||||||
|
// Convert a vec32 (only 16 lsb) depth into a RGB5A1 color texture
|
||||||
|
uint d = uint(sample_c(v_tex).r * exp2(32.0f));
|
||||||
|
o_col0 = vec4(uvec4((d & 0x1Fu), ((d >> 5) & 0x1Fu), ((d >> 10) & 0x1Fu), (d >> 15) & 0x01u)) / vec4(32.0f, 32.0f, 32.0f, 1.0f);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float rgba8_to_depth32(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||||
|
return float(c.r | (c.g << 8) | (c.b << 16) | (c.a << 24)) * exp2(-32.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float rgba8_to_depth24(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec3 c = uvec3(unorm.rgb * vec3(255.5f));
|
||||||
|
return float(c.r | (c.g << 8) | (c.b << 16)) * exp2(-32.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float rgba8_to_depth16(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec2 c = uvec2(unorm.rg * vec2(255.5f));
|
||||||
|
return float(c.r | (c.g << 8)) * exp2(-32.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float rgb5a1_to_depth16(vec4 unorm)
|
||||||
|
{
|
||||||
|
uvec4 c = uvec4(unorm * vec4(255.5f));
|
||||||
|
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float32
|
||||||
|
void ps_convert_rgba8_float32()
|
||||||
|
{
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
gl_FragDepth = rgba8_to_depth32(sample_c(v_tex));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float24
|
||||||
|
void ps_convert_rgba8_float24()
|
||||||
|
{
|
||||||
|
// Same as above but without the alpha channel (24 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
gl_FragDepth = rgba8_to_depth24(sample_c(v_tex));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float16
|
||||||
|
void ps_convert_rgba8_float16()
|
||||||
|
{
|
||||||
|
// Same as above but without the A/B channels (16 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
gl_FragDepth = rgba8_to_depth16(sample_c(v_tex));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgb5a1_float16
|
||||||
|
void ps_convert_rgb5a1_float16()
|
||||||
|
{
|
||||||
|
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||||
|
gl_FragDepth = rgb5a1_to_depth16(sample_c(v_tex));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
|
||||||
|
ivec2 dims = textureSize(samp0, 0); \
|
||||||
|
vec2 top_left_f = v_tex * vec2(dims) - 0.5f; \
|
||||||
|
ivec2 top_left = ivec2(floor(top_left_f)); \
|
||||||
|
ivec4 coords = clamp(ivec4(top_left, top_left + 1), ivec4(0), dims.xyxy - 1); \
|
||||||
|
vec2 mix_vals = fract(top_left_f); \
|
||||||
|
float depthTL = CONVERT_FN(texelFetch(samp0, coords.xy, 0)); \
|
||||||
|
float depthTR = CONVERT_FN(texelFetch(samp0, coords.zy, 0)); \
|
||||||
|
float depthBL = CONVERT_FN(texelFetch(samp0, coords.xw, 0)); \
|
||||||
|
float depthBR = CONVERT_FN(texelFetch(samp0, coords.zw, 0)); \
|
||||||
|
gl_FragDepth = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float32_biln
|
||||||
|
void ps_convert_rgba8_float32_biln()
|
||||||
|
{
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth32);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float24_biln
|
||||||
|
void ps_convert_rgba8_float24_biln()
|
||||||
|
{
|
||||||
|
// Same as above but without the alpha channel (24 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth24);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba8_float16_biln
|
||||||
|
void ps_convert_rgba8_float16_biln()
|
||||||
|
{
|
||||||
|
// Same as above but without the A/B channels (16 bits Z)
|
||||||
|
|
||||||
|
// Convert an RGBA texture into a float depth texture
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgba8_to_depth16);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgb5a1_float16_biln
|
||||||
|
void ps_convert_rgb5a1_float16_biln()
|
||||||
|
{
|
||||||
|
// Convert an RGB5A1 (saved as RGBA8) color to a 16 bit Z
|
||||||
|
SAMPLE_RGBA_DEPTH_BILN(rgb5a1_to_depth16);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_convert_rgba_8i
|
||||||
|
void ps_convert_rgba_8i()
|
||||||
|
{
|
||||||
|
// Convert a RGBA texture into a 8 bits packed texture
|
||||||
|
// Input column: 8x2 RGBA pixels
|
||||||
|
// 0: 8 RGBA
|
||||||
|
// 1: 8 RGBA
|
||||||
|
// Output column: 16x4 Index pixels
|
||||||
|
// 0: 8 R | 8 B
|
||||||
|
// 1: 8 R | 8 B
|
||||||
|
// 2: 8 G | 8 A
|
||||||
|
// 3: 8 G | 8 A
|
||||||
|
uvec2 pos = uvec2(gl_FragCoord.xy);
|
||||||
|
|
||||||
|
// Collapse separate R G B A areas into their base pixel
|
||||||
|
uvec2 block = (pos & ~uvec2(15u, 3u)) >> 1;
|
||||||
|
uvec2 subblock = pos & uvec2(7u, 1u);
|
||||||
|
uvec2 coord = block | subblock;
|
||||||
|
|
||||||
|
// Apply offset to cols 1 and 2
|
||||||
|
uint is_col23 = pos.y & 4u;
|
||||||
|
uint is_col13 = pos.y & 2u;
|
||||||
|
uint is_col12 = is_col23 ^ (is_col13 << 1);
|
||||||
|
coord.x ^= is_col12; // If cols 1 or 2, flip bit 3 of x
|
||||||
|
|
||||||
|
if (floor(PS_SCALE_FACTOR) != PS_SCALE_FACTOR)
|
||||||
|
coord = uvec2(vec2(coord) * PS_SCALE_FACTOR);
|
||||||
|
else
|
||||||
|
coord *= uvec2(PS_SCALE_FACTOR);
|
||||||
|
|
||||||
|
vec4 pixel = texelFetch(samp0, ivec2(coord), 0);
|
||||||
|
vec2 sel0 = (pos.y & 2u) == 0u ? pixel.rb : pixel.ga;
|
||||||
|
float sel1 = (pos.x & 8u) == 0u ? sel0.x : sel0.y;
|
||||||
|
o_col0 = vec4(sel1); // Divide by something here?
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ps_yuv
|
||||||
|
layout(push_constant) uniform cb10
|
||||||
|
{
|
||||||
|
int EMODA;
|
||||||
|
int EMODC;
|
||||||
|
};
|
||||||
|
|
||||||
|
void ps_yuv()
|
||||||
|
{
|
||||||
|
vec4 i = sample_c(v_tex);
|
||||||
|
vec4 o;
|
||||||
|
|
||||||
|
mat3 rgb2yuv;
|
||||||
|
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||||
|
rgb2yuv[1] = vec3(0.114, 0.500, -0.081);
|
||||||
|
rgb2yuv[2] = vec3(0.299, -0.169, 0.500);
|
||||||
|
|
||||||
|
vec3 yuv = rgb2yuv * i.gbr;
|
||||||
|
|
||||||
|
float Y = float(0xDB)/255.0f * yuv.x + float(0x10)/255.0f;
|
||||||
|
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||||
|
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||||
|
|
||||||
|
switch(EMODA) {
|
||||||
|
case 0:
|
||||||
|
o.a = i.a;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
o.a = Y;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
o.a = Y/2.0f;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
o.a = 0.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(EMODC) {
|
||||||
|
case 0:
|
||||||
|
o.rgb = i.rgb;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
o.rgb = vec3(Y);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
o.rgb = vec3(Y, Cb, Cr);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
o.rgb = vec3(i.a);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
o_col0 = o;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ps_stencil_image_init_0) || defined(ps_stencil_image_init_1)
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
o_col0 = vec4(0x7FFFFFFF);
|
||||||
|
|
||||||
|
#ifdef ps_stencil_image_init_0
|
||||||
|
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
|
||||||
|
o_col0 = vec4(-1);
|
||||||
|
#endif
|
||||||
|
#ifdef ps_stencil_image_init_1
|
||||||
|
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
|
||||||
|
o_col0 = vec4(-1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 619 B |
Binary file not shown.
|
After Width: | Height: | Size: 620 B |
@@ -0,0 +1,56 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "BLOX",
|
||||||
|
"id": "f82d4c9fdd81518537d88f70c6602bb5",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/BLOX.vb",
|
||||||
|
"authors": ["KR155E"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "BLOX 2",
|
||||||
|
"id": "cc91d6389df2c9777919e8e8ab2c0e66",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/BLOX 2.vb",
|
||||||
|
"authors": ["KR155E"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Elevated Speed",
|
||||||
|
"id": "8f7bcfdd0f412d9060b06a97a89fe202",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/Elevated Speed.vb",
|
||||||
|
"authors": ["PizzaRollsRoyce"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fishbone",
|
||||||
|
"id": "61e38e4e0c43aa8d6274a89ebedd3063",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/Fishbone.vb",
|
||||||
|
"authors": ["thunderstruck"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Formula V Public Demo",
|
||||||
|
"id": "34e9a2ffd60f7ea565caada82d57f29f",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/Formula V Public Demo.vb",
|
||||||
|
"authors": ["KR155E"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Red Square",
|
||||||
|
"id": "9c372321204b9fa65f9324f98aae53ff",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/Red Square.vb",
|
||||||
|
"authors": ["Kresna", "Nyrator"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "The Red Castle",
|
||||||
|
"id": "cdb404ff3e1df7b3c13214ac5409d512",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/The Red Castle.vb",
|
||||||
|
"authors": ["Timothy Beck"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VUE Snake",
|
||||||
|
"id": "ccfa400a0ff3d717dad36a3f736fd34d",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/VUE Snake.vb",
|
||||||
|
"authors": ["KR155E"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VUEngine Platformer Demo",
|
||||||
|
"id": "c96d91fb97572a0af7d53f63b292e0f2",
|
||||||
|
"uri": "content://com.simongellis.vvb.assets/games/VUEngine Platformer Demo.vb",
|
||||||
|
"authors": ["KR155E"]
|
||||||
|
}
|
||||||
|
]
|
||||||
+6
-2
@@ -228,11 +228,15 @@ files:
|
|||||||
- name: gamecontrollerdb.txt
|
- name: gamecontrollerdb.txt
|
||||||
required: false
|
required: false
|
||||||
bundled: true
|
bundled: true
|
||||||
|
unsourceable: "opened through the asset manager inside the package, so no file on disk reaches this load"
|
||||||
description: "SDL controller mapping database"
|
description: "SDL controller mapping database"
|
||||||
note: >-
|
note: >-
|
||||||
Read from the assets of the package at startup and handed to SDL as a
|
Read from the assets of the package at startup and handed to SDL as a
|
||||||
memory stream. Nothing outside the archive replaces this copy; an added pad
|
memory stream. The asset manager reads inside the archive and the path is
|
||||||
mapping goes in through controller_map.txt instead.
|
a constant, so there is no search order and nothing outside the package
|
||||||
|
replaces this copy; an added pad mapping goes in through
|
||||||
|
controller_map.txt instead. The revision shipped here is 589031 bytes and
|
||||||
|
is not the one other releases carry under this name.
|
||||||
source_ref: "android/app/src/main/cpp/xemu_android.cpp:193-268"
|
source_ref: "android/app/src/main/cpp/xemu_android.cpp:193-268"
|
||||||
|
|
||||||
- name: X1_Covers.txt
|
- name: X1_Covers.txt
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
emulator: "My Boy!"
|
||||||
|
type: standalone
|
||||||
|
core_classification: embedded_hle
|
||||||
|
source: "https://play.google.com/store/apps/details?id=com.fastemulator.gba"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Pixel Respawn LLC"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "2.0.3"
|
||||||
|
display_name: "Nintendo - Game Boy Advance (My Boy!)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "my-boy"
|
||||||
|
- "My Boy!"
|
||||||
|
- "MY-BOY"
|
||||||
|
systems:
|
||||||
|
- nintendo-gba
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Android package com.fastemulator.gba, closed source, sold on Google Play, reached by
|
||||||
|
ES-DE through its MY-BOY find rule and started with android.intent.action.VIEW on the
|
||||||
|
content URI of the game. Two Play distribution builds carrying the developer
|
||||||
|
certificate sha256 942e532dc3a3608a1d04760b8e1b09a2f11c0c8f64ae8bb441f0c8ab1122a7ab
|
||||||
|
are read here: 2.0.3 (versionCode 90053, minSdk 21, targetSdk 33, arm64-v8a and
|
||||||
|
armeabi-v7a, bundletool v1 signer and the Play source stamp) and 1.8.0 (versionCode
|
||||||
|
90048, armeabi and x86). Line numbers below are those of 2.0.3 and native addresses
|
||||||
|
are arm64-v8a of the same build; 1.8.0 addresses are its x86 library. Four rebuilt
|
||||||
|
copies were rejected on their certificate: 2.0.9 (CN=APKVISION.ORG), 2.0.8 (C=RU,
|
||||||
|
O=A1), 2.0.6 (C=IN) and a second 1.8.0 (O=jojoy.mod).
|
||||||
|
|
||||||
|
One system is emulated, Game Boy Advance, in libgba.so behind a JNI bridge
|
||||||
|
(Link.java:21-23,83). Content is a .gba or .bin document, or the first entry with one
|
||||||
|
of those extensions in a zip document (g.java:71-78,80-100,113-122,
|
||||||
|
EmulatorActivity.java:2001).
|
||||||
|
|
||||||
|
The BIOS is the one file the user supplies. The document picker takes any name from
|
||||||
|
any location, and the choice is stored as the persisted URI biosUri
|
||||||
|
(settings/EmulatorSettings.java:65-73,121-135). A document is
|
||||||
|
accepted only when its reported size is exactly 16384 bytes, or, for an
|
||||||
|
application/zip document, when an entry declares that size; the name is never
|
||||||
|
examined (g.java:66-68,80-100,102-111). One that fails leaves the preference reading
|
||||||
|
"Unrecognized BIOS file." at pick time and on every later visit to the screen
|
||||||
|
(settings/EmulatorSettings.java:101-108,131-133). At game start the stream is read
|
||||||
|
until 16384 bytes are in hand and anything shorter raises, which reports "Load BIOS
|
||||||
|
failed." and passes null (EmulatorActivity.java:1564-1599).
|
||||||
|
|
||||||
|
The read happens only while Use BIOS is on, off until the user turns it on; both Boot
|
||||||
|
BIOS and the file picker depend on that switch, and the advanced reset returns all
|
||||||
|
three to their defaults (res/xml/settings_advanced.xml,
|
||||||
|
settings/EmulatorSettings.java:79-80).
|
||||||
|
|
||||||
|
The bytes are copied to the head of the emulator's 32 KB BIOS area, offsets 0x2c and
|
||||||
|
0x39 are cleared, the remainder is zero filled and a flag byte at the end of the area
|
||||||
|
records that an image is installed (libgba.so 0x165fbc-0x166070, 0x15faf0-0x15fb5c).
|
||||||
|
With no image that flag is false and the area is filled instead with a 692 byte
|
||||||
|
replacement inflated from a 488 byte deflate stream in .rodata, byte identical between
|
||||||
|
1.8.0 and 2.0.3 (0x15ec0c-0x15ec60). Nothing else about the file is examined: no hash
|
||||||
|
and no content test exists on either side of the bridge.
|
||||||
|
|
||||||
|
Two features refuse to mix the two modes. A save state made under the other setting
|
||||||
|
returns -5 and reports "The save file requires using the BIOS file."
|
||||||
|
(EmulatorActivity.java:909), and a link connection whose peer disagrees returns 3 and
|
||||||
|
reports "BIOS settings do not match!" (EmulatorActivity.java:768).
|
||||||
|
|
||||||
|
1.8.0 reached the same file through a filesystem path. Its own browser filtered on
|
||||||
|
.bin, .bios and .zip and wrote the path to biosFile
|
||||||
|
(settings/EmulatorSettings.java:478-486, FileBrowserActivity.java:196-211), and the
|
||||||
|
native loader opened it with fopen "rb", or walked it as a zip and took the first
|
||||||
|
entry, keeping either only when the size callback returned true for exactly 16384
|
||||||
|
bytes (0x10b680-0x10b76f, 0x10b770-0x10b783, 0x10a1e0-0x10a38d). That build also
|
||||||
|
looked beside the ROM for a .ips then a .ups image and applied it on load, and wrote
|
||||||
|
"<name> (patched).gba" from the manual patch entry (Link.java:18,
|
||||||
|
MainActivity.java:181-208, 0x10b910). Neither the code nor the strings survive in
|
||||||
|
2.0.3.
|
||||||
|
|
||||||
|
Per game settings come from rom_config.ini, an asset of the application keyed on the
|
||||||
|
four character game code (Console.java:108-130). Shaders are read from the assets of the
|
||||||
|
separate package com.fastemulator.shaderpack, whose own shaders array names them
|
||||||
|
(EmulatorActivity.java:1491, settings/EmulatorSettings.java:420,434-438). Battery
|
||||||
|
saves, states, cheats, screen layouts and key maps are written by the application
|
||||||
|
under its external files directory (w0/d.java:13-43, Console.java:61-68).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: gba_bios.bin
|
||||||
|
system: nintendo-gba
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
has_builtin: true
|
||||||
|
agnostic: true
|
||||||
|
size: 16384
|
||||||
|
validation: [size]
|
||||||
|
config_key: "useBios"
|
||||||
|
description: "Game Boy Advance BIOS"
|
||||||
|
note: >-
|
||||||
|
Chosen from any location under any name through the document picker, or taken from
|
||||||
|
the first entry of that size in a zip document. A file of another size is refused
|
||||||
|
when picked and again when the game starts, and the emulator runs on the
|
||||||
|
replacement compiled into its library.
|
||||||
|
source_ref: "My Boy! 2.0.3 g.java:66-68 (size test), g.java:80-100 (zip walk and direct open), settings/EmulatorSettings.java:65-73,121-135 (picker and validation), EmulatorActivity.java:1564-1599 (read and loadBios), libgba.so 0x165fbc-0x166070 (bridge), 0x15faf0-0x15fb5c (install), 0x15ec0c-0x15ec60 (replacement); 1.8.0 settings/EmulatorSettings.java:478-486, libgba.so 0x10b680-0x10b76f, 0x10b770-0x10b783, 0x10a1e0-0x10a38d"
|
||||||
|
|
||||||
|
- name: rom_config.ini
|
||||||
|
system: nintendo-gba
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Per game settings database"
|
||||||
|
note: >-
|
||||||
|
Opened from the application assets when a game starts and read as the section
|
||||||
|
named by its four character code. Save type, flash size, mirroring, sprite limit,
|
||||||
|
cpu core and the timing hacks become console options, and the addon key arms the
|
||||||
|
solar, tilt, gyroscope and rumble sensors. Byte identical in 1.8.0 and 2.0.3.
|
||||||
|
source_ref: "My Boy! 2.0.3 Console.java:108-130, EmulatorActivity.java:642,1132; 1.8.0 Console.java:130-151"
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
emulator: "My OldBoy!"
|
||||||
|
type: standalone
|
||||||
|
core_classification: embedded_hle
|
||||||
|
source: "https://play.google.com/store/apps/details?id=com.fastemulator.gbc"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Pixel Respawn LLC"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "2.0.0"
|
||||||
|
display_name: "Nintendo - Game Boy / Game Boy Color (My OldBoy!)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "my-oldboy"
|
||||||
|
- "My OldBoy!"
|
||||||
|
- "MY-OLDBOY"
|
||||||
|
systems:
|
||||||
|
- nintendo-gb
|
||||||
|
- nintendo-gbc
|
||||||
|
- nintendo-sgb
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Android package com.fastemulator.gbc, closed source, sold on Google Play, reached by
|
||||||
|
ES-DE through its MY-OLDBOY find rule and started with android.intent.action.VIEW on
|
||||||
|
the content URI of the game. Two builds carrying the developer certificate sha256
|
||||||
|
942e532dc3a3608a1d04760b8e1b09a2f11c0c8f64ae8bb441f0c8ab1122a7ab are read here: 2.0.0
|
||||||
|
(versionCode 90022, minSdk 21, targetSdk 33, arm64-v8a and armeabi-v7a, bundletool v1
|
||||||
|
signer and the Play source stamp) and 1.5.1 (versionCode 90020, minSdk 9, armeabi,
|
||||||
|
v1 signature verified entry by entry). Line numbers below are those of 2.0.0 and
|
||||||
|
native addresses are arm64-v8a of the same build; 1.5.1 addresses are its armeabi
|
||||||
|
library. 2.0.2 (versionCode 90024) is the current Play build, offered by no mirror
|
||||||
|
reached here.
|
||||||
|
|
||||||
|
Emulation runs in libgbc.so behind a JNI bridge (Link.java:23,29-97). Content is a
|
||||||
|
.gb, .gbc, .cgb or .dmg document, or the first entry with one of those extensions in a
|
||||||
|
zip document (g.java:74-81,124-133). A registered .ips or .ups patch is applied to the
|
||||||
|
loaded image when autoIPS is on (EmulatorActivity.java:2049-2057, Link.patch).
|
||||||
|
|
||||||
|
The machine is chosen by consoleType2, one of auto, gbc, gb, gba or sgb
|
||||||
|
(res/xml/settings_advanced.xml, console_type_entryvalues, EmulatorActivity.java:1168).
|
||||||
|
The native setter maps those names to 0, 2, 1, 0x12 and 0x21 and then resolves them
|
||||||
|
against the cartridge header: bit 0x80 of byte 0x143 keeps Game Boy Color, otherwise
|
||||||
|
byte 0x146 equal to 3 gives Super Game Boy under auto, and everything else falls to
|
||||||
|
Game Boy (libgbc.so 0x29e74-0x29f30, 0x2436c-0x243bc). Super Game Boy allocates its
|
||||||
|
own 0x2200 byte state (0x24420-0x24438).
|
||||||
|
|
||||||
|
Two boot ROMs are the files the user supplies, one per machine, and the resolved
|
||||||
|
machine decides which one is installed: type 1 takes the 256 byte image, type 2 takes
|
||||||
|
the 2304 byte image, both into the same area, and any other type clears the flag that
|
||||||
|
records an image (libgbc.so 0x2446c-0x2454c). Game Boy Advance and Super Game Boy
|
||||||
|
modes therefore run without one. The library carries no image of its own, and on reset
|
||||||
|
the area is passed only when the flag and the reset argument are both set, null
|
||||||
|
otherwise (0x24550-0x245a8), which is the state the application ships in.
|
||||||
|
|
||||||
|
Both files are read only while Boot BIOS is on, off until the user turns it on, and
|
||||||
|
both pickers declare it as their dependency (res/xml/settings_advanced.xml). A save
|
||||||
|
state made under the other setting returns -5 and reports "The save file requires
|
||||||
|
using the BIOS file." (EmulatorActivity.java:898), and a link connection whose peer
|
||||||
|
disagrees returns 3 and reports "BIOS settings do not match!"
|
||||||
|
(EmulatorActivity.java:743).
|
||||||
|
|
||||||
|
Shaders are read from the assets of the separate package com.fastemulator.shaderpack,
|
||||||
|
whose own shaders and shader_names arrays name them, with a store link offered when it
|
||||||
|
is absent (EmulatorActivity.java:1513, settings/EmulatorSettings.java:405,419-423).
|
||||||
|
Battery saves, real time clock files, states, cheats, screen layouts and key maps are
|
||||||
|
written by the application under its external files directory (y0/d.java:13-43,
|
||||||
|
Console.java:58). The only file calls left in the library are those saves, the gzipped
|
||||||
|
states and one stat on /data/data/com.fastemulator.gbc.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: gb_bios.bin
|
||||||
|
system: nintendo-gb
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
agnostic: true
|
||||||
|
size: 256
|
||||||
|
validation: [size]
|
||||||
|
config_key: "bootBios"
|
||||||
|
description: "Game Boy boot ROM"
|
||||||
|
note: >-
|
||||||
|
Chosen from any location under any name through the document picker and kept as
|
||||||
|
the persisted URI gbBiosUri, or taken from the first entry of that size in a zip
|
||||||
|
document. A document of another size is refused at pick time with "Invalid GB/GBC
|
||||||
|
BIOS file." and, if it later reports short, the game starts without it. Installed
|
||||||
|
only while the resolved machine is Game Boy.
|
||||||
|
source_ref: "My OldBoy! 2.0.0 EmulatorActivity.java:1170-1175 (gate and 256 byte read), EmulatorActivity.java:1132-1161 (exact length or null), g.java:105-118 (size test), g.java:83-103 (zip walk and direct open), settings/EmulatorSettings.java:84-98,101-120 (picker and validation), libgbc.so 0x2a268-0x2a364 (bridge), 0x2446c-0x2450c (install under type 1), 0x24550-0x245a8 (reset with or without); 1.5.1 settings/EmulatorSettings.java:142-155,229-238, EmulatorActivity.java:683-684, libgbc.so 0x1f7e8-0x1f8c0, 0x10cc0-0x10d3c, 0x10db8 (size 0x100), 0x13180-0x1335c (file or zip entry)"
|
||||||
|
|
||||||
|
- name: gbc_bios.bin
|
||||||
|
system: nintendo-gbc
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
agnostic: true
|
||||||
|
size: 2304
|
||||||
|
validation: [size]
|
||||||
|
config_key: "bootBios"
|
||||||
|
description: "Game Boy Color boot ROM"
|
||||||
|
note: >-
|
||||||
|
Chosen from any location under any name through the document picker and kept as
|
||||||
|
the persisted URI gbcBiosUri, or taken from the first entry of that size in a zip
|
||||||
|
document. A document of another size is refused at pick time with "Invalid GB/GBC
|
||||||
|
BIOS file." and, if it later reports short, the game starts without it. Installed
|
||||||
|
only while the resolved machine is Game Boy Color.
|
||||||
|
source_ref: "My OldBoy! 2.0.0 EmulatorActivity.java:1170-1175 (gate and 2304 byte read), EmulatorActivity.java:1132-1161 (exact length or null), g.java:105-114,120-122 (size test), g.java:83-103 (zip walk and direct open), settings/EmulatorSettings.java:84-98,101-120 (picker and validation), libgbc.so 0x2a268-0x2a364 (bridge), 0x24510-0x2453c (install under type 2), 0x24550-0x245a8 (reset with or without); 1.5.1 settings/EmulatorSettings.java:142-155,229-238, EmulatorActivity.java:683-684, libgbc.so 0x1f7e8-0x1f8c0, 0x10d40-0x10d7c, 0x10dc8 (size 0x900), 0x13180-0x1335c (file or zip entry)"
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
emulator: "NES.emu"
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/Rakashazi/emu-ex-plus-alpha"
|
||||||
|
upstream: "https://github.com/TASEmulators/fceux"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "1c12fac5ce49badaadff2e2f210dcc30b89f4943"
|
||||||
|
upstream_commit: "d339f1fa0cd8b69cc637a0de3fb3f04cb28748ea"
|
||||||
|
core_version: "1.5.85"
|
||||||
|
display_name: "Nintendo - NES / Famicom (NES.emu)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "nes-emu"
|
||||||
|
- "NES.emu"
|
||||||
|
- "NES-EMU"
|
||||||
|
systems:
|
||||||
|
- nintendo-nes
|
||||||
|
- nintendo-fds
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Member of the EX Emulator series by Robert Broglia, which targets Android and
|
||||||
|
Linux (README.md:1,3-4,12-13) and keeps iOS and Pandora build shortcuts in the
|
||||||
|
tree (NES.emu/ios.mk, NES.emu/pandora.mk). Published as com.explusalpha.NesEmu
|
||||||
|
(NES.emu/metadata/conf.mk:2,4,6,7) and reached by ES-DE through its NES-EMU
|
||||||
|
find rule, which only the Android rule set carries. FCEUX 2.7.0 is vendored
|
||||||
|
under NES.emu/src/fceu (NES.emu/src/fceu/version.h:63-65,
|
||||||
|
NES.emu/src/main/AppMeta.cc:26), synced at FCEUX git d339f1f of 2025.11.11 per
|
||||||
|
the app changelog, and driven by the app's own video, audio, input
|
||||||
|
and save layers. The Qt and Windows drivers, netplay, PNG snapshots, WAV
|
||||||
|
logging and FCEUX's own config parser are left out of the build
|
||||||
|
(NES.emu/src/CMakeLists.txt:8-62), and the file name types for movies,
|
||||||
|
snapshots and on-disk states return an empty string
|
||||||
|
(NES.emu/src/main/FceuApi.cc:367-379). Content is read from
|
||||||
|
.nes, .unf, .unif, .fds and .nsf files (NES.emu/metadata/conf.mk:5,
|
||||||
|
NES.emu/src/main/system.ccm:108-118, NES.emu/src/main/AppMeta.cc:34); an
|
||||||
|
archive is opened by the framework, which keeps the first entry passing that
|
||||||
|
same filter (EmuFramework/src/EmuSystem.cc:394-412).
|
||||||
|
|
||||||
|
The Disk System BIOS is the one file the user has to supply, and only for .fds
|
||||||
|
content. Its location is an option rather than a fixed name
|
||||||
|
(NES.emu/src/main/system.ccm:64,143, NES.emu/src/main/options.cc:64-65,112),
|
||||||
|
set through a selector that accepts a name ending .rom or .bin caselessly, or
|
||||||
|
an archive holding such an entry (NES.emu/src/main/EmuMenuViews.cc:609-624,
|
||||||
|
NES.emu/src/main/system.ccm:107, NES.emu/src/main/FceuApi.cc:233-254). The
|
||||||
|
image must measure exactly 8192 bytes; a shorter or longer one is refused as
|
||||||
|
"Incompatible FDS BIOS" and an unset path as "No FDS BIOS set"
|
||||||
|
(NES.emu/src/main/FceuApi.cc:227-231,244-248,257-263). Either answer makes the
|
||||||
|
loader free the disk data and return an error, so the content never runs
|
||||||
|
(NES.emu/src/fceu/fds.cpp:915-926, NES.emu/src/main/Main.cc:317-322). The
|
||||||
|
bytes are mapped as PRG bank 0 and are never hashed
|
||||||
|
(NES.emu/src/fceu/fds.cpp:916-917).
|
||||||
|
|
||||||
|
The Default Palette option selects FCEUX's built-in table, one of six palettes
|
||||||
|
read from the palette directory of the application bundle, or a .pal file the
|
||||||
|
user picks (NES.emu/src/main/EmuMenuViews.cc:311-315,318,336-361,
|
||||||
|
NES.emu/src/main/Main.cc:149-175, NES.emu/src/main/options.cc:30). The loader
|
||||||
|
reads up to 512 three byte entries, skips a file carrying fewer than 64 colors
|
||||||
|
and generates the deemphasis rows for any count other than 512
|
||||||
|
(NES.emu/src/main/Main.cc:134-147). Two further palette names are declared and
|
||||||
|
never wired to a menu item or shipped as assets
|
||||||
|
(NES.emu/src/main/EmuMenuViews.cc:316-317). A .pal named after the content in
|
||||||
|
the palettes directory overrides the default at load time
|
||||||
|
(NES.emu/src/main/FceuApi.cc:365-366, NES.emu/src/fceu/fceu.cpp:522,
|
||||||
|
NES.emu/src/fceu/palette.cpp:318-338).
|
||||||
|
|
||||||
|
FCEU_MakeFName maps the Game Genie ROM to gg.rom beside the content
|
||||||
|
(NES.emu/src/main/FceuApi.cc:361-362), but the only site that opens it sits
|
||||||
|
behind FSettings.GameGenie (NES.emu/src/fceu/cart.cpp:351-368,
|
||||||
|
NES.emu/src/fceu/fceu.cpp:509-511). FCEUI_Initialize clears that structure
|
||||||
|
(NES.emu/src/fceu/fceu.cpp:601,613) and nothing sets the flag: the app declares
|
||||||
|
no option for it (NES.emu/src/main/system.ccm:62-76,
|
||||||
|
NES.emu/src/main/options.cc:58-142) and the single call site of
|
||||||
|
FCEUI_SetGameGenie passes false (NES.emu/src/fceu/fceu.cpp:513,1218-1219). The
|
||||||
|
file is never read.
|
||||||
|
|
||||||
|
Per content the app writes and reads back files named after the ROM: a .sav for
|
||||||
|
cartridges wired to a battery (NES.emu/src/fceu/cart.cpp:536-586,
|
||||||
|
NES.emu/src/main/Main.cc:98-120), a .fds.sav holding the modified disk
|
||||||
|
(NES.emu/src/fceu/fds.cpp:1011-1040), .fcs states
|
||||||
|
(NES.emu/src/main/Main.cc:78-96), a .cht cheat list under the cheats path
|
||||||
|
(NES.emu/src/fceu/cheat.cpp:200-227,324-343, NES.emu/src/main/Cheats.cc:42-50)
|
||||||
|
and NesEmu.config (NES.emu/src/main/AppMeta.cc:27). An .ips named after the
|
||||||
|
content in the patches path is applied to the image as it loads
|
||||||
|
(NES.emu/src/main/Main.cc:312-316). The app declares no bundled content, the
|
||||||
|
framework definition defaulting to an empty span
|
||||||
|
(EmuFramework/src/AppMeta.cc:40,
|
||||||
|
EmuFramework/include/emuframework/AppMeta.hh:66-68).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: "disksys.rom"
|
||||||
|
system: nintendo-fds
|
||||||
|
required: true
|
||||||
|
size: 8192
|
||||||
|
validation: [size]
|
||||||
|
description: "Famicom Disk System BIOS"
|
||||||
|
note: >-
|
||||||
|
Read through a path the user sets, so no name is compiled in; the selector
|
||||||
|
accepts any name ending .rom or .bin caselessly, or an archive whose first
|
||||||
|
entry with one of those extensions is used. The size must be exactly 8192
|
||||||
|
bytes, and a mismatch or an unset path ends the load of any .fds content.
|
||||||
|
The image is never hashed.
|
||||||
|
source_ref: "NES.emu/src/main/FceuApi.cc:221-265, NES.emu/src/fceu/fds.cpp:915-926, NES.emu/src/main/EmuMenuViews.cc:609-624, NES.emu/src/main/system.ccm:107"
|
||||||
|
|
||||||
|
- name: "Digital Prime (FBX).pal"
|
||||||
|
path: "palette/Digital Prime (FBX).pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
size: 192
|
||||||
|
sha1: "e37da23fa2c644a40fb6c08dd885a96fd65bf4e5"
|
||||||
|
description: "Default Palette option, 64 colors"
|
||||||
|
source_ref: "NES.emu/src/main/EmuMenuViews.cc:311,339, NES.emu/src/main/Main.cc:134-147,159-163"
|
||||||
|
|
||||||
|
- name: "Smooth V2 (FBX).pal"
|
||||||
|
path: "palette/Smooth V2 (FBX).pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
size: 192
|
||||||
|
sha1: "1e1993f917ec098268a0af15e79b1002bf425e47"
|
||||||
|
description: "Default Palette option, 64 colors"
|
||||||
|
source_ref: "NES.emu/src/main/EmuMenuViews.cc:312,340, NES.emu/src/main/Main.cc:134-147,159-163"
|
||||||
|
|
||||||
|
- name: "Magnum (FBX).pal"
|
||||||
|
path: "palette/Magnum (FBX).pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
size: 192
|
||||||
|
sha1: "04d7490bb3a284ab266a555c02526f6743756661"
|
||||||
|
description: "Default Palette option, 64 colors"
|
||||||
|
source_ref: "NES.emu/src/main/EmuMenuViews.cc:313,341, NES.emu/src/main/Main.cc:134-147,159-163"
|
||||||
|
|
||||||
|
- name: "Classic (FBX).pal"
|
||||||
|
path: "palette/Classic (FBX).pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
size: 192
|
||||||
|
sha1: "37027d92e1015b82a7dc5c43e9f1649a961577ab"
|
||||||
|
description: "Default Palette option, 64 colors"
|
||||||
|
source_ref: "NES.emu/src/main/EmuMenuViews.cc:314,342, NES.emu/src/main/Main.cc:134-147,159-163"
|
||||||
|
|
||||||
|
- name: "Wavebeam.pal"
|
||||||
|
path: "palette/Wavebeam.pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
size: 192
|
||||||
|
sha1: "a33356beefeb0b110464e7d77b3238fc1fb90230"
|
||||||
|
description: "Default Palette option, 64 colors"
|
||||||
|
source_ref: "NES.emu/src/main/EmuMenuViews.cc:315,343, NES.emu/src/main/Main.cc:134-147,159-163"
|
||||||
|
|
||||||
|
- name: "Five Reality.pal"
|
||||||
|
path: "palette/Five Reality.pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
size: 192
|
||||||
|
sha1: "5008c37920c614e8b471b45ac23118d00162b804"
|
||||||
|
description: "Default Palette option, 64 colors"
|
||||||
|
source_ref: "NES.emu/src/main/EmuMenuViews.cc:318,344, NES.emu/src/main/Main.cc:134-147,159-163"
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
emulator: Nesoid
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/proninyaroslav/nesoid"
|
||||||
|
upstream: "https://sourceforge.net/p/nesoid/code"
|
||||||
|
author: "Yongzh (androidemu.com)"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "b2ff53fefa56a668aad4a579af85adc672d7a791"
|
||||||
|
core_version: "2.5"
|
||||||
|
display_name: "Nintendo - NES / Famicom (Nesoid)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "nesoid"
|
||||||
|
- "Nesoid"
|
||||||
|
- "NESOID"
|
||||||
|
systems:
|
||||||
|
- nintendo-nes
|
||||||
|
- nintendo-fds
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Android package com.androidemu.nes, launched on the path of the content with
|
||||||
|
android.intent.action.VIEW; the activity declares the file scheme with the
|
||||||
|
application/zip and application/octet-stream types
|
||||||
|
(app/src/main/AndroidManifest.xml:59-71). Two build families answer to that
|
||||||
|
package id. Yongzh's own closed builds come first, and 2.3 (versionCode 56)
|
||||||
|
and 2.5.0 (versionCode 62) are read here, both carrying his certificate sha256
|
||||||
|
744b1df1b3610d58e447d243521a0957cc5f4ebd50b12d2816a92396d1aa32f2 (C=CN,
|
||||||
|
O=androidemu.com, freeman.yong@gmail.com). He later published the sources; the
|
||||||
|
SourceForge project carried them on and Yaroslav Pronin forked that tree to
|
||||||
|
GitHub, where release 2.5-4 (versionName 2.5, versionCode 61, armeabi-v7a,
|
||||||
|
certificate O=Free Software CN=Yaroslav Pronin) is the build ES-DE names. The
|
||||||
|
SourceForge community rebuild of the same tree (com.androidemu.nes_61.apk,
|
||||||
|
certificate O=Alcatraz CN=Birdman) was read beside it. Line numbers are the
|
||||||
|
fork's, native addresses are the armeabi library of Yongzh's 2.5.0, and the
|
||||||
|
SourceForge tree carries general.c and fds.c byte identical to the fork.
|
||||||
|
|
||||||
|
The emulation core is neslib, FCE Ultra 0.98 reached through the GP2X port
|
||||||
|
GPFCE, whose driver and blitters still sit in the tree unbuilt
|
||||||
|
(app/jni/neslib/drivers/gp2x/, giz_blit.s). The Android build compiles the
|
||||||
|
mapper, board and input sets with its own four file driver
|
||||||
|
(app/jni/neslib/Android.mk:12-197), leaves netplay out of the library and
|
||||||
|
runs it from Java instead (app/jni/neslib/fce.c:1081,1206,
|
||||||
|
app/jni/neslib/drivers/android/netplay.c:1,28), and reduces
|
||||||
|
FCEUD_PrintError and FCEUD_Message to empty bodies, so every message the core
|
||||||
|
raises is discarded (app/jni/neslib/drivers/android/debug.c:4-11).
|
||||||
|
|
||||||
|
The activity accepts a name ending .nes, .fds or .zip caselessly and refuses
|
||||||
|
anything else before the loader runs (EmulatorActivity.java:933-957,
|
||||||
|
app/src/main/res/values/arrays.xml:4-8). An archive is opened by the core,
|
||||||
|
which keeps the first entry ending .nes, .fds, .nsf, .unf, .nez or .unif, and
|
||||||
|
a plain file also opens gzipped (app/jni/neslib/file.c:192-232,250-273).
|
||||||
|
FCEUI_LoadGame then tries the iNES, NSF, FDS and UNIF loaders in that order on
|
||||||
|
the bytes themselves (app/jni/neslib/fce.c:1180-1187).
|
||||||
|
|
||||||
|
The Disk System BIOS is the file the user has to supply. FDSLoad asks
|
||||||
|
FCEU_MakeFName for it, opens it with a plain fopen and reads 8192 bytes into
|
||||||
|
the array mapped over 0xE000 to 0xFFFF (app/jni/neslib/fds.c:76,146,160,
|
||||||
|
808-843, app/jni/neslib/drivers/android/file.c:3-6). Where that name resolves
|
||||||
|
is the one place the two build families differ. Yongzh's builds carry a
|
||||||
|
setOption entry fdsRom that duplicates the path the settings screen holds and
|
||||||
|
return it from FCEU_MakeFName when set (libnes.so setOption 0x455a4-0x45694,
|
||||||
|
setter 0x8804-0x8848, FCEUMKF_FDSROM case 0x8094-0x80ac,
|
||||||
|
Nesoid 2.5.0 EmulatorActivity.java:834). The published sources carry neither
|
||||||
|
the option nor that branch, so only the fallback remains: FCEUMKF_FDSROM
|
||||||
|
formats disksys.rom under the base directory, and nothing on Android ever
|
||||||
|
calls FCEUI_SetBaseDirectory, which leaves that buffer empty
|
||||||
|
(app/jni/neslib/general.c:46,52-56,215). The settings screen still writes the
|
||||||
|
fdsRom preference and still shows the chosen path, but no code reads it back
|
||||||
|
(EmulatorSettingsFragment.java:96-99,150-156,195-210,
|
||||||
|
app/src/main/res/xml/preferences.xml:240-251). Disk switching went the same
|
||||||
|
way: the menu asks the engine for fdsTotalSides and fdsCurrentDisk, which
|
||||||
|
Yongzh's builds answer and the fork's does not, the base class returning zero
|
||||||
|
for any name (EmulatorActivity.java:417,969,1244-1249,
|
||||||
|
app/jni/common/emuengine.h:49).
|
||||||
|
|
||||||
|
The Game Genie ROM is a second path the user picks, kept across both families.
|
||||||
|
loadGameGenie passes it to the engine only while the Enable Game Genie switch
|
||||||
|
is on, the setter duplicates it into FSettings.GameGenie and OpenGenie reads it
|
||||||
|
once the content has loaded (EmulatorActivity.java:870-874,
|
||||||
|
app/jni/neslib/drivers/android/nesengine.cpp:242-243,
|
||||||
|
app/jni/neslib/svga.c:132-140, app/jni/neslib/fce.c:1201-1203). Both pickers
|
||||||
|
list names ending .nes, .rom or .bin
|
||||||
|
(EmulatorSettingsFragment.java:179-210, FileChooser.java:157-172).
|
||||||
|
|
||||||
|
A palette named after the content is read from the pal directory of the same
|
||||||
|
unset base directory as the disk BIOS, 192 bytes taken as 64 RGB triples; a
|
||||||
|
missing file leaves the built-in table in place
|
||||||
|
(app/jni/neslib/palette.c:205-224, app/jni/neslib/general.c:216-221,
|
||||||
|
app/jni/neslib/fce.c:1212).
|
||||||
|
|
||||||
|
Per content the emulator writes and reads back its own files, all under that
|
||||||
|
same base directory: sav/<name>.sav for battery backed cartridge RAM
|
||||||
|
(app/jni/neslib/cart.c:641-700), sav/<name>.fds for the modified disk
|
||||||
|
(app/jni/neslib/fds.c:845-870,915-930), fcs/<name>.fc<n> states,
|
||||||
|
snaps/ screenshots and movie/<name>.fcm recordings
|
||||||
|
(app/jni/neslib/general.c:134-195,222-238), and cheats/<name>.cht, which
|
||||||
|
FCEU_LoadGameCheats reads at load and FCEU_FlushGameCheats rewrites at close
|
||||||
|
(app/jni/neslib/cheat.c:183-208,272-300, app/jni/neslib/fce.c:1080,1213).
|
||||||
|
The application writes its own files through Java paths instead: state slots
|
||||||
|
at <content>.ss<n> beside the content (StateSlotsActivity.java:39-45,135-140),
|
||||||
|
an XML cheat list at <content>.cht, also beside the content
|
||||||
|
(Cheats.java:37-46,105-160), key profiles under its data directory
|
||||||
|
(KeyProfilesActivity.java:47-60,92-100), PNG screenshots under screenshot/ on
|
||||||
|
external storage (EmulatorActivity.java:1258-1281) and a netplay state
|
||||||
|
exchanged through its cache directory (EmulatorActivity.java:1292-1293).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: disksys.rom
|
||||||
|
system: nintendo-fds
|
||||||
|
required: true
|
||||||
|
min_size: 8192
|
||||||
|
validation: [size]
|
||||||
|
config_key: "fdsRom"
|
||||||
|
description: "Famicom Disk System BIOS"
|
||||||
|
note: >-
|
||||||
|
Read as 8192 bytes into the 8 KB array mapped over 0xE000 to 0xFFFF. A
|
||||||
|
failed open or a short read frees the disk data and ends the load, so no
|
||||||
|
.fds content runs; both messages are discarded and the application reports
|
||||||
|
only that the ROM failed to load. Nothing else about the image is
|
||||||
|
examined, so a longer file passes on its first 8192 bytes and no hash is
|
||||||
|
compared. The open is a plain fopen, so neither a zipped nor a gzipped
|
||||||
|
copy answers. Yongzh's builds take the path from the fdsRom setting, whose
|
||||||
|
picker lists names ending .nes, .rom or .bin; the builds made from the
|
||||||
|
published sources ignore that setting and resolve the compiled name under
|
||||||
|
a base directory that is never set, which puts it at the root of the
|
||||||
|
filesystem.
|
||||||
|
source_ref: "app/jni/neslib/fds.c:808-843 (open, read, failure), app/jni/neslib/fds.c:76,146,160 (array and mapping), app/jni/neslib/general.c:46,52-56,215 (name and empty base directory), app/jni/neslib/drivers/android/file.c:3-6 (plain fopen); Nesoid 2.5.0 libnes.so 0x455a4-0x45694 (setOption fdsRom), 0x8804-0x8848 (setter), 0x8094-0x80ac (FCEUMKF_FDSROM returns the set path), Nesoid 2.5.0 EmulatorActivity.java:834"
|
||||||
|
|
||||||
|
- name: gg.rom
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
min_size: 4352
|
||||||
|
validation: [size]
|
||||||
|
config_key: "gameGenieRom"
|
||||||
|
description: "Game Genie add-on cartridge ROM"
|
||||||
|
note: >-
|
||||||
|
Read only while the Enable Game Genie switch is on and a path is set,
|
||||||
|
through a picker listing names ending .nes, .rom or .bin. The first 16
|
||||||
|
bytes decide the format: a leading 0x4E is taken as an iNES image, from
|
||||||
|
which 4096 bytes of program ROM are read, then 256 bytes of character ROM
|
||||||
|
16 KB further in, so such a file needs at least 16656 bytes; anything else
|
||||||
|
is read as a raw 4352 byte image. A failed open or a short read leaves the
|
||||||
|
Game Genie off and the content still runs. No hash is compared.
|
||||||
|
source_ref: "app/jni/neslib/cart.c:475-521 (open and format branch), app/jni/neslib/svga.c:132-140 (setter), app/jni/neslib/drivers/android/nesengine.cpp:242-243, app/jni/neslib/fce.c:1201-1203 (call site), EmulatorActivity.java:870-874, EmulatorSettingsFragment.java:179-193 (picker)"
|
||||||
|
|
||||||
|
- name: "<game>.pal"
|
||||||
|
system: nintendo-nes
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
unsourceable: "any 64 colour palette the user picks for one title"
|
||||||
|
description: "colour palette for one title"
|
||||||
|
note: >-
|
||||||
|
Opened as pal/<name>.pal under the base directory when content loads, with
|
||||||
|
the name taken from the content. 192 bytes are read as 64 RGB triples and
|
||||||
|
replace the built-in table, without checking how many arrived, so a
|
||||||
|
shorter file leaves the remaining entries unset; a missing file changes
|
||||||
|
nothing. The base directory is never set on Android, so the name resolves
|
||||||
|
at the root of the filesystem.
|
||||||
|
source_ref: "app/jni/neslib/palette.c:205-224, app/jni/neslib/general.c:216-221, app/jni/neslib/fce.c:1212"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
Left out are the files the emulator writes and reads back, which are its own
|
||||||
|
state rather than anything a user obtains: sav/<name>.sav for battery backed
|
||||||
|
cartridge RAM, sav/<name>.fds for the modified disk, fcs/<name>.fc<n> states,
|
||||||
|
snaps/ screenshots, movie/<name>.fcm recordings and cheats/<name>.cht, which
|
||||||
|
is reread at load and rewritten at close. The application writes its own set
|
||||||
|
through Java paths: state slots at <content>.ss<n>, an XML cheat list at
|
||||||
|
<content>.cht beside the content, key profiles, PNG screenshots under
|
||||||
|
screenshot/ and the netplay state in its cache directory. The IPS branch is
|
||||||
|
unreachable: FCEUMKF_IPS has no call site, and the only patcher applies a .ips
|
||||||
|
handed in as the content itself, which the activity refuses before the loader
|
||||||
|
runs. The netplay temporary file
|
||||||
|
goes with the netplay code, which the Android build does not compile. The
|
||||||
|
gg.rom name FCEU_MakeFName builds is never opened, the Game Genie image
|
||||||
|
arriving as a path instead. assets/about.html and assets/faq.html are the help
|
||||||
|
screens of the application and carry no emulation data.
|
||||||
|
ref: app/jni/neslib/general.c:196-213,222-238, app/jni/neslib/cart.c:641-700,
|
||||||
|
app/jni/neslib/fds.c:845-870,915-930, app/jni/neslib/cheat.c:183-208,
|
||||||
|
272-300, app/jni/neslib/fce.c:1080,1145-1177,1206,1213,
|
||||||
|
EmulatorActivity.java:949-957,1258-1293, Cheats.java:37-46,
|
||||||
|
StateSlotsActivity.java:39-45,135-140,
|
||||||
|
KeyProfilesActivity.java:47-60,92-100, app/jni/neslib/Android.mk:193-197,
|
||||||
|
HelpActivity.java:14-22, MainActivity.java:20,
|
||||||
|
EmulatorSettingsFragment.java:30-31
|
||||||
@@ -0,0 +1,823 @@
|
|||||||
|
emulator: NetherSX2-Turnip Classic
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
bios_mode: agnostic
|
||||||
|
source: "https://github.com/nckstwrt/NetherSX2-Turnip"
|
||||||
|
upstream: "https://github.com/Trixarian/AetherSX2"
|
||||||
|
author: "nckstwrt"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "8e17e584884e19b0a912f1988730d576d6d5aa84"
|
||||||
|
upstream_commit: "1d1f795dfc70e38da67724c7298779260f513889"
|
||||||
|
core_version: "2.2n-3668-Turnip-v0.7"
|
||||||
|
display_name: "Sony - PlayStation 2 (NetherSX2-Turnip Classic)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "nethersx2-turnip-classic"
|
||||||
|
- "NetherSX2-Turnip-Classic"
|
||||||
|
- "NETHERSX2-TURNIP-CLASSIC"
|
||||||
|
systems:
|
||||||
|
- sony-playstation-2
|
||||||
|
|
||||||
|
bios_directory: "bios/"
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
PlayStation 2 emulator for Android, package xyz.aethersx2.cturnip, activity
|
||||||
|
xyz.aethersx2.android.EmulationActivity, version name v2.2n-3668, label
|
||||||
|
NetherSX2 Classic (Turnip). It sits on the 3668 line: the library it starts
|
||||||
|
from is NetherSX2 Classic v2.2n-3668, itself a patch of the AetherSX2
|
||||||
|
v1.5-3668 package, and the library still names itself NetherSX2 v2.2n-3668
|
||||||
|
(Classic). Everything below was read from the v0.7 package:
|
||||||
|
lib/arm64-v8a/libemucore.so, libvulkad.so, the dex and the assets.
|
||||||
|
ref: nethersx2-turnip-classic v0.7 AndroidManifest.xml,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0xcdcba
|
||||||
|
|
||||||
|
The package pairs two revisions of the project. libemucore.so is the blob the
|
||||||
|
v0.7 commit carries, byte for byte; libvulkad.so is the one committed for
|
||||||
|
v0.6 and reports its own build date. libhook_impl.so, libmain_hook.so and the
|
||||||
|
six packed drivers are the same at both revisions. The shim rules described
|
||||||
|
here are therefore those of the older revision, which this profile pins:
|
||||||
|
SM8350, lahaina, sdm845 and napali still route to the a6xx-Patched driver,
|
||||||
|
and SM6475, SM6650 and SM7325 are not known to it.
|
||||||
|
ref: VulkanShim2/vulkan_shim.cpp:1027-1059,
|
||||||
|
nethersx2-turnip-classic v0.7 libvulkad.so
|
||||||
|
|
||||||
|
The patch rewrites twenty-four places in the library it starts from. Three are
|
||||||
|
the strings libvulkan.so, libvulkan.so.1 and the message naming them, each
|
||||||
|
turned into libvulkad.so, so the Vulkan loader opens the shim instead of the
|
||||||
|
system driver. Sixteen turn comparisons into unconditional paths, among them
|
||||||
|
the memchr scan for the twenty-two byte pattern that precedes the certificate
|
||||||
|
test and two byte-wise string comparisons whose result is forced to equal,
|
||||||
|
which is what lets the package be resigned under a new application id. Five
|
||||||
|
move settings defaults: the renderer enum from 12 to 14, the upscale
|
||||||
|
multiplier fallback from 1.0 to 2.0 with the configuration read
|
||||||
|
short-circuited, the hardware download mode default, and the warning text that
|
||||||
|
went with it. The same five sites carry their unpatched forms in the 4248
|
||||||
|
library this project also starts from, which is what places them here rather
|
||||||
|
than in the base. None of them is in a file loading path.
|
||||||
|
ref: nethersx2-turnip-classic v0.7 libemucore.so 0x105f5b,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x829ae0-0x82a018,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x82d10c-0x82d5c0,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x82e41c,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x82fbac-0x82fcac,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x8034c4,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x833d04,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x83401c-0x834028,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x834cb0
|
||||||
|
|
||||||
|
A BIOS image is required and boot stops without one, the application raising a
|
||||||
|
startup error saying it needs a PS2 BIOS in the bios folder of the data
|
||||||
|
directory. The data directory is getExternalFilesDir(null) with getDataDir()
|
||||||
|
behind it, so it follows the application id, and the folder names under it
|
||||||
|
come from the Folders section, Bios defaulting to bios. An image imported
|
||||||
|
through the interface is written to that folder under the CRC32 of its
|
||||||
|
contents, as %08X.bin.
|
||||||
|
ref: nethersx2-turnip-classic v0.7 libemucore.so 0x8057dc,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x7dfaf0-0x7dfb10,
|
||||||
|
xyz/aethersx2/android/NativeLibrary initializeOnce,
|
||||||
|
xyz/aethersx2/android/NativeLibrary importBIOS
|
||||||
|
|
||||||
|
Detection is by content. The scan lists the BIOS folder with a * mask, keeps
|
||||||
|
files between 4194304 and 8388608 bytes, and accepts an image whose romdir
|
||||||
|
carries a RESET entry followed by a readable ROMVER; the fifth ROMVER
|
||||||
|
character gives the zone, A for USA, C for China, E for Europe, H for Asia,
|
||||||
|
J for Japan, P for Free, T for T10K and X for Test, any other character
|
||||||
|
standing for itself. The sixth character is read only to pick the word
|
||||||
|
Console or Devel for the description, and the acceptance flag is set outright
|
||||||
|
once ROMVER has been read, so development images pass with nothing patched
|
||||||
|
here. RESET and ROMVER are the only two names the scan compares. An image
|
||||||
|
named in the configuration is combined with the BIOS folder and opened at that
|
||||||
|
path when it exists, without the size filter and without the romdir test. No
|
||||||
|
name and no hash is matched anywhere. The image is read into the 4 MB ROM
|
||||||
|
region and truncated to it, and one shorter than 2465792 bytes turns off the
|
||||||
|
OSDSys parameter HLE.
|
||||||
|
ref: aethersx2/pcsx2/ps2/BiosTools.cpp:27-28,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:62-175,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:235-260,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:272-332,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x81bc00-0x81bc24,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x81be44-0x81c1c0,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x81b5e8-0x81b62c
|
||||||
|
|
||||||
|
Companions derive from the selected image. rom1 and rom2 are appended to the
|
||||||
|
full name first, then substituted for the existing extension, so an image at
|
||||||
|
ps2-0230a-20080220.bin is followed by ps2-0230a-20080220.bin.rom1 then
|
||||||
|
ps2-0230a-20080220.rom1. The nvm and the mec are read at the substituted
|
||||||
|
extension only, and both are written with defaults when they are absent or too
|
||||||
|
short. This code line loads no erom: the extension is named nowhere in the
|
||||||
|
library and the boot path goes from rom2 straight to the IRX.
|
||||||
|
ref: aethersx2/pcsx2/ps2/BiosTools.cpp:193-218,
|
||||||
|
aethersx2/pcsx2/CDVD/CDVD.cpp:120-144,
|
||||||
|
aethersx2/pcsx2/CDVD/CDVD.cpp:158-226,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x81b688-0x81b9a4
|
||||||
|
|
||||||
|
The network adapter opens eeprom.dat and flash.dat by bare name, so they
|
||||||
|
resolve against the process working directory, which the application never
|
||||||
|
sets. A compiled-in image stands in for the first and a card filled with 0xFF
|
||||||
|
for the second. DEV9hdd.raw is the default name of the empty disk image its
|
||||||
|
settings page writes. An IRX named in the configuration is read into the ROM
|
||||||
|
region at 0x3C0000 at boot; the field is empty by default and names no file of
|
||||||
|
its own.
|
||||||
|
ref: aethersx2/pcsx2/DEV9/DEV9.cpp:73, aethersx2/pcsx2/DEV9/DEV9.cpp:145-160,
|
||||||
|
aethersx2/pcsx2/DEV9/flash.cpp:76-103,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:220-233,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x7bb5cc-0x7bb680,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x81b9a4-0x81bac4
|
||||||
|
|
||||||
|
The Vulkan path is the reason this build exists. libemucore.so opens
|
||||||
|
libvulkad.so.1 then libvulkad.so where the stock library names libvulkan.so,
|
||||||
|
and vkCreateInstance is resolved from it. That shim reads the Adreno model and
|
||||||
|
the platform name from the kgsl sysfs nodes, picks one of six Turnip drivers
|
||||||
|
packed beside it, creates a linker namespace over its own library directory
|
||||||
|
and loads libhook_impl.so and libmain_hook.so into it. The system
|
||||||
|
/system/lib64/libvulkan.so is then opened inside that namespace with its
|
||||||
|
soname patched, so its own driver load lands in the hook, which opens the
|
||||||
|
chosen Turnip driver instead of the vendor ICD. A driver present at
|
||||||
|
/data/local/tmp/libvulkan_freedreno.so is tested first and wins over all six.
|
||||||
|
When the namespace cannot be built the shim falls back to patching the system
|
||||||
|
library's global offset table, and that path alone loads libbase.so,
|
||||||
|
libcutils.so, libvndksupport.so and libhardware.so from the library directory.
|
||||||
|
The shim derives the package name from its own library path and appends to
|
||||||
|
vulkan_shim.log under the files folder of that package.
|
||||||
|
ref: VulkanShim2/vulkan_shim.cpp:43-73,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1008-1085,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1107-1175,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1179-1194,
|
||||||
|
VulkanShim2/hook_impl.cpp:38-140,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x8a45ec-0x8a4624
|
||||||
|
|
||||||
|
Resources are read out of the package itself. The library has no asset manager
|
||||||
|
of its own and calls back into readPackageFile, readPackageFileToString and
|
||||||
|
playSoundAsync, each taking an asset-relative name, so the game database, the
|
||||||
|
patch archives, the interface fonts, the shader sources every backend compiles
|
||||||
|
at startup and the achievement sounds are versioned with the build and never
|
||||||
|
looked for on disk. The sound names are joined to a file:///android_asset base
|
||||||
|
before they cross into Java. The game list draws its region flags and rating
|
||||||
|
stars from the same assets. The game database is this build's own, and five of
|
||||||
|
the shader sources differ from the ones the 4248 line carries: the OpenGL
|
||||||
|
preamble, its format conversion and texture function fragment shaders, and the
|
||||||
|
Vulkan texture function and format conversion shaders.
|
||||||
|
ref: nethersx2-turnip-classic v0.7 libemucore.so 0x828110,
|
||||||
|
xyz/aethersx2/android/NativeLibrary readPackageFile,
|
||||||
|
xyz/aethersx2/android/NativeLibrary playSoundAsync
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: ps2-0230a-20080220.bin
|
||||||
|
path: bios/ps2-0230a-20080220.bin
|
||||||
|
required: true
|
||||||
|
min_size: 4194304
|
||||||
|
max_size: 8388608
|
||||||
|
validation: [size]
|
||||||
|
description: "PS2 BIOS image"
|
||||||
|
note: >-
|
||||||
|
Any image whose romdir holds RESET and a readable ROMVER is accepted,
|
||||||
|
whatever its name. The 4 to 8 MB range gates the folder scan; an image
|
||||||
|
named in the configuration skips both that range and the romdir test.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:27-28, aethersx2/pcsx2/ps2/BiosTools.cpp:235-260, nethersx2-turnip-classic v0.7 libemucore.so 0x81bc00-0x81bc24 (size window), nethersx2-turnip-classic v0.7 libemucore.so 0x81c1c0 (acceptance flag set outright)"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.rom1
|
||||||
|
path: bios/ps2-0230a-20080220.rom1
|
||||||
|
required: false
|
||||||
|
max_size: 4194304
|
||||||
|
description: "DVD player ROM"
|
||||||
|
note: >-
|
||||||
|
Tried as {bios}.rom1 then {biosbase}.rom1. Read at 0x2404000 of the EE
|
||||||
|
memory block and truncated to 4 MB. Logged and skipped when absent.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:193-218, nethersx2-turnip-classic v0.7 libemucore.so 0x81b688-0x81b810"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.rom2
|
||||||
|
aliases:
|
||||||
|
- "SCPH-90006_BIOS_VX_HK _230.ROM2"
|
||||||
|
path: bios/ps2-0230a-20080220.rom2
|
||||||
|
required: false
|
||||||
|
max_size: 524288
|
||||||
|
description: "Chinese ROM extension"
|
||||||
|
note: >-
|
||||||
|
Same two-step naming as rom1. Read at 0x2804000 of the EE memory block and
|
||||||
|
truncated to 512 KB. Only present on Chinese region consoles.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:193-218, nethersx2-turnip-classic v0.7 libemucore.so 0x81b820-0x81b994"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.nvm
|
||||||
|
path: bios/ps2-0230a-20080220.nvm
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
min_size: 1024
|
||||||
|
validation: [size]
|
||||||
|
description: "Console NVRAM"
|
||||||
|
note: >-
|
||||||
|
Read at the BIOS path with the extension replaced by nvm, opened r+b.
|
||||||
|
Carries the console id, the iLink id, the language and the OSD
|
||||||
|
configuration. A 1024 byte image is written when the file is missing or
|
||||||
|
shorter, zeroed except for a fixed iLink id and the language defaults of
|
||||||
|
the BIOS region.
|
||||||
|
source_ref: "aethersx2/pcsx2/CDVD/CDVD.cpp:158-226, nethersx2-turnip-classic v0.7 libemucore.so 0x790470-0x7906c8, nethersx2-turnip-classic v0.7 libemucore.so 0x790820-0x790944"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.mec
|
||||||
|
path: bios/ps2-0230a-20080220.mec
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
min_size: 4
|
||||||
|
validation: [size]
|
||||||
|
description: "Mechacon version"
|
||||||
|
note: >-
|
||||||
|
Read at the BIOS path with the extension replaced by mec. Written as
|
||||||
|
03 06 02 00 when the file is missing or shorter than 4 bytes.
|
||||||
|
source_ref: "aethersx2/pcsx2/CDVD/CDVD.cpp:120-144, nethersx2-turnip-classic v0.7 libemucore.so 0x791700-0x7918f4"
|
||||||
|
|
||||||
|
- name: eeprom.dat
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
size: 64
|
||||||
|
description: "DEV9 EEPROM"
|
||||||
|
note: >-
|
||||||
|
Opened O_RDWR by bare name when the network adapter starts and mapped over
|
||||||
|
64 bytes. A compiled-in image stands in when the file is missing or cannot
|
||||||
|
be mapped.
|
||||||
|
source_ref: "aethersx2/pcsx2/DEV9/DEV9.cpp:73, aethersx2/pcsx2/DEV9/DEV9.cpp:145-160, nethersx2-turnip-classic v0.7 libemucore.so 0x7bb620-0x7bb680"
|
||||||
|
|
||||||
|
- name: flash.dat
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
max_size: 8650752
|
||||||
|
description: "DEV9 SmartMedia flash image"
|
||||||
|
note: >-
|
||||||
|
Opened rb by bare name at network adapter init and read as 1024 blocks of
|
||||||
|
16 pages of 512 bytes plus 16 ECC bytes. The card is filled with 0xFF when
|
||||||
|
the file is absent.
|
||||||
|
source_ref: "aethersx2/pcsx2/DEV9/flash.cpp:76-103, nethersx2-turnip-classic v0.7 libemucore.so 0x7bb5cc-0x7bb61c"
|
||||||
|
|
||||||
|
- name: "<module>.irx"
|
||||||
|
required: false
|
||||||
|
unsourceable: "any IOP module the user points at, under no name the code expects"
|
||||||
|
description: "IOP module injected at boot"
|
||||||
|
note: >-
|
||||||
|
Opened at the path the configuration holds once it is four characters or
|
||||||
|
longer, and read into the ROM region at 0x3C0000, capped at 0x40000 bytes.
|
||||||
|
The field is empty by default and names no file of its own.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:220-233, aethersx2/pcsx2/ps2/BiosTools.cpp:327-328, nethersx2-turnip-classic v0.7 libemucore.so 0x81b9a4-0x81bac4"
|
||||||
|
|
||||||
|
- name: libvulkad.so
|
||||||
|
path: lib/arm64-v8a/libvulkad.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 484560
|
||||||
|
md5: 1a68e1ac1eec29005c19df924146cf19
|
||||||
|
sha1: 2655469eca935d89a6d8fe0c3998fe3ec0dd2d65
|
||||||
|
description: "Vulkan loader shim"
|
||||||
|
note: >-
|
||||||
|
Opened as libvulkad.so.1 then libvulkad.so where the stock library names
|
||||||
|
libvulkan.so, and vkCreateInstance is resolved from it. Without it the
|
||||||
|
Vulkan backend does not open and the message names the shim. This package
|
||||||
|
carries the build committed for v0.6, one revision behind the emulator
|
||||||
|
library beside it.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:969-1272 (the constructor that runs on load), nethersx2-turnip-classic v0.7 libemucore.so 0x8a45ec-0x8a4624"
|
||||||
|
|
||||||
|
- name: libhook_impl.so
|
||||||
|
path: lib/arm64-v8a/libhook_impl.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 461856
|
||||||
|
md5: c2a10d75f7a186f78debc79dd2204841
|
||||||
|
sha1: 5a86d24c83f4a0867a3526638182c8dc67e0033b
|
||||||
|
description: "Driver load hook"
|
||||||
|
note: >-
|
||||||
|
Opened into the adrenotools-libvulkan namespace and asked for
|
||||||
|
init_hook_param, which receives the driver directory and driver name. Its
|
||||||
|
hook_android_dlopen_ext is what replaces the vendor driver with the Turnip
|
||||||
|
one, and it reopens itself in each driver namespace it creates.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1138-1156, VulkanShim2/hook_impl.cpp:38-140"
|
||||||
|
|
||||||
|
- name: libmain_hook.so
|
||||||
|
path: lib/arm64-v8a/libmain_hook.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 5648
|
||||||
|
md5: 3ded83b3f45773199b82bf81c86f8c89
|
||||||
|
sha1: e2ee6c00247fc05b88afe43237fa4bfa90212c54
|
||||||
|
description: "Namespace interposer"
|
||||||
|
note: >-
|
||||||
|
Loaded RTLD_GLOBAL into the same namespace before the system Vulkan
|
||||||
|
library, so its android_dlopen_ext and android_load_sphal_library are the
|
||||||
|
ones that library binds to.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1159-1160, VulkanShim2/main_hook.c:3-9"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_T28.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_T28.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 18606849
|
||||||
|
md5: 315f4b037b77dea81ea099e13e94fa11
|
||||||
|
sha1: 83406408d328d8529ffa2faf7ab878664a5c7a79
|
||||||
|
description: "Turnip driver, default branch"
|
||||||
|
note: >-
|
||||||
|
Chosen when no other branch matches. Loaded by name from the library
|
||||||
|
directory through the hook; a load failure falls back to the vendor
|
||||||
|
driver.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1011, VulkanShim2/vulkan_shim.cpp:1079-1080, VulkanShim2/hook_impl.cpp:127-135"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_a8xx-turnip-gen8-V31.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_a8xx-turnip-gen8-V31.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 14509832
|
||||||
|
md5: 7f6dbc9ec12cb53b1802c418cf532f9b
|
||||||
|
sha1: 2dc32726b7a68ced6a40ea2c6cc60848716907ab
|
||||||
|
description: "Turnip driver, Adreno 8xx branch"
|
||||||
|
note: >-
|
||||||
|
Chosen whenever the Adreno model reads non-zero, model 810 and 825
|
||||||
|
included. Model 825 also turns off framebuffer fetch.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1010, VulkanShim2/vulkan_shim.cpp:1037-1052, nethersx2-turnip-classic v0.7 libvulkad.so 0x22770-0x23108"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_T24.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_T24.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 18003849
|
||||||
|
md5: e90d691859e0ff8f0221f3fb497cca5d
|
||||||
|
sha1: d28f7c64a8296a6d1886b348946d01433c10b493
|
||||||
|
description: "Turnip driver, Adreno 810 branch"
|
||||||
|
note: >-
|
||||||
|
The Adreno 810 branch writes this path and the block it falls into
|
||||||
|
overwrites it with the 8xx driver before anything reads it, so this
|
||||||
|
revision never opens the file. The branch gained its own exit after the
|
||||||
|
revision this package was built from.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1039-1043, nethersx2-turnip-classic v0.7 libvulkad.so 0x22784-0x230d4"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_25.3.0_R6_Gmem.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_25.3.0_R6_Gmem.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 12048553
|
||||||
|
md5: 3f1b01295ab08d070bede8122ebd0aea
|
||||||
|
sha1: 2159a5172176f9ee0076370314d2d100de2fe1b1
|
||||||
|
description: "Turnip driver, Adreno 710 and 720 branch"
|
||||||
|
note: >-
|
||||||
|
Chosen when the model is unreadable and the GPU name holds 710 or 720.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1056-1059"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_v24.1.0_R18.a6xx-Patched.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_v24.1.0_R18.a6xx-Patched.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 9407968
|
||||||
|
md5: 7af55500464d372a609084fb4698e16d
|
||||||
|
sha1: 1abf76c578cb1330e354d5588634b87cef4bc057
|
||||||
|
description: "Turnip driver, SD845 to SD888 branch"
|
||||||
|
note: >-
|
||||||
|
Chosen when the platform reads SM8250, kona, SM8350, lahaina, sdm845 or
|
||||||
|
napali.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1027-1033"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_T19.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_T19.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 11581209
|
||||||
|
md5: 5f953080ba9ac858a99f3742c8302055
|
||||||
|
sha1: 4dc276dfd5842302c978ce9b2996f961dc6452f1
|
||||||
|
description: "Turnip driver, SM6125 branch"
|
||||||
|
note: "Chosen when the platform reads SM6125 or trinket."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1020-1023"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno.so
|
||||||
|
path: data/local/tmp/libvulkan_freedreno.so
|
||||||
|
required: false
|
||||||
|
unsourceable: "any Turnip build the user places at that path"
|
||||||
|
description: "Turnip driver override"
|
||||||
|
note: >-
|
||||||
|
Tested with access before any detection runs. When it exists it becomes
|
||||||
|
the driver and the driver directory becomes /data/local/tmp/, so none of
|
||||||
|
the six packed drivers is consulted.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1009, VulkanShim2/vulkan_shim.cpp:1012-1017"
|
||||||
|
|
||||||
|
- name: libbase.so
|
||||||
|
path: lib/arm64-v8a/libbase.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 255352
|
||||||
|
md5: eae5ccb3f801b3333ec0e65592ce8a87
|
||||||
|
sha1: fecf95a804a7cb57e210f55d5482a56826c8684c
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: >-
|
||||||
|
Opened RTLD_GLOBAL from the library directory only when the namespace
|
||||||
|
approach failed and the shim falls back to patching the global offset
|
||||||
|
table.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1179-1194"
|
||||||
|
|
||||||
|
- name: libcutils.so
|
||||||
|
path: lib/arm64-v8a/libcutils.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 91200
|
||||||
|
md5: 185cd93c21cce12ab4c3bc2430934684
|
||||||
|
sha1: 63e55bcae5ee690cf6bc7db69a5077c5502e4334
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: "Same fallback list as libbase.so, and a dependency of every packed driver."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1179-1194, VulkanShim2/vulkan_shim.cpp:1248-1255"
|
||||||
|
|
||||||
|
- name: libvndksupport.so
|
||||||
|
path: lib/arm64-v8a/libvndksupport.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 66881
|
||||||
|
md5: aa5065cca6695aa4b8cfdd3c164f3d28
|
||||||
|
sha1: a6f2d8498a2f0a00776dd69c58f012cdbb75a308
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: >-
|
||||||
|
Same fallback list as libbase.so. Its android_load_sphal_library is the
|
||||||
|
call the shim stubs so a vendor load can be redirected.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1179-1194, VulkanShim2/vulkan_shim.cpp:1257-1269"
|
||||||
|
|
||||||
|
- name: libhardware.so
|
||||||
|
path: lib/arm64-v8a/libhardware.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 66961
|
||||||
|
md5: 71e06a0726aa60b010e066d37021d36a
|
||||||
|
sha1: 555a6203cd7c23c2b49916d70615e5df7973aa87
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: "Same fallback list as libbase.so, and a dependency of every packed driver."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1179-1194, VulkanShim2/vulkan_shim.cpp:1235-1246"
|
||||||
|
|
||||||
|
- name: GameIndex.yaml
|
||||||
|
path: assets/GameIndex.yaml
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1758721
|
||||||
|
md5: 3f33de7bf8e40e00a05cf27c18a6be0c
|
||||||
|
sha1: 58fb1f8ea6cf2d526904349640453e682fe388a1
|
||||||
|
description: "Game database"
|
||||||
|
note: >-
|
||||||
|
Read from the package by name, keyed by serial, and carrying the per-game
|
||||||
|
fixes, patches and settings overrides. Parsed into gamedb.cache in the
|
||||||
|
cache folder.
|
||||||
|
source_ref: "aethersx2/pcsx2/GameDatabase.cpp:35, nethersx2-turnip-classic v0.7 libemucore.so 0x2e45fc"
|
||||||
|
|
||||||
|
- name: cheats_ws.zip
|
||||||
|
path: assets/cheats_ws.zip
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1694454
|
||||||
|
md5: cc19970629feb0a25b9b95263194f08f
|
||||||
|
sha1: 1caae7ddf0cbba5f1f6d7404b2309300d913778c
|
||||||
|
description: "Widescreen patch archive"
|
||||||
|
note: >-
|
||||||
|
Per-game pnach entries matched on the disc CRC, read from the package when
|
||||||
|
widescreen patches are enabled. The cheats_ws folder under the data
|
||||||
|
directory takes precedence and the archive is skipped when it holds a
|
||||||
|
match.
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x804464"
|
||||||
|
|
||||||
|
- name: cheats_ni.zip
|
||||||
|
path: assets/cheats_ni.zip
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 223122
|
||||||
|
md5: fb2a43dcea094a19db4f4bcdc4ad32eb
|
||||||
|
sha1: 31cbff66380f255d359ff9ee09b6edc06102579a
|
||||||
|
description: "No-interlacing patch archive"
|
||||||
|
note: >-
|
||||||
|
Same form as cheats_ws.zip, read when no-interlacing patches are enabled,
|
||||||
|
with the cheats_ni folder taking precedence.
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x80460c"
|
||||||
|
|
||||||
|
- name: Roboto-Regular.ttf
|
||||||
|
path: assets/fonts/Roboto-Regular.ttf
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 305608
|
||||||
|
md5: 86da78cb59576328483a11c6ef74bc2b
|
||||||
|
sha1: 00d62fbdc8d5dec4c659005e116d0ba2ee63b547
|
||||||
|
description: "Interface font"
|
||||||
|
note: "Read as the standard font when the interface comes up. An empty read aborts the process."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x7d1e78-0x7d1e8c, nethersx2-turnip-classic v0.7 libemucore.so 0x7d2270"
|
||||||
|
|
||||||
|
- name: RobotoMono-Medium.ttf
|
||||||
|
path: assets/fonts/RobotoMono-Medium.ttf
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 86820
|
||||||
|
md5: 8ad82b1dc550319993a7d6c932b2656d
|
||||||
|
sha1: 9056e59b69c6f1160fdfb92a0773f17f6307f3ad
|
||||||
|
description: "Fixed-width interface font"
|
||||||
|
note: "Read for the fixed-width font. An empty read aborts the process."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x7d1ecc-0x7d1ee0, nethersx2-turnip-classic v0.7 libemucore.so 0x7d2270"
|
||||||
|
|
||||||
|
- name: fa-solid-900.ttf
|
||||||
|
path: assets/fonts/fa-solid-900.ttf
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 204528
|
||||||
|
md5: dffd9504fcb1894620fa41c700172994
|
||||||
|
sha1: 694b8a2445ff39de415bf4791845442a7b1b81e5
|
||||||
|
description: "Font Awesome icon font"
|
||||||
|
note: "Read for the interface icon glyphs. An empty read aborts the process."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x7d1f20-0x7d1f34, nethersx2-turnip-classic v0.7 libemucore.so 0x7d2270"
|
||||||
|
|
||||||
|
- name: ffx_a.h
|
||||||
|
path: assets/shaders/common/ffx_a.h
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 161481
|
||||||
|
md5: 2c539b603dcb15dcdcfdc420eda56ced
|
||||||
|
sha1: 726370c10154ad092c15c251b98c79185e980c7c
|
||||||
|
description: "FidelityFX common header"
|
||||||
|
note: "Prepended to the sharpening shader of both backends."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x627178"
|
||||||
|
|
||||||
|
- name: ffx_cas.h
|
||||||
|
path: assets/shaders/common/ffx_cas.h
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 63512
|
||||||
|
md5: f8a3d7f48ae19fc372cd0d5d375d5a8d
|
||||||
|
sha1: a1d1a687577f7a607fda35bc88950f57c2129ca5
|
||||||
|
description: "FidelityFX CAS header"
|
||||||
|
note: "Prepended to the sharpening shader of both backends."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x627188"
|
||||||
|
|
||||||
|
- name: fxaa.fx
|
||||||
|
path: assets/shaders/common/fxaa.fx
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 19420
|
||||||
|
md5: 5cdeb2963c1b68c3ffb04a789cc66d6e
|
||||||
|
sha1: 3ac5f68049ed00d8ff3d2811bd09ef0c036efd0a
|
||||||
|
description: "FXAA shader source"
|
||||||
|
note: "Read by both backends when FXAA is enabled."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x67c710, nethersx2-turnip-classic v0.7 libemucore.so 0x685fd0"
|
||||||
|
|
||||||
|
- name: common_header.glsl
|
||||||
|
path: assets/shaders/opengl/common_header.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1938
|
||||||
|
md5: 86a37e282f029d20f395cfd05263fddd
|
||||||
|
sha1: 9c391aae0daddf0c2ba3f0d5265aee9b491286e4
|
||||||
|
description: "OpenGL shader preamble"
|
||||||
|
note: "Prepended to every OpenGL program the renderer builds."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x674618"
|
||||||
|
|
||||||
|
- name: convert.glsl
|
||||||
|
path: assets/shaders/opengl/convert.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 10361
|
||||||
|
md5: 0dba3321d9f902439a50b79680b220c7
|
||||||
|
sha1: 26a17de3b4abc30e5c19987efad4ceac22e9a369
|
||||||
|
description: "OpenGL format conversion shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x674f78"
|
||||||
|
|
||||||
|
- name: present.glsl
|
||||||
|
path: assets/shaders/opengl/present.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 9458
|
||||||
|
md5: afbb9a89f17ead2d8ce7252c1b44186f
|
||||||
|
sha1: bf2688971a8ef2f2c262c3c2ec579d3dd39793e6
|
||||||
|
description: "OpenGL presentation shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x675480"
|
||||||
|
|
||||||
|
- name: merge.glsl
|
||||||
|
path: assets/shaders/opengl/merge.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 455
|
||||||
|
md5: 2c4d70f62928eac933eec932d7bfa0b3
|
||||||
|
sha1: d1a3c11a1273e1d6c740e4eacc3159842f206683
|
||||||
|
description: "OpenGL frame merge shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x675780"
|
||||||
|
|
||||||
|
- name: interlace.glsl
|
||||||
|
path: assets/shaders/opengl/interlace.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 6246
|
||||||
|
md5: 0e537dd838a7ecd3b687f3f7cc60a7be
|
||||||
|
sha1: e74e58f530abb4af02c0875c2f04d507e854869e
|
||||||
|
description: "OpenGL deinterlacing shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x675aac"
|
||||||
|
|
||||||
|
- name: shadeboost.glsl
|
||||||
|
path: assets/shaders/opengl/shadeboost.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1457
|
||||||
|
md5: 3d1e2be521a66cbfc2c5ff32057e7bf4
|
||||||
|
sha1: 8d8b8966afd2ad840151f7fcb494739041708c89
|
||||||
|
description: "OpenGL brightness and contrast shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x675cb8"
|
||||||
|
|
||||||
|
- name: cas.glsl
|
||||||
|
path: assets/shaders/opengl/cas.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2448
|
||||||
|
md5: f8a684763e24557c97e3f5d05935bb3b
|
||||||
|
sha1: 1a69a0fc522caff98fc3829ebf3f12a6a006a058
|
||||||
|
description: "OpenGL sharpening shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x676fa0"
|
||||||
|
|
||||||
|
- name: tfx_vgs.glsl
|
||||||
|
path: assets/shaders/opengl/tfx_vgs.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 5756
|
||||||
|
md5: a97e9616f298bb9041bf9e45ee2ec597
|
||||||
|
sha1: 0e9e98f766c9250b465af776d0077f49f797fed2
|
||||||
|
description: "OpenGL texture function vertex and geometry shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x677318"
|
||||||
|
|
||||||
|
- name: tfx_fs.glsl
|
||||||
|
path: assets/shaders/opengl/tfx_fs.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 25906
|
||||||
|
md5: 9d80855607a6da1014f083340741b845
|
||||||
|
sha1: 919c3308c8850852d529d0127ce94e873375bfd2
|
||||||
|
description: "OpenGL texture function fragment shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x677328"
|
||||||
|
|
||||||
|
- name: tfx.glsl
|
||||||
|
path: assets/shaders/vulkan/tfx.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 28290
|
||||||
|
md5: ebc0ffa3de6fd0a7a4dea17f8b74d806
|
||||||
|
sha1: b4ebf3f7f20fc88f91cda033552a7489a9ff179c
|
||||||
|
description: "Vulkan texture function shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x682098"
|
||||||
|
|
||||||
|
- name: convert.glsl
|
||||||
|
path: assets/shaders/vulkan/convert.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 8025
|
||||||
|
md5: 553d33859963a1abe5508e8e45f1cb1e
|
||||||
|
sha1: 7a133d4cf115dc49cd1921bd7049ea64ad58acce
|
||||||
|
description: "Vulkan format conversion shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x68394c, nethersx2-turnip-classic v0.7 libemucore.so 0x685fb8"
|
||||||
|
|
||||||
|
- name: present.glsl
|
||||||
|
path: assets/shaders/vulkan/present.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 8177
|
||||||
|
md5: 72626d625bb963c6cd7074d4dfd0adda
|
||||||
|
sha1: 4871ee00b249b41d16232769e2f661bedd1c83db
|
||||||
|
description: "Vulkan presentation shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x684728"
|
||||||
|
|
||||||
|
- name: interlace.glsl
|
||||||
|
path: assets/shaders/vulkan/interlace.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 6707
|
||||||
|
md5: bf3caa2532873593218bc4a09e924d4e
|
||||||
|
sha1: f8d14d80036f11707c7e94db2a77531d582019dd
|
||||||
|
description: "Vulkan deinterlacing shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x684f74"
|
||||||
|
|
||||||
|
- name: merge.glsl
|
||||||
|
path: assets/shaders/vulkan/merge.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 669
|
||||||
|
md5: b776383d21609db24d5348c381c2c286
|
||||||
|
sha1: b09de39d6459c70ffab28dcb3e3ef879b1648674
|
||||||
|
description: "Vulkan frame merge shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x6857c4"
|
||||||
|
|
||||||
|
- name: shadeboost.glsl
|
||||||
|
path: assets/shaders/vulkan/shadeboost.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1741
|
||||||
|
md5: 366b45b6c4e9ed8e6b7454eebcb5d010
|
||||||
|
sha1: 26b29f57685d8108cf519c4f1d340d43aacbff6e
|
||||||
|
description: "Vulkan brightness and contrast shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x686284"
|
||||||
|
|
||||||
|
- name: cas.glsl
|
||||||
|
path: assets/shaders/vulkan/cas.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2624
|
||||||
|
md5: 56f3cf4de895dd4d32d6c79d564d0c5b
|
||||||
|
sha1: 709fd5393188f7cff0fe4230d0e3e8b69a82f5b9
|
||||||
|
description: "Vulkan sharpening shader"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x6869c4"
|
||||||
|
|
||||||
|
- name: unlock.wav
|
||||||
|
path: assets/sounds/achievements/unlock.wav
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 87714
|
||||||
|
md5: 4d035ee86f836bfed422a975cf65c9cc
|
||||||
|
sha1: eb488a76217629f620e40287567d7e2b30337680
|
||||||
|
description: "Achievement unlock sound"
|
||||||
|
note: >-
|
||||||
|
Joined to the file:///android_asset base and handed to playSoundAsync,
|
||||||
|
which opens it from the package and plays it through MediaPlayer.
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x811190"
|
||||||
|
|
||||||
|
- name: lbsubmit.wav
|
||||||
|
path: assets/sounds/achievements/lbsubmit.wav
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 82096
|
||||||
|
md5: fa6a7030a9f259ee7300dd0bd49f24f3
|
||||||
|
sha1: 5ad1e110dcf0ffd26405981398892a82e4f3bad1
|
||||||
|
description: "Leaderboard submission sound"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x811814"
|
||||||
|
|
||||||
|
- name: message.wav
|
||||||
|
path: assets/sounds/achievements/message.wav
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 15696
|
||||||
|
md5: d66b0bccd743bd11eaca55bcaec925da
|
||||||
|
sha1: c54f04b63ac6f04e0a0944ef260b5497e4494dbd
|
||||||
|
description: "Achievement notification sound"
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x810254"
|
||||||
|
|
||||||
|
- name: placeholder.png
|
||||||
|
path: assets/placeholder.png
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2762
|
||||||
|
md5: 8f846541ccbf088ee7f8c49c8dcb3a6a
|
||||||
|
sha1: c36292ab7e16bf5a6cbc4063f638e24872349c45
|
||||||
|
description: "Fallback interface texture"
|
||||||
|
note: >-
|
||||||
|
Requested from the texture cache when a notification or a loading screen
|
||||||
|
has no image of its own. A miss logs that it cannot continue and the
|
||||||
|
caller tears the interface down instead of bringing it up.
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 libemucore.so 0x7d21fc, nethersx2-turnip-classic v0.7 libemucore.so 0x817be0, nethersx2-turnip-classic v0.7 libemucore.so 0x7ec54c"
|
||||||
|
|
||||||
|
- name: "<region>.png"
|
||||||
|
path: assets/icons/flags/NTSC-U.png
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Game list region flag"
|
||||||
|
note: >-
|
||||||
|
Loaded as icons/flags/<region>.png with the region string of the entry.
|
||||||
|
Thirty are carried, seven NTSC and twenty-two PAL plus Other.
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 classes.dex icons/flags/%s.png"
|
||||||
|
|
||||||
|
- name: "star-<rating>.png"
|
||||||
|
path: assets/icons/star-0.png
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Game list compatibility rating icon"
|
||||||
|
note: "Loaded as icons/star-<rating>.png for ratings 0 to 5."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 classes.dex icons/star-%d.png"
|
||||||
|
|
||||||
|
- name: faq.html
|
||||||
|
path: assets/faq.html
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 14048
|
||||||
|
md5: c2a64e0bcc401da9b0a3c7adf3cff410
|
||||||
|
sha1: 9163d4a3d19b87483f843e4bf3afe236a50a72d2
|
||||||
|
description: "Help page"
|
||||||
|
note: "Opened under the android_asset scheme by the setup wizard's browser view."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 classes.dex android_asset faq.html"
|
||||||
|
|
||||||
|
- name: 3rdparty.html
|
||||||
|
path: assets/3rdparty.html
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 90296
|
||||||
|
md5: fb4ff036f3e4769aa6daefdc4c5dba57
|
||||||
|
sha1: 7743bf1d7e6e09a02f1b2972aa63bd8a9f26050d
|
||||||
|
description: "Third party notices page"
|
||||||
|
note: "Opened under the android_asset scheme in the built-in browser view."
|
||||||
|
source_ref: "nethersx2-turnip-classic v0.7 classes.dex android_asset 3rdparty.html"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
Left out are the libraries the package carries for the dynamic linker rather
|
||||||
|
than for its own code. libc.so, libm.so, libdl.so, ld-android.so, liblog.so
|
||||||
|
and libc++_shared.so sit beside the drivers so the namespace built over that
|
||||||
|
directory can satisfy their DT_NEEDED, and no code path names any of them;
|
||||||
|
android_linker_ns.o is a relocatable object nothing can open. libc++.so and
|
||||||
|
libsync.so are named in the fallback and promote arrays but the package
|
||||||
|
carries neither, and the promote call passes RTLD_NOLOAD, which never reads
|
||||||
|
from disk. libfile_redirect_hook.so and libgsl_alloc_hook.so are reachable
|
||||||
|
only under feature flags the shim never sets, the only flag passed being the
|
||||||
|
custom driver one. The system Vulkan loader and libandroid.so come from the
|
||||||
|
platform. Also left out are the assets no code path on this platform opens:
|
||||||
|
game_controller_db.txt, whose name appears in neither the library nor the dex,
|
||||||
|
pad input arriving through handleControllerButtonEvent and
|
||||||
|
handleControllerAxisEvent; the seven Direct3D shader sources under
|
||||||
|
shaders/dx11; icons/AppIconLarge.png and cover-placeholder.png;
|
||||||
|
fonts/Roboto-Regular-copyright and sounds/achievements/README.txt, which are
|
||||||
|
licence and credit texts; and dexopt/baseline.prof and baseline.profm, which
|
||||||
|
the Android runtime consumes. Everything the emulator produces for itself
|
||||||
|
under the data directory is out as well: memory cards as Mcd<nnn>.ps2 and
|
||||||
|
Mcd-Multitap<n>-Slot<nn>.ps2, DEV9hdd.raw for the internal disk, save states,
|
||||||
|
screenshots, covers, texture dumps, playtime.dat, emulog.txt, imgui.ini,
|
||||||
|
per-game settings, input profiles, the gamedb and gl_programs caches, and
|
||||||
|
vulkan_shim.log.
|
||||||
|
ref: VulkanShim2/vulkan_shim.cpp:1099-1105, VulkanShim2/vulkan_shim.cpp:1150,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1179-1194,
|
||||||
|
nethersx2-turnip-classic v0.7 libemucore.so 0x4a8c7c
|
||||||
@@ -0,0 +1,801 @@
|
|||||||
|
emulator: NetherSX2-Turnip
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
bios_mode: agnostic
|
||||||
|
source: "https://github.com/nckstwrt/NetherSX2-Turnip"
|
||||||
|
upstream: "https://github.com/Trixarian/AetherSX2"
|
||||||
|
author: "nckstwrt"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "3b7cf800ccac4ab5af768aee24b04363bedeb711"
|
||||||
|
upstream_commit: "1d1f795dfc70e38da67724c7298779260f513889"
|
||||||
|
core_version: "2.2n-4248-Turnip-v0.7"
|
||||||
|
display_name: "Sony - PlayStation 2 (NetherSX2-Turnip)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "nethersx2-turnip"
|
||||||
|
- "NetherSX2-Turnip"
|
||||||
|
- "NETHERSX2-TURNIP"
|
||||||
|
systems:
|
||||||
|
- sony-playstation-2
|
||||||
|
|
||||||
|
bios_directory: "bios/"
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
PlayStation 2 emulator for Android, package xyz.aethersx2.tturnip, activity
|
||||||
|
xyz.aethersx2.android.EmulationActivity. The application id is the only part
|
||||||
|
of the package name that changes, which is what lets it sit beside the build
|
||||||
|
it derives from. That build is NetherSX2 v2.2n-4248, itself a patch of the
|
||||||
|
AetherSX2 v1.5-4248 package, and the library still reports itself as
|
||||||
|
NetherSX2 v2.2n-4248 (Patched). The project publishes its shim sources and
|
||||||
|
the libraries it packs; lib/libvulkad.so, lib/libhook_impl.so and
|
||||||
|
lib/libmain_hook.so at the pinned revision are byte for byte the ones in the
|
||||||
|
v0.7 package, so the sources describe the shipped binaries. Everything below
|
||||||
|
was read from that package: lib/arm64-v8a/libemucore.so, libvulkad.so, the
|
||||||
|
dex and the assets.
|
||||||
|
ref: VulkanShim2/compile2.bat:21-64,
|
||||||
|
nethersx2-turnip v0.7 AndroidManifest.xml,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0xe180c
|
||||||
|
|
||||||
|
The patch rewrites twenty places in the 4248 library. Three are the strings
|
||||||
|
libvulkan.so, libvulkan.so.1 and the message naming them, each turned into
|
||||||
|
libvulkad.so, so the Vulkan loader opens the shim instead of the system
|
||||||
|
driver. Twelve turn comparisons into unconditional paths, among them the
|
||||||
|
memchr scan for the twenty-two byte pattern that precedes the certificate
|
||||||
|
test and two byte-wise string comparisons whose result is forced to equal,
|
||||||
|
which is what lets the package be resigned under a new application id. One
|
||||||
|
skips the notification built from the android_warning key. The last four move
|
||||||
|
settings defaults: the renderer enum from 12 to 14, the upscale multiplier
|
||||||
|
fallback from 1.0 to 2.0 with the configuration read short-circuited, the
|
||||||
|
hardware download mode default, and the warning text that went with it. None
|
||||||
|
of them is in a file loading path, so the file set below is that of the
|
||||||
|
package it patches, read from this library rather than carried over.
|
||||||
|
ref: nethersx2-turnip v0.7 libemucore.so 0x10728e,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x83cebc-0x83cee4,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x83b728,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x83bb3c,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x83cfbc,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x80e910,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x840ff4,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x84130c,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x8421a0
|
||||||
|
|
||||||
|
A BIOS image is required and boot stops without one, the application saying
|
||||||
|
it needs a PS2 BIOS in the bios folder of the data directory. The data
|
||||||
|
directory is getExternalFilesDir(null) with getDataDir() behind it, so it
|
||||||
|
follows the application id, and the folder names under it come from the
|
||||||
|
Folders section, Bios defaulting to bios.
|
||||||
|
ref: nethersx2-turnip v0.7 libemucore.so 0xf70a9,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x7ea908-0x7ea930,
|
||||||
|
xyz/aethersx2/android/NativeLibrary getExternalFilesDir
|
||||||
|
|
||||||
|
Detection is by content. The scan lists the BIOS folder with a * mask, keeps
|
||||||
|
files between 4194304 and 8388608 bytes, and accepts an image whose romdir
|
||||||
|
carries a RESET entry followed by a readable ROMVER; the fifth ROMVER
|
||||||
|
character gives the zone, A for USA, C for China, E for Europe, H for Asia,
|
||||||
|
J for Japan, P for Free, T for T10K and X for Test, any other character
|
||||||
|
standing for itself. The sixth character is compared against D and the result
|
||||||
|
discarded, the acceptance flag being set outright, so development images pass.
|
||||||
|
An image named in the configuration is combined with the BIOS folder and
|
||||||
|
opened at that path when it exists, without the size filter and without the
|
||||||
|
romdir test. No name and no hash is matched anywhere. The image is read into
|
||||||
|
the 4 MB ROM region and truncated to it.
|
||||||
|
ref: aethersx2/pcsx2/ps2/BiosTools.cpp:27-28,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:62-145,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:235-260,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:272-322,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x828d80-0x828f14,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x829140-0x8292f4
|
||||||
|
|
||||||
|
Companions derive from the selected image. rom1 and rom2 are appended to the
|
||||||
|
full name first, then substituted for the existing extension, so an image at
|
||||||
|
ps2-0230a-20080220.bin is followed by ps2-0230a-20080220.bin.rom1 then
|
||||||
|
ps2-0230a-20080220.rom1. The nvm and the mec are read at the substituted
|
||||||
|
extension only, and both are written with defaults when they are absent or
|
||||||
|
too short. No erom is loaded on this code line.
|
||||||
|
ref: aethersx2/pcsx2/ps2/BiosTools.cpp:193-216,
|
||||||
|
aethersx2/pcsx2/CDVD/CDVD.cpp:120-144,
|
||||||
|
aethersx2/pcsx2/CDVD/CDVD.cpp:158-214,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x8288b0-0x828bb8
|
||||||
|
|
||||||
|
The network adapter opens eeprom.dat and flash.dat by bare name, so they
|
||||||
|
resolve against the process working directory, which the application never
|
||||||
|
sets. A compiled-in image stands in for the first and a card filled with 0xFF
|
||||||
|
for the second. DEV9hdd.raw is the default name of the empty disk image its
|
||||||
|
settings page writes. An IRX named in the configuration is read into the ROM
|
||||||
|
region at 0x3C0000 at boot; the field is empty by default and names no file
|
||||||
|
of its own.
|
||||||
|
ref: aethersx2/pcsx2/DEV9/DEV9.cpp:146-161,
|
||||||
|
aethersx2/pcsx2/DEV9/flash.cpp:76-103,
|
||||||
|
aethersx2/pcsx2/ps2/BiosTools.cpp:220-233,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x7c5bec-0x7c5ca0,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x828bb8-0x828ca8
|
||||||
|
|
||||||
|
The Vulkan path is the reason this build exists. libemucore.so opens
|
||||||
|
libvulkad.so where the stock library opens libvulkan.so, and that shim reads
|
||||||
|
the Adreno model from the kgsl sysfs nodes, picks one of six Turnip drivers
|
||||||
|
packed beside it, creates a linker namespace over its own library directory
|
||||||
|
and loads libhook_impl.so and libmain_hook.so into it. The system
|
||||||
|
/system/lib64/libvulkan.so is then opened inside that namespace with its
|
||||||
|
soname patched, so its own driver load lands in the hook, which opens the
|
||||||
|
chosen Turnip driver instead of the vendor ICD. A driver present at
|
||||||
|
/data/local/tmp/libvulkan_freedreno.so is tested first and wins over all six.
|
||||||
|
When the namespace cannot be built the shim falls back to patching the
|
||||||
|
system library's global offset table, and that path alone loads libbase.so,
|
||||||
|
libcutils.so, libvndksupport.so and libhardware.so from the library
|
||||||
|
directory. The shim appends to vulkan_shim.log under the files folder of the
|
||||||
|
data directory.
|
||||||
|
ref: VulkanShim2/vulkan_shim.cpp:43-73,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1010-1092,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1099-1171,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1186-1204,
|
||||||
|
VulkanShim2/hook_impl.cpp:38-139,
|
||||||
|
nethersx2-turnip v0.7 libemucore.so 0x8b473c-0x8b4768
|
||||||
|
|
||||||
|
Resources are read out of the package itself. The library has no asset
|
||||||
|
manager of its own and calls back into readPackageFile, readPackageFileToString
|
||||||
|
and playSoundAsync, each taking an asset-relative name, so the game database,
|
||||||
|
the patch archives, the interface fonts, the shader sources every backend
|
||||||
|
compiles at startup and the achievement sounds are versioned with the build
|
||||||
|
and never looked for on disk. The game list draws its region flags and rating
|
||||||
|
stars from the same assets. Four of the Vulkan shader sources differ from the
|
||||||
|
ones the package it patches carries.
|
||||||
|
ref: nethersx2-turnip v0.7 libemucore.so 0x8348d0,
|
||||||
|
xyz/aethersx2/android/NativeLibrary readPackageFile,
|
||||||
|
xyz/aethersx2/android/NativeLibrary playSoundAsync
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: ps2-0230a-20080220.bin
|
||||||
|
path: bios/ps2-0230a-20080220.bin
|
||||||
|
required: true
|
||||||
|
min_size: 4194304
|
||||||
|
max_size: 8388608
|
||||||
|
validation: [size]
|
||||||
|
description: "PS2 BIOS image"
|
||||||
|
note: >-
|
||||||
|
Any image whose romdir holds RESET and a readable ROMVER is accepted,
|
||||||
|
whatever its name. The 4 to 8 MB range gates the folder scan; an image
|
||||||
|
named in the configuration skips both that range and the romdir test.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:27-28, aethersx2/pcsx2/ps2/BiosTools.cpp:235-260, nethersx2-turnip v0.7 libemucore.so 0x828e20-0x828e44 (size window), nethersx2-turnip v0.7 libemucore.so 0x829244-0x829248 (device type result discarded)"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.rom1
|
||||||
|
path: bios/ps2-0230a-20080220.rom1
|
||||||
|
required: false
|
||||||
|
max_size: 4194304
|
||||||
|
description: "DVD player ROM"
|
||||||
|
note: >-
|
||||||
|
Tried as {bios}.rom1 then {biosbase}.rom1. Read at 0x2404000 of the EE
|
||||||
|
memory block and truncated to 4 MB. Logged and skipped when absent.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:193-216, nethersx2-turnip v0.7 libemucore.so 0x8288b0-0x828a24"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.rom2
|
||||||
|
aliases:
|
||||||
|
- "SCPH-90006_BIOS_VX_HK _230.ROM2"
|
||||||
|
path: bios/ps2-0230a-20080220.rom2
|
||||||
|
required: false
|
||||||
|
max_size: 524288
|
||||||
|
description: "Chinese ROM extension"
|
||||||
|
note: >-
|
||||||
|
Same two-step naming as rom1. Read at 0x2804000 of the EE memory block and
|
||||||
|
truncated to 512 KB. Only present on Chinese region consoles.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:193-216, nethersx2-turnip v0.7 libemucore.so 0x828a34-0x828ba8"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.nvm
|
||||||
|
path: bios/ps2-0230a-20080220.nvm
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
min_size: 1024
|
||||||
|
validation: [size]
|
||||||
|
description: "Console NVRAM"
|
||||||
|
note: >-
|
||||||
|
Read at the BIOS path with the extension replaced by nvm, opened r+b.
|
||||||
|
Carries the console id, the iLink id, the language and the OSD
|
||||||
|
configuration. A 1024 byte image is written when the file is missing or
|
||||||
|
shorter, zeroed except for a fixed iLink id and the language defaults of
|
||||||
|
the BIOS region.
|
||||||
|
source_ref: "aethersx2/pcsx2/CDVD/CDVD.cpp:158-214, nethersx2-turnip v0.7 libemucore.so 0x79b930-0x79ba68"
|
||||||
|
|
||||||
|
- name: ps2-0230a-20080220.mec
|
||||||
|
path: bios/ps2-0230a-20080220.mec
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
min_size: 4
|
||||||
|
validation: [size]
|
||||||
|
description: "Mechacon version"
|
||||||
|
note: >-
|
||||||
|
Read at the BIOS path with the extension replaced by mec. Written as
|
||||||
|
03 06 02 00 when the file is missing or shorter than 4 bytes.
|
||||||
|
source_ref: "aethersx2/pcsx2/CDVD/CDVD.cpp:120-144, nethersx2-turnip v0.7 libemucore.so 0x79cbd0-0x79cc20"
|
||||||
|
|
||||||
|
- name: eeprom.dat
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
size: 64
|
||||||
|
description: "DEV9 EEPROM"
|
||||||
|
note: >-
|
||||||
|
Opened O_RDWR by bare name when the network adapter starts and mapped over
|
||||||
|
64 bytes. A compiled-in image stands in when the file is missing or cannot
|
||||||
|
be mapped.
|
||||||
|
source_ref: "aethersx2/pcsx2/DEV9/DEV9.cpp:146-161, nethersx2-turnip v0.7 libemucore.so 0x7c5c44"
|
||||||
|
|
||||||
|
- name: flash.dat
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
max_size: 8650752
|
||||||
|
description: "DEV9 SmartMedia flash image"
|
||||||
|
note: >-
|
||||||
|
Opened rb by bare name at network adapter init and read as 1024 blocks of
|
||||||
|
16 pages of 512 bytes plus 16 ECC bytes. The card is filled with 0xFF when
|
||||||
|
the file is absent.
|
||||||
|
source_ref: "aethersx2/pcsx2/DEV9/flash.cpp:76-103, nethersx2-turnip v0.7 libemucore.so 0x7c5bf0"
|
||||||
|
|
||||||
|
- name: "<module>.irx"
|
||||||
|
required: false
|
||||||
|
unsourceable: "any IOP module the user points at, under no name the code expects"
|
||||||
|
description: "IOP module injected at boot"
|
||||||
|
note: >-
|
||||||
|
Opened at the path the configuration holds once it is longer than three
|
||||||
|
characters, and read into the ROM region at 0x3C0000, capped at 0x40000
|
||||||
|
bytes. The field is empty by default and names no file of its own.
|
||||||
|
source_ref: "aethersx2/pcsx2/ps2/BiosTools.cpp:220-233, aethersx2/pcsx2/ps2/BiosTools.cpp:327-328, nethersx2-turnip v0.7 libemucore.so 0x828bb8-0x828ca8"
|
||||||
|
|
||||||
|
- name: libvulkad.so
|
||||||
|
path: lib/arm64-v8a/libvulkad.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 484528
|
||||||
|
md5: 07a891beadc7c3baf4b98b7358cc6e2c
|
||||||
|
sha1: 55f845c4ea0262cfdc4882a3caccc6848c4f0a6b
|
||||||
|
description: "Vulkan loader shim"
|
||||||
|
note: >-
|
||||||
|
Opened as libvulkad.so.1 then libvulkad.so where the stock library names
|
||||||
|
libvulkan.so, and vkCreateInstance is resolved from it. Without it the
|
||||||
|
Vulkan backend does not open and the message names the shim.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:971-1279 (the constructor that runs on load), nethersx2-turnip v0.7 libemucore.so 0x8b473c-0x8b4768"
|
||||||
|
|
||||||
|
- name: libhook_impl.so
|
||||||
|
path: lib/arm64-v8a/libhook_impl.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 461856
|
||||||
|
md5: c2a10d75f7a186f78debc79dd2204841
|
||||||
|
sha1: 5a86d24c83f4a0867a3526638182c8dc67e0033b
|
||||||
|
description: "Driver load hook"
|
||||||
|
note: >-
|
||||||
|
Opened into the adrenotools-libvulkan namespace and asked for
|
||||||
|
init_hook_param, which receives the driver directory and driver name. Its
|
||||||
|
hook_android_dlopen_ext is what replaces the vendor driver with the Turnip
|
||||||
|
one, and it reopens itself in each driver namespace it creates.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1145-1163, VulkanShim2/hook_impl.cpp:38-139"
|
||||||
|
|
||||||
|
- name: libmain_hook.so
|
||||||
|
path: lib/arm64-v8a/libmain_hook.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 5648
|
||||||
|
md5: 3ded83b3f45773199b82bf81c86f8c89
|
||||||
|
sha1: e2ee6c00247fc05b88afe43237fa4bfa90212c54
|
||||||
|
description: "Namespace interposer"
|
||||||
|
note: >-
|
||||||
|
Loaded RTLD_GLOBAL into the same namespace before the system Vulkan
|
||||||
|
library, so its android_dlopen_ext and android_load_sphal_library are the
|
||||||
|
ones that library binds to.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1166-1167, VulkanShim2/main_hook.c:3-8"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_T28.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_T28.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 18606849
|
||||||
|
md5: 315f4b037b77dea81ea099e13e94fa11
|
||||||
|
sha1: 83406408d328d8529ffa2faf7ab878664a5c7a79
|
||||||
|
description: "Turnip driver, default branch"
|
||||||
|
note: >-
|
||||||
|
Chosen when no other branch matches. Loaded by name from the library
|
||||||
|
directory through the hook; a load failure falls back to the vendor
|
||||||
|
driver.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1014, VulkanShim2/vulkan_shim.cpp:1086-1087, VulkanShim2/hook_impl.cpp:127-135"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_a8xx-turnip-gen8-V31.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_a8xx-turnip-gen8-V31.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 14509832
|
||||||
|
md5: 7f6dbc9ec12cb53b1802c418cf532f9b
|
||||||
|
sha1: 2dc32726b7a68ced6a40ea2c6cc60848716907ab
|
||||||
|
description: "Turnip driver, Adreno 8xx branch"
|
||||||
|
note: >-
|
||||||
|
Chosen when the Adreno model reads non-zero and is not 810. Model 825 also
|
||||||
|
turns off framebuffer fetch.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1013, VulkanShim2/vulkan_shim.cpp:1041-1058"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_T24.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_T24.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 18003849
|
||||||
|
md5: e90d691859e0ff8f0221f3fb497cca5d
|
||||||
|
sha1: d28f7c64a8296a6d1886b348946d01433c10b493
|
||||||
|
description: "Turnip driver, Adreno 810 branch"
|
||||||
|
note: "Chosen when the Adreno model reads 810."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1043-1046"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_25.3.0_R6_Gmem.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_25.3.0_R6_Gmem.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 12048553
|
||||||
|
md5: 3f1b01295ab08d070bede8122ebd0aea
|
||||||
|
sha1: 2159a5172176f9ee0076370314d2d100de2fe1b1
|
||||||
|
description: "Turnip driver, Adreno 710 and 720 branch"
|
||||||
|
note: >-
|
||||||
|
Chosen when the model is unreadable and the GPU name holds 710 or 720, or
|
||||||
|
the platform reads SM6475.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1062-1065"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_v24.1.0_R18.a6xx-Patched.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_v24.1.0_R18.a6xx-Patched.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 9407968
|
||||||
|
md5: 7af55500464d372a609084fb4698e16d
|
||||||
|
sha1: 1abf76c578cb1330e354d5588634b87cef4bc057
|
||||||
|
description: "Turnip driver, SM8250 and SM7325 branch"
|
||||||
|
note: "Chosen when the platform reads SM8250, kona or SM7325."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1030-1037"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno_T19.so
|
||||||
|
path: lib/arm64-v8a/libvulkan_freedreno_T19.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 11581209
|
||||||
|
md5: 5f953080ba9ac858a99f3742c8302055
|
||||||
|
sha1: 4dc276dfd5842302c978ce9b2996f961dc6452f1
|
||||||
|
description: "Turnip driver, SM6125 branch"
|
||||||
|
note: "Chosen when the platform reads SM6125 or trinket."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1023-1026"
|
||||||
|
|
||||||
|
- name: libvulkan_freedreno.so
|
||||||
|
path: data/local/tmp/libvulkan_freedreno.so
|
||||||
|
required: false
|
||||||
|
unsourceable: "any Turnip build the user places at that path"
|
||||||
|
description: "Turnip driver override"
|
||||||
|
note: >-
|
||||||
|
Tested with access before any detection runs. When it exists it becomes
|
||||||
|
the driver and the driver directory becomes /data/local/tmp/, so none of
|
||||||
|
the six packed drivers is consulted.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1012, VulkanShim2/vulkan_shim.cpp:1015-1020"
|
||||||
|
|
||||||
|
- name: libbase.so
|
||||||
|
path: lib/arm64-v8a/libbase.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 255352
|
||||||
|
md5: eae5ccb3f801b3333ec0e65592ce8a87
|
||||||
|
sha1: fecf95a804a7cb57e210f55d5482a56826c8684c
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: >-
|
||||||
|
Opened RTLD_GLOBAL from the library directory only when the namespace
|
||||||
|
approach failed and the shim falls back to patching the global offset
|
||||||
|
table.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1186-1201"
|
||||||
|
|
||||||
|
- name: libcutils.so
|
||||||
|
path: lib/arm64-v8a/libcutils.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 91200
|
||||||
|
md5: 185cd93c21cce12ab4c3bc2430934684
|
||||||
|
sha1: 63e55bcae5ee690cf6bc7db69a5077c5502e4334
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: "Same fallback list as libbase.so, and a dependency of every packed driver."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1186-1201"
|
||||||
|
|
||||||
|
- name: libvndksupport.so
|
||||||
|
path: lib/arm64-v8a/libvndksupport.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 66881
|
||||||
|
md5: aa5065cca6695aa4b8cfdd3c164f3d28
|
||||||
|
sha1: a6f2d8498a2f0a00776dd69c58f012cdbb75a308
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: >-
|
||||||
|
Same fallback list as libbase.so. Its android_load_sphal_library is the
|
||||||
|
call the shim stubs so a vendor load can be redirected.
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1186-1201, VulkanShim2/vulkan_shim.cpp:742-750"
|
||||||
|
|
||||||
|
- name: libhardware.so
|
||||||
|
path: lib/arm64-v8a/libhardware.so
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 66961
|
||||||
|
md5: 71e06a0726aa60b010e066d37021d36a
|
||||||
|
sha1: 555a6203cd7c23c2b49916d70615e5df7973aa87
|
||||||
|
description: "Platform support library for the fallback path"
|
||||||
|
note: "Same fallback list as libbase.so, and a dependency of every packed driver."
|
||||||
|
source_ref: "VulkanShim2/vulkan_shim.cpp:1186-1201"
|
||||||
|
|
||||||
|
- name: GameIndex.yaml
|
||||||
|
path: assets/GameIndex.yaml
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1850565
|
||||||
|
md5: 26ab10d8de93c9b9806fa7602faa2b62
|
||||||
|
sha1: fca26d4f7c1fe0abf6534b470da2ee5ad461eba5
|
||||||
|
description: "Game database"
|
||||||
|
note: >-
|
||||||
|
Read from the package by name, keyed by serial, and carrying the per-game
|
||||||
|
fixes, patches and settings overrides. Parsed into gamedb.cache in the
|
||||||
|
cache folder.
|
||||||
|
source_ref: "aethersx2/pcsx2/GameDatabase.cpp:35, nethersx2-turnip v0.7 libemucore.so 0x2e35e4"
|
||||||
|
|
||||||
|
- name: cheats_ws.zip
|
||||||
|
path: assets/cheats_ws.zip
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1694454
|
||||||
|
md5: cc19970629feb0a25b9b95263194f08f
|
||||||
|
sha1: 1caae7ddf0cbba5f1f6d7404b2309300d913778c
|
||||||
|
description: "Widescreen patch archive"
|
||||||
|
note: >-
|
||||||
|
Per-game pnach entries matched on the disc CRC, read from the package when
|
||||||
|
widescreen patches are enabled. The cheats_ws folder under the data
|
||||||
|
directory takes precedence and the archive is skipped when it holds a
|
||||||
|
match.
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x80f8e4"
|
||||||
|
|
||||||
|
- name: cheats_ni.zip
|
||||||
|
path: assets/cheats_ni.zip
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 223122
|
||||||
|
md5: fb2a43dcea094a19db4f4bcdc4ad32eb
|
||||||
|
sha1: 31cbff66380f255d359ff9ee09b6edc06102579a
|
||||||
|
description: "No-interlacing patch archive"
|
||||||
|
note: >-
|
||||||
|
Same form as cheats_ws.zip, read when no-interlacing patches are enabled,
|
||||||
|
with the cheats_ni folder taking precedence.
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x80fa8c"
|
||||||
|
|
||||||
|
- name: Roboto-Regular.ttf
|
||||||
|
path: assets/fonts/Roboto-Regular.ttf
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 305608
|
||||||
|
md5: 86da78cb59576328483a11c6ef74bc2b
|
||||||
|
sha1: 00d62fbdc8d5dec4c659005e116d0ba2ee63b547
|
||||||
|
description: "Interface font"
|
||||||
|
note: "Read as the standard font when the interface comes up. The load fails without it."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xf6f27"
|
||||||
|
|
||||||
|
- name: RobotoMono-Medium.ttf
|
||||||
|
path: assets/fonts/RobotoMono-Medium.ttf
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 86820
|
||||||
|
md5: 8ad82b1dc550319993a7d6c932b2656d
|
||||||
|
sha1: 9056e59b69c6f1160fdfb92a0773f17f6307f3ad
|
||||||
|
description: "Fixed-width interface font"
|
||||||
|
note: "Read for the fixed-width font. The load fails without it."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xdb98d"
|
||||||
|
|
||||||
|
- name: fa-solid-900.ttf
|
||||||
|
path: assets/fonts/fa-solid-900.ttf
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 204528
|
||||||
|
md5: dffd9504fcb1894620fa41c700172994
|
||||||
|
sha1: 694b8a2445ff39de415bf4791845442a7b1b81e5
|
||||||
|
description: "Font Awesome icon font"
|
||||||
|
note: "Read for the interface icon glyphs. The load fails without it."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x11a567"
|
||||||
|
|
||||||
|
- name: ffx_a.h
|
||||||
|
path: assets/shaders/common/ffx_a.h
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 161481
|
||||||
|
md5: 2c539b603dcb15dcdcfdc420eda56ced
|
||||||
|
sha1: 726370c10154ad092c15c251b98c79185e980c7c
|
||||||
|
description: "FidelityFX common header"
|
||||||
|
note: "Prepended to the sharpening shader of both backends."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x10cfb5"
|
||||||
|
|
||||||
|
- name: ffx_cas.h
|
||||||
|
path: assets/shaders/common/ffx_cas.h
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 63512
|
||||||
|
md5: f8a3d7f48ae19fc372cd0d5d375d5a8d
|
||||||
|
sha1: a1d1a687577f7a607fda35bc88950f57c2129ca5
|
||||||
|
description: "FidelityFX CAS header"
|
||||||
|
note: "Prepended to the sharpening shader of both backends."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xce5f7"
|
||||||
|
|
||||||
|
- name: fxaa.fx
|
||||||
|
path: assets/shaders/common/fxaa.fx
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 19420
|
||||||
|
md5: 5cdeb2963c1b68c3ffb04a789cc66d6e
|
||||||
|
sha1: 3ac5f68049ed00d8ff3d2811bd09ef0c036efd0a
|
||||||
|
description: "FXAA shader source"
|
||||||
|
note: "Read by both backends when FXAA is enabled."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xe4f55"
|
||||||
|
|
||||||
|
- name: common_header.glsl
|
||||||
|
path: assets/shaders/opengl/common_header.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1863
|
||||||
|
md5: 1dcf4ca0cc95f2f8e11b66c2ffeeaffe
|
||||||
|
sha1: 3f47597187030144498af7a92531e8f205561211
|
||||||
|
description: "OpenGL shader preamble"
|
||||||
|
note: "Prepended to every OpenGL program the renderer builds."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x10cfcc"
|
||||||
|
|
||||||
|
- name: convert.glsl
|
||||||
|
path: assets/shaders/opengl/convert.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 11276
|
||||||
|
md5: c3db4fcdd142912c0d9a07f3fb40bbbc
|
||||||
|
sha1: b2a059787ee297654b27f633e37382e239693a36
|
||||||
|
description: "OpenGL format conversion shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xb5bd7"
|
||||||
|
|
||||||
|
- name: present.glsl
|
||||||
|
path: assets/shaders/opengl/present.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 9458
|
||||||
|
md5: afbb9a89f17ead2d8ce7252c1b44186f
|
||||||
|
sha1: bf2688971a8ef2f2c262c3c2ec579d3dd39793e6
|
||||||
|
description: "OpenGL presentation shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x11a06b"
|
||||||
|
|
||||||
|
- name: merge.glsl
|
||||||
|
path: assets/shaders/opengl/merge.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 455
|
||||||
|
md5: 2c4d70f62928eac933eec932d7bfa0b3
|
||||||
|
sha1: d1a3c11a1273e1d6c740e4eacc3159842f206683
|
||||||
|
description: "OpenGL frame merge shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x117b1c"
|
||||||
|
|
||||||
|
- name: interlace.glsl
|
||||||
|
path: assets/shaders/opengl/interlace.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 6246
|
||||||
|
md5: 0e537dd838a7ecd3b687f3f7cc60a7be
|
||||||
|
sha1: e74e58f530abb4af02c0875c2f04d507e854869e
|
||||||
|
description: "OpenGL deinterlacing shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x103b11"
|
||||||
|
|
||||||
|
- name: shadeboost.glsl
|
||||||
|
path: assets/shaders/opengl/shadeboost.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1457
|
||||||
|
md5: 3d1e2be521a66cbfc2c5ff32057e7bf4
|
||||||
|
sha1: 8d8b8966afd2ad840151f7fcb494739041708c89
|
||||||
|
description: "OpenGL brightness and contrast shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x1007b6"
|
||||||
|
|
||||||
|
- name: cas.glsl
|
||||||
|
path: assets/shaders/opengl/cas.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2448
|
||||||
|
md5: f8a684763e24557c97e3f5d05935bb3b
|
||||||
|
sha1: 1a69a0fc522caff98fc3829ebf3f12a6a006a058
|
||||||
|
description: "OpenGL sharpening shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x10967c"
|
||||||
|
|
||||||
|
- name: tfx_vgs.glsl
|
||||||
|
path: assets/shaders/opengl/tfx_vgs.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 5756
|
||||||
|
md5: a97e9616f298bb9041bf9e45ee2ec597
|
||||||
|
sha1: 0e9e98f766c9250b465af776d0077f49f797fed2
|
||||||
|
description: "OpenGL texture function vertex and geometry shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xd49ab"
|
||||||
|
|
||||||
|
- name: tfx_fs.glsl
|
||||||
|
path: assets/shaders/opengl/tfx_fs.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 26680
|
||||||
|
md5: 24e39ca8f97a1ee4cbd1e9bf8b8da2fd
|
||||||
|
sha1: 00eb0418e7a25c89aaf7c526922fe45d83243ec5
|
||||||
|
description: "OpenGL texture function fragment shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x117b36"
|
||||||
|
|
||||||
|
- name: tfx.glsl
|
||||||
|
path: assets/shaders/vulkan/tfx.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 29670
|
||||||
|
md5: df60c4e6c5690dd2d3a0cc740800b284
|
||||||
|
sha1: 1c3a966a42cefcb9c26ce2fa77e4cd90f2d50329
|
||||||
|
description: "Vulkan texture function shader"
|
||||||
|
note: "This project's own bytes, neither the New nor the Old copy it also carries."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xe14fc"
|
||||||
|
|
||||||
|
- name: convert.glsl
|
||||||
|
path: assets/shaders/vulkan/convert.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 9379
|
||||||
|
md5: f3aaf5697b069d1eb9be66fc1c932786
|
||||||
|
sha1: aedc25c370bf3fe28923dc8359111a098293a503
|
||||||
|
description: "Vulkan format conversion shader"
|
||||||
|
note: "This project's own bytes, neither the New nor the Old copy it also carries."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xc3d36"
|
||||||
|
|
||||||
|
- name: interlace.glsl
|
||||||
|
path: assets/shaders/vulkan/interlace.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 7745
|
||||||
|
md5: 08bc6e44a6d86ccad4b0673b445bd9d8
|
||||||
|
sha1: 5a433c891e071c3885af7a5f7e47fed7e5ec30cf
|
||||||
|
description: "Vulkan deinterlacing shader"
|
||||||
|
note: "This project's own bytes, neither the New nor the Old copy it also carries."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xb86eb"
|
||||||
|
|
||||||
|
- name: cas.glsl
|
||||||
|
path: assets/shaders/vulkan/cas.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2637
|
||||||
|
md5: deb7394a31184990c78c9753a293ff60
|
||||||
|
sha1: 005cecf1a5e20b05407d55d0aad22cf81ad66c31
|
||||||
|
description: "Vulkan sharpening shader"
|
||||||
|
note: "The New copy the project also carries, byte for byte."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xd4a2c"
|
||||||
|
|
||||||
|
- name: present.glsl
|
||||||
|
path: assets/shaders/vulkan/present.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 8177
|
||||||
|
md5: 72626d625bb963c6cd7074d4dfd0adda
|
||||||
|
sha1: 4871ee00b249b41d16232769e2f661bedd1c83db
|
||||||
|
description: "Vulkan presentation shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xd777a"
|
||||||
|
|
||||||
|
- name: merge.glsl
|
||||||
|
path: assets/shaders/vulkan/merge.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 669
|
||||||
|
md5: b776383d21609db24d5348c381c2c286
|
||||||
|
sha1: b09de39d6459c70ffab28dcb3e3ef879b1648674
|
||||||
|
description: "Vulkan frame merge shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xe8c36"
|
||||||
|
|
||||||
|
- name: shadeboost.glsl
|
||||||
|
path: assets/shaders/vulkan/shadeboost.glsl
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 1741
|
||||||
|
md5: 366b45b6c4e9ed8e6b7454eebcb5d010
|
||||||
|
sha1: 26b29f57685d8108cf519c4f1d340d43aacbff6e
|
||||||
|
description: "Vulkan brightness and contrast shader"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xde3c2"
|
||||||
|
|
||||||
|
- name: unlock.wav
|
||||||
|
path: assets/sounds/achievements/unlock.wav
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 87714
|
||||||
|
md5: 4d035ee86f836bfed422a975cf65c9cc
|
||||||
|
sha1: eb488a76217629f620e40287567d7e2b30337680
|
||||||
|
description: "Achievement unlock sound"
|
||||||
|
note: "Handed to playSoundAsync, which opens it from the package and plays it through MediaPlayer."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xceb85"
|
||||||
|
|
||||||
|
- name: lbsubmit.wav
|
||||||
|
path: assets/sounds/achievements/lbsubmit.wav
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 82096
|
||||||
|
md5: fa6a7030a9f259ee7300dd0bd49f24f3
|
||||||
|
sha1: 5ad1e110dcf0ffd26405981398892a82e4f3bad1
|
||||||
|
description: "Leaderboard submission sound"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xe1a29"
|
||||||
|
|
||||||
|
- name: message.wav
|
||||||
|
path: assets/sounds/achievements/message.wav
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 15696
|
||||||
|
md5: d66b0bccd743bd11eaca55bcaec925da
|
||||||
|
sha1: c54f04b63ac6f04e0a0944ef260b5497e4494dbd
|
||||||
|
description: "Achievement notification sound"
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0xfd47d"
|
||||||
|
|
||||||
|
- name: placeholder.png
|
||||||
|
path: assets/placeholder.png
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2762
|
||||||
|
md5: 8f846541ccbf088ee7f8c49c8dcb3a6a
|
||||||
|
sha1: c36292ab7e16bf5a6cbc4063f638e24872349c45
|
||||||
|
description: "Fallback interface texture"
|
||||||
|
note: >-
|
||||||
|
Requested from the texture cache when a notification or a loading screen
|
||||||
|
has no image of its own.
|
||||||
|
source_ref: "nethersx2-turnip v0.7 libemucore.so 0x7dcbf4, nethersx2-turnip v0.7 libemucore.so 0x8238e0"
|
||||||
|
|
||||||
|
- name: "<region>.png"
|
||||||
|
path: assets/icons/flags/NTSC-U.png
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Game list region flag"
|
||||||
|
note: >-
|
||||||
|
Loaded as icons/flags/<region>.png with the region string of the entry.
|
||||||
|
Thirty are carried, seven NTSC and twenty-two PAL plus Other.
|
||||||
|
source_ref: "nethersx2-turnip v0.7 classes.dex icons/flags/%s.png"
|
||||||
|
|
||||||
|
- name: "star-<rating>.png"
|
||||||
|
path: assets/icons/star-0.png
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Game list compatibility rating icon"
|
||||||
|
note: "Loaded as icons/star-<rating>.png for ratings 0 to 5."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 classes.dex icons/star-%d.png"
|
||||||
|
|
||||||
|
- name: faq.html
|
||||||
|
path: assets/faq.html
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 14048
|
||||||
|
md5: c2a64e0bcc401da9b0a3c7adf3cff410
|
||||||
|
sha1: 9163d4a3d19b87483f843e4bf3afe236a50a72d2
|
||||||
|
description: "Help page"
|
||||||
|
note: "Opened under the android_asset scheme in the built-in browser view."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 classes.dex android_asset faq.html"
|
||||||
|
|
||||||
|
- name: 3rdparty.html
|
||||||
|
path: assets/3rdparty.html
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 90296
|
||||||
|
md5: fb4ff036f3e4769aa6daefdc4c5dba57
|
||||||
|
sha1: 7743bf1d7e6e09a02f1b2972aa63bd8a9f26050d
|
||||||
|
description: "Third party notices page"
|
||||||
|
note: "Opened under the android_asset scheme in the built-in browser view."
|
||||||
|
source_ref: "nethersx2-turnip v0.7 classes.dex android_asset 3rdparty.html"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
Left out are the libraries the package carries for the dynamic linker rather
|
||||||
|
than for its own code. libc.so, libm.so, libdl.so, ld-android.so and
|
||||||
|
libc++_shared.so sit beside the drivers so the namespace built over that
|
||||||
|
directory can satisfy their DT_NEEDED, and no code path names any of them;
|
||||||
|
android_linker_ns.o is a relocatable object nothing can open. libc++.so and
|
||||||
|
libsync.so are named in the fallback and promote arrays but the package
|
||||||
|
carries neither, and the promote call passes RTLD_NOLOAD, which never reads
|
||||||
|
from disk. libnativewindow.so, libsync.so and libz.so, which every driver
|
||||||
|
needs, come from the system through the link to the default namespace. The
|
||||||
|
deps cache the shim would fill under cache/vulkan_deps is unreachable: the
|
||||||
|
functions that build it have no call site and the compiler dropped their
|
||||||
|
strings. Also left out are the assets no code path on this platform opens:
|
||||||
|
shaders/vulkan/New and shaders/vulkan/Old, reference copies for which no path
|
||||||
|
string exists in the library; game_controller_db.txt, whose name appears in
|
||||||
|
neither the library nor the dex, pad input arriving through
|
||||||
|
handleControllerButtonEvent and handleControllerAxisEvent; the seven Direct3D
|
||||||
|
shader sources under shaders/dx11; icons/AppIconLarge.png and
|
||||||
|
cover-placeholder.png; fonts/Roboto-Regular-copyright and
|
||||||
|
sounds/achievements/README.txt, which are licence and credit texts; and
|
||||||
|
dexopt/baseline.prof and baseline.profm, which the Android runtime consumes.
|
||||||
|
Everything the emulator produces for itself under the data directory is out
|
||||||
|
as well: memory cards as Mcd<nnn>.ps2, DEV9hdd.raw for the internal disk,
|
||||||
|
save states, screenshots, covers, texture dumps, per-game settings, input
|
||||||
|
profiles, the gamedb and pipeline caches, and vulkan_shim.log.
|
||||||
|
ref: VulkanShim2/vulkan_shim.cpp:599-729, VulkanShim2/vulkan_shim.cpp:1107-1112,
|
||||||
|
VulkanShim2/vulkan_shim.cpp:1186-1201,
|
||||||
|
nethersx2-turnip v0.7 libvulkad.so
|
||||||
@@ -15,8 +15,6 @@ cores:
|
|||||||
- "nethersx2"
|
- "nethersx2"
|
||||||
- "NetherSX2"
|
- "NetherSX2"
|
||||||
- "NETHERSX2"
|
- "NETHERSX2"
|
||||||
- "NETHERSX2-TURNIP"
|
|
||||||
- "NETHERSX2-TURNIP-CLASSIC"
|
|
||||||
systems:
|
systems:
|
||||||
- sony-playstation-2
|
- sony-playstation-2
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
emulator: "NGP.emu"
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/Rakashazi/emu-ex-plus-alpha"
|
||||||
|
upstream: "https://mednafen.github.io/"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "1c12fac5ce49badaadff2e2f210dcc30b89f4943"
|
||||||
|
core_version: "1.5.85"
|
||||||
|
display_name: "SNK - Neo Geo Pocket / Color (NGP.emu)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "ngp-emu"
|
||||||
|
- "NGP.emu"
|
||||||
|
- "NGP-EMU"
|
||||||
|
systems:
|
||||||
|
- snk-ngp
|
||||||
|
- snk-ngpc
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Member of the EX Emulator series by Robert Broglia, which targets Android and
|
||||||
|
Linux (README.md:1,3-4,12-13) and keeps iOS and Pandora build shortcuts in the
|
||||||
|
tree (NGP.emu/ios.mk, NGP.emu/pandora.mk). Published as com.explusalpha.NgpEmu
|
||||||
|
(NGP.emu/metadata/conf.mk:2,4,6,7) and reached by ES-DE through its NGP-EMU
|
||||||
|
find rule, which only the Android rule set carries. Mednafen's Neo Geo Pocket
|
||||||
|
module, itself descended from NeoPop, is vendored under NGP.emu/src/ngp
|
||||||
|
(NGP.emu/metadata/conf.mk:8, NGP.emu/src/main/AppMeta.cc:27) on the 1.32 line
|
||||||
|
(EmuFramework/include/shared/mednafen/mednafen-config.h:167) and driven by the
|
||||||
|
app's own video, audio, input and save layers. Three files differ from the
|
||||||
|
Mednafen 1.32.1 release, all of it frontend plumbing: the pixel format and
|
||||||
|
sound rate hooks, the input latch and the flash file I/O move to the app
|
||||||
|
(NGP.emu/src/main/Main.cc:84,102,118-131, NGP.emu/src/main/system.ccm:87,93).
|
||||||
|
The TLCS-900h disassembler is left out of the build
|
||||||
|
(NGP.emu/src/CMakeLists.txt:6-32). Content is read from .ngp, .ngc, .npc and
|
||||||
|
.ngpc files (NGP.emu/metadata/conf.mk:5, NGP.emu/src/main/AppMeta.cc:31-34,
|
||||||
|
NGP.emu/src/ngp/neopop.cpp:336-337); an archive is opened by the framework,
|
||||||
|
which keeps the first entry passing that same filter
|
||||||
|
(EmuFramework/src/EmuSystem.cc:392-412).
|
||||||
|
|
||||||
|
The content image is the only one the app loads. It is read into a 4 MiB
|
||||||
|
buffer, hashed for the save file names and handed to the module, which refuses
|
||||||
|
an image over 8 MiB (NGP.emu/src/main/Main.cc:80-85,
|
||||||
|
EmuFramework/src/shared/mednafen-emuex/MDFNUtils.hh:133-146,
|
||||||
|
NGP.emu/src/ngp/neopop.cpp:183-193). The BIOS is built in memory rather than
|
||||||
|
read: bios_install fills a 64 KiB array with the 27 system call vectors, writes
|
||||||
|
opcode 0x1F at each target, copies an 0x800 byte system font held in the binary
|
||||||
|
to 0x8DCF and closes the image with a RETI and an infinite loop
|
||||||
|
(NGP.emu/src/ngp/bios.cpp:29,50-180,182-239, NGP.emu/src/ngp/neopop.cpp:211).
|
||||||
|
That opcode is bound to the HLE handler in the interpreter decode table, and
|
||||||
|
the handler answers only from the 0xFF0000 region
|
||||||
|
(NGP.emu/src/ngp/TLCS-900h/TLCS900h_interpret.cpp:921-926,
|
||||||
|
NGP.emu/src/ngp/biosHLE.cpp:43-47). The same array is what the memory map
|
||||||
|
returns for the BIOS region and where the font routine reads its glyphs
|
||||||
|
(NGP.emu/src/ngp/mem.cpp:121, NGP.emu/src/ngp/biosHLE.cpp:221). The NGP
|
||||||
|
Language menu item feeds the ngp.language setting, written to RAM at boot
|
||||||
|
rather than selecting a file (NGP.emu/src/main/EmuMenuViews.cc:31-40,
|
||||||
|
NGP.emu/src/main/options.cc:82-83, NGP.emu/src/ngp/mem.cpp:620,
|
||||||
|
NGP.emu/src/ngp/neopop.cpp:286-299).
|
||||||
|
|
||||||
|
No firmware path exists by construction: the app answers Mednafen's file name
|
||||||
|
request for save states, saves and save backups only, and any other kind ends
|
||||||
|
in unreachable() (NGP.emu/src/main/options.cc:96-106). Cheat loading and IPS
|
||||||
|
patching are compiled in from the shared Mednafen sources and called from
|
||||||
|
nowhere (EmuFramework/src/shared/mednafen/mempatcher.cpp:251-254,
|
||||||
|
EmuFramework/src/shared/mednafen/file.cpp:38-53). Per content the app writes
|
||||||
|
and reads back a .ngf image holding the cartridge flash, plus save states and
|
||||||
|
NgpEmu.config (NGP.emu/src/main/Main.cc:53-73,118-131,
|
||||||
|
NGP.emu/src/main/system.ccm:76, NGP.emu/src/main/AppMeta.cc:28). ui.png,
|
||||||
|
gpOverlay.png and the shader sources are drawn from the application bundle
|
||||||
|
(EmuFramework/include/emuframework/AssetManager.hh:61-66,
|
||||||
|
EmuFramework/src/AssetManager.cc:58-65,
|
||||||
|
EmuFramework/src/VideoImageEffect.cc:163-173). The app declares no bundled
|
||||||
|
content, the framework definition defaulting to an empty span
|
||||||
|
(EmuFramework/src/AppMeta.cc:40,
|
||||||
|
EmuFramework/include/emuframework/AppMeta.hh:66-68).
|
||||||
|
|
||||||
|
files: []
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
emulator: openbor
|
||||||
|
type: standalone
|
||||||
|
core_classification: game_engine
|
||||||
|
source: "https://github.com/DCurrent/openbor"
|
||||||
|
upstream: "https://github.com/DCurrent/openbor"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "0ece95d1c113c1ce86f2da826b3c25b521ee116d"
|
||||||
|
core_version: "4.0 Build 7949"
|
||||||
|
display_name: "OpenBOR Game Engine"
|
||||||
|
cores:
|
||||||
|
- openbor
|
||||||
|
- openbor4432
|
||||||
|
- openbor6330
|
||||||
|
- openbor6412
|
||||||
|
- openbor6510
|
||||||
|
- openbor7142
|
||||||
|
- openbor7530
|
||||||
|
systems:
|
||||||
|
- openbor
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Sprite based side scrolling engine continuing Senile Team's Beats of Rage,
|
||||||
|
built for beat em up and shooter style 2D games. A game is a module: a .pak
|
||||||
|
archive carrying its own data tree, and that archive is what the frontends
|
||||||
|
hand over as content. ES-DE runs the .pak on macOS, the game's own AppImage,
|
||||||
|
.exe or .lnk on Linux and Windows, and opens the engine UI on Android since
|
||||||
|
the package takes no file argument. Batocera runs OpenBOR<build> <rom> after
|
||||||
|
reading a four digit build tag out of the file name in openborGenerator.py,
|
||||||
|
which is why it packages several engine versions side by side. RetroDECK
|
||||||
|
launches the 4.0 Linux AppImage, RetroBat runs OpenBOR.exe from a per build
|
||||||
|
folder.
|
||||||
|
|
||||||
|
packfile holds "bor.pak" until argv[1] names a path that exists, and with no
|
||||||
|
such argument the built in menu lists Paks/ and the player picks one
|
||||||
|
(engine/sdl/sdlport.c:25,124-135, engine/sdl/menu.c:172-203,802).
|
||||||
|
packfile_supported accepts any name containing .pak and skips menu.pak
|
||||||
|
(engine/source/gamelib/packfile.c:1577-1584).
|
||||||
|
|
||||||
|
Everything read for a running game comes out of that module. buffer_pakfile
|
||||||
|
tries the real filesystem first through fopen, then the same path inside the
|
||||||
|
archive (engine/openbor.c:921-965,969-1018), so data/models.txt,
|
||||||
|
data/levels.txt, data/video.txt, data/menu.txt, the scene scripts and the
|
||||||
|
sprites and sounds under data/ resolve either from an unpacked data/ directory
|
||||||
|
beside the binary (engine/source/gamelib/packfile.c:781-810) or from the pak.
|
||||||
|
Four names take precedence over their in-pak copy when they exist on disk:
|
||||||
|
translation/translation.txt and translation/menu.txt over data/translation.txt
|
||||||
|
(engine/source/gamelib/translation.c:102-106, engine/openbor.c:5975,53240),
|
||||||
|
saves/lifebar.txt over data/lifebar.txt (engine/openbor.c:4965-4972), and on
|
||||||
|
Android Saves/<module>/touch.txt then Saves/touch.txt over data/touch.txt
|
||||||
|
(engine/android/app/jni/openbor/video.c:210-218). Each holds text or a control
|
||||||
|
layout written for one module. The engine/translation.txt copied into the
|
||||||
|
release folder by CMakeLists.txt:239 is a blank msgid template whose own first
|
||||||
|
line sends it to the module data folder, and the published Windows archive for
|
||||||
|
v7533 contains only OpenBOR.exe.
|
||||||
|
|
||||||
|
Startup reads nothing. Logo, menu and log viewer artwork are PNG byte arrays
|
||||||
|
compiled in from engine/resources (engine/sdl/menu.c:20-27), menu text draws
|
||||||
|
from the embedded hankaku face (engine/sdl/menu.c:16,228), the GLSL fragment
|
||||||
|
shaders are string literals (engine/sdl/opengl.c:45-116), and the Android
|
||||||
|
touch skin is a header (engine/android/app/jni/openbor/video.c:49). No gamepad
|
||||||
|
mapping file is read, nothing is dlopened at runtime, the Android package
|
||||||
|
ships an empty assets directory, and the SecurePAK paths compile out of every
|
||||||
|
build because no build file defines SPK_SUPPORTED
|
||||||
|
(engine/source/gamelib/packfile.c:36, engine/source/gamelib/packfile.h:9,135).
|
||||||
|
|
||||||
|
Files the engine writes rather than expects: Paks, Saves, Logs and ScreenShots
|
||||||
|
are created at startup when missing (engine/sdl/sdlport.c:30-33,119-122),
|
||||||
|
settings and progress land in Saves as <module>.cfg, .sav, .hi, .scr and .inp
|
||||||
|
alongside default.cfg (engine/source/utils.c:284-312,
|
||||||
|
engine/openbor.c:2675-3040), and the viewer reads back Logs/OpenBorLog.txt and
|
||||||
|
Logs/ScriptLog.txt (engine/source/utils.c:47-62, engine/sdl/menu.c:652-700).
|
||||||
|
paks/logoff.txt is a marker whose existence alone skips the startup logo, so
|
||||||
|
the player creates it empty (engine/sdl/menu.c:707-716). Module script can
|
||||||
|
open any path it names through openfilestream
|
||||||
|
(engine/openborscript.c:10505-10600).
|
||||||
|
|
||||||
|
files: []
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
emulator: pce-emu
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/Rakashazi/emu-ex-plus-alpha"
|
||||||
|
upstream: "https://mednafen.github.io/"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "1c12fac5ce49badaadff2e2f210dcc30b89f4943"
|
||||||
|
core_version: "1.5.85"
|
||||||
|
display_name: "PCE.emu"
|
||||||
|
cores: ["pce-emu", "PCE.emu", "pceemu", "PCE-EMU", "com.PceEmu"]
|
||||||
|
systems: [nec-pc-engine, nec-pc-engine-cd, nec-supergrafx]
|
||||||
|
verification: existence
|
||||||
|
notes: >
|
||||||
|
Android and desktop application by Robert Broglia built on EmuFramework,
|
||||||
|
vendoring Mednafen's pce_fast and pce modules. Both are compiled and
|
||||||
|
selectable at runtime; pce_fast is what an unset core option resolves to
|
||||||
|
(system.ccm:125).
|
||||||
|
|
||||||
|
HuCard content (.pce, .sgx) loads with no external file. CD content
|
||||||
|
(.cue, .toc, .ccd, .chd) requires a System Card image: loadContent throws
|
||||||
|
"No System Card Set" when the path is unset or the file is gone
|
||||||
|
(Main.cc:88-91).
|
||||||
|
|
||||||
|
The System Card is a single path the user picks through a file browser
|
||||||
|
filtered to .pce and .sgx (EmuMenuViews.cc:176-191), stored as
|
||||||
|
CFGKEY_SYSCARD_PATH. No filename is fixed and no directory is scanned.
|
||||||
|
MDFN_GetSettingS returns an empty string for pce.cdbios, pce_fast.cdbios
|
||||||
|
and pce.gecdbios, and MDFN_MakeFName answers every MDFNMKF_FIRMWARE
|
||||||
|
request with that one path (options.cc:275-301), so the Games Express
|
||||||
|
branch reads whichever image the setting points at. Mednafen's settings
|
||||||
|
table still carries the syscard3.pce and gecard.pce defaults but
|
||||||
|
settings.cpp is not compiled, so they are never read.
|
||||||
|
|
||||||
|
A path with an archive extension is opened as an archive and the first
|
||||||
|
member ending in .pce, .bin or .bios is used (MDFNFILE.cc:41-76).
|
||||||
|
|
||||||
|
Neither module hashes the image. pce_fast skips a 512-byte copier header
|
||||||
|
then reads a fixed 262144 bytes (huc.cpp:299-302); pce reads
|
||||||
|
min(rounded length, length) and accepts any size (huc.cpp:225-316).
|
||||||
|
HuC_Load is always called with SYSCARD_3, or SYSCARD_ARCADE when Arcade
|
||||||
|
Card emulation is on (pce.cpp:653).
|
||||||
|
|
||||||
|
SuperGrafx is enabled by the .sgx extension, by a CRC match against the
|
||||||
|
built-in sgx_table (pce.cpp:345, 382-395), or by DetectSGXCD on disc.
|
||||||
|
HES playback is compiled out (pce.cpp:76) and cheats are disabled
|
||||||
|
(options.cc:245-246).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: "syscard3.pce"
|
||||||
|
description: "Super CD-ROM2 System Card 3.0"
|
||||||
|
required: true
|
||||||
|
validation: [existence, size]
|
||||||
|
min_size: 262144
|
||||||
|
category: bios
|
||||||
|
source_ref: "src/main/Main.cc:80-91 (throws without it), src/main/options.cc:275-301 (path resolution), src/main/EmuMenuViews.cc:176-191 (selection), src/pce_fast/pce.cpp:477-483 + src/pce_fast/huc.cpp:284-304 (default module load), src/pce/pce.cpp:645-653 (accurate module load), src/pce_fast/pce.cpp:663 + src/pce/pce.cpp:1094 (name)"
|
||||||
|
note: >
|
||||||
|
min_size comes from the fixed 262144-byte read in pce_fast
|
||||||
|
(huc.cpp:302) with Stream::read throwing on a short file
|
||||||
|
(Stream.h:88); a 262656-byte dump passes through the copier-header
|
||||||
|
skip at huc.cpp:299. The pce module imposes no minimum.
|
||||||
|
|
||||||
|
- name: "gecard.pce"
|
||||||
|
description: "Games Express CD Card"
|
||||||
|
required: false
|
||||||
|
validation: [existence]
|
||||||
|
category: bios
|
||||||
|
source_ref: "src/pce/pce.cpp:512-551 (DetectGECD), src/pce/pce.cpp:644-646 (gecdbios branch), src/pce/huc.cpp:225-316 (size-agnostic read), src/pce/pce.cpp:1095 (name)"
|
||||||
|
note: >
|
||||||
|
Reached only when the accurate module runs and DetectGECD matches the
|
||||||
|
disc; pce_fast has no Games Express branch. Served through the same
|
||||||
|
System Card setting, so the user points it at this image to boot those
|
||||||
|
discs.
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
emulator: "Pizza Boy GBA"
|
||||||
|
type: standalone
|
||||||
|
core_classification: embedded_hle
|
||||||
|
source: "https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboygbapro"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Pizza Emulators"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "2.8.13"
|
||||||
|
display_name: "Nintendo - Game Boy Advance (Pizza Boy GBA)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "pizza-boy-gba"
|
||||||
|
- "Pizza Boy GBA"
|
||||||
|
- "PIZZA-BOY-GBA"
|
||||||
|
systems:
|
||||||
|
- nintendo-gba
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Two Android packages, closed source, sold and given away on Google Play under the
|
||||||
|
Pizza Boy A name, reached by ES-DE through its PIZZA-BOY-GBA find rule and started
|
||||||
|
with the game passed as the rom_uri extra: it.dbtecno.pizzaboygbapro, the paid build
|
||||||
|
the rule names first, and it.dbtecno.pizzaboygba, the free one. Two Play distribution
|
||||||
|
builds are read here, both carrying the source stamp: Pro 2.8.13 (versionCode 343,
|
||||||
|
Play App Signing certificate sha256
|
||||||
|
6b5547246e41921f25eba8abb1bc018729c4f0b8db029debbd3380a2b1ec2fe1), which supplies the
|
||||||
|
Java and the resources, and Basic 2.3.3 (versionCode 236, developer certificate sha256
|
||||||
|
b3ee584096acf4667bb9346daa9cce19237ef7ce95c99e9260ac89be0f7d6130, CN=Davide Berra,
|
||||||
|
O=DBTecno), whose arm64-v8a libpizzaboy-jni.so ships DWARF and an unstripped symbol
|
||||||
|
table and supplies every native reference below as its own file and line. Java line
|
||||||
|
numbers are those of Pro 2.8.13. Two rebuilt copies of Pro 1.35.11 were rejected on
|
||||||
|
their certificate, one signed C=debugging with no source stamp and one signed
|
||||||
|
O=APKMODY. 69 of the 77 native methods the Pro declares are exported by the Basic
|
||||||
|
core, the three BIOS entry points among them: one core, compiled per package.
|
||||||
|
|
||||||
|
One system is emulated, Game Boy Advance: the core is built from a tree named
|
||||||
|
pizzaboyadvance whose compilation units carry gba.c and no Game Boy core, and the
|
||||||
|
three Game Boy Color and Super Game Boy methods the Pro still declares are among the
|
||||||
|
eight the library does not export.
|
||||||
|
|
||||||
|
The BIOS is the one file the user supplies, and it is read only while Load BIOS file
|
||||||
|
is on, off by default; the picker and the Run BIOS animation switch, on by default,
|
||||||
|
both depend on that box (res/xml/pref_general.xml). In the free package the same
|
||||||
|
three preferences are declared android:enabled="false".
|
||||||
|
|
||||||
|
A per rom Low precision BIOS set to On clears the stored path and makes the core keep
|
||||||
|
its own replacement, and one cartridge, checksum 0xc7d89508, forces the same at load
|
||||||
|
time. When a real image is installed the boot animation starts execution at 0 rather
|
||||||
|
than at the cartridge entry, and a multiplayer session exchanges the CRC32 of the file
|
||||||
|
so that both peers run the same one.
|
||||||
|
|
||||||
|
Everything else the app opens it makes itself: boxart.db and cheat.db are created by
|
||||||
|
their own CREATE TABLE, the default skins, the shaders and the cheat descriptors are
|
||||||
|
raw resources unpacked at first run, and <rom>.keys is an input recording. The
|
||||||
|
obfuscated assets are PairIP tamper protection.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: gba_bios.bin
|
||||||
|
system: nintendo-gba
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
has_builtin: true
|
||||||
|
agnostic: true
|
||||||
|
size: 16384
|
||||||
|
config_key: "bios_file"
|
||||||
|
description: "Game Boy Advance BIOS"
|
||||||
|
note: >-
|
||||||
|
Chosen from any location under any name through the document picker, or, when the
|
||||||
|
picked document is named .zip, taken from its first entry; the legacy browser
|
||||||
|
offers .gba, .bin and .zip and writes the entry it extracts to bios.bin under the
|
||||||
|
application directory. The absolute path is stored and handed to the library,
|
||||||
|
which copies it into a 256 byte buffer. At load time the 16 KB BIOS area is first
|
||||||
|
filled with a 744 byte replacement compiled into the library, then, if the path is
|
||||||
|
set, the file is opened and up to 16384 bytes are read over it and a flag records
|
||||||
|
that a real image is installed. Nothing about the file is examined: any read
|
||||||
|
returning at least one byte is accepted, and no size, name or hash test exists on
|
||||||
|
either side of the bridge. A read of zero bytes leaves the replacement in place
|
||||||
|
and logs "Cannot read BIOS file".
|
||||||
|
source_ref: "Pizza Boy GBA Pro 2.8.13 SettingsActivity.java:116-140 (import), :143-183
|
||||||
|
(preference and picker), FileDialog.java:57,72,77,846-857 (legacy browser, zip entry
|
||||||
|
to bios.bin), Common.java:85-105 (copy to temp), :160-190 (single entry unzip),
|
||||||
|
MainActivity.java:833,835,865 (bridge), :10936-10941 (gate and handoff),
|
||||||
|
res/xml/pref_general.xml (defaults); Pizza Boy A Basic 2.3.3 libpizzaboy-jni.so
|
||||||
|
pizza.c:932-938 (path buffer), :945-946 (boot flag), :632-642 (low precision BIOS),
|
||||||
|
global.c:93-95 (defaults), mmu.c:1522-1543 (replacement, gate, read, flag),
|
||||||
|
:2106-2110 (forced HLE), cpu.c:40 (boot vector)"
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
emulator: "Pizza Boy GBC"
|
||||||
|
type: standalone
|
||||||
|
core_classification: embedded_hle
|
||||||
|
source: "https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboypro"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Pizza Emulators"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "6.0.6"
|
||||||
|
display_name: "Nintendo - Game Boy / Color (Pizza Boy GBC)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "pizza-boy-gbc"
|
||||||
|
- "Pizza Boy GBC"
|
||||||
|
- "PIZZA-BOY-GBC"
|
||||||
|
systems:
|
||||||
|
- nintendo-gb
|
||||||
|
- nintendo-gbc
|
||||||
|
- nintendo-sgb
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Two Android packages, closed source, sold and given away on Google Play under the
|
||||||
|
Pizza Boy C name, reached by ES-DE through its PIZZA-BOY-GBC find rule and started
|
||||||
|
with the game passed as the rom_uri extra: it.dbtecno.pizzaboypro, the paid build the
|
||||||
|
rule names first, and it.dbtecno.pizzaboy, the free one. Two Play distribution builds
|
||||||
|
are read here, both carrying the developer certificate sha256
|
||||||
|
b3ee584096acf4667bb9346daa9cce19237ef7ce95c99e9260ac89be0f7d6130 (CN=Davide Berra,
|
||||||
|
O=DBTecno) and a source stamp: Pro 6.0.6 (versionCode 231), which supplies the Java
|
||||||
|
and the resources, and Basic 4.1.6 (versionCode 202), whose arm64-v8a
|
||||||
|
libpizzaboy-jni.so ships DWARF and an unstripped symbol table and supplies every
|
||||||
|
native reference below as its own file and line. Java line numbers are those of Pro
|
||||||
|
6.0.6. The Pro on the store is 7.4.5 (versionCode 324) and no genuine copy of it is
|
||||||
|
reachable: apkcombo bounces the download page of a paid app back to the app page,
|
||||||
|
apkvision carries no copy, and archive.org holds 6.0.6 alone. The Pro ships its core
|
||||||
|
as a stripped armeabi-v7a build; it carries the same log strings and the same
|
||||||
|
constants as the Basic core, the 64 KB clear, the 8192 byte read cap, the 256 byte
|
||||||
|
header copy and the 256 and 2304 byte gate, and 65 of the 70 entry points it exports
|
||||||
|
are exported by the Basic core as well. The Pro also ships libpizza-jni.so, an
|
||||||
|
older core exporting the free package JNI names and carrying no BIOS entry point,
|
||||||
|
which no loadLibrary call reaches.
|
||||||
|
|
||||||
|
Three systems are emulated from one tree named pizzaboy, whose compilation units
|
||||||
|
carry gameboy.c, mmu.c, sgb.c and camera.c: Game Boy, Game Boy Color and Super Game
|
||||||
|
Boy. The SGB command set, borders and palettes are handled by sgb.c behind a Super
|
||||||
|
Game Boy switch that is on by default, with a preference that gives Game Boy Color
|
||||||
|
precedence over Super Game Boy on a cartridge that offers both. camera.c drives the
|
||||||
|
Game Boy Camera cartridge from the device camera, and the Game Boy Printer is served
|
||||||
|
over the link port.
|
||||||
|
|
||||||
|
The boot ROM is the one file the user supplies, in two slots, Gameboy Classic ROMs
|
||||||
|
BIOS and Gameboy Color ROMs BIOS, and it is read only while Load BIOS file is on,
|
||||||
|
off by default (res/xml/pref_general.xml:89-99). In the free package the same three
|
||||||
|
preferences are declared android:enabled="false" behind a paid badge. A ROM whose
|
||||||
|
name ends in .gb or .sgb takes the first slot, every other name takes the second.
|
||||||
|
|
||||||
|
The library never examines the name, the extension or the content: the byte count of
|
||||||
|
the read decides the machine. A file of 256 bytes runs the cartridge as a Game Boy,
|
||||||
|
one of 2304 bytes as a Game Boy Color, and any other length is refused with "Unknown
|
||||||
|
BIOS file", after which the run continues with the boot skipped. The image is read
|
||||||
|
into a second MMU whose 0x100 to 0x1FF window is overwritten with the cartridge
|
||||||
|
header from the active one, the program counter starts at 0 instead of at the
|
||||||
|
cartridge entry, and the animation runs until it reaches 0x100, at which point the
|
||||||
|
active MMU returns to the cartridge and the accumulator is restored. A multiplayer
|
||||||
|
session exchanges the CRC32 of the Game Boy slot so that both peers run the same
|
||||||
|
file.
|
||||||
|
|
||||||
|
Everything else the app opens it makes itself: the default skins and the cheat
|
||||||
|
descriptors are raw resources unpacked at first run, the box art, cheat, sticker,
|
||||||
|
layout and per-ROM databases are created by their own CREATE TABLE, and the save
|
||||||
|
states, the RTC files, the screenshots and the GIF captures are outputs. No boot ROM
|
||||||
|
is compiled into the library: neither Game Boy image nor the Nintendo logo appears
|
||||||
|
anywhere in the loaded sections, and the post-boot register state comes from the
|
||||||
|
reset path instead.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: dmg_boot.bin
|
||||||
|
system: nintendo-gb
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
agnostic: true
|
||||||
|
size: 256
|
||||||
|
validation: [size]
|
||||||
|
config_key: "bios_file"
|
||||||
|
description: "Game Boy (DMG) boot ROM"
|
||||||
|
note: >-
|
||||||
|
Chosen from any location under any name through the document picker and copied
|
||||||
|
into the application directory under the name the picker reports; the legacy
|
||||||
|
browser offers .gbc, .gb, .bin and .zip and writes the entry it extracts from a
|
||||||
|
zip to bios.bin. The absolute path is stored and handed to the library, which
|
||||||
|
copies it into a 256 byte buffer. It is used when the ROM name ends in .gb or
|
||||||
|
.sgb, and only on the first run of that ROM and with no multiplayer peer
|
||||||
|
connected. The file is read into a second MMU image, up to 8192 bytes, and a
|
||||||
|
count of exactly 256 starts the run as a Game Boy, keeping the default palette.
|
||||||
|
Nothing else is examined: no name, size range, header or hash test exists on
|
||||||
|
either side of the bridge, and a count that is neither 256 nor 2304 is refused.
|
||||||
|
A multiplayer session exchanges the CRC32 of this file so that both peers run
|
||||||
|
the same one.
|
||||||
|
source_ref: "Pizza Boy GBC Pro 6.0.6 MainActivity.java:702 (native method),
|
||||||
|
:8067-8081 (gate and slot selection), :1734-1757 (CRC32 of the file),
|
||||||
|
:1907, :2136 (multiplayer handshake), SettingsActivity.java:40-41 (request
|
||||||
|
codes), :96-113 (picker result and copy), :116-192 (both preferences),
|
||||||
|
Common.java:42 (copy to the application directory), FileDialog.java:949-975
|
||||||
|
(legacy browser, zip entry to bios.bin), res/xml/pref_general.xml:89-99
|
||||||
|
(defaults); Pizza Boy C Basic 4.1.6 libpizzaboy-jni.so pizza.c:1023-1024 (path
|
||||||
|
into global_bios_file), global.c:28 (char[256]), mmu.c:431-463 (open, 64 KB
|
||||||
|
clear, 8192 byte read, cartridge header copy, 256 and 2304 gate, refusal),
|
||||||
|
gameboy.c:1161-1168 (conditions and call), :1171, :1238 (failure),
|
||||||
|
:1179-1198 (model, MMU switch, program counter at 0, accumulator),
|
||||||
|
:1201-1235 (run to 0x100, return to the cartridge)"
|
||||||
|
|
||||||
|
- name: cgb_boot.bin
|
||||||
|
system: nintendo-gbc
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
agnostic: true
|
||||||
|
size: 2304
|
||||||
|
validation: [size]
|
||||||
|
config_key: "bios_file_cgb"
|
||||||
|
description: "Game Boy Color (CGB) boot ROM"
|
||||||
|
note: >-
|
||||||
|
Same picker, same copy and same handoff as the Game Boy slot, used for every ROM
|
||||||
|
whose name does not end in .gb or .sgb. A count of exactly 2304 starts the run as
|
||||||
|
a Game Boy Color, which sets the accumulator to 0x11 and keeps the hardware
|
||||||
|
palettes instead of reloading the default one. The 0x100 to 0x1FF window of the
|
||||||
|
image is overwritten with the cartridge header before execution, which is the
|
||||||
|
gap the 2304 byte layout leaves for it.
|
||||||
|
source_ref: "Pizza Boy GBC Pro 6.0.6 MainActivity.java:8073-8078 (slot selection),
|
||||||
|
SettingsActivity.java:98 (preference key), :158-192 (preference and picker),
|
||||||
|
res/xml/pref_general.xml:97-99; Pizza Boy C Basic 4.1.6 libpizzaboy-jni.so
|
||||||
|
mmu.c:435-452 (read, header copy, 2304 gate), gameboy.c:1179 (model from the
|
||||||
|
return value), :1189-1198 (program counter, accumulator, palette)"
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
emulator: "Pizza Boy SC"
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboyscpro"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Pizza Emulators"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "1.2.4"
|
||||||
|
display_name: "Sega - MS/GG/MD/CD (Pizza Boy SC)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "pizza-boy-sc"
|
||||||
|
- "Pizza Boy SC"
|
||||||
|
- "PIZZA-BOY-SC"
|
||||||
|
- "it.dbtecno.pizzaboyscpro"
|
||||||
|
- "it.dbtecno.pizzaboyscbasic"
|
||||||
|
systems:
|
||||||
|
- sega-mastersystem
|
||||||
|
- sega-gamegear
|
||||||
|
- sega-megadrive
|
||||||
|
- sega-megacd
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Two Android packages, closed source, sold and given away on Google Play under the
|
||||||
|
Pizza Boy SC name, reached by ES-DE through its PIZZA-BOY-SC find rule and started
|
||||||
|
with the game passed as the rom_uri extra: it.dbtecno.pizzaboyscpro, the paid build
|
||||||
|
the rule names first, and it.dbtecno.pizzaboyscbasic, the free one. The build read
|
||||||
|
here is Basic 1.2.4 (versionCode 33), a Play distribution drop carrying the source
|
||||||
|
stamp and signed by the Play App Signing certificate sha256
|
||||||
|
5ae32245362ccafab6977e759f658dda66bac81cebdd804581cb55db2f219149. The Pro on the
|
||||||
|
store is 1.4.25 and no genuine copy of it is reachable: apkcombo bounces the
|
||||||
|
download page of a paid app back to the app page, apkmirror carries no SC build,
|
||||||
|
archive.org holds none, and the one apkvision copy, labelled Pro 1.3.7, is signed
|
||||||
|
CN=APKVISION.ORG with no source stamp and was rejected. The Basic library serves
|
||||||
|
both packages: besides its own entry points it exports
|
||||||
|
Java_it_dbtecno_pizzaboyscpro_MainActivity_jniEnableCallback.
|
||||||
|
|
||||||
|
The core is libsc.so, a Rust tree built as one workspace whose compilation units
|
||||||
|
are named in its own panic and log records: emulated/systems/genesis,
|
||||||
|
emulated/systems/sms, emulated/systems/mega_cd, emulated/components/cdrom,
|
||||||
|
emulated/common and frontend/android. The armeabi-v7a build shipped in the split
|
||||||
|
is stripped and carries no DWARF, so the file and line of every reference below
|
||||||
|
comes from the Location records the Rust log and panic paths embed. Four machines
|
||||||
|
run: engine start compares the system name against SMS, GameGear and SegaCD and
|
||||||
|
falls through to Genesis (lib.rs:481, 517, 538, 550), which covers Master System
|
||||||
|
and Mark III, Game Gear, Mega Drive and Genesis, and Mega CD and Sega CD. Discs
|
||||||
|
are read from cue and chd images through components/cdrom.
|
||||||
|
|
||||||
|
Four BIOS slots exist, one per machine, set in one call whose log reads
|
||||||
|
"jni setBIOSFiles sms: {} gg: {} cd: {} md: {}" (lib.rs:424); a fifth setter stores
|
||||||
|
a single path in a slot of its own that engine start never reads (lib.rs:416), and
|
||||||
|
setBIOSBoot logs "TODO jni setBIOSboot" and does nothing. Each branch reads the
|
||||||
|
slots its machines use, the Master System one reading the Game Gear slot as well,
|
||||||
|
and an empty slot is an ordinary case for Master System, Game Gear and Mega Drive.
|
||||||
|
Only the Mega CD slot is mandatory: without it the run stops at "MegaCD Bios not
|
||||||
|
provided" (lib.rs:564) and engine start returns its failure code.
|
||||||
|
|
||||||
|
The Mega CD image is the only file the core examines. It is read and its length
|
||||||
|
compared with 131072, then handed to the machine, which repeats the same
|
||||||
|
comparison and panics on a mismatch (megacd_main_machine.rs:156-157). Nothing else
|
||||||
|
about it is tested: no name, no header, no hash, and no region, the Game Region
|
||||||
|
setting being passed separately as jap, usa or eu and never selecting a file.
|
||||||
|
|
||||||
|
The user supplies each file through the document picker, which filters nothing:
|
||||||
|
the chosen document is copied into the application temp directory under the name
|
||||||
|
the picker reports, or, when that name ends in zip, the first entry is extracted
|
||||||
|
there instead, and the absolute path of the copy is stored. In the free package the
|
||||||
|
BIOS preferences are declared android:enabled="false" behind a paid badge, and its
|
||||||
|
Java never hands a path to the core.
|
||||||
|
|
||||||
|
Everything else the app opens it makes itself: the default skins, the cheat
|
||||||
|
descriptors and the two shaders are raw resources unpacked at first run, and the
|
||||||
|
box art, cheat, layout, sticker and per-ROM databases are created by their own
|
||||||
|
CREATE TABLE.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: bios_CD_U.bin
|
||||||
|
system: sega-megacd
|
||||||
|
required: true
|
||||||
|
agnostic: true
|
||||||
|
variant_group: "megacd-boot-rom"
|
||||||
|
size: 131072
|
||||||
|
validation: [size]
|
||||||
|
description: "Sega CD boot ROM"
|
||||||
|
note: >-
|
||||||
|
Chosen from any location under any name through the document picker, or, when
|
||||||
|
the picked document is named .zip, taken from its first entry. The stored path
|
||||||
|
is read at engine start and the byte count compared with 131072; the machine
|
||||||
|
compares it a second time and panics when it differs. An absent path ends the
|
||||||
|
run with "MegaCD Bios not provided", an empty one with "MegaCD BIOS path is
|
||||||
|
missing", a failed read with "Error loading BIOS file", and a wrong length with
|
||||||
|
"Invalid BIOS len". The core holds one Mega CD slot and applies no other test,
|
||||||
|
so the boot ROM of any region satisfies it; the three are listed because the
|
||||||
|
region of the discs decides which one has to be installed.
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:424
|
||||||
|
(four slot handoff), :517 (SegaCD branch), :564 (absent), :567 (validation
|
||||||
|
entry), :573 (empty path), :580 (read failure), :592 (length), :596 (accepted);
|
||||||
|
emulated/systems/mega_cd/src/megacd_main_machine.rs:156-157 (second length test
|
||||||
|
and panic); SettingsActivity.java:177-219 (picker, zip entry, stored path),
|
||||||
|
res/xml/pref_general.xml:105-123 (preferences and defaults)"
|
||||||
|
|
||||||
|
- name: bios_CD_E.bin
|
||||||
|
system: sega-megacd
|
||||||
|
required: true
|
||||||
|
agnostic: true
|
||||||
|
variant_group: "megacd-boot-rom"
|
||||||
|
size: 131072
|
||||||
|
validation: [size]
|
||||||
|
description: "Mega CD boot ROM"
|
||||||
|
note: >-
|
||||||
|
Same slot, same picker and same length test as the other Mega CD boot ROMs.
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:567-596,
|
||||||
|
emulated/systems/mega_cd/src/megacd_main_machine.rs:156-157"
|
||||||
|
|
||||||
|
- name: bios_CD_J.bin
|
||||||
|
system: sega-megacd
|
||||||
|
required: true
|
||||||
|
agnostic: true
|
||||||
|
variant_group: "megacd-boot-rom"
|
||||||
|
size: 131072
|
||||||
|
validation: [size]
|
||||||
|
description: "Mega CD boot ROM (Japan)"
|
||||||
|
note: >-
|
||||||
|
Same slot, same picker and same length test as the other Mega CD boot ROMs.
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:567-596,
|
||||||
|
emulated/systems/mega_cd/src/megacd_main_machine.rs:156-157"
|
||||||
|
|
||||||
|
- name: bios_U.sms
|
||||||
|
system: sega-mastersystem
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
variant_group: "mastersystem-boot-rom"
|
||||||
|
description: "Master System boot ROM"
|
||||||
|
note: >-
|
||||||
|
Picked and stored like the Mega CD image and handed to the machine as a path.
|
||||||
|
Nothing about the file is examined on either side of the bridge, and an empty
|
||||||
|
slot is not an error: the cartridge runs with the boot sequence skipped.
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:424
|
||||||
|
(slot), :538 (branch reading the Master System and Game Gear slots),
|
||||||
|
emulated/systems/sms/src/system.rs:202 (path logged into the machine)"
|
||||||
|
|
||||||
|
- name: bios_E.sms
|
||||||
|
system: sega-mastersystem
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
variant_group: "mastersystem-boot-rom"
|
||||||
|
description: "Master System boot ROM (Europe)"
|
||||||
|
note: "Same slot and same absence of tests as the other Master System boot ROMs."
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:538,
|
||||||
|
emulated/systems/sms/src/system.rs:202"
|
||||||
|
|
||||||
|
- name: bios_J.sms
|
||||||
|
system: sega-mastersystem
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
variant_group: "mastersystem-boot-rom"
|
||||||
|
description: "Master System boot ROM (Japan)"
|
||||||
|
note: "Same slot and same absence of tests as the other Master System boot ROMs."
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:538,
|
||||||
|
emulated/systems/sms/src/system.rs:202"
|
||||||
|
|
||||||
|
- name: bios.gg
|
||||||
|
system: sega-gamegear
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
description: "Game Gear boot ROM"
|
||||||
|
note: >-
|
||||||
|
Its own slot, separate from the Master System one, both read on the branch that
|
||||||
|
serves the two machines. Picked and stored the same way, handed to the machine
|
||||||
|
as a path, and never examined; an empty slot is not an error.
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:424
|
||||||
|
(slot), :481 (system name match, GameGear), :538 (branch reading the Master
|
||||||
|
System and Game Gear slots)"
|
||||||
|
|
||||||
|
- name: bios_MD.bin
|
||||||
|
system: sega-megadrive
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
description: "Mega Drive TMSS boot ROM"
|
||||||
|
note: >-
|
||||||
|
Read on the Genesis branch, the one engine start falls through to when the
|
||||||
|
system name is neither SMS, GameGear nor SegaCD. Picked and stored the same
|
||||||
|
way and never examined; the machine reports it as "BIOS detected" and runs
|
||||||
|
without it when the slot is empty.
|
||||||
|
source_ref: "Pizza Boy SC Basic 1.2.4 libsc.so frontend/android/src/lib.rs:424
|
||||||
|
(slot), :550 (Genesis branch and slot read),
|
||||||
|
emulated/systems/genesis/src/system.rs:270 (path logged into the machine),
|
||||||
|
emulated/systems/genesis/src/genesis_machine.rs:135 (detection)"
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
emulator: Plastic
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://github.com/Amjad50/plastic"
|
||||||
|
upstream: "https://github.com/Amjad50/plastic"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "74152adb3acd890d3abee2ff5906408f26a199e2"
|
||||||
|
core_version: "0.3.5"
|
||||||
|
display_name: "Nintendo - NES / Famicom (Plastic)"
|
||||||
|
cores:
|
||||||
|
- plastic
|
||||||
|
systems:
|
||||||
|
- nintendo-nes
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
NES emulator written in Rust by Amjad Alsharafi. The emulation lives in the
|
||||||
|
plastic_core crate and two binaries drive it: plastic, an egui window, and
|
||||||
|
plastic_tui, a terminal frontend (docs/man/plastic.1). Both take the ROM
|
||||||
|
path as their first argument (plastic_ui/src/main.rs:418-424,
|
||||||
|
plastic_tui/src/main.rs:5-38).
|
||||||
|
|
||||||
|
A cartridge boots with nothing supplied. The 2A03, the PPU and every mapper
|
||||||
|
are emulated in software and the console has no boot ROM, so no BIOS or
|
||||||
|
firmware is read. Cartridge::from_file accepts a path only when its
|
||||||
|
extension is nes and its first four bytes are the iNES magic
|
||||||
|
(plastic_core/src/cartridge/mod.rs:184-263, :157-165). get_mapper implements
|
||||||
|
0, 1, 2, 3, 4, 7, 9, 10, 11, 12 and 66, and any other number returns
|
||||||
|
MapperNotImplemented (:280-296). No Famicom Disk System path exists and
|
||||||
|
therefore no disksys.rom.
|
||||||
|
|
||||||
|
The NES to RGB table is a constant compiled into the binary
|
||||||
|
(plastic_core/src/display/color.rs:22-87, selected at :158) and the 32 bytes
|
||||||
|
at 0x3F00 are the PPU palette RAM (plastic_core/src/ppu2c02/palette.rs:6-19),
|
||||||
|
so no palette file is opened. The window icon is embedded at build time
|
||||||
|
(plastic_ui/src/main.rs:430).
|
||||||
|
|
||||||
|
The emulator reads back only what it wrote itself. A cartridge whose header
|
||||||
|
carries the battery bit gets <rom>.nes.sav beside the ROM, written on drop
|
||||||
|
and reloaded on the next run (plastic_core/src/cartridge/mod.rs:319-348,
|
||||||
|
:457-463). Save state slots 0 to 9 are <rom-stem>_<slot>.pst under the data
|
||||||
|
directory, ~/.local/share/plastic/saved_states on Linux
|
||||||
|
(plastic_ui/src/main.rs:16-32,95-118; plastic_tui/src/ui.rs:38-51,144-176;
|
||||||
|
plastic_core/src/nes.rs:393-406).
|
||||||
|
|
||||||
|
Gamepad support comes from gilrs, which compiles the SDL controller database
|
||||||
|
into the binary and takes its only override from the SDL_GAMECONTROLLERCONFIG
|
||||||
|
environment variable rather than a file (gilrs src/mapping/mod.rs:477-485).
|
||||||
|
|
||||||
|
files: []
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
emulator: project64
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://github.com/project64/project64"
|
||||||
|
upstream: "https://github.com/project64/project64"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "6188e9a88dd2e7487df346fecc445716654e18ec"
|
||||||
|
core_version: "Dev-4.0.0"
|
||||||
|
display_name: "Nintendo - Nintendo 64 (Project64)"
|
||||||
|
cores:
|
||||||
|
- project64
|
||||||
|
systems:
|
||||||
|
- nintendo-64
|
||||||
|
- nintendo-64dd
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Nintendo 64 and 64DD emulator for Windows. Project64.exe plus the plugin DLLs
|
||||||
|
the same solution builds, driven by the plugin spec in Source/Project64-plugin-spec.
|
||||||
|
ES-DE passes the ROM as the only argument. AppVeyor builds Win32 and x64 only;
|
||||||
|
Source/Android holds no build file.
|
||||||
|
|
||||||
|
Cartridge boot reads no file. PostPif is hardcoded true, so Reset seeds the
|
||||||
|
general purpose registers from the CIC identified in the ROM image, points the
|
||||||
|
program counter at 0xA4000040 and the boot block is copied into SP DMEM. The
|
||||||
|
branch that would start at the PIF ROM address is unreachable and the PIF ROM
|
||||||
|
read in the memory handler is commented out, so neither a PIF ROM nor a CIC ROM
|
||||||
|
is opened (Source/Project64-core/N64System/N64System.cpp:911-916,
|
||||||
|
Source/Project64-core/N64System/Mips/Register.cpp:342,371-373,395-535,
|
||||||
|
Source/Project64-core/N64System/MemoryHandler/PifRamHandler.cpp:26).
|
||||||
|
|
||||||
|
The CIC is identified from the boot block. ByteSwapRom normalises the image so
|
||||||
|
each 32-bit read yields the ROM's big-endian word, then GetCicChipID sums those
|
||||||
|
words from 0x40 to 0x1000 and matches the total against a table of constants.
|
||||||
|
Three of them are 64DD IPL images: 0xD2E53EF008 for the Japanese retail chip
|
||||||
|
8303, 0xD2E53E5DDA for the American retail chip 8501, 0xD2E53EF39F for the
|
||||||
|
development chip 8401. IsLoadedRomDDIPL is that test
|
||||||
|
(Source/Project64-core/N64System/N64Rom.cpp:240-273,281-305,500-511).
|
||||||
|
|
||||||
|
Aleck64 images are recognised by the same table, through a second sum taken at
|
||||||
|
0xC00, and get their own boot register seed. No arcade hardware is emulated and
|
||||||
|
no Aleck64 file is opened
|
||||||
|
(Source/Project64-core/N64System/N64Rom.cpp:283,310-316,
|
||||||
|
Source/Project64-core/N64System/Mips/Register.cpp:477-479).
|
||||||
|
|
||||||
|
Transfer Pak reads a Game Boy cartridge image and its save from paths the user
|
||||||
|
sets per game. Both are the user's own cartridge dump, and no Game Boy boot ROM
|
||||||
|
is involved (Source/Project64-core/N64System/Mips/GBCart.cpp:695-698,744,788,
|
||||||
|
Source/Project64-core/Settings.cpp:242-243).
|
||||||
|
|
||||||
|
The support files under Config ship in the installer and in the nightly package.
|
||||||
|
CIniFile returns silently when the path does not exist, so each of them degrades
|
||||||
|
to the defaults registered in AddHandler rather than failing
|
||||||
|
(Source/Common/IniFile.cpp:493-522, Source/Project64-core/Settings.cpp:134-145).
|
||||||
|
|
||||||
|
GLideN64 ships as a bundled plugin, pinned as a submodule at
|
||||||
|
gonetz/GLideN64 c8ef81c7d9aede9f67f6ed3d3426c90541f9f13e, and brings its own
|
||||||
|
GLideN64.ini, GLideN64.custom.ini and translations. Project64's own code names
|
||||||
|
none of them; only Installer.iss and package_zip.cmd copy them
|
||||||
|
(Source/Installer/Installer.iss:38, Source/Script/package_zip.cmd:42-47).
|
||||||
|
|
||||||
|
Generated at runtime, never supplied: Project64.cfg, Project64.rdn,
|
||||||
|
Project64.cache3, Project64.zcache, Config/Cheats-User, Config/Enhancements-User,
|
||||||
|
Save, Screenshots, Logs and the texture caches.
|
||||||
|
|
||||||
|
files:
|
||||||
|
# -- 64DD IPL ROMs, user supplied --
|
||||||
|
- name: "64DD_IPL_v12_JPN.bin"
|
||||||
|
aliases: ["64DD_IPL.bin", "64DD_IPL_JP.n64", "64dd_ipl_J.bin"]
|
||||||
|
system: nintendo-64dd
|
||||||
|
region: [japan]
|
||||||
|
required: true
|
||||||
|
validation: [signature]
|
||||||
|
description: "64DD IPL ROM (Japanese retail)"
|
||||||
|
note: >
|
||||||
|
Loaded when the disk image reports Country_Japan. The path is the free text
|
||||||
|
Disk IPL ROM Path setting, typed or pasted into a plain edit box, so the
|
||||||
|
code fixes no filename and no directory. SelectAndLoadFileImageIPL tests
|
||||||
|
that the path exists, warns and returns false if not, and the disk never
|
||||||
|
starts. The file is accepted on two content checks and nothing else: the
|
||||||
|
first word must be one of the four image magics, 0x40072780 being the 64DD
|
||||||
|
one, and the boot block sum must be 0xD2E53EF008. Size is not checked and
|
||||||
|
no file hash is computed.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:316, Source/Project64-core/N64System/N64System.cpp:577,599,649-652,673-677,690-704, Source/Project64-core/N64System/N64Rom.cpp:303,479-498,500-511, Source/Project64/UserInterface/Settings/SettingsPage-DiskDrive.cpp:13,18,47,140"
|
||||||
|
|
||||||
|
- name: "64DD_IPL_USA.bin"
|
||||||
|
aliases: ["64DD_IPL_US.n64", "64dd_ipl_U.bin"]
|
||||||
|
system: nintendo-64dd
|
||||||
|
region: [north-america]
|
||||||
|
required: true
|
||||||
|
validation: [signature]
|
||||||
|
description: "64DD IPL ROM (American retail)"
|
||||||
|
note: >
|
||||||
|
Loaded when the disk image reports Country_NorthAmerica, from the Disk IPL
|
||||||
|
USA ROM Path setting. Same acceptance path as the Japanese image, matched on
|
||||||
|
boot block sum 0xD2E53E5DDA. The chip differs from the Japanese one, and
|
||||||
|
CalculateRomCrc carries a separate seed and a 0xA0000 length for it.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:317, Source/Project64-core/N64System/N64System.cpp:653-656,673-677, Source/Project64-core/N64System/N64Rom.cpp:305,369-372,500-511, Source/Project64/UserInterface/Settings/SettingsPage-DiskDrive.cpp:14,19,56,142"
|
||||||
|
|
||||||
|
- name: "64DD_IPL_DEV.bin"
|
||||||
|
aliases: ["64DD_IPL_DEV.n64", "64dd_ipl_DEV.bin"]
|
||||||
|
system: nintendo-64dd
|
||||||
|
required: true
|
||||||
|
validation: [signature]
|
||||||
|
description: "64DD IPL ROM (development)"
|
||||||
|
note: >
|
||||||
|
Loaded from the Development 64DD IPL ROM Path setting for disks whose country
|
||||||
|
byte is unknown, which is what development and prototype disks carry. Matched
|
||||||
|
on boot block sum 0xD2E53EF39F. When a cartridge and a disk are launched
|
||||||
|
together and this path is empty, the loader falls back to the Japanese image
|
||||||
|
and then to the American one, so the development image is only unavoidable
|
||||||
|
for a development disk on its own.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:318, Source/Project64-core/N64System/N64System.cpp:657-670,673-677, Source/Project64-core/N64System/N64Rom.cpp:304,377-380,500-511, Source/Project64/UserInterface/Settings/SettingsPage-DiskDrive.cpp:15,20,65,144"
|
||||||
|
|
||||||
|
# -- Per game databases shipped in the installer --
|
||||||
|
- name: "Project64.rdb"
|
||||||
|
path: "Config/Project64.rdb"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "ROM settings database"
|
||||||
|
note: >
|
||||||
|
Sections keyed by the ROM identifier CRC1-CRC2-C:country. Backs the whole
|
||||||
|
Rdb_ setting family, among them RDRAM size, counter factor, save chip, VI
|
||||||
|
refresh rate, disk seek timing and the overclock modifier, so it decides how
|
||||||
|
the machine is configured per game. It also carries the microcode identifier
|
||||||
|
table. Absent, every lookup falls through to the Defaults section and the
|
||||||
|
ROM browser lists no known titles.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:87-88,134-145,151-188, Source/Project64-core/Settings/SettingType/SettingsType-RomDatabase.cpp:63,117, Source/Project64-core/RomList/RomList.cpp:47,52,58-61, Source/Project64-core/N64System/N64Rom.cpp:722,914"
|
||||||
|
|
||||||
|
- name: "Video.rdb"
|
||||||
|
path: "Config/Video.rdb"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Per game video plugin settings"
|
||||||
|
note: >
|
||||||
|
Second ini opened by the ROM database setting type, keyed on the same ROM
|
||||||
|
identifier, holding the microcode CRCs the ucode detector matches and the per
|
||||||
|
game video overrides. Without it the plugin asks the user to add an unknown
|
||||||
|
microcode CRC.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:89-90, Source/Project64-core/Settings/SettingType/SettingsType-RomDatabase.cpp:64,118"
|
||||||
|
|
||||||
|
- name: "Audio.rdb"
|
||||||
|
path: "Config/Audio.rdb"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Per game audio plugin settings"
|
||||||
|
note: >
|
||||||
|
Third ini opened by the ROM database setting type, same key, carrying the per
|
||||||
|
game audio overrides such as FPSBuffer, Fixed Audio and Sync Audio.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:91-92, Source/Project64-core/Settings/SettingType/SettingsType-RomDatabase.cpp:65,119"
|
||||||
|
|
||||||
|
- name: "Project64.rdx"
|
||||||
|
path: "Config/Project64.rdx"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "ROM database extension"
|
||||||
|
note: >
|
||||||
|
Extended per game information the ROM browser shows, loaded into the romlist
|
||||||
|
as m_ExtIniFile alongside the ROM database itself. Absent, the browser
|
||||||
|
columns it feeds stay empty.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:103-104, Source/Project64-core/RomList/RomList.cpp:46,51"
|
||||||
|
|
||||||
|
- name: "Config/Cheats/*.cht"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Shipped cheat database"
|
||||||
|
note: >
|
||||||
|
Directory scanned for that pattern, one file per game, sections keyed on the
|
||||||
|
ROM identifier and holding the GameShark style codes. The user directory
|
||||||
|
Config/Cheats-User is scanned straight after and is where the UI writes.
|
||||||
|
671 files ship in the installer.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:93-96, Source/Project64-core/N64System/Enhancement/Enhancements.cpp:629,647, Source/Installer/Installer.iss:29"
|
||||||
|
|
||||||
|
- name: "Config/Enhancements/*.enh"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Shipped enhancement database"
|
||||||
|
note: >
|
||||||
|
Directory scanned for that pattern, same per game keying as the cheat files,
|
||||||
|
holding the patches offered under Enhancements such as widescreen hacks. The
|
||||||
|
user directory Config/Enhancements-User is scanned straight after. 115 files
|
||||||
|
ship in the installer.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:97-100, Source/Project64-core/N64System/Enhancement/Enhancements.cpp:665,684, Source/Installer/Installer.iss:30"
|
||||||
|
|
||||||
|
# -- Interface localisation --
|
||||||
|
- name: "Lang/*.pj.Lang"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Interface translations"
|
||||||
|
note: >
|
||||||
|
Directory scanned for that pattern, each file naming its language in a header
|
||||||
|
string. English is compiled in through the DEF_STR table, so an empty
|
||||||
|
directory leaves the interface in English.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:127-128, Source/Project64-core/Multilanguage/Language.cpp:9-571,656-673, Source/Installer/Installer.iss:33"
|
||||||
|
|
||||||
|
# -- Prebuilt plugins with no source in the tree --
|
||||||
|
- name: "Jabo_Direct3D8.dll"
|
||||||
|
path: "Plugin/GFX/Jabo_Direct3D8.dll"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Jabo's Direct3D8 video plugin"
|
||||||
|
note: >
|
||||||
|
Committed as a prebuilt binary under Plugin/Win32 and copied by both the
|
||||||
|
installer and the nightly packager. No source for it exists in the tree, so a
|
||||||
|
build from source cannot produce it. Project64-Video is the default graphics
|
||||||
|
plugin, so it is only selected when the user picks it.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:383, Source/Installer/Installer.iss:36, Source/Script/package_zip.cmd:60"
|
||||||
|
|
||||||
|
- name: "Jabo_Dsound.dll"
|
||||||
|
path: "Plugin/Audio/Jabo_Dsound.dll"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Jabo's DirectSound audio plugin"
|
||||||
|
note: >
|
||||||
|
Committed as a prebuilt binary under Plugin/Win32 and copied by both the
|
||||||
|
installer and the nightly packager, with no source in the tree.
|
||||||
|
Project64-Audio is the default audio plugin.
|
||||||
|
source_ref: "Source/Project64-core/Settings.cpp:385, Source/Installer/Installer.iss:34, Source/Script/package_zip.cmd:58"
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
emulator: "Real3DOPlayer"
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "http://www.arts-union.ru/node/23"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "AltmerSoft (Maxim Grishin)"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "1.0.32"
|
||||||
|
display_name: "The 3DO Company - 3DO (Real3DOPlayer)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "real3doplayer"
|
||||||
|
- "Real3DOPlayer"
|
||||||
|
- "REAL3DOPLAYER"
|
||||||
|
systems:
|
||||||
|
- 3do
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Android package ru.vastness.altmer.real3doplayer, closed source, published by the
|
||||||
|
author of the Phoenix Emulation Project and reached by ES-DE through its
|
||||||
|
REAL3DOPLAYER find rule. The build read here is app-release.apk of 2019-11-19,
|
||||||
|
taken from real3DOPlayer_free_1.0.32.zip on the author's own site, carrying the
|
||||||
|
certificate sha256 336dca7bf758d4d4d3e31783a1cb3f777cf0f0791ff6b1a8bbf698892f8860a9
|
||||||
|
(C=RU, L=Tula, O=AltmerSoft, CN=MAXIM GRISHIN): versionCode 33, minSdk 14,
|
||||||
|
targetSdk 23, seven ABIs. Java line numbers below are jadx output of that build and
|
||||||
|
native addresses are its arm64-v8a library; the armeabi-v7a library carries the same
|
||||||
|
strings and the same constants. The decompiled tree published as
|
||||||
|
BoUnCe587/Real3DOPlayer was rejected: it is signed with the AOSP test key
|
||||||
|
a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc.
|
||||||
|
|
||||||
|
One system is emulated, 3DO Interactive Multiplayer, in libphoenixcore.so behind a
|
||||||
|
JNI bridge (NativeCore.java:6-51). The library names itself "PhoenixEmuProject core
|
||||||
|
2.8.21" and builds the console out of MADAM, CLIO, SPORT, CD-ROM, BIOS, FONT-ROM,
|
||||||
|
FMV-ROM and NVRAM devices.
|
||||||
|
|
||||||
|
The user points the app at one directory holding both the discs and the ROMs, shown
|
||||||
|
as "Current ISOs and BIOS path". countGames lists it, keeping the extensions bin,
|
||||||
|
cdi, img, iso, nrg and rom, and offers every file to three adapters in turn: CD
|
||||||
|
image, then BIOS, then font ROM (0xdd390-0xdd9e0, dispatch at 0xdc43c). An external
|
||||||
|
launcher can instead pass explicit paths through the intent extras rom, cd and font,
|
||||||
|
which become the config keys ext-rom, ext-cd and ext-font
|
||||||
|
(MainActivity.java:469-471,412-414).
|
||||||
|
|
||||||
|
Nothing is recognised by name. A ROM candidate is measured, and a file of 3 MB or
|
||||||
|
more is dropped before it is read; the remainder is scanned on four byte boundaries
|
||||||
|
for the RomTag signature 01 5A 5A 5A 5A 5A 01 00, and the 0x84 byte header at that
|
||||||
|
point is read back. The null terminated string at header offset 0x28 is what sorts
|
||||||
|
the file: "rom" fills the BIOS list, "rom2" the font list, and "fmvrom" is compared
|
||||||
|
for but never requested (0xaa0e0-0xaa350). Running that scan over the published 3DO
|
||||||
|
dumps sorts every system BIOS into "rom" and every kanji dump into "rom2", the
|
||||||
|
512 KB arcade ROM and the 933636 byte FZ-1 font included.
|
||||||
|
|
||||||
|
The BIOS is the one file the app refuses to run without: an empty
|
||||||
|
NativeCore.nameOfBios() raises "BIOS not found." and returns instead of starting the
|
||||||
|
emulator, and at startup it raises "Select 3DO directory on SD card with BIOS and
|
||||||
|
CD-images." (MainActivity.java:539-543,583-584). Nothing gates on the font ROM.
|
||||||
|
|
||||||
|
The md5 of the loaded BIOS is compared against a48e6746bd7edec0f40cff078f0bb19f, the
|
||||||
|
Panasonic FZ-10 PAL ANVIL dump, and the outcome is passed as one construction
|
||||||
|
argument of the device set (0x8eea0-0x8ef58, again at 0x916c0-0x916f4). It selects
|
||||||
|
behaviour for that dump and is not an acceptance test: acceptance is the RomTag.
|
||||||
|
Four further md5 constants (5df7f21286290b2b4e9bd939f747f985,
|
||||||
|
dacffcf51e54e76b68fb62ec73faff42, 0da811a327361f9a3d7dca63ad503f30,
|
||||||
|
2536bf786f05af221038313a3e28f9aa) are all compared against the md5 taken for the
|
||||||
|
CD-ROM device, so they identify game discs rather than firmware.
|
||||||
|
|
||||||
|
The FMV-ROM device is built but can never be fed: the ROM adapter is only ever
|
||||||
|
constructed for tags "rom" and "rom2" (0xdc4e8, 0xe9784, 0xe98bc), the frontend
|
||||||
|
registers only Library/CD-ROM, Library/BIOS and Library/FONT-ROM (0xe965c, 0xe9794,
|
||||||
|
0xe98cc), and no ext-fmv key exists.
|
||||||
|
|
||||||
|
Files the app makes for itself, in its storage directory rather than the scan
|
||||||
|
directory: nvram.bin, the 32 KB console save area, erasable from the interface;
|
||||||
|
configs.xml and settings.ini; save states; and the controller maps. madam.bin and
|
||||||
|
clio.bin name 2 KB and 64 KB regions of the emulator's own state blob and are
|
||||||
|
reached only in mode 2 (0x8ce8c-0x8d064).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: panafz10e-anvil.bin
|
||||||
|
system: 3do
|
||||||
|
required: true
|
||||||
|
agnostic: true
|
||||||
|
max_size: 3145727
|
||||||
|
validation: [size]
|
||||||
|
config_key: "ext-rom"
|
||||||
|
description: "3DO system BIOS ROM"
|
||||||
|
note: >-
|
||||||
|
Any 3DO system ROM is accepted, under any name and from any directory the user
|
||||||
|
picks. The file is measured, then searched on four byte boundaries for the
|
||||||
|
RomTag signature, and it is taken as the BIOS when the header names itself
|
||||||
|
"rom". A file of 3 MB or more is rejected unread. The emulator will not start
|
||||||
|
until one is found, and the interface lists it above the discs.
|
||||||
|
source_ref: "Real3DOPlayer 1.0.32 MainActivity.java:100-101 (scan and BIOS name),
|
||||||
|
MainActivity.java:539-543,583-584 (refusal without it), MainActivity.java:412,469
|
||||||
|
(ext-rom), libphoenixcore.so arm64-v8a 0xaa0e0-0xaa118 (size gate),
|
||||||
|
0xaa140-0xaa1b0 (RomTag scan and header read), 0xaa218-0xaa27c (\"rom\" test),
|
||||||
|
0xdc43c-0xdc53c (dispatch and list), 0xdd228-0xdd2e0 (nameOfBios),
|
||||||
|
0xdd390-0xdd908 (directory scan and extensions), 0x8f6f0-0x8f71c (1 MB window)"
|
||||||
|
|
||||||
|
- name: panafz1j-kanji.bin
|
||||||
|
system: 3do
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
max_size: 3145727
|
||||||
|
validation: [size]
|
||||||
|
config_key: "ext-font"
|
||||||
|
description: "3DO kanji font ROM"
|
||||||
|
note: >-
|
||||||
|
Found by the same scan of the same directory, and taken as the font when the
|
||||||
|
RomTag header names itself "rom2". Held in its own list and mapped into a second
|
||||||
|
1 MB window of the machine. Japanese titles draw their kanji from it; the
|
||||||
|
emulator starts and runs without one, and the core carries GRAFERR_NO_FONT and
|
||||||
|
GRAFERR_BADFONTFILE for that case.
|
||||||
|
source_ref: "Real3DOPlayer 1.0.32 MainActivity.java:413,471 (ext-font),
|
||||||
|
libphoenixcore.so arm64-v8a 0xaa2e8-0xaa34c (\"rom2\" test),
|
||||||
|
0xdc4d0-0xdc52c (dispatch and list), 0xdd9dc-0xdd9e0 (third scan pass),
|
||||||
|
0xe98bc-0xe98cc (Library/FONT-ROM), 0x8f74c-0x8f780 (1 MB window)"
|
||||||
@@ -0,0 +1,219 @@
|
|||||||
|
emulator: "Saturn.emu"
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/Rakashazi/emu-ex-plus-alpha"
|
||||||
|
upstream: "https://mednafen.github.io/"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "1c12fac5ce49badaadff2e2f210dcc30b89f4943"
|
||||||
|
core_version: "1.5.85"
|
||||||
|
display_name: "Sega - Saturn (Saturn.emu)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "saturn-emu"
|
||||||
|
- "Saturn.emu"
|
||||||
|
- "SATURN-EMU"
|
||||||
|
- "saturnemu"
|
||||||
|
systems:
|
||||||
|
- sega-saturn
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Member of the EX Emulator series by Robert Broglia, published as
|
||||||
|
com.explusalpha.SaturnEmu and built for arm64 and x86_64 only
|
||||||
|
(Saturn.emu/metadata/conf.mk:2-7, Saturn.emu/config.mk:7-9). ES-DE reaches it
|
||||||
|
through the SATURN-EMU find rule, which only the Android rule set carries, and
|
||||||
|
offers it under both the saturn and saturnjp systems. Mednafen's Saturn module
|
||||||
|
is vendored under Saturn.emu/src/ss on the 1.32 line
|
||||||
|
(EmuFramework/include/shared/mednafen/mednafen-config.h:167) and driven by the
|
||||||
|
app's own video, audio, input and save layers
|
||||||
|
(Saturn.emu/src/CMakeLists.txt:6-40). Seventeen files differ from the Mednafen
|
||||||
|
1.32.1 release, none of it touching file loading: statics become externals the
|
||||||
|
app reads (Saturn.emu/src/ss/ss.cpp:146, Saturn.emu/src/ss/smpc.cpp:96,146,
|
||||||
|
Saturn.emu/src/ss/vdp2.cpp:46,63, Saturn.emu/src/ss/cdb.cpp:535), backup memory
|
||||||
|
moves to the app's file objects and the periodic save timers are dropped
|
||||||
|
(Saturn.emu/src/ss/ss.cpp:1836-1849, mednafen 1.32.1 src/ss/ss.cpp:927-970,
|
||||||
|
1592-1600,1867-1874), the VDP2 work queue becomes a framework ring buffer
|
||||||
|
(Saturn.emu/src/ss/vdp2_render.cpp:3211-3231), and the rest is enum and virtual
|
||||||
|
qualifier tidying. The BIOS and cart ROM block is byte-identical to the release,
|
||||||
|
as are cart.cpp, cart/rom.cpp and db.cpp.
|
||||||
|
|
||||||
|
Content is read from .cue, .ccd, .chd, .toc and .m3u files
|
||||||
|
(Saturn.emu/metadata/conf.mk:5, Saturn.emu/src/main/system.ccm:106-109). An
|
||||||
|
archive is opened by the app, which prefers an .m3u member and otherwise keeps
|
||||||
|
the first entry passing that filter, and an .m3u names up to 16 images
|
||||||
|
(Saturn.emu/src/main/Main.cc:186-246). Every load goes through the module's
|
||||||
|
LoadCD entry point (Saturn.emu/src/main/Main.cc:275,
|
||||||
|
Saturn.emu/src/ss/ss.cpp:1757-1806). The ROM entry point Load is never called:
|
||||||
|
its only call site in the tree is a shared helper this app does not use
|
||||||
|
(EmuFramework/src/shared/mednafen-emuex/MDFNUtils.hh:133-146).
|
||||||
|
|
||||||
|
Four files the user supplies carry no name of their own. Pickers store
|
||||||
|
arbitrary URIs under NA/EU BIOS, JP BIOS, KoF '95 ROM and Ultraman ROM, each
|
||||||
|
filtered to names ending in .bin and each refusing to descend into archives
|
||||||
|
(Saturn.emu/src/main/EmuMenuViews.cc:34-37,44-145,
|
||||||
|
EmuFramework/include/emuframework/DataPathSelectView.hh:77-102,
|
||||||
|
Saturn.emu/src/main/system.ccm:85-95,128-131,
|
||||||
|
Saturn.emu/src/main/options.cc:65-68,98-101). MDFN_GetSettingS answers the four
|
||||||
|
path settings with the fixed tokens jp, na, kof95 and ultraman, and
|
||||||
|
MDFN_MakeFName turns each token back into the matching URI, ending the load
|
||||||
|
with a message pointing at the File Paths menu when it is unset
|
||||||
|
(Saturn.emu/src/main/options.cc:215-228,245-285). Every other setting name
|
||||||
|
reaches unreachable(), so no other firmware request can be made.
|
||||||
|
|
||||||
|
Which BIOS is read follows the emulated area: Japan and Asia NTSC take the JP
|
||||||
|
path, every other area the NA/EU path (Saturn.emu/src/ss/ss.cpp:1388-1394). The
|
||||||
|
area comes from the Region menu, or when that is Auto from the first 16 sectors
|
||||||
|
of the disc, checked against the security code hash and the "SEGA SEGASATURN "
|
||||||
|
magic (Saturn.emu/src/main/EmuMenuViews.cc:216-251,
|
||||||
|
Saturn.emu/src/main/options.cc:203-204, Saturn.emu/src/ss/ss.cpp:959-968,
|
||||||
|
1126-1144,1778-1787). The image is rejected at any length other than 524288 and
|
||||||
|
then hashed (Saturn.emu/src/ss/ss.cpp:1400-1404). With ss.bios_sanity forced on
|
||||||
|
(Saturn.emu/src/main/options.cc:193-194) a table of five known images drives two
|
||||||
|
further tests: a file whose name is one of the five must hash to that entry, and
|
||||||
|
a file whose hash is one of the five must belong to the area being emulated
|
||||||
|
(Saturn.emu/src/ss/ss.cpp:1406-1439). An image outside the table passes both,
|
||||||
|
since each test only rejects on a match. A third test compares Saturn against
|
||||||
|
ST-V images and can never fire here.
|
||||||
|
|
||||||
|
Cart type comes from the Cart Type menu when it is not Auto, otherwise from the
|
||||||
|
internal game database, otherwise none
|
||||||
|
(Saturn.emu/src/main/EmuMenuViews.cc:180-214,
|
||||||
|
Saturn.emu/src/main/options.cc:161-164, Saturn.emu/src/ss/ss.cpp:1761-1790).
|
||||||
|
The database forces the KoF '95 cart for MK-81088 and T-3101G and the Ultraman
|
||||||
|
cart for T-13308G, marking all three a game requirement
|
||||||
|
(Saturn.emu/src/ss/db.cpp:93-96,403), so those three discs read a ROM image and
|
||||||
|
every other disc reads none.
|
||||||
|
|
||||||
|
ST-V, the bootable ROM cart and Action Replay 4M Plus are compiled and
|
||||||
|
unreachable. All three exist only behind cart types the Cart Type menu does not
|
||||||
|
list and the database never assigns, and the first two are entered from Load
|
||||||
|
alone (Saturn.emu/src/ss/ss.cpp:1630,1669, Saturn.emu/src/ss/cart.cpp:166-181).
|
||||||
|
Their paths would ask for ss.bios_stv_jp, ss.bios_stv_na, ss.bios_stv_eu and
|
||||||
|
ss.cart.satar4mp_path, none of which MDFN_GetSettingS answers
|
||||||
|
(Saturn.emu/src/ss/ss.cpp:1379-1387,1293,
|
||||||
|
Saturn.emu/src/main/options.cc:215-228). The ST-V EEPROM save file and the
|
||||||
|
ST-V branches in the app's own backup memory code are dead for the same reason
|
||||||
|
(Saturn.emu/src/main/Main.cc:119-123,141-142).
|
||||||
|
|
||||||
|
Per content the app writes and reads back a .bkr backup RAM image, a .smpc real
|
||||||
|
time clock block, .mca save states and, when a memory cart is selected, a
|
||||||
|
gzipped .bcr cart image; settings live in SaturnEmu.config
|
||||||
|
(Saturn.emu/src/main/Main.cc:50-129,152-155,
|
||||||
|
Saturn.emu/src/main/system.ccm:180, Saturn.emu/src/ss/cart/backup.cpp:69-73,
|
||||||
|
Saturn.emu/src/main/AppMeta.cc:28). Mednafen's image reader picks up an .sbi
|
||||||
|
beside a cue sheet when one is present
|
||||||
|
(EmuFramework/src/shared/mednafen/cdrom/CDAccess_Image.cpp:924-941). Cheats are
|
||||||
|
off (Saturn.emu/src/main/options.cc:187-188), and ui.png, gpOverlay.png and the
|
||||||
|
shader sources are drawn from the application bundle
|
||||||
|
(EmuFramework/include/emuframework/AssetManager.hh:61-66,
|
||||||
|
EmuFramework/src/AssetManager.cc:63-69,
|
||||||
|
EmuFramework/src/VideoImageEffect.cc:163-173).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: "sega_101.bin"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "Saturn BIOS v1.01, read for Japan and Asia NTSC"
|
||||||
|
required: true
|
||||||
|
region: [japan, asia-ntsc]
|
||||||
|
size: 524288
|
||||||
|
sha256: "dcfef4b99605f872b6c3b6d05c045385cdea3d1b702906a0ed930df7bcb7deac"
|
||||||
|
validation: [existence, size, sha256]
|
||||||
|
config_key: "CFGKEY_JP_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >
|
||||||
|
The image the module's own setting table names for the JP path
|
||||||
|
(Saturn.emu/src/ss/ss.cpp:2398), and one of three the sanity table accepts
|
||||||
|
for Japan and Asia NTSC. Any 524288-byte image the user picks loads unless
|
||||||
|
the sanity table contradicts it, but a file carrying this name must carry
|
||||||
|
this hash.
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1388-1394 (area picks the JP path), Saturn.emu/src/ss/ss.cpp:1396-1404 (open, size, hash), Saturn.emu/src/ss/ss.cpp:1418 (name, hash, areas), Saturn.emu/src/ss/ss.cpp:2398 (setting default), Saturn.emu/src/main/options.cc:218-219,276-281 (token and path), Saturn.emu/src/main/EmuMenuViews.cc:67-88 (picker)"
|
||||||
|
|
||||||
|
- name: "mpr-17933.bin"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "Saturn BIOS read for every area outside Japan and Asia NTSC"
|
||||||
|
required: true
|
||||||
|
region: [north-america, europe, south-korea, asia-pal, brazil, latin-america]
|
||||||
|
size: 524288
|
||||||
|
sha256: "96e106f740ab448cf89f0dd49dfbac7fe5391cb6bd6e14ad5e3061c13330266f"
|
||||||
|
validation: [existence, size, sha256]
|
||||||
|
config_key: "CFGKEY_NA_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >
|
||||||
|
The image the module's own setting table names for the NA/EU path
|
||||||
|
(Saturn.emu/src/ss/ss.cpp:2399). The sanity table grants it every area
|
||||||
|
except Japan and Asia NTSC, which covers North America, Europe, South
|
||||||
|
Korea, Asia PAL, Brazil and Latin America as the Region menu names them.
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1388-1394 (area picks the NA/EU path), Saturn.emu/src/ss/ss.cpp:1396-1404 (open, size, hash), Saturn.emu/src/ss/ss.cpp:1420 (name, hash, areas), Saturn.emu/src/ss/ss.cpp:2399 (setting default), Saturn.emu/src/main/options.cc:220-221,270-275 (token and path), Saturn.emu/src/main/EmuMenuViews.cc:44-65 (picker), Saturn.emu/src/main/EmuMenuViews.cc:162-176 (area names)"
|
||||||
|
|
||||||
|
- name: "sega_100.bin"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "Saturn BIOS v1.00, accepted for Japan and Asia NTSC"
|
||||||
|
required: false
|
||||||
|
region: [japan, asia-ntsc]
|
||||||
|
size: 524288
|
||||||
|
sha256: "ae4058627bb5db9be6d8d83c6be95a4aa981acc8a89042e517e73317886c8bc2"
|
||||||
|
validation: [existence, size, sha256]
|
||||||
|
config_key: "CFGKEY_JP_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >
|
||||||
|
Interchangeable with the other two Japan images: the sanity table gives all
|
||||||
|
three the same areas, and nothing in the module ranks them.
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1417 (name, hash, areas), Saturn.emu/src/ss/ss.cpp:1396-1439 (open, size, hash, sanity tests)"
|
||||||
|
|
||||||
|
- name: "sega1003.bin"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "Saturn BIOS v1.003, accepted for Japan and Asia NTSC"
|
||||||
|
required: false
|
||||||
|
region: [japan, asia-ntsc]
|
||||||
|
size: 524288
|
||||||
|
sha256: "cc1e1b7f88f1c6e6fc35994bae2c2292e06fdae258c79eb26a1f1391e72914a8"
|
||||||
|
validation: [existence, size, sha256]
|
||||||
|
config_key: "CFGKEY_JP_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1416 (name, hash, areas), Saturn.emu/src/ss/ss.cpp:1396-1439 (open, size, hash, sanity tests)"
|
||||||
|
|
||||||
|
- name: "sega_100a.bin"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "Saturn BIOS v1.00a, accepted for every area outside Japan and Asia NTSC"
|
||||||
|
required: false
|
||||||
|
region: [north-america, europe, south-korea, asia-pal, brazil, latin-america]
|
||||||
|
size: 524288
|
||||||
|
sha256: "87293093fad802fcff31fcab427a16caff1acbc5184899b8383b360fd58efb73"
|
||||||
|
validation: [existence, size, sha256]
|
||||||
|
config_key: "CFGKEY_NA_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1419 (name, hash, areas), Saturn.emu/src/ss/ss.cpp:1396-1439 (open, size, hash, sanity tests)"
|
||||||
|
|
||||||
|
- name: "mpr-18811-mx.ic1"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "King of Fighters '95 ROM cart"
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
min_size: 2097152
|
||||||
|
validation: [existence, size]
|
||||||
|
config_key: "CFGKEY_KOF_ROM_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >
|
||||||
|
Read when the cart type is KoF '95, which the internal database forces for
|
||||||
|
MK-81088 and T-3101G and which the Cart Type menu also offers. Those two
|
||||||
|
discs end the load when the path is unset; every other disc ignores it.
|
||||||
|
CART_ROM_Init takes a fixed 2097152 bytes and Stream::read throws on a
|
||||||
|
shorter file, so anything smaller aborts and anything larger has its tail
|
||||||
|
ignored. The name comes from the module's setting table, which this build
|
||||||
|
never reads: settings.cpp is out of the shared source list, and the picker
|
||||||
|
lists names ending in .bin.
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1291 (cart to setting), Saturn.emu/src/ss/ss.cpp:1348-1357 (firmware path, open, hand to CART_Init), Saturn.emu/src/ss/cart.cpp:162-164 (dispatch), Saturn.emu/src/ss/cart/rom.cpp:37-47 (fixed read), Saturn.emu/src/ss/db.cpp:94-95,403 (database forces the cart), Saturn.emu/src/ss/ss.cpp:2434 (setting default), Saturn.emu/src/main/options.cc:222-223,258-263 (token and path), Saturn.emu/src/main/EmuMenuViews.cc:90-111 (picker)"
|
||||||
|
|
||||||
|
- name: "mpr-19367-mx.ic1"
|
||||||
|
system: sega-saturn
|
||||||
|
description: "Ultraman - Hikari no Kyojin Densetsu ROM cart"
|
||||||
|
required: false
|
||||||
|
agnostic: true
|
||||||
|
min_size: 2097152
|
||||||
|
validation: [existence, size]
|
||||||
|
config_key: "CFGKEY_ULTRAMAN_ROM_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >
|
||||||
|
Read when the cart type is Ultraman, which the internal database forces for
|
||||||
|
T-13308G and which the Cart Type menu also offers. Same fixed 2097152-byte
|
||||||
|
read as the other ROM cart, and the same picker filtered to .bin.
|
||||||
|
source_ref: "Saturn.emu/src/ss/ss.cpp:1292 (cart to setting), Saturn.emu/src/ss/ss.cpp:1348-1357 (firmware path, open, hand to CART_Init), Saturn.emu/src/ss/cart.cpp:163-164 (dispatch), Saturn.emu/src/ss/cart/rom.cpp:37-47 (fixed read), Saturn.emu/src/ss/db.cpp:96,403 (database forces the cart), Saturn.emu/src/ss/ss.cpp:2435 (setting default), Saturn.emu/src/main/options.cc:224-225,264-269 (token and path), Saturn.emu/src/main/EmuMenuViews.cc:113-134 (picker)"
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
emulator: sixtyforce
|
||||||
|
type: standalone
|
||||||
|
core_classification: embedded_hle
|
||||||
|
source: "https://sixtyforce.com/"
|
||||||
|
upstream: "https://sixtyforce.com/"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "2.0.2"
|
||||||
|
display_name: "Nintendo - Nintendo 64 (sixtyforce)"
|
||||||
|
cores:
|
||||||
|
- sixtyforce
|
||||||
|
systems:
|
||||||
|
- nintendo-64
|
||||||
|
- nintendo-64dd
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Nintendo 64 emulator for macOS by Gerrit Goossen, closed source since its first
|
||||||
|
release in 2001. ES-DE runs it from
|
||||||
|
/Applications/sixtyforce.app/Contents/MacOS/sixtyforce and passes the ROM path.
|
||||||
|
Everything below is read from the distributed 2.0.2 build (CFBundleVersion 87,
|
||||||
|
single x86_64 slice, macOS 10.9 or later); addresses are the virtual addresses
|
||||||
|
of Contents/MacOS/sixtyforce. None of it appears on the site, in the help pages
|
||||||
|
or in the release notes.
|
||||||
|
|
||||||
|
The boot chain reads nothing. There is no PIF ROM and no CIC image: the boot
|
||||||
|
writes the constants for the CIC itself, dispatching on a number in the 6101 to
|
||||||
|
7106 range kept in the machine state (0x100071dbf-0x100071e2c). That number is
|
||||||
|
what Overrides.plist gives for the game, and when the table has no entry the
|
||||||
|
code sums the ROM's own IPL3 region instead (0x100071c78-0x100071c8f,
|
||||||
|
0x100071e31-0x100071e94). The country code byte of the cartridge header takes
|
||||||
|
the PAL branch for D, F, I, P, S, U, X and Y (0x100071d84-0x100071da3).
|
||||||
|
|
||||||
|
Every primitive the binary can open a file with (URLForResource:withExtension:,
|
||||||
|
initWithContentsOfURL:options:error:, initWithFileURL:,
|
||||||
|
fileHandleForReadingFromURL:error:, the two directory enumerators, mmap)
|
||||||
|
resolves to three sources: the ROM the user picks, the five bundle resources
|
||||||
|
below, and the app's own saves.
|
||||||
|
|
||||||
|
A ROM is read in any of three byte orders. The first word decides:
|
||||||
|
0x80371240, 0x80371241 and the 64DD IPL word 0x80270740 are big endian and get
|
||||||
|
a 32 bit reversal, 0x37804012, 0x37804112 and 0x27804007 are word swapped and
|
||||||
|
get a 16 bit reversal, 0x40123780, 0x41123780 and 0x40072780 are already in the
|
||||||
|
internal little endian word order and pass through. A gzip stream or a 60gz
|
||||||
|
container is decompressed first, and the length has to be a multiple of four
|
||||||
|
(0x1000ad5c0-0x1000ad6ce, SFGZFile at 0x1000ae2d0). Anything else fails with
|
||||||
|
"Error Loading Cartridge Format".
|
||||||
|
|
||||||
|
64DD support stops at the IPL image. HardwareState carries a cartridge slot
|
||||||
|
(pointer at +0x120, length at +0x128) and an IPL slot (+0x138, +0x140) and no
|
||||||
|
disk slot; the document types are n64, v64 and z64, and the only occurrences of
|
||||||
|
the letters ndd in the whole binary are the two NDDJ immediates in the loader.
|
||||||
|
Loading the IPL while a cartridge is open leaves the cartridge in place.
|
||||||
|
|
||||||
|
Autosaves, game freezes, controller paks and the controller configuration are
|
||||||
|
written by the app, so none of them is an entry here.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: 64DD_IPL.bin
|
||||||
|
system: nintendo-64dd
|
||||||
|
required: false
|
||||||
|
description: "64DD IPL ROM"
|
||||||
|
note: >
|
||||||
|
Opened through the file panel like a cartridge. The loader builds the four
|
||||||
|
byte game code from the header, media format at 0x3b, then the two
|
||||||
|
cartridge id bytes read 0x3d before 0x3c, then country at 0x3e, and keeps
|
||||||
|
the image in the 64DD slot instead of the cartridge slot when that code
|
||||||
|
reads NDDJ. That is the Japanese retail IPL; the USA image reads NDDE and
|
||||||
|
the development image NDXJ, so neither can reach that slot. No code path
|
||||||
|
opens the file by name, so the entry carries no
|
||||||
|
alias and the name is a label. The image is mapped at 0x06000000 and read
|
||||||
|
back by PI DMA bounded by its own length, and the 64DD register window at
|
||||||
|
0x05000000, 0x524 bytes for the ASIC buffers and registers, is installed
|
||||||
|
only once the image is loaded. The same pointer and length decide the disk
|
||||||
|
drive flag the booting game reads, so an absent image is a supported state.
|
||||||
|
Nothing checks a hash, and nothing checks a size beyond the container
|
||||||
|
format and the multiple of four.
|
||||||
|
source_ref: "sixtyforce 2.0.2 MacOS/sixtyforce 0x100026b18-0x100026b64 (game code test, 64DD slot), 0x10006e470-0x10006e4a7 (game code), 0x100081942-0x1000819b1 (memory map), 0x1000831b2-0x100083285 (PI DMA), 0x100071d62-0x100071d7d (drive flag)"
|
||||||
|
|
||||||
|
- name: Overrides.plist
|
||||||
|
path: "Contents/Resources/Overrides.plist"
|
||||||
|
system: nintendo-64
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 12855
|
||||||
|
description: "Per-game hardware overrides"
|
||||||
|
note: >
|
||||||
|
561 entries keyed by the four byte game code, read at cartridge load and
|
||||||
|
carrying the CIC seed, the cartridge memory type, the framebuffer flags and
|
||||||
|
the expanded memory and timing settings. The CIC a game boots with comes
|
||||||
|
from this table, and the code falls back to a checksum of the ROM when the
|
||||||
|
table has no entry for it.
|
||||||
|
source_ref: "sixtyforce 2.0.2 MacOS/sixtyforce 0x100039336 (resource name), 0x1000392d0-0x1000393fa (lookup by game code, CIC key), 0x100026e67-0x100026e89 (called with the game code), 0x100071c78-0x100071c8f (CIC read at boot), 0x1000d21a0 (expanded memory log)"
|
||||||
|
|
||||||
|
- name: Controller-Devices.plist
|
||||||
|
path: "Contents/Resources/Controller-Devices.plist"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 73988
|
||||||
|
description: "Controller device database"
|
||||||
|
note: >
|
||||||
|
The bundle carries one device list. SFControllerManager loads a bundle
|
||||||
|
property list while it initialises and keeps it in its supportedDevices
|
||||||
|
table, which the handlers read when a HID device arrives or leaves. The
|
||||||
|
user's own mappings are a separate file the manager reads and writes from
|
||||||
|
the application support folder.
|
||||||
|
source_ref: "sixtyforce 2.0.2 MacOS/sixtyforce 0x100013494-0x1000134e6 (bundle load into supportedDevices), 0x10001918e (read on device arrival), 0x100013870-0x100013a87 (user mappings, separate read)"
|
||||||
|
|
||||||
|
- name: HID-Usage-Names.plist
|
||||||
|
path: "Contents/Resources/HID-Usage-Names.plist"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 28249
|
||||||
|
description: "HID usage names"
|
||||||
|
note: >
|
||||||
|
Read from the bundle to name the HID usages and usage pages shown while
|
||||||
|
mapping a controller element.
|
||||||
|
source_ref: "sixtyforce 2.0.2 MacOS/sixtyforce 0x10001cc6d-0x10001cc81 (resource name and load)"
|
||||||
|
|
||||||
|
- name: Key-Names.plist
|
||||||
|
path: "Contents/Resources/Base.lproj/Key-Names.plist"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 2440
|
||||||
|
description: "Keyboard key names"
|
||||||
|
note: >
|
||||||
|
Localised key names for the keyboard controller configuration sheet, read
|
||||||
|
from the bundle through the same loader as the other property lists.
|
||||||
|
source_ref: "sixtyforce 2.0.2 MacOS/sixtyforce 0x100010c8d-0x100010ca1 (resource name and load)"
|
||||||
|
|
||||||
|
- name: Unit.data
|
||||||
|
path: "Contents/Resources/Unit.data"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 65536
|
||||||
|
description: "Display texture"
|
||||||
|
note: >
|
||||||
|
Read from the bundle while the video controller sets up its OpenGL context
|
||||||
|
and kept as the unitTexture the controller draws with.
|
||||||
|
source_ref: "sixtyforce 2.0.2 MacOS/sixtyforce 0x10004245b-0x10004247b (resource name and load), 0x10004686d (called from video setup), 0x10004658a (unitTexture use)"
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
emulator: Skyline
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://github.com/skyline-emu/skyline"
|
||||||
|
upstream: "https://github.com/skyline-emu/skyline"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "dc20a615275f66bee20a4fd851ef0231daca4f14"
|
||||||
|
core_version: "0.0.3"
|
||||||
|
display_name: "Nintendo - Switch (Skyline)"
|
||||||
|
cores:
|
||||||
|
- "skyline"
|
||||||
|
- "SKYLINE"
|
||||||
|
systems:
|
||||||
|
- nintendo-switch
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Nintendo Switch emulator for ARMv8 Android, written from scratch in C++ and Kotlin.
|
||||||
|
Android package skyline.emu, versionCode 3, minSdk 29, with the debug variant taking a
|
||||||
|
.dev suffix (build.gradle:23,28-29,120-121). ES-DE reaches it through its SKYLINE find
|
||||||
|
rule and starts it with android.intent.action.VIEW on the content URI of the game.
|
||||||
|
Development ceased and the README at the pinned commit records it; the code is split
|
||||||
|
across skyline and skyline-dev, whose external file surface is identical (key_store.cpp
|
||||||
|
:10-13 and shared_font_core.h:40-47 in both).
|
||||||
|
|
||||||
|
NCA, NRO, NSO, NSP and XCI are loaded (loader/). Two key files are read, from keys/
|
||||||
|
under the application internal files directory, which os.cpp:35 hands to the key store
|
||||||
|
as its root. Both arrive through the in-app importer, which accepts only the two names
|
||||||
|
and rewrites the trimmed pairs into that directory (KeyReader.kt:25-26,56-60); nothing
|
||||||
|
else is consulted for keys, and there is no dev.keys or console.keys path.
|
||||||
|
|
||||||
|
No firmware is installed and none is read. The system version is answered from a
|
||||||
|
hardcoded 9.0.0-4.0 structure (ISystemSettingsServer.cpp:9-10) and the system data
|
||||||
|
archives a game asks for through OpenDataStorageByDataId are served as stub RomFS
|
||||||
|
images from the application assets (IFileSystemProxy.cpp:84-90). Two are carried:
|
||||||
|
0100000000000806, the NgWord filter, holding 0.txt through 15.txt plus common.txt and
|
||||||
|
version.dat, and 0100000000000823, NgWord2, holding ac_<0-15>_b1_nx, ac_<0-15>_b2_nx
|
||||||
|
and ac_<0-15>_not_b_nx. A data id without a matching asset opens nothing.
|
||||||
|
|
||||||
|
The six shared fonts are the one place where a firmware file replaces a built-in one.
|
||||||
|
Each is looked for in fonts/ under the application external files directory, which
|
||||||
|
resolves to /storage/emulated/0/Android/data/skyline.emu/files/ (SkylineApplication.kt
|
||||||
|
:19,41), and only when it is absent does the asset of the same name serve instead
|
||||||
|
(shared_font_core.h:40-47). The emulator writes the shared font header itself, a magic
|
||||||
|
followed by the length XORed with a key derived at shared_font_core.h:36-38, and then
|
||||||
|
copies the whole file after it (shared_font_core.h:51-55), so the file it expects is
|
||||||
|
the raw TTF payload rather than the headered form the firmware stores. Sizes are taken
|
||||||
|
from the file and never checked, and the six together have to fit the 0x140A000 shared
|
||||||
|
memory block.
|
||||||
|
|
||||||
|
A custom Vulkan driver can be loaded through adrenotools from gpu_drivers/<label>/
|
||||||
|
under the internal files directory (gpu.cpp:342-357). The label and the library
|
||||||
|
filename are both read from a meta.json inside the archive the user installs
|
||||||
|
(GpuDriverHelper.kt:19-22,150-191,219), so the code names no driver file of its own;
|
||||||
|
loading falls back to the built-in driver and then to the system libvulkan.so. Save
|
||||||
|
data and the emulated SD card live under switch/ in the external files directory
|
||||||
|
(IFileSystemProxy.cpp:21,67) and are written by the emulator.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: prod.keys
|
||||||
|
path: "keys/prod.keys"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: true
|
||||||
|
description: "Production keys for content decryption"
|
||||||
|
note: >-
|
||||||
|
Read as name=value pairs from keys/ under the application internal files directory.
|
||||||
|
Supplies header_key, and the titlekek_XX, key_area_key_application_XX,
|
||||||
|
key_area_key_ocean_XX and key_area_key_system_XX generation-indexed sets. An
|
||||||
|
encrypted NCA without header_key fails with MissingHeaderKey, and one whose key
|
||||||
|
area cannot be unwrapped fails with MissingKeyArea, so no retail title loads
|
||||||
|
without this file. The importer accepts a pair only when the name contains an
|
||||||
|
underscore and the value is hexadecimal.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/os.cpp:35 (root directory), app/src/main/cpp/skyline/crypto/key_store.cpp:12-13 (read), app/src/main/cpp/skyline/crypto/key_store.h:30-39 (key names), app/src/main/cpp/skyline/crypto/key_store.cpp:46-62 (parse), app/src/main/cpp/skyline/vfs/nca.cpp:21-22,126 (failures), app/src/main/java/emu/skyline/KeyReader.kt:83-88 (import check)"
|
||||||
|
|
||||||
|
- name: title.keys
|
||||||
|
path: "keys/title.keys"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
description: "Per-title keys"
|
||||||
|
note: >-
|
||||||
|
Read as rights id to title key pairs from the same directory. A title key normally
|
||||||
|
arrives instead from the .tik tickets carried inside an NSP, which are parsed and
|
||||||
|
pushed into the same store, so this file is only needed when no ticket supplies
|
||||||
|
one; that case fails with MissingTitleKey. The importer requires both halves of a
|
||||||
|
pair to be 32 hexadecimal characters.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/crypto/key_store.cpp:10-11 (read), app/src/main/cpp/skyline/crypto/key_store.cpp:35-39 (parse), app/src/main/cpp/skyline/loader/nsp.cpp:14-21 (tickets), app/src/main/cpp/skyline/vfs/nca.cpp:108-110 (failure), app/src/main/java/emu/skyline/KeyReader.kt:77-82 (import check)"
|
||||||
|
|
||||||
|
- name: FontStandard.ttf
|
||||||
|
path: "fonts/FontStandard.ttf"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
has_builtin: true
|
||||||
|
description: "Shared font, standard"
|
||||||
|
note: >-
|
||||||
|
Loaded from fonts/ under the application external files directory when present,
|
||||||
|
otherwise from the asset of the same name, which carries Noto Sans CJK. Copied
|
||||||
|
into the shared font block behind a header the emulator generates, so the expected
|
||||||
|
content is the raw TTF payload.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/pl/shared_font_core.h:26 (entry), :40-47 (lookup and fallback), :51-55 (header and copy)"
|
||||||
|
|
||||||
|
- name: FontChineseSimplified.ttf
|
||||||
|
path: "fonts/FontChineseSimplified.ttf"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
has_builtin: true
|
||||||
|
description: "Shared font, simplified Chinese"
|
||||||
|
note: >-
|
||||||
|
Same lookup as the standard font, with a Noto Sans CJK asset behind it.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/pl/shared_font_core.h:27 (entry), :40-47 (lookup and fallback), :51-55 (header and copy)"
|
||||||
|
|
||||||
|
- name: FontExtendedChineseSimplified.ttf
|
||||||
|
path: "fonts/FontExtendedChineseSimplified.ttf"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
has_builtin: true
|
||||||
|
description: "Shared font, extended simplified Chinese"
|
||||||
|
note: >-
|
||||||
|
Same lookup as the standard font, with a Noto Sans CJK asset behind it.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/pl/shared_font_core.h:28 (entry), :40-47 (lookup and fallback), :51-55 (header and copy)"
|
||||||
|
|
||||||
|
- name: FontChineseTraditional.ttf
|
||||||
|
path: "fonts/FontChineseTraditional.ttf"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
has_builtin: true
|
||||||
|
description: "Shared font, traditional Chinese"
|
||||||
|
note: >-
|
||||||
|
Same lookup as the standard font, with a Noto Sans CJK asset behind it.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/pl/shared_font_core.h:29 (entry), :40-47 (lookup and fallback), :51-55 (header and copy)"
|
||||||
|
|
||||||
|
- name: FontKorean.ttf
|
||||||
|
path: "fonts/FontKorean.ttf"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
has_builtin: true
|
||||||
|
description: "Shared font, Korean"
|
||||||
|
note: >-
|
||||||
|
Same lookup as the standard font, with a Noto Sans CJK asset behind it.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/pl/shared_font_core.h:30 (entry), :40-47 (lookup and fallback), :51-55 (header and copy)"
|
||||||
|
|
||||||
|
- name: FontNintendoExtended.ttf
|
||||||
|
path: "fonts/FontNintendoExtended.ttf"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
has_builtin: true
|
||||||
|
description: "Shared font, extended button glyphs"
|
||||||
|
note: >-
|
||||||
|
Same lookup as the standard font, with a Roboto asset behind it.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/pl/shared_font_core.h:31 (entry), :40-47 (lookup and fallback), :51-55 (header and copy)"
|
||||||
|
|
||||||
|
- name: "0100000000000806"
|
||||||
|
path: "romfs/0100000000000806"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "stub image the emulator build carries inside its package, not a dump of the system data archive it stands in for"
|
||||||
|
description: "NgWord system data archive"
|
||||||
|
note: >-
|
||||||
|
Stub RomFS image served from the application assets when a game opens the data
|
||||||
|
storage for this title id. Holds 0.txt through 15.txt, common.txt and version.dat.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp:84-90"
|
||||||
|
|
||||||
|
- name: "0100000000000823"
|
||||||
|
path: "romfs/0100000000000823"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "stub image the emulator build carries inside its package, not a dump of the system data archive it stands in for"
|
||||||
|
description: "NgWord2 system data archive"
|
||||||
|
note: >-
|
||||||
|
Stub RomFS image served from the application assets when a game opens the data
|
||||||
|
storage for this title id. Holds ac_<0-15>_b1_nx, ac_<0-15>_b2_nx and
|
||||||
|
ac_<0-15>_not_b_nx.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp:84-90"
|
||||||
|
|
||||||
|
- name: binaryList.txt
|
||||||
|
path: "tzdata/binaryList.txt"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "generated by the emulator build from the public time zone database and carried inside its package"
|
||||||
|
description: "Time zone location list"
|
||||||
|
note: >-
|
||||||
|
Read from the application assets at time service init and used as the list of
|
||||||
|
known locations. It names the 594 zone binaries under tzdata/zoneinfo/, each of
|
||||||
|
which is opened by location name when a zone rule is loaded. The set is generated
|
||||||
|
from tzdb 2021a in Horizon format.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/timesrv/core.cpp:272 (list), :293 (zone binary by name), app/src/main/cpp/skyline/services/glue/ITimeZoneService.cpp:29,56 (zone binary by requested location)"
|
||||||
|
|
||||||
|
- name: version.txt
|
||||||
|
path: "tzdata/version.txt"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "generated by the emulator build from the public time zone database and carried inside its package"
|
||||||
|
description: "Time zone data version"
|
||||||
|
note: >-
|
||||||
|
Read from the application assets at time service init and reported as the time
|
||||||
|
zone binary version.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/timesrv/core.cpp:289"
|
||||||
|
|
||||||
|
- name: profile_picture.jpeg
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "placeholder image carried inside the emulator package"
|
||||||
|
description: "Default user profile image"
|
||||||
|
note: >-
|
||||||
|
Opened from the application assets when a game asks the account service for the
|
||||||
|
profile image of the emulated user.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/services/account/IProfile.cpp:66"
|
||||||
|
|
||||||
|
- name: blit.vert.spv
|
||||||
|
path: "shaders/blit.vert.spv"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "build output of the emulator's own shader source, carried inside its package"
|
||||||
|
description: "Blit vertex helper shader"
|
||||||
|
note: >-
|
||||||
|
Opened from the application assets when the GPU helper shaders are built. Compiled
|
||||||
|
at build time from app/src/main/shaders/blit.vert.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/gpu/shaders/helper_shaders.cpp:201, app/src/main/cpp/skyline/gpu.cpp:403 (asset filesystem)"
|
||||||
|
|
||||||
|
- name: blit.frag.spv
|
||||||
|
path: "shaders/blit.frag.spv"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "build output of the emulator's own shader source, carried inside its package"
|
||||||
|
description: "Blit fragment helper shader"
|
||||||
|
note: >-
|
||||||
|
Opened from the application assets when the GPU helper shaders are built. Compiled
|
||||||
|
at build time from app/src/main/shaders/blit.frag.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/gpu/shaders/helper_shaders.cpp:201, app/src/main/cpp/skyline/gpu.cpp:403 (asset filesystem)"
|
||||||
|
|
||||||
|
- name: clear.vert.spv
|
||||||
|
path: "shaders/clear.vert.spv"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "build output of the emulator's own shader source, carried inside its package"
|
||||||
|
description: "Clear vertex helper shader"
|
||||||
|
note: >-
|
||||||
|
Opened from the application assets when the GPU helper shaders are built. Compiled
|
||||||
|
at build time from app/src/main/shaders/clear.vert.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/gpu/shaders/helper_shaders.cpp:328, app/src/main/cpp/skyline/gpu.cpp:403 (asset filesystem)"
|
||||||
|
|
||||||
|
- name: clear.frag.spv
|
||||||
|
path: "shaders/clear.frag.spv"
|
||||||
|
system: nintendo-switch
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "build output of the emulator's own shader source, carried inside its package"
|
||||||
|
description: "Clear fragment helper shader"
|
||||||
|
note: >-
|
||||||
|
Opened from the application assets when the GPU helper shaders are built. Compiled
|
||||||
|
at build time from app/src/main/shaders/clear.frag.
|
||||||
|
source_ref: "app/src/main/cpp/skyline/gpu/shaders/helper_shaders.cpp:328, app/src/main/cpp/skyline/gpu.cpp:403 (asset filesystem)"
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
emulator: "Snes9x EX+"
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/Rakashazi/emu-ex-plus-alpha"
|
||||||
|
upstream: "https://github.com/snes9xgit/snes9x"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "1c12fac5ce49badaadff2e2f210dcc30b89f4943"
|
||||||
|
upstream_commit: "b33f2afb33c61d675aaf0319bd3b8cc8d6924d49"
|
||||||
|
core_version: "1.5.85"
|
||||||
|
display_name: "Nintendo - SNES / SFC (Snes9x EX+)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "snes9x-explus"
|
||||||
|
- "SNES9X-EXPLUS"
|
||||||
|
- "Snes9x EX+"
|
||||||
|
- "Snes9xEXPlus"
|
||||||
|
systems:
|
||||||
|
- nintendo-snes
|
||||||
|
- nintendo-satellaview
|
||||||
|
- nintendo-sufami-turbo
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Member of the EX Emulator series by Robert Broglia, published as
|
||||||
|
com.explusalpha.Snes9xPlus and built around the target s9xp
|
||||||
|
(Snes9x/metadata/conf.mk:2-7, Snes9x/CMakeLists.txt:4,10). ES-DE reaches it
|
||||||
|
through the SNES9X-EXPLUS find rule, which only the Android rule set carries,
|
||||||
|
and offers it under satellaview, sfc, snes, snesna and sufami. Snes9x 1.63 is
|
||||||
|
vendored under Snes9x/src/snes9x at upstream b33f2af, the revision the sync
|
||||||
|
commit 96b2f850 names, and 114 of the 152 vendored source files are
|
||||||
|
byte-identical to it. The app built from Snes9x/1.43 is a separate package,
|
||||||
|
com.explusalpha.Snes9x, and carries none of what follows.
|
||||||
|
|
||||||
|
Content is any .smc, .sfc, .swc, .bs, .st, .fig or .mgd file, or an archive
|
||||||
|
whose first entry with one of those extensions is used, the app leaving
|
||||||
|
archives to the framework (Snes9x/src/main/AppMeta.cc:30-33,
|
||||||
|
EmuFramework/src/EmuSystem.cc:392-425, EmuFramework/src/AppMeta.cc:29). It
|
||||||
|
is read whole into memory and goes to LoadROMMem, except a Sufami Turbo cart,
|
||||||
|
recognized by a length of 0x80000 to 0x100000 with "BANDAI SFC-ADX" at 0 and
|
||||||
|
no "SFC-ADX BACKUP" at 0x10, which goes to LoadMultiCartMem with the base
|
||||||
|
cartridge placed in front of it (Snes9x/src/main/Main.cc:177-181,221-273,
|
||||||
|
Snes9x/src/snes9x/memmap.cpp:1575-1608). Dual Sufami Turbo carts are not
|
||||||
|
loaded: slot B is always passed as null (Snes9x/src/main/Main.cc:250-260).
|
||||||
|
|
||||||
|
Two firmware images are read, and both differ from upstream in how they are
|
||||||
|
found. Upstream opens BS-X.bin then BS-X.bios in its BIOS directory
|
||||||
|
(bsx.cpp:1204-1236) and STBIOS.bin for a Sufami Turbo load
|
||||||
|
(memmap.cpp:1663-1686); the app deletes both blocks and reads a URI the user
|
||||||
|
picks instead, so no filename is compiled in
|
||||||
|
(Snes9x/src/snes9x/bsx.cpp:1199-1203,
|
||||||
|
Snes9x/src/snes9x/memmap.cpp:1644-1670, Snes9x/src/main/S9XApi.cc:225-253,
|
||||||
|
Snes9x/src/main/Main.cc:194-219). Each picker lists directories, names ending
|
||||||
|
.bin or .bios caselessly, and .7z, .rar and .zip archives, whose first member
|
||||||
|
with one of those two extensions is taken (Snes9x/src/main/Main.cc:189-192,
|
||||||
|
Snes9x/src/main/EmuMenuViews.cc:345-387,
|
||||||
|
EmuFramework/include/emuframework/DataPathSelectView.hh:77-101,
|
||||||
|
EmuFramework/src/gui/FilePicker.cc:39-48,
|
||||||
|
imagine/src/fs/ArchiveFS.cc:75-78). An unset path or a failed check throws,
|
||||||
|
and the loader thread turns that into a failed load with the message on
|
||||||
|
screen (EmuFramework/src/EmuApp.cc:794-819). Neither image is hashed.
|
||||||
|
|
||||||
|
A BS-X cartridge image loaded as content takes the other branch of
|
||||||
|
S9xInitBSX, which copies it into the BIOS area itself and asks for nothing
|
||||||
|
(Snes9x/src/snes9x/bsx.cpp:1213-1233). Broadcast data is read per requested
|
||||||
|
channel as BSXHHHH-D.bin under the Satellaview Files path, which defaults to
|
||||||
|
the content directory; a miss only leaves the stream unloaded
|
||||||
|
(Snes9x/src/snes9x/bsx.cpp:736-790, Snes9x/src/main/S9XApi.cc:203-216,
|
||||||
|
Snes9x/src/main/system.ccm:108).
|
||||||
|
|
||||||
|
Every coprocessor is emulated in code with no external firmware: DSP-1 to
|
||||||
|
DSP-4, ST010, ST011, ST018, Cx4, S-DD1 and SPC7110, each implemented under
|
||||||
|
Snes9x/src/snes9x in dsp1.cpp through dsp4.cpp, seta010.cpp, seta011.cpp,
|
||||||
|
seta018.cpp, c4emu.cpp, sdd1emu.cpp and spc7110emu.cpp. The 1.43 branch's
|
||||||
|
S-DD1 data call and SPC7110 pack directory are compiled out here
|
||||||
|
(Snes9x/src/main/S9XApi.cc:64,89-131).
|
||||||
|
|
||||||
|
Per content the app writes and reads back a .srm, an .rtc for the S-RTC,
|
||||||
|
.frz states and a .cht cheat list under the cheats path; settings live in
|
||||||
|
Snes9xP.config (Snes9x/src/main/Main.cc:78-90,153-172,
|
||||||
|
Snes9x/src/snes9x/memmap.cpp:1791-1812, Snes9x/src/main/Cheats.cc:33-45,
|
||||||
|
Snes9x/src/main/AppMeta.cc:19). A BS game with no save of its own falls back
|
||||||
|
to BS-X.srm (Snes9x/src/snes9x/memmap.cpp:1874-1890). A .bps, .ups or .ips
|
||||||
|
named after the content in the patches path is applied as the image loads,
|
||||||
|
the app having dropped the search beside the content
|
||||||
|
(Snes9x/src/snes9x/memmap.cpp:1327,3888-4027). MSU-1 data and tracks are read
|
||||||
|
beside the content as .msu, or the content name with msu1.rom appended, and
|
||||||
|
-N.pcm per track (Snes9x/src/snes9x/msu1.cpp:60-70,116-118,157-160). UNZIP_SUPPORT is not defined, so the .msu1 pack and the
|
||||||
|
patch-inside-a-zip paths are not compiled (Snes9x/CMakeLists.txt:18).
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: "BS-X.bin"
|
||||||
|
aliases: ["BS-X.bios"]
|
||||||
|
system: nintendo-satellaview
|
||||||
|
description: "Satellaview BS-X cartridge ROM"
|
||||||
|
required: true
|
||||||
|
agnostic: true
|
||||||
|
min_size: 1048576
|
||||||
|
validation: [existence, size]
|
||||||
|
config_key: "CFGKEY_BSX_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >-
|
||||||
|
Read for every BS game, the branch taken when the header at 0x7FC0 or
|
||||||
|
0xFFC0 marks the image as one. The read takes 1048576 bytes and compares
|
||||||
|
the count returned, so a shorter file is rejected and a longer one has its
|
||||||
|
tail ignored, then the 21 bytes at 0x7FC0 must read "Satellaview BS-X"
|
||||||
|
padded with spaces.
|
||||||
|
The name is the user's: the app compiles none in and only the .bin and
|
||||||
|
.bios endings limit what the picker offers.
|
||||||
|
source_ref: "Snes9x/src/snes9x/memmap.cpp:2065 (run on every load), Snes9x/src/snes9x/bsx.cpp:1240-1274 (BS branch calls the loader), Snes9x/src/snes9x/bsx.cpp:1199-1203 (loader is the app hook), Snes9x/src/main/S9XApi.cc:218-253 (path, archive, size and header checks), Snes9x/src/main/EmuMenuViews.cc:345-365 (picker), Snes9x/src/main/system.ccm:110 (setting), Snes9x/src/main/options.cc:46,79 (config key)"
|
||||||
|
|
||||||
|
- name: "STBIOS.bin"
|
||||||
|
system: nintendo-sufami-turbo
|
||||||
|
description: "Sufami Turbo base cartridge ROM"
|
||||||
|
required: true
|
||||||
|
agnostic: true
|
||||||
|
size: 262144
|
||||||
|
validation: [existence, size]
|
||||||
|
config_key: "CFGKEY_SUFAMI_BIOS_PATH"
|
||||||
|
category: bios
|
||||||
|
note: >-
|
||||||
|
Read whenever the content is a Sufami Turbo cart, and copied to the front
|
||||||
|
of the ROM area with the cart behind it. The whole file is buffered, so
|
||||||
|
the length must be exactly 262144, with "BANDAI SFC-ADX" at 0 and
|
||||||
|
"SFC-ADX BACKUP" at 0x10. The name is the user's, the picker accepting any
|
||||||
|
.bin or .bios.
|
||||||
|
source_ref: "Snes9x/src/main/Main.cc:250-260 (cart routes through the BIOS read), Snes9x/src/main/Main.cc:183-187,194-219 (path, archive, size and header checks), Snes9x/src/snes9x/memmap.cpp:1018-1025,1575-1608 (second check and placement), Snes9x/src/main/EmuMenuViews.cc:367-387 (picker), Snes9x/src/main/system.ccm:109 (setting), Snes9x/src/main/options.cc:45,78 (config key)"
|
||||||
|
|
||||||
|
- name: "BSX0120-0.bin"
|
||||||
|
system: nintendo-satellaview
|
||||||
|
description: "Satellaview data stream for channel 0120"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 34
|
||||||
|
validation: [existence]
|
||||||
|
config_key: "CFGKEY_SATELLAVIEW_PATH"
|
||||||
|
note: >-
|
||||||
|
Opened by the name the emulated unit asks for, BSXHHHH-D.bin from the
|
||||||
|
channel registers at 0x2188 and 0x218E, under the Satellaview Files path,
|
||||||
|
which defaults to the content directory. The file is measured to size the
|
||||||
|
queue and read 22 bytes at a time; a miss leaves the stream unloaded.
|
||||||
|
source_ref: "Snes9x/src/snes9x/bsx.cpp:736-790, Snes9x/src/main/S9XApi.cc:203-216, Snes9x/src/main/system.ccm:108, Snes9x/src/main/EmuMenuViews.cc:325-343"
|
||||||
|
|
||||||
|
- name: "BSX0121-0.bin"
|
||||||
|
system: nintendo-satellaview
|
||||||
|
description: "Satellaview data stream for channel 0121"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 34
|
||||||
|
validation: [existence]
|
||||||
|
config_key: "CFGKEY_SATELLAVIEW_PATH"
|
||||||
|
source_ref: "Snes9x/src/snes9x/bsx.cpp:736-790, Snes9x/src/main/S9XApi.cc:203-216"
|
||||||
|
|
||||||
|
- name: "BSX0122-0.bin"
|
||||||
|
system: nintendo-satellaview
|
||||||
|
description: "Satellaview data stream for channel 0122"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 1031
|
||||||
|
validation: [existence]
|
||||||
|
config_key: "CFGKEY_SATELLAVIEW_PATH"
|
||||||
|
source_ref: "Snes9x/src/snes9x/bsx.cpp:736-790, Snes9x/src/main/S9XApi.cc:203-216"
|
||||||
|
|
||||||
|
- name: "BSX0123-0.bin"
|
||||||
|
system: nintendo-satellaview
|
||||||
|
description: "Satellaview data stream for channel 0123"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 16
|
||||||
|
validation: [existence]
|
||||||
|
config_key: "CFGKEY_SATELLAVIEW_PATH"
|
||||||
|
source_ref: "Snes9x/src/snes9x/bsx.cpp:736-790, Snes9x/src/main/S9XApi.cc:203-216"
|
||||||
|
|
||||||
|
- name: "BSX0124-0.bin"
|
||||||
|
system: nintendo-satellaview
|
||||||
|
description: "Satellaview data stream for channel 0124"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 97
|
||||||
|
validation: [existence]
|
||||||
|
config_key: "CFGKEY_SATELLAVIEW_PATH"
|
||||||
|
source_ref: "Snes9x/src/snes9x/bsx.cpp:736-790, Snes9x/src/main/S9XApi.cc:203-216"
|
||||||
|
|
||||||
|
- name: "Bio Worm.7z"
|
||||||
|
aliases: ["BioWorm.7z"]
|
||||||
|
system: nintendo-snes
|
||||||
|
description: "Bundled homebrew game, listed under Bundled Content"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
validation: [existence]
|
||||||
|
size: 42479
|
||||||
|
sha1: "38e44c9868c0b8a5a99ec0b6e901a28f617d25bf"
|
||||||
|
note: >-
|
||||||
|
Opened from the application bundle by the name the build gives it, the
|
||||||
|
Linux build dropping the space, and loaded as content.
|
||||||
|
source_ref: "Snes9x/src/main/AppMeta.cc:20-21 (names), EmuFramework/src/gui/BundledGamesView.cc:41,47 (open and load)"
|
||||||
@@ -0,0 +1,422 @@
|
|||||||
|
emulator: Speccy
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://fms.komkon.org/Speccy/"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Marat Fayzullin (Garage Research)"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "5.9.11"
|
||||||
|
display_name: "Sinclair - ZX Spectrum and Sam Coupe (Speccy)"
|
||||||
|
verification: existence
|
||||||
|
cores:
|
||||||
|
- speccy
|
||||||
|
- SPECCY
|
||||||
|
- com.fms.speccy.deluxe
|
||||||
|
- com.fms.speccy
|
||||||
|
systems:
|
||||||
|
- sinclair-zx-spectrum
|
||||||
|
- timex-tc2048
|
||||||
|
- timex-ts2068
|
||||||
|
- sam-coupe
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Sinclair emulator by Marat Fayzullin, covering ZX Spectrum 16kB, 48kB and
|
||||||
|
128kB, Spectrum +2, +2A and +3, Timex TC2048 and TS2068, the Slovak Didaktik
|
||||||
|
Gama, the Russian Pentagon and Scorpion clones, and the Sam Coupe. The build
|
||||||
|
read here is the free Android package com.fms.speccy, versionName 5.9.11
|
||||||
|
versionCode 5911, taken as the Play app bundle drop, xapk sha256
|
||||||
|
a93f2fd474234291d2c0dee57885204ffb12a22c94602fdfcdfbf084ed7cb354, base apk
|
||||||
|
sha256 7163451489ac59b8c63ca49976571ad284cffa11b54d615c1693c909dd6bf768. Its
|
||||||
|
META-INF/BNDLTOOL.RSA is the author's own key, CN=Marat Fayzullin O=Garage
|
||||||
|
Research issued 2011, fingerprint
|
||||||
|
d09469e9b550cbc9005d3bd089f3df5f0ba89cba71cdd3b33736a0382d6f9848, beside a
|
||||||
|
Play distribution source stamp in the signing block. The paid package
|
||||||
|
com.fms.speccy.deluxe, last published as 5.9.3 versionCode 5903 in December
|
||||||
|
2021, is carried by no mirror that answers: the author's site links only to
|
||||||
|
Play for it, apkcombo bounces its download page back to the app page, apkpure
|
||||||
|
redirects to its generic downloader, apkvision holds no copy and archive.org
|
||||||
|
none either. The native libraries keep their symbol tables, so the readings
|
||||||
|
below cite libmain.so offsets in the x86_64 slice; the arm64-v8a slice carries
|
||||||
|
the same nineteen ROM names. The free Speccy 5.9 builds for Windows and Ubuntu
|
||||||
|
were read beside it and open the same names with the same lengths and the same
|
||||||
|
order. No source has ever been published: every download on the site, from 1.7
|
||||||
|
for MSDOS through 5.9, is a binary package, while ColEm and fMSX on the same
|
||||||
|
site ship source archives.
|
||||||
|
ref: com.fms.speccy.apk META-INF/BNDLTOOL.RSA, https://fms.komkon.org/Speccy/,
|
||||||
|
Speccy59-Windows-bin.zip, Speccy59-Ubuntu-x86-bin.tgz
|
||||||
|
|
||||||
|
One directory holds everything. MainActivity hands the home directory to
|
||||||
|
jniStart, which copies it into the buffer GetHomeDir returns and passes that
|
||||||
|
same buffer to SetPrivateDir, and Application stores what GetHomeDir returns as
|
||||||
|
the directory LoadBIOS changes into before it opens the first ROM and back out
|
||||||
|
of when it is done. That directory is external storage
|
||||||
|
joined with the application label up to its first space, so /sdcard/Speccy for
|
||||||
|
the package read here, falling back to getExternalFilesDirs(null) when it is
|
||||||
|
not a writable directory; the author's own instructions give the same
|
||||||
|
placement. Every open goes through mopen, which calls OpenRealFile first: the
|
||||||
|
name is tried as given, and again as <PrivateDir>/<basename>, keeping the
|
||||||
|
larger of the two when both open. mopen then layers gzdopen over the
|
||||||
|
descriptor, so any of these files also opens gzipped, and a content:// name is
|
||||||
|
routed to the Android storage framework. The desktop builds have no home
|
||||||
|
directory of their own and open every name where they stand, which -home
|
||||||
|
changes for the system ROMs alone.
|
||||||
|
ref: MainActivity.java:2561-2573, EMULib.java:750, 812,
|
||||||
|
libmain.so jniStart 0x32dd0-0x33530 (0x332af-0x332c1, 0x33312),
|
||||||
|
GetHomeDir 0x30a90, SetPrivateDir 0x571d0,
|
||||||
|
Application 0x602f0-0x60324, OpenRealFile 0x57440-0x5766c,
|
||||||
|
mopen 0x57680-0x57800, LoadBIOS 0x6436d-0x6439a, 0x6466b-0x6467b,
|
||||||
|
Speccy59-Ubuntu-x86-bin speccy 0x3dae5-0x3db17, Speccy.html
|
||||||
|
"-home <dirname>", EmuAndroid "System ROMs"
|
||||||
|
|
||||||
|
LoadBIOS drives the whole set from one word of hardware flags, calling
|
||||||
|
TryLoadROM once per name in a fixed order with the length to read and the bit
|
||||||
|
that asks for it. TryLoadROM does nothing when the bit is clear, and clears
|
||||||
|
the bit when mopen fails, which is the only check the emulator makes: the
|
||||||
|
count mread returns is compared against the requested length solely to pick
|
||||||
|
the word it logs, OK or FAILED, and a short read leaves the bit set. Nothing
|
||||||
|
else about a file is examined and no hash is compared. A machine ROM that
|
||||||
|
loads clears every other machine bit and a peripheral ROM that loads clears
|
||||||
|
every other peripheral bit, so one machine and one disk interface stand at a
|
||||||
|
time. StartZXS gives up when no machine bit survives, logging FAILED TO LOAD
|
||||||
|
SYSTEM ROM! and returning zero without starting the emulation, which makes the
|
||||||
|
ROM of the selected model the one file the emulator cannot run without.
|
||||||
|
ref: libmain.so LoadBIOS 0x64350-0x646cd, TryLoadROM 0x659b0-0x65aa4
|
||||||
|
(mopen 0x659d4, mread 0x65a3c, bit cleared 0x65a1c, masks
|
||||||
|
0x65a7d-0x65a94), StartZXS 0x64040-0x6434c (LoadBIOS 0x6416d, mask
|
||||||
|
0x64172, message 0x64315), Speccy59-Ubuntu-x86-bin speccy
|
||||||
|
0x3dac0-0x3ddaa, 0x3d970-0x3da04, 0x3f43c-0x3f469, 0x3f640
|
||||||
|
|
||||||
|
Two names are reached only through another. ZXS128TR.ROM is tried in place of
|
||||||
|
ZXS128.ROM when the 128kB model and the TR-DOS interface are both asked for,
|
||||||
|
and ZXS128.ROM is loaded after it when it fails. The Multiface bit picks its
|
||||||
|
image from the machine already loaded, MFPLUS3.ROM behind a +2A or +3,
|
||||||
|
MF128.ROM behind a 128kB or +2 and MF1.ROM behind a 16kB or 48kB, and the 8192
|
||||||
|
bytes at offset 8192 of what it read are copied into the page below the machine
|
||||||
|
ROM.
|
||||||
|
ref: libmain.so LoadBIOS 0x64564-0x6458b, 0x645d9-0x645f5, 0x645c2-0x64651,
|
||||||
|
Speccy59-Ubuntu-x86-bin speccy 0x3dc79-0x3dca1, 0x3ddf0-0x3de10,
|
||||||
|
0x3dcd9-0x3dd64, Speccy.html "Now trying to load ZXS128TR.ROM BIOS file"
|
||||||
|
|
||||||
|
Thirteen of the nineteen ROMs ship inside the Android package. MainActivity
|
||||||
|
reads assets/memfs.mp3 whole and jniStart mounts it through SetMemoryFS as an
|
||||||
|
in-memory filesystem, which mopen consults only after OpenRealFile has failed,
|
||||||
|
so a copy in the home directory is served ahead of the packaged one. The
|
||||||
|
directory is a run of 32 byte entries, a length then a name, closed by an entry
|
||||||
|
with an empty name whose first word is the key: rotated left by three times the
|
||||||
|
entry count, XORed sixteen bits at a time into each length and rotated right by
|
||||||
|
three after each, it yields the thirteen lengths, which run consecutively from
|
||||||
|
the end of the directory and account for the file exactly. Eleven of the
|
||||||
|
thirteen are the same bytes the Windows and Ubuntu distributions ship, and
|
||||||
|
TC2048.ROM and TS2068.ROM appear in no distribution at all.
|
||||||
|
ref: MainActivity.java:2561-2573, libmain.so jniStart 0x32f72-0x32f98,
|
||||||
|
InitMemoryFS 0x57180, SetMemoryFS 0x57200-0x57422 (key 0x572a0-0x572c1,
|
||||||
|
lengths 0x572e0-0x57305), mopen 0x57749-0x577e4
|
||||||
|
|
||||||
|
Companion files come from the loaded program's path. LoadFile derives .sta,
|
||||||
|
.pok, .cht and .pal from it and reads each when it is there, and the startup
|
||||||
|
palette is a name of its own, <HomeDir>/Speccy.pal on Android and Speccy.pal
|
||||||
|
beside the binary on the desktop, which -palette redirects.
|
||||||
|
ref: libmain.so LoadFile 0x65482, 0x65569, 0x65590, 0x655b7,
|
||||||
|
Application 0x60436-0x60484, StartZXS 0x641c5-0x641d4,
|
||||||
|
LoadPAL 0x648d0, Speccy59-Ubuntu-x86-bin speccy 0x3f4ac-0x3f4bd,
|
||||||
|
0x3e450-0x3e494, Speccy.html "-palette <filename>"
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: ZXS48.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 16384
|
||||||
|
md5: 4c42a2f075212361c3117015b107ff68
|
||||||
|
sha1: 5ea7c2b824672e914525d1d5c419d71b84a426a2
|
||||||
|
crc32: "ddee531f"
|
||||||
|
description: "ZX Spectrum 48kB BASIC ROM"
|
||||||
|
note: "Read as 16384 bytes for the 48kB model, which is the model the emulator starts in when nothing else is asked for. Present in the packaged filesystem and in the Windows and Ubuntu distributions."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x645a8-0x645bb, Speccy59-Ubuntu-x86-bin speccy 0x3dcbe-0x3dcd1"
|
||||||
|
|
||||||
|
- name: ZXS16.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
max_size: 16384
|
||||||
|
description: "ZX Spectrum 16kB BASIC ROM"
|
||||||
|
note: "Read for the 16kB model under a name of its own, with no fallback to ZXS48.ROM, so the model refuses to start without it however many other ROMs are present. Neither the package nor the desktop distributions carry a copy."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64590-0x645a3, Speccy59-Ubuntu-x86-bin speccy 0x3dca8-0x3dcbb"
|
||||||
|
|
||||||
|
- name: ZXS128.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 32768
|
||||||
|
md5: 85fede415f4294cc777517d7eada482e
|
||||||
|
sha1: 16375d42ea109b47edded7a16028de7fdb3013a1
|
||||||
|
crc32: "2cbe8995"
|
||||||
|
description: "ZX Spectrum 128kB ROM pair"
|
||||||
|
note: "Read as 32768 bytes, two pages. Loaded after ZXS128TR.ROM has been tried when the TR-DOS interface is on as well."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64575-0x6458b, Speccy59-Ubuntu-x86-bin speccy 0x3dc85-0x3dca1"
|
||||||
|
|
||||||
|
- name: ZXS128TR.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 32768
|
||||||
|
md5: 44082607f78a3b643f260b0c7e443bbb
|
||||||
|
sha1: 9b8bc3190086774fe6887e975c81e9976e2711ef
|
||||||
|
crc32: "ce98811c"
|
||||||
|
description: "ZX Spectrum 128kB ROM pair carrying TR-DOS"
|
||||||
|
note: "Tried in place of ZXS128.ROM when the 128kB model and the TR-DOS interface are both asked for, and ZXS128.ROM is loaded in its place when it fails."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x645d9-0x645f5, Speccy59-Ubuntu-x86-bin speccy 0x3ddf0-0x3de10"
|
||||||
|
|
||||||
|
- name: ZXSPLUS2.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 32768
|
||||||
|
md5: 238f77692156a5c49d20c0aa2862e8bb
|
||||||
|
sha1: 8cafb292af58617907b9e6b9093d3588a75849b8
|
||||||
|
crc32: "e7a517dc"
|
||||||
|
description: "ZX Spectrum +2 ROM pair"
|
||||||
|
note: "Read as 32768 bytes for the +2. The +2A bit is cleared ahead of the call whenever the +3 bit is set, so the pair that asks for ZXSPLUS3.ROM cannot leave a second machine standing."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64544-0x6455f, Speccy59-Ubuntu-x86-bin speccy 0x3dc56-0x3dc72"
|
||||||
|
|
||||||
|
- name: ZXSPLUS3.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 65536
|
||||||
|
md5: 7e00ed3562abfd188d0d4da03e80bc0a
|
||||||
|
sha1: 500c0945760abeefcbd08bc22c0d07b14b336cf0
|
||||||
|
crc32: "be0d9ec4"
|
||||||
|
description: "ZX Spectrum +2A and +3 ROM set"
|
||||||
|
note: "Read as 65536 bytes, four pages covering both the +2A and the +3, which the loader asks for under one bit pair."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x6452c-0x6453f, Speccy59-Ubuntu-x86-bin speccy 0x3dc3e-0x3dc51"
|
||||||
|
|
||||||
|
- name: TC2048.ROM
|
||||||
|
system: timex-tc2048
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 16384
|
||||||
|
md5: 9dd7ecf784a6c04265c073c236f5fadb
|
||||||
|
sha1: febb2d495b6eda7cdcb4074935d6e9d9f328972d
|
||||||
|
crc32: "f1b5fa67"
|
||||||
|
description: "Timex Computer 2048 ROM"
|
||||||
|
note: "Read as 16384 bytes for the TC2048. Carried in the packaged filesystem only: the Windows and Ubuntu distributions ship no copy."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x644e4-0x644f7, Speccy59-Ubuntu-x86-bin speccy 0x3dbf6-0x3dc09"
|
||||||
|
|
||||||
|
- name: TS2068.ROM
|
||||||
|
system: timex-ts2068
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 24576
|
||||||
|
md5: 9194283503a105f3f3dfba13e61e993f
|
||||||
|
sha1: 34cd8113bf75b65a4da6eea355f9d46ad635f7e4
|
||||||
|
crc32: "48004230"
|
||||||
|
description: "Timex Sinclair 2068 ROM set"
|
||||||
|
note: "The loader asks for 49152 bytes while the author's own image is 24576, so the read stops short of what was asked and the machine starts anyway. Carried in the packaged filesystem only."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x644cc-0x644df, Speccy59-Ubuntu-x86-bin speccy 0x3dbdd-0x3dbf1"
|
||||||
|
|
||||||
|
- name: DIDAKTIK.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 16384
|
||||||
|
md5: 28287c397defff765b39bd0660da6d01
|
||||||
|
sha1: 8466a9da0169666210ccff5d43376d70bae0ae9b
|
||||||
|
crc32: "45c29401"
|
||||||
|
description: "Didaktik Gama ROM"
|
||||||
|
note: "Read as 16384 bytes for the Slovak Didaktik Gama clone."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x644fc-0x6450f, Speccy59-Ubuntu-x86-bin speccy 0x3dc0e-0x3dc21"
|
||||||
|
|
||||||
|
- name: PENTAGON.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 49152
|
||||||
|
md5: 36e48cd8984702fa9628121f83264ed0
|
||||||
|
sha1: 582254842091d9f6263652f06c6a86bd54dcf736
|
||||||
|
crc32: "e7bbb552"
|
||||||
|
description: "Pentagon 128kB ROM set"
|
||||||
|
note: "Read as 49152 bytes, three pages. The third is copied into the disk interface window once it has loaded, so the Pentagon carries its own TR-DOS and does not need TRDOS.ROM."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64488-0x644c7, Speccy59-Ubuntu-x86-bin speccy 0x3dbb8-0x3dbd7, 0x3de18-0x3de37"
|
||||||
|
|
||||||
|
- name: SCORPION.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 65536
|
||||||
|
md5: b26cba495108d1227aa5124cd9a1456d
|
||||||
|
sha1: 66cecdadf992d8adb9c66deee929eb56600dc9bc
|
||||||
|
crc32: "fef73c28"
|
||||||
|
description: "Scorpion 256kB ROM set"
|
||||||
|
note: "Read as 65536 bytes, four pages, the last copied into the disk interface window. The Scorpion bit also drops every peripheral bit before the first ROM is opened, so its own service ROM stands in place of the separate interfaces."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64444-0x64483, 0x643d5-0x643e3, Speccy59-Ubuntu-x86-bin speccy 0x3db94-0x3dbb2, 0x3de40-0x3de5f"
|
||||||
|
|
||||||
|
- name: COUPE.ROM
|
||||||
|
system: sam-coupe
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
size: 32768
|
||||||
|
md5: 9f40c46cce4008e0548db44f39527914
|
||||||
|
sha1: 58186fd34a8b9c1929913e2b1d7dc4efa507c160
|
||||||
|
crc32: "39ff160a"
|
||||||
|
description: "Sam Coupe ROM"
|
||||||
|
note: "Read as 32768 bytes for the Sam Coupe, which is a machine of its own in the same flag word, so selecting it clears every Spectrum bit and the trapdoor devices are switched off with it."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64514-0x64527, TryLoadROM 0x65a7d-0x65a94, Speccy59-Ubuntu-x86-bin speccy 0x3dc26-0x3dc39, Speccy.html \"Now disabling all trapdoor-based devices in Sam Coupe mode\""
|
||||||
|
|
||||||
|
- name: TRDOS.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 16384
|
||||||
|
md5: 53e2f417c6996df9af170e147df8e369
|
||||||
|
sha1: 282eb7bc819aad2a12fd954e76f7838a4e1a7929
|
||||||
|
crc32: "d8882a8c"
|
||||||
|
description: "Beta Disk TR-DOS interface ROM"
|
||||||
|
note: "Opened first of all, before any machine ROM, and read as 16384 bytes. A failed open drops the interface and leaves the emulation running without it. Its presence is also what makes the 128kB model reach for ZXS128TR.ROM."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x643e6-0x643f7, Speccy59-Ubuntu-x86-bin speccy 0x3db20-0x3db47"
|
||||||
|
|
||||||
|
- name: IF1.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
size: 8192
|
||||||
|
md5: 31b704ae925305e74f50699271fddd9a
|
||||||
|
sha1: 5cfb6bca4177c45fefd571734576b55e3a127c08
|
||||||
|
crc32: "bb66dd1e"
|
||||||
|
description: "Sinclair Interface I ROM"
|
||||||
|
note: "Read as 8192 bytes when the Interface I is on, and dropped silently when it is missing. Snapshots that page it in need it to restore."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x643fc-0x6440f, Speccy59-Ubuntu-x86-bin speccy 0x3db4c-0x3db5f, Speccy.html \"Fixed some .Z80 snapshots not loading when IF1.ROM is missing\""
|
||||||
|
|
||||||
|
- name: DISCIPLE.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
max_size: 16384
|
||||||
|
description: "DISCiPLE disk interface ROM"
|
||||||
|
note: "Read when the DISCiPLE interface is on, up to 16384 bytes, and dropped silently when it is missing. Neither the package nor the desktop distributions carry a copy."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64414-0x64427, Speccy59-Ubuntu-x86-bin speccy 0x3db64-0x3db77"
|
||||||
|
|
||||||
|
- name: PLUSD.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
max_size: 8192
|
||||||
|
description: "MGT +D disk interface ROM"
|
||||||
|
note: "Read when the +D interface is on, up to 8192 bytes, and dropped silently when it is missing. Neither the package nor the desktop distributions carry a copy."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x6442c-0x6443f, Speccy59-Ubuntu-x86-bin speccy 0x3db7c-0x3db8f"
|
||||||
|
|
||||||
|
- name: MF1.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
max_size: 16384
|
||||||
|
description: "Multiface One ROM"
|
||||||
|
note: "Read up to 16384 bytes when the Multiface is on behind a 16kB or 48kB machine, and the 8192 bytes at offset 8192 of what it read are copied into the page below the machine ROM. Dropped silently when it is missing."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x64605-0x64651, Speccy59-Ubuntu-x86-bin speccy 0x3dea8-0x3deb7, 0x3dcf9-0x3dd0b"
|
||||||
|
|
||||||
|
- name: MF128.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
max_size: 16384
|
||||||
|
description: "Multiface 128 ROM"
|
||||||
|
note: "Read up to 16384 bytes when the Multiface is on behind a 128kB or +2 machine, and the 8192 bytes at offset 8192 of what it read are copied into the page below the machine ROM. Dropped silently when it is missing."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x645f7-0x64651, Speccy59-Ubuntu-x86-bin speccy 0x3dcea-0x3dd0b"
|
||||||
|
|
||||||
|
- name: MFPLUS3.ROM
|
||||||
|
system: sinclair-zx-spectrum
|
||||||
|
required: false
|
||||||
|
max_size: 16384
|
||||||
|
description: "Multiface +3 ROM"
|
||||||
|
note: "Read up to 16384 bytes when the Multiface is on behind a +2A or +3 machine, and the 8192 bytes at offset 8192 of what it read are copied into the page below the machine ROM. Dropped silently when it is missing. Neither the package nor the desktop distributions carry a copy."
|
||||||
|
source_ref: "libmain.so LoadBIOS 0x645cb-0x64651, Speccy59-Ubuntu-x86-bin speccy 0x3dee0-0x3dee7, 0x3dcf9-0x3dd0b"
|
||||||
|
|
||||||
|
- name: Speccy.pal
|
||||||
|
required: false
|
||||||
|
unsourceable: "any palette the user writes, in the text format the parser reads"
|
||||||
|
category: game_data
|
||||||
|
description: "startup colour palette"
|
||||||
|
note: "Built as <HomeDir>/Speccy.pal on Android and taken as the bare name beside the binary on the desktop, loaded once the machine has started and left alone when it is absent. The parser reads the file line by line, skipping blanks and comments, so a palette is text rather than a dump, and -palette points the desktop builds at another name or at one of four built-in palettes."
|
||||||
|
source_ref: "libmain.so Application 0x60436-0x60484, StartZXS 0x641c5-0x641d4, LoadPAL 0x648d0-0x64c5a, Speccy59-Ubuntu-x86-bin speccy 0x3f4ac-0x3f4bd, 0x3e450-0x3e560"
|
||||||
|
|
||||||
|
- name: ROOT.chts
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 1652893
|
||||||
|
md5: b41d9ebf814806a25438a6d937804e54
|
||||||
|
sha1: 0b53d51635a2ce3d4e12c2077df9aeffeac02517
|
||||||
|
crc32: "b58e81f1"
|
||||||
|
description: "cheat database read by the Cheatopedia browser"
|
||||||
|
note: "The package ships no cheat set. Cheatopedia looks for the file in the package assets, then in the home directory and its subdirectories, and takes it from Speccy-Cheats.zip in the Downloads directory when that is newer, unpacking it into <HomeDir>/Cheats. The author publishes that archive at fms.komkon.org/EmuAndroid/Speccy-Cheats.zip and states it is what re-enables the cheat features Google Play made him disable in March 2019; the copy read here holds this one file."
|
||||||
|
source_ref: "CheatHelper.java:17-67, Cheatopedia.java:397-427, EmuAndroid \"Cheats support\""
|
||||||
|
|
||||||
|
- name: Controls.png
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
size: 22587
|
||||||
|
md5: d10635cb6f101ed733f3d1133bc78f61
|
||||||
|
sha1: 14c4ab8ccc8ecb81ebf99fec336a3e872c13aabc
|
||||||
|
crc32: "dc9da322"
|
||||||
|
description: "virtual joystick skin"
|
||||||
|
note: "Read as <HomeDir>/Controls.png by the overlay button loader and by the layout editor. The author publishes the template to draw over at fms.komkon.org/EmuAndroid/Controls.png."
|
||||||
|
source_ref: "MainActivity.java:1100, LayoutEditor.java:415"
|
||||||
|
|
||||||
|
- name: Backdrop.png
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
unsourceable: "any picture the user places behind the emulated screen"
|
||||||
|
description: "backdrop drawn around the emulated screen"
|
||||||
|
note: "Read as <HomeDir>/Backdrop.png. A built-in drawable stands in when the file is absent."
|
||||||
|
source_ref: "MainActivity.java:1287-1292"
|
||||||
|
|
||||||
|
- name: "<game>.back.png"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
unsourceable: "any picture the user places behind one title"
|
||||||
|
description: "backdrop for one title"
|
||||||
|
note: "Named from the loaded program's path and preferred over the shared backdrop for that game."
|
||||||
|
source_ref: "MainActivity.java:1287-1292"
|
||||||
|
|
||||||
|
- name: "<game>.pok"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
unsourceable: "POKEs the user writes or collects per title"
|
||||||
|
description: "POKE list for one title"
|
||||||
|
note: "Named from the loaded program's path and read by LoadPOK when present."
|
||||||
|
source_ref: "libmain.so LoadFile 0x65569-0x6558b, LoadPOK 0x692c0"
|
||||||
|
|
||||||
|
- name: "<game>.cht"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
unsourceable: "cheat codes the user writes or collects per title"
|
||||||
|
description: "cheat codes for one title"
|
||||||
|
note: "Named from the loaded program's path and read by LoadCHT when present. Distinct from the .chts sets of the Cheatopedia browser."
|
||||||
|
source_ref: "libmain.so LoadFile 0x65590-0x655b2, LoadCHT 0x696a0"
|
||||||
|
|
||||||
|
- name: "<game>.pal"
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
unsourceable: "any palette the user writes for one title"
|
||||||
|
description: "colour palette for one title"
|
||||||
|
note: "Named from the loaded program's path and read by LoadPAL when present, taking effect over the startup palette for that program."
|
||||||
|
source_ref: "libmain.so LoadFile 0x655b7-0x655d1, LoadPAL 0x648d0"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
Left out are the files Speccy writes and reads back itself, which are emulator
|
||||||
|
state rather than anything a user obtains: <game>.sta holding saved emulation
|
||||||
|
state, which LoadFile restores ahead of everything else it derives from the
|
||||||
|
program path, LOG.MID holding the MIDI soundtrack the recorder writes,
|
||||||
|
<HomeDir>/PrinterOutput.txt holding what the ZX and Timex printers print, and
|
||||||
|
the replay files of the instant replay recorder. Snapshots, tapes, disk images
|
||||||
|
and screens are the user's own content: .z80, .sna, .szx, .scs, .tap, .tzx,
|
||||||
|
.trd, .scl, .fdi, .dsk, .mgt, .sad and .scr all reach LoadFile, and the
|
||||||
|
emulator writes most of them back. DEFAULT.Z80 is only the name the desktop builds
|
||||||
|
fall back to when they are started with no file at all. names.dat is left out
|
||||||
|
because the path is dead in this build: FileInfo opens assets/names.dat and
|
||||||
|
<HomeDir>/names.dat inside one try block, and no split of the package carries
|
||||||
|
that asset, so the failed asset read takes the home directory copy down with
|
||||||
|
it. changelog.html is left out as the release history shown from the menu, read
|
||||||
|
from the package assets and from nowhere else. The Android audio and graphics
|
||||||
|
libraries the loader opens by name are provided by the system.
|
||||||
|
ref: libmain.so LoadFile 0x65380-0x655d1 (0x65482-0x654d4), STAName 0x97ad0,
|
||||||
|
SndName 0x93970, StartZXS 0x64180-0x6418a, Application 0x603e0-0x6042d,
|
||||||
|
LoadRPL 0x80040, SaveRPL 0x7fc80, SaveSCR 0x69e70,
|
||||||
|
FileInfo.java:244-257, EMULib.java:1038, 1067,
|
||||||
|
Speccy59-Ubuntu-x86-bin speccy 0xbf50,
|
||||||
|
Speccy.html "[filename] = Name of the file to load [DEFAULT.Z80]"
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
emulator: SSF
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://github.com/shimazzz/SEGASaturnEmulator-SSF"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "Shima"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "PreviewVer R38"
|
||||||
|
display_name: "Sega - Saturn/ST-V (SSF)"
|
||||||
|
cores:
|
||||||
|
- ssf
|
||||||
|
systems:
|
||||||
|
- sega-saturn
|
||||||
|
- sega-stv
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Sega Saturn and ST-V emulator by Shima, closed source and distributed as a
|
||||||
|
binary. Two artifacts are read here and they describe the same emulator: the
|
||||||
|
Windows build SSF_PreviewVer_R38.zip of 2026-01-01, sha256
|
||||||
|
7325a9b9d666560ddf632f747fb42ab880f82c45391e51fe0716beb1c535f00b, whose
|
||||||
|
emulator is the 64-bit SSF.exe and which is cited by virtual address; and the
|
||||||
|
Android build SSF_AndroidVer.zip of 2022-08-07, package
|
||||||
|
com.xrea.g2.aaaaaaaa.ssf, whose lib/arm64-v8a/libnative-lib.so keeps its 40738
|
||||||
|
dynamic symbols and which is cited by symbol. Prose references name the
|
||||||
|
Japanese documentation shipped in Document/.
|
||||||
|
|
||||||
|
Every path below is stored in full in SSF.ini and picked through a file dialog
|
||||||
|
filtered on "all files (*.*)". SSF fixes no filename and no directory for any
|
||||||
|
of them and looks for none, so the names used here are the dumps that fill
|
||||||
|
each slot rather than names the code searches.
|
||||||
|
|
||||||
|
Saturn BIOS, [Peripheral] SaturnBIOS. Readme.txt describes the image as the
|
||||||
|
console address range 00000000-0007FFFF and states that the filename is free.
|
||||||
|
Neither a length nor a hash is compared against the file. The one routine that
|
||||||
|
walks the 512 KiB BIOS area is CStateSaveBase::_GetBIOSHash, which folds it
|
||||||
|
into the checksum pair that tags a save state.
|
||||||
|
|
||||||
|
Running without it is a supported mode, [Program4] NoBIOS. SSF carries a boot
|
||||||
|
ROM of its own, an embedded program with the SYS_* system calls and the
|
||||||
|
interrupt vectors, and in that mode the backup library is always hooked.
|
||||||
|
Readme.txt records lower compatibility and advises supplying a BIOS.
|
||||||
|
|
||||||
|
ST-V is entered by holding left Shift at launch. [Peripheral] STVBIOS names
|
||||||
|
the motherboard EPROM, and both the option reference and the No BIOS entry of
|
||||||
|
Readme.txt state that ST-V does not run without it.
|
||||||
|
|
||||||
|
ST-V cartridges are the game and are read from a ZIP: the loader takes the
|
||||||
|
extension of each member as its IC number, accepts 1 through 13, byte-swaps
|
||||||
|
every mask ROM in 16-bit units, doubles each byte of the IC13 EPROM across the
|
||||||
|
16-bit bus, then mirrors each chip over its window. IC7 and IC13 are
|
||||||
|
exclusive. STV_ROM.html gives the same layout and notes that MAME ROM sets fit
|
||||||
|
once the extensions are changed.
|
||||||
|
|
||||||
|
Cheat scripts live in Cheat/ under the disc product number. Six ship with the
|
||||||
|
emulator and the memory cheat dialog writes more.
|
||||||
|
|
||||||
|
Everything else the binary opens it also writes: SSF.ini, Setting.ini,
|
||||||
|
Setting/, Backup/, StateSave/, CDIndex/, Snapshot/, Wave/, ExtractSound/,
|
||||||
|
DebugData/, and the LLVM/ object cache that the bundled CreateObject.exe and
|
||||||
|
clang.exe compile from the user's own disc for the local CPU.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: "sega_101.bin"
|
||||||
|
aliases:
|
||||||
|
- mpr-17933.bin
|
||||||
|
- sega_100.bin
|
||||||
|
- sega_100a.bin
|
||||||
|
- sega1003.bin
|
||||||
|
- hisaturn.bin
|
||||||
|
- vsaturn.bin
|
||||||
|
system: sega-saturn
|
||||||
|
required: false
|
||||||
|
hle_fallback: true
|
||||||
|
size: 524288
|
||||||
|
description: "Saturn BIOS"
|
||||||
|
note: "Any dump of the 512 KiB console ROM, the compatible machines included. Area code is chosen by [Peripheral] Areacode and AutoAreacode, not by the image, so no region selects this file."
|
||||||
|
source_ref: "SSF.exe 0x43d770 (SaturnBIOS 0x129b1f8), SSF.exe 0x129a2f8 with the filter at 0x129a310, SSF.exe 0x43ff96 (NoBIOS 0x129b4cc), libnative-lib.so SSF::CStateSaveBase::_GetBIOSHash 0x134b8ec-0x134b924, Document/Readme.txt BIOSファイルについて"
|
||||||
|
|
||||||
|
- name: "epr-20091.ic8"
|
||||||
|
aliases:
|
||||||
|
- epr-23603.ic8
|
||||||
|
- epr-19730.ic8
|
||||||
|
- epr-19854.ic8
|
||||||
|
- epr-17951a.ic8
|
||||||
|
- epr-17952a.ic8
|
||||||
|
- epr-17953a.ic8
|
||||||
|
- epr-17954a.ic8
|
||||||
|
- epr-17740.ic8
|
||||||
|
- epr-17740a.ic8
|
||||||
|
- epr-17741a.ic8
|
||||||
|
- epr-17742a.ic8
|
||||||
|
system: sega-stv
|
||||||
|
required: true
|
||||||
|
size: 524288
|
||||||
|
description: "ST-V BIOS"
|
||||||
|
note: "Loose 512 KiB EPROM image, read outside the cartridge ZIP. Any of the board revisions is accepted, the code branching on none of them."
|
||||||
|
source_ref: "SSF.exe 0x43d91f (STVBIOS 0x129b218), SSF.exe 0x129a328, Document/Readme.txt ST-V BIOS option, Document/Readme.txt No BIOS option"
|
||||||
|
|
||||||
|
- name: "<cartridge>.bin"
|
||||||
|
system: sega-saturn
|
||||||
|
required: false
|
||||||
|
category: game_data
|
||||||
|
description: "cartridge image mapped at A-Bus CS0"
|
||||||
|
note: "[Peripheral] DataCartridge, gated by DataCartridgeEnable and off by default. SSF reads the file at the configured path into the 32 MiB A-Bus CS0 window and identifies it in no way; the dumps that belong there are the two Saturn ROM carts, mpr-18811-mx.ic1 for The King of Fighters '95 and mpr-19367-mx.ic1 for Ultraman. Readme.txt records the option as unverified."
|
||||||
|
source_ref: "SSF.exe 0x43e26b (DataCartridge 0x1298838), SSF.exe 0x43e178 (DataCartridgeEnable 0x1298820), SSF.exe 0x129a340, SSF.exe 0x916e5e-0x916e84, Document/Readme.txt Data Cartridge option"
|
||||||
|
|
||||||
|
- name: "<name>.cht"
|
||||||
|
path: "Cheat/<product id>/<name>.cht"
|
||||||
|
system: sega-saturn
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
description: "cheat script"
|
||||||
|
note: "Read when [Program4] EnableCheat is set, from the directory named after the disc product number. The format is a script language: triggers on first read, field, file, sector, CDDA and scanline, memory reads and writes, storage slots, branches and labels. Six ship with the emulator; the memory cheat dialog saves its own with the target address in the name."
|
||||||
|
source_ref: "SSF.exe 0x4403c0 (EnableCheat 0x1298de0), SSF.exe 0x12998a0, SSF.exe 0x129a658, SSF.exe command table 0x128c570-0x128c808"
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
emulator: Starboard
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://github.com/get-starboard/starboard"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "force9"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "0.23.0"
|
||||||
|
display_name: "PortMaster library (Starboard)"
|
||||||
|
verification: existence
|
||||||
|
cores:
|
||||||
|
- starboard
|
||||||
|
- STARBOARD
|
||||||
|
- org.force9.starboard
|
||||||
|
systems: []
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Catalogue manager and execution environment for the PortMaster library on
|
||||||
|
Android ARM64 handhelds. PortMaster ports are Linux ARM64 builds, so nothing
|
||||||
|
is emulated: proot opens a userspace chroot into a Debian bookworm root
|
||||||
|
filesystem and the games run there as native binaries against glibc, SDL2 and
|
||||||
|
Mesa. ES-DE reaches it through the ports system, passing a .port file as the
|
||||||
|
port_file extra to org.force9.starboard/.ui.game.GameActivity.
|
||||||
|
|
||||||
|
The build read here is the signed release Starboard-v0.23.0.apk, sha256
|
||||||
|
a81b69d471ee88ad6c47497e616c5a7c68bf8ebfb32bc7ae9348ed46c3190b3d, matching the
|
||||||
|
digest GitHub records for the asset. The source is not published, so the
|
||||||
|
readings below cite a jadx decompilation of classes.dex taken with
|
||||||
|
--show-bad-code, where org.force9.starboard.* keeps its names and the rest is
|
||||||
|
r8 output under defpackage.
|
||||||
|
|
||||||
|
The APK carries its own execution stack in lib/arm64-v8a: libproot.so,
|
||||||
|
libproot_loader.so and libtalloc2.so mirrored from Termux through
|
||||||
|
get-starboard/starboard-prebuilts, libSDL2_starboard.so preloaded ahead of the
|
||||||
|
SDL2 in the rootfs, libasound_module_pcm_starboard.so as the ALSA output
|
||||||
|
plugin, libGLESv2_wrap.so with libvirgl_vtest.so and libvirglrenderer_sb.so
|
||||||
|
for the per-port GPU path, libandroid-shmem.so, and libgame_bridge.so which
|
||||||
|
starts proot and builds the PortMaster environment. Android installs all of
|
||||||
|
them with the package.
|
||||||
|
|
||||||
|
What the ports find under /opt/system/Tools/PortMaster is written at launch by
|
||||||
|
libgame_bridge.so: bind_directories.sh, patch_ld_preload.sh,
|
||||||
|
seed_retroarch_cfg.sh and launcher.sh under /tmp/sb, the gptokeyb shim,
|
||||||
|
runtimes.json, control.txt and device_info.txt, with etc/resolv.conf and
|
||||||
|
etc/hosts seeded straight after extraction. The ES-DE sync writes the .port
|
||||||
|
files it later launches from, each holding a zip_name and a launcher key,
|
||||||
|
along with a ports entry in custom_systems/es_systems.xml and
|
||||||
|
gamelists/ports/gamelist.xml.
|
||||||
|
|
||||||
|
Games install to Starboard/ports on shared storage, marked by a
|
||||||
|
.starboard_installed file, and come from the PortMaster catalogue rather than
|
||||||
|
from this profile. A port that declares a runtime pulls a squashfs image into
|
||||||
|
opt/system/Tools/PortMaster/libs inside the rootfs on first launch, named by
|
||||||
|
the port and resolved through the utils index of PortsMaster/PortMaster-New
|
||||||
|
filtered to arch aarch64. Starboard names no runtime of its own and that index
|
||||||
|
is republished with the catalogue, so the set belongs to PortMaster.
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: starboard-rootfs.tar.gz
|
||||||
|
aliases:
|
||||||
|
- rootfs.tar.gz
|
||||||
|
path: "rootfs.tar.gz"
|
||||||
|
required: true
|
||||||
|
category: game_data
|
||||||
|
validation: [sha256]
|
||||||
|
size: 582086462
|
||||||
|
sha256: "a40dd11b24802325b37ab6454feb5fda84a6f1de9d769c84a2dd7b6fee8035e1"
|
||||||
|
unsourceable: "runtime image the app fetches into its own cache and unpacks into internal storage, leaving no path a user or a pack can write"
|
||||||
|
description: "Debian bookworm ARM64 root filesystem the ports execute in"
|
||||||
|
note: >-
|
||||||
|
Fetched from releases/latest/download of get-starboard/starboard-runtime,
|
||||||
|
written to the cache directory as rootfs.tar.gz, gunzipped into a rootfs
|
||||||
|
directory under internal storage, then deleted. Nothing launches without
|
||||||
|
it: the gate reads usr/bin/env and bin/sh in the extracted tree beside
|
||||||
|
libproot.so in the native library directory. Integrity comes from a
|
||||||
|
.sha256 sidecar requested next to the asset, whose first whitespace token
|
||||||
|
must be 64 hex characters; the file is hashed and dropped on a mismatch,
|
||||||
|
while a missing sidecar logs "No rootfs checksum sidecar available" and the
|
||||||
|
download is kept on TLS trust alone, which is what happens today since that
|
||||||
|
sidecar answers 404. The size and hash recorded here identify release
|
||||||
|
starboard-rootfs-20260604.1, the one that URL served at profiling time, and
|
||||||
|
the app follows whatever release is latest. Its own version is read back
|
||||||
|
from etc/starboard-release, which carries release, commit and built keys.
|
||||||
|
source_ref: "Starboard 0.23.0 ze0.java:75,421-422 (base and asset URL), xe0.java:66-70 (download, verify, extract, delete), ze0.java:236-342 (sha256 sidecar and comparison), ze0.java:130-144 (gunzip into place), ze0.java:416-418 (install directory), ze0.java:426-428 and t20.java:125 (launch gate), ze0.java:439-463 (etc/starboard-release)"
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
emulator: SUPER3
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/izzy2lost/Super3"
|
||||||
|
upstream: "https://github.com/trzy/Supermodel"
|
||||||
|
based_on: "Supermodel 0.3a through the arm branch of DirtBagXon/model3emu-code-sinden at fa1e305"
|
||||||
|
author: "izzy2lost"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "b435c80a88fd496d4a9858be0681260e84342c85"
|
||||||
|
core_version: "1.2.1"
|
||||||
|
display_name: "Sega - Model 3 (SUPER3)"
|
||||||
|
verification: existence
|
||||||
|
cores:
|
||||||
|
- super3
|
||||||
|
- SUPER3
|
||||||
|
- com.izzy2lost.super3
|
||||||
|
systems:
|
||||||
|
- sega-model3
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Sega Model 3 emulator for Android, package com.izzy2lost.super3, versionName 1.2.1
|
||||||
|
versionCode 22, arm64-v8a alone, minSdk 26 and targetSdk 36, GPL-3.0 with the tree in
|
||||||
|
the open. A Kotlin front end carries the launcher, setup wizard, ini editor and save
|
||||||
|
state browser over the Supermodel core, built through CMake against SDL2 with an
|
||||||
|
OpenGL ES presenter of its own. The core states its own lineage: SUPERMODEL_VERSION
|
||||||
|
reads "0.3a-fa1e305-arm-mm DirtBagXon (Sinden)", and the app names both sources it
|
||||||
|
draws on, so the emulator is Supermodel 0.3a as carried by the arm branch of
|
||||||
|
DirtBagXon/model3emu-code-sinden at fa1e305, "Add ManyMouse License" of 2025-07-28.
|
||||||
|
No upstream commit is pinned because neither this repo nor that fork shares git
|
||||||
|
history with trzy/Supermodel: both report themselves as independent repositories and
|
||||||
|
a comparison against trzy/Supermodel has no merge base. ES-DE reaches the app through
|
||||||
|
its SUPER3 find rule, on Android alone among the seven find rule sets, starting
|
||||||
|
MainActivity with an intent VIEW whose data is the storage framework URI of the game.
|
||||||
|
ref: android/app/build.gradle.kts:22-36, Src/Version.h:32, README.md:3-4,
|
||||||
|
android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt:453-463,
|
||||||
|
es-de resources/systems/android/es_find_rules.xml:552-557,
|
||||||
|
es-de resources/systems/android/es_systems.xml:1091
|
||||||
|
|
||||||
|
The Android build compiles a subset of the tree, which decides where a load path can
|
||||||
|
be read. The CMake source list globs Src/ and then drops all of Src/OSD/ and all of
|
||||||
|
Src/Graphics/ twice over, by regex and again by an explicit removal loop, adding back
|
||||||
|
only a named list of Src/Graphics/New3D files. So the desktop SDL frontend is absent
|
||||||
|
from this binary: Src/OSD/SDL/Main.cpp holds the command line and its own config file
|
||||||
|
handling, Src/OSD/SDL/SDLInputSystem.cpp its own controller database call, and
|
||||||
|
Src/Graphics/Shader.cpp the loader for external GLSL files, and none of the three is
|
||||||
|
built here. The paths below are the ones this build actually runs.
|
||||||
|
ref: android/app/src/main/cpp/CMakeLists.txt:32-91, 135-158
|
||||||
|
|
||||||
|
One directory holds everything the emulator reads. MainActivity hands the native side
|
||||||
|
a user data root of getExternalFilesDir(null)/super3, so
|
||||||
|
/storage/emulated/0/Android/data/com.izzy2lost.super3/files/super3, and
|
||||||
|
SetUserDataRoot creates it and changes into it, which is what makes the relative names
|
||||||
|
below resolve. AssetInstaller copies five trees out of the package assets into that
|
||||||
|
root before every launch, Assets, Config, GraphicsAnalysis, NVRAM and Saves, never
|
||||||
|
overwriting a file that is already there, so the emulator always finds its own
|
||||||
|
configuration whatever the user has done. The native entry point also probes
|
||||||
|
<root>/super3/Games.xml over external storage, internal storage, /storage/emulated/0
|
||||||
|
and /sdcard when no path is passed, but the front end always passes one, along with
|
||||||
|
the ROM path, the game name and the user data root as its four arguments.
|
||||||
|
ref: android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt:501-503,
|
||||||
|
1155-1161, 1209-1222,
|
||||||
|
android/app/src/main/java/com/izzy2lost/super3/AssetInstaller.kt:7-18,
|
||||||
|
android/app/src/main/cpp/native-lib.cpp:247-260, 1080-1117,
|
||||||
|
android/app/src/main/java/com/izzy2lost/super3/Super3Activity.kt:99-111
|
||||||
|
|
||||||
|
Model 3 boards carry no shared system BIOS and this emulator loads none. Every byte
|
||||||
|
the machine needs comes out of the per-game MAME format zip: the program ROMs, the
|
||||||
|
video ROMs, the sound program and samples, and where the board has them the drive
|
||||||
|
board program, the MPEG program and the MPEG music, all declared as regions of one
|
||||||
|
game in Games.xml. The set is identified by the basename of the zip, not by a scan,
|
||||||
|
and the ErrorLog asks for an appropriately named archive when no game answers to that
|
||||||
|
name; the individual members are then matched by name or by crc32. A child set names a
|
||||||
|
parent and the loader opens <same directory>/<parent>.zip for the rest of its regions,
|
||||||
|
which the front end prepares for by walking the parent chain and staging every zip it
|
||||||
|
names into romcache, refusing to start and naming what is missing when one cannot be
|
||||||
|
found. This Games.xml declares 63 games with 41 of those lines naming a parent, every
|
||||||
|
named parent itself a game, and not one non-game or BIOS set among them.
|
||||||
|
ref: Src/GameLoader.cpp:873-928, 882-890, 913-921, 148-153,
|
||||||
|
Src/Model3/Model3.cpp:2919-2933,
|
||||||
|
android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt:1163-1208,
|
||||||
|
Config/Games.xml
|
||||||
|
|
||||||
|
Three files ship inside the package and are read from Config/ at runtime. Games.xml is
|
||||||
|
the one the emulator cannot do without: InitLoader tests for it and returns failure
|
||||||
|
when it is absent, which leaves the loading thread in its failed state and no game
|
||||||
|
running. Supermodel.ini and gamecontrollerdb.txt are both skipped when they are
|
||||||
|
missing, on built-in defaults in the first case and SDL's built-in controller mappings
|
||||||
|
in the second. Nothing about any of the three is verified: no length is compared and
|
||||||
|
no hash is computed, the only tests being that the file is there and that it parses.
|
||||||
|
ref: android/app/src/main/cpp/native-lib.cpp:531-538, 568-580, 1123-1135,
|
||||||
|
android/app/src/main/cpp/android_input_system.cpp:291-311,
|
||||||
|
Src/Util/ConfigBuilders.cpp:60-73, 134-142
|
||||||
|
|
||||||
|
Two files that AssetInstaller lands are read by nothing in this build.
|
||||||
|
Config/Music.xml declares substitute MPEG tracks for DSB1 and DSB2 games, and neither
|
||||||
|
its own name nor the attributes it is written in appear anywhere in the tree, nor any
|
||||||
|
handling of mp2 or mp3 files: the DSB reads its music from the mpeg_music region of
|
||||||
|
the game zip and from nowhere else. Assets/p1crosshair.bmp and Assets/p2crosshair.bmp
|
||||||
|
are documented by the inherited Manual for a crosshair-style option that does not
|
||||||
|
exist here, and the tree holds no bitmap reader at all, Src/Util/BMPFile.h being a
|
||||||
|
writer; the Crosshairs setting is a two bit mask and the presenter draws the crosshair
|
||||||
|
as geometry. A build that wires either feature up would turn these into files to
|
||||||
|
collect.
|
||||||
|
ref: android/app/src/main/assets/Config/Music.xml, Manual.txt:99-102,
|
||||||
|
Src/Model3/Model3.cpp:2932, Src/Util/BMPFile.h:391,
|
||||||
|
android/app/src/main/cpp/native-lib.cpp:763-772, 909-976,
|
||||||
|
android/app/src/main/cpp/gles_presenter.cpp:364-369
|
||||||
|
|
||||||
|
The rest of the tree is written, not read. NVRAM/<game>.nv is created on exit and read
|
||||||
|
back on the next launch of the same game, Saves/ holds the ten save state slots and
|
||||||
|
their screenshots, romcache/ holds the staged copies of the user's own archives, and
|
||||||
|
Flyers/ is filled on request from the GitHub contents API of izzy2lost/Model3flyers
|
||||||
|
for the artwork in the launcher list. An optional sync copies NVRAM, Saves, Config and
|
||||||
|
Flyers between the internal root and a folder the user picks in the system picker.
|
||||||
|
ref: android/app/src/main/cpp/native-lib.cpp:262-313, 793-797,
|
||||||
|
android/app/src/main/java/com/izzy2lost/super3/FlyerRepoSync.kt:16-46,
|
||||||
|
android/app/src/main/java/com/izzy2lost/super3/UserDataSync.kt:10-25
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: Games.xml
|
||||||
|
path: "Config/Games.xml"
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Installed from the package assets on every launch and never obtained separately"
|
||||||
|
size: 154928
|
||||||
|
md5: fc26e2deaa532794d91fe33ca73f8e2c
|
||||||
|
sha1: b41150f8cff409dde89939b80a980a20e853df0b
|
||||||
|
crc32: "b2ea6948"
|
||||||
|
description: "Game and ROM set definitions"
|
||||||
|
note: >-
|
||||||
|
The ROM set database, 63 games, giving for each one the regions to fill and the
|
||||||
|
name and crc32 of every file that fills them, the stepping, the PCI bridge, the
|
||||||
|
encryption key, the drive board, net board and MPEG board the machine carries, the
|
||||||
|
patches to apply and the parent set to fall back on. Handed to the GameLoader
|
||||||
|
constructor, parsed as XML, and a game load is refused outright when the file is
|
||||||
|
not there. The Kotlin launcher parses the same copy out of the assets for its game
|
||||||
|
list and its per-game input hints. Byte identical to the copy in the repository
|
||||||
|
root Config directory.
|
||||||
|
source_ref: "android/app/src/main/cpp/native-lib.cpp:568-580, 1096-1114, Src/GameLoader.cpp:492-502, 930-933, Src/Util/ConfigBuilders.cpp:60-73, android/app/src/main/java/com/izzy2lost/super3/GameXml.kt:23-24, android/app/src/main/java/com/izzy2lost/super3/MainActivity.kt:1211"
|
||||||
|
|
||||||
|
- name: Supermodel.ini
|
||||||
|
path: "Config/Supermodel.ini"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Installed from the package assets on every launch and rewritten in place by the app"
|
||||||
|
size: 6887
|
||||||
|
md5: a468e45e005caa89356bd67b70e0d37d
|
||||||
|
sha1: 6c38cc6fba14863bfbdc730e53d3274fd79a4544
|
||||||
|
crc32: "2d012d14"
|
||||||
|
description: "Input and per-game settings"
|
||||||
|
note: >-
|
||||||
|
Read after the built-in defaults have been applied, the Global section first and
|
||||||
|
then the section named after the loaded game, each merged over what is already
|
||||||
|
set; a file that is absent or unparseable leaves the defaults standing. The hashes
|
||||||
|
are those of the copy in the package assets, which is not the 13290 byte copy in
|
||||||
|
the repository root Config directory: the Android build ships its own. They
|
||||||
|
describe the file as shipped, since AssetInstaller rewrites it on first run,
|
||||||
|
substituting the Android control defaults, and the in-app editor writes per-game
|
||||||
|
keys such as LegacyReal3DTiming afterwards.
|
||||||
|
source_ref: "android/app/src/main/cpp/native-lib.cpp:531-566, 620-621, Src/Util/ConfigBuilders.cpp:134-142, android/app/src/main/java/com/izzy2lost/super3/AssetInstaller.kt:17, 43-159, android/app/src/main/java/com/izzy2lost/super3/Super3Activity.kt:880-884"
|
||||||
|
|
||||||
|
- name: gamecontrollerdb.txt
|
||||||
|
path: "Config/gamecontrollerdb.txt"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Installed from the package assets on every launch and never obtained separately"
|
||||||
|
size: 587398
|
||||||
|
md5: e8da2d033e90d6fefa884ee78690b4e0
|
||||||
|
sha1: cb6be8206308470ecaa8b9cc882d82abe0ef3562
|
||||||
|
crc32: "94468d79"
|
||||||
|
description: "SDL controller mapping database"
|
||||||
|
note: >-
|
||||||
|
Opened once, on the first pad the input system sees, and handed to SDL as mappings
|
||||||
|
to add. The name is fixed unless the ini key SDLGameControllerDB carries a path of
|
||||||
|
its own, and a handle that cannot be opened is passed over, leaving SDL on its
|
||||||
|
built-in mappings. Byte identical to the copy in the repository root Config
|
||||||
|
directory.
|
||||||
|
source_ref: "android/app/src/main/cpp/android_input_system.cpp:291-311, 207-213"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
No BIOS or firmware file is loaded. Sega Model 3 hardware has no shared system ROM:
|
||||||
|
each board carries its own program, video, sound and where fitted drive board, MPEG
|
||||||
|
program and MPEG music ROMs, and every one of them reaches the emulator as a region of
|
||||||
|
a per-game MAME format zip declared in Games.xml, a child set drawing its remaining
|
||||||
|
regions from its parent's zip in the same directory. The three files listed above are
|
||||||
|
the emulator's own configuration, reinstalled from the package assets before every
|
||||||
|
launch. Config/Music.xml and the two crosshair bitmaps in Assets are shipped by the
|
||||||
|
package as well and read by no code in this build.
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
emulator: Supermodel Dojo
|
||||||
|
type: standalone
|
||||||
|
core_classification: enhanced_fork
|
||||||
|
source: "https://github.com/blueminder/supermodel-dojo"
|
||||||
|
upstream: "https://github.com/trzy/Supermodel"
|
||||||
|
author: "blueminder"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "ff8cde225298fe5c4ad47fba3c581b2cd19ffc41"
|
||||||
|
upstream_commit: "77d28eec84a5ededaa23bb31bc74db631cbe5530"
|
||||||
|
core_version: "dojo-preview6"
|
||||||
|
display_name: "Sega - Model 3 (Supermodel Dojo)"
|
||||||
|
verification: existence
|
||||||
|
cores:
|
||||||
|
- supermodel-dojo
|
||||||
|
systems:
|
||||||
|
- sega-model3
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Fork of Supermodel adding delay based netplay, session replay with mid replay
|
||||||
|
takeover, a training mode, and a launcher binary built from Frontend/. The
|
||||||
|
emulator side is upstream merged forward: the dojo branch takes trzy/Supermodel
|
||||||
|
at 77d28ee of 2026-05-28 through merge 627f023, and the commits after it are
|
||||||
|
launcher fixes. The two repositories are not linked on GitHub, so the pin is
|
||||||
|
read from the merge itself, whose second parent 77d28ee resolves in both trees
|
||||||
|
while the first does not.
|
||||||
|
ref: README.md:4-20, Makefiles/Rules.inc:179-186
|
||||||
|
|
||||||
|
Windows and macOS return relative names, Config/, Assets/, NVRAM/, Saves/,
|
||||||
|
resolved against the working directory, which is where the release archive puts
|
||||||
|
them and where ES-DE starts the process. Linux uses the working directory when
|
||||||
|
no home directory resolves, $HOME/.supermodel-dojo/<dir> when that directory
|
||||||
|
exists, otherwise $HOME/.config/supermodel-dojo/Config and
|
||||||
|
$HOME/.local/share/supermodel-dojo/<dir> under the XDG variables, and falls back
|
||||||
|
to the Config/Games.xml and Assets/ sitting next to the binary when the home copy
|
||||||
|
is absent. Replays/ is a path type there and a working directory folder on Windows.
|
||||||
|
ref: Src/OSD/Windows/FileSystemPath.cpp:28-56, Src/OSD/OSX/FileSystemPath.cpp:28-54,
|
||||||
|
Src/OSD/Unix/FileSystemPath.cpp:63-77, 127-138, 141-195, Src/Dojo/Replay.cpp:24-30,
|
||||||
|
es-de resources/systems/windows/es_systems.xml:171
|
||||||
|
|
||||||
|
ROM sets are MAME format per game archives identified by the CRC32 values in
|
||||||
|
Games.xml, 63 sets at this revision. A parent set holds the ROMs a regional
|
||||||
|
variant reuses, a relation between versions of one game rather than a shared
|
||||||
|
BIOS: a split child archive makes the loader open <parent>.zip from the same
|
||||||
|
directory. Each Model 3 board carries its own program, video, sound and drive
|
||||||
|
board ROMs, so no system ROM is read outside those archives.
|
||||||
|
ref: Config/Games.xml, Src/GameLoader.cpp:325-560, Src/GameLoader.cpp:979-1010
|
||||||
|
|
||||||
|
The emulator writes and reads back its own Supermodel.ini, generated from the
|
||||||
|
built in Dojo defaults whenever it is absent, plus NVRAM/<game>.nv,
|
||||||
|
Saves/<game>.st<slot> and Replays/<game>_<timestamp>.supr with a .st0 sidecar
|
||||||
|
when the session starts from a save state.
|
||||||
|
ref: Src/OSD/SDL/Main.cpp:1572-1592, 2425, 713-741, 775-798,
|
||||||
|
Src/OSD/DojoConfigFile.h:31, Src/Dojo/Replay.cpp:19-50
|
||||||
|
|
||||||
|
Two reads take a path the user chooses and have no fixed name: the MP3 tracks
|
||||||
|
named inside Music.xml, and external GLSL vertex and fragment shaders for the
|
||||||
|
legacy 3D engine, whose config keys are empty by default so the built in shader
|
||||||
|
source is compiled instead.
|
||||||
|
ref: Src/Sound/MPEG/MpegAudio.cpp:71-86, Src/OSD/SDL/Main.cpp:1692-1693,
|
||||||
|
Src/Graphics/Shader.cpp:93-99
|
||||||
|
|
||||||
|
The repository publishes two release trains. The Dojo builds carry the
|
||||||
|
dojo-preview tags, Preview 6 of 2025-04-27 being the current one, and ship
|
||||||
|
supermodel.exe, the dojo.exe launcher, Assets/ and Config/. The
|
||||||
|
v0.3a-<date>-git-<rev> releases come from a workflow that fires only on the
|
||||||
|
master branch, which tracks upstream: the archive of 2026-06-25 holds Games.xml,
|
||||||
|
Music.xml and both crosshair names in its binary and none of the Dojo strings.
|
||||||
|
A build stamps its version from the commit date and short sha, and the tree
|
||||||
|
falls back to 0.3a-WIP.
|
||||||
|
ref: .github/workflows/release.yml:4-5, .github/workflows/release.yml:21,
|
||||||
|
Makefiles/Rules.inc:289-291, Src/Version.h:32
|
||||||
|
|
||||||
|
ES-DE reaches it through the SUPERMODEL-DOJO find rule, present in the Windows
|
||||||
|
set alone among the seven, for the arcade, mame and model3 systems.
|
||||||
|
ref: es-de resources/systems/windows/es_find_rules.xml:1107-1116,
|
||||||
|
es-de resources/systems/windows/es_systems.xml:171, 1068, 1220
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: Games.xml
|
||||||
|
path: "Config/Games.xml"
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
description: "ROM set definitions"
|
||||||
|
note: "Parsed at startup into the game database. Every ROM region, file name and CRC32 the loader matches against comes from here, so an unreadable file leaves no set to resolve and the launch returns before the emulator is built. The path is a config key, so -game-xml-file moves it."
|
||||||
|
source_ref: "Src/OSD/SDL/Main.cpp:117, 1684, 2143, 2509-2520, Src/GameLoader.cpp:551-561, 1016-1019, Src/OSD/Windows/FileSystemPath.cpp:28-32"
|
||||||
|
|
||||||
|
- name: p1crosshair.bmp
|
||||||
|
path: "Assets/p1crosshair.bmp"
|
||||||
|
size: 295992
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Ships in the release archive next to the binary that loads it"
|
||||||
|
description: "Player 1 light gun crosshair texture"
|
||||||
|
note: "Both bitmaps are read on every launch whatever CrosshairStyle holds, since the load runs before the style decides anything, and a null surface aborts startup ahead of the Model 3 object. 32 bit BMP with alpha, sides a multiple of 2."
|
||||||
|
source_ref: "Src/OSD/SDL/Crosshair.cpp:34-51, Src/OSD/SDL/Main.cpp:2563-2569, Assets/DIR.txt"
|
||||||
|
|
||||||
|
- name: p2crosshair.bmp
|
||||||
|
path: "Assets/p2crosshair.bmp"
|
||||||
|
size: 295992
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Ships in the release archive next to the binary that loads it"
|
||||||
|
description: "Player 2 light gun crosshair texture"
|
||||||
|
note: "Read in the same call as the player 1 bitmap and equally fatal when it fails to load."
|
||||||
|
source_ref: "Src/OSD/SDL/Crosshair.cpp:35, 49-51, Src/OSD/SDL/Main.cpp:2563-2569"
|
||||||
|
|
||||||
|
- name: Music.xml
|
||||||
|
path: "Config/Music.xml"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Ships in the release archive as a template whose every example sits inside a dummy comment tag"
|
||||||
|
description: "Custom MPEG music track map"
|
||||||
|
note: "Consulted only for a game with a DSB1 or DSB2 board, and skipped when the file is absent. Maps an MPEG ROM offset to an MP3 the user supplies."
|
||||||
|
source_ref: "Src/OSD/SDL/Main.cpp:118, 967, Src/Sound/MPEG/MpegAudio.cpp:88-108"
|
||||||
@@ -26,12 +26,54 @@ notes: |
|
|||||||
EmuDeck installs the Flatpak package (com.supermodel3.Supermodel). Config
|
EmuDeck installs the Flatpak package (com.supermodel3.Supermodel). Config
|
||||||
stored in ~/.supermodel/Config/. No checkBIOS entry in EmuDeck.
|
stored in ~/.supermodel/Config/. No checkBIOS entry in EmuDeck.
|
||||||
|
|
||||||
files: []
|
Four data files of its own are read from the install tree, Config/ and Assets/
|
||||||
|
relative to the working directory on Windows and macOS, under the home
|
||||||
|
directory on Linux. Supermodel.ini, NVRAM/<game>.nv and Saves/<game>.st<slot>
|
||||||
|
are written by the emulator itself.
|
||||||
|
ref: Src/OSD/Windows/FileSystemPath.cpp:28-49
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: Games.xml
|
||||||
|
path: "Config/Games.xml"
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
description: "ROM set definitions"
|
||||||
|
note: "Parsed at startup into the game database. Every ROM region, file name and CRC32 the loader matches against comes from here, so an unreadable file leaves no set to resolve and the launch returns before the emulator is built. The path is a config key, so -game-xml-file moves it."
|
||||||
|
source_ref: "Src/OSD/SDL/Main.cpp:114, 1498, 1939, 2297-2307, Src/GameLoader.cpp:551-561, 1016-1019"
|
||||||
|
|
||||||
|
- name: p1crosshair.bmp
|
||||||
|
path: "Assets/p1crosshair.bmp"
|
||||||
|
size: 295992
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Ships in the release archive next to the binary that loads it"
|
||||||
|
description: "Player 1 light gun crosshair texture"
|
||||||
|
note: "Both bitmaps are read on every launch whatever CrosshairStyle holds, since the load runs before the style decides anything, and a null surface aborts startup ahead of the Model 3 object. 32 bit BMP with alpha, sides a multiple of 2."
|
||||||
|
source_ref: "Src/OSD/SDL/Crosshair.cpp:34-51, Src/OSD/SDL/Main.cpp:2350-2356, Assets/DIR.txt"
|
||||||
|
|
||||||
|
- name: p2crosshair.bmp
|
||||||
|
path: "Assets/p2crosshair.bmp"
|
||||||
|
size: 295992
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Ships in the release archive next to the binary that loads it"
|
||||||
|
description: "Player 2 light gun crosshair texture"
|
||||||
|
note: "Read in the same call as the player 1 bitmap and equally fatal when it fails to load."
|
||||||
|
source_ref: "Src/OSD/SDL/Crosshair.cpp:35, 49-51, Src/OSD/SDL/Main.cpp:2350-2356"
|
||||||
|
|
||||||
|
- name: Music.xml
|
||||||
|
path: "Config/Music.xml"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "Ships in the release archive as a template whose every example sits inside a dummy comment tag"
|
||||||
|
description: "Custom MPEG music track map"
|
||||||
|
note: "Consulted only for a game with a DSB1 or DSB2 board, and skipped when the file is absent. Maps an MPEG ROM offset to an MP3 the user supplies."
|
||||||
|
source_ref: "Src/OSD/SDL/Main.cpp:115, 940, Src/Sound/MPEG/MpegAudio.cpp:88-108"
|
||||||
|
|
||||||
exclusion_note: >
|
exclusion_note: >
|
||||||
The Sega Model 3 arcade hardware has no shared system BIOS. Each game board
|
The Sega Model 3 arcade hardware has no shared system BIOS. Each game board
|
||||||
contains its own program ROMs (CROM), video ROMs (VROM), sound program, sound
|
contains its own program ROMs (CROM), video ROMs (VROM), sound program, sound
|
||||||
samples, and optional DSB/drive board ROMs, all contained within per-game
|
samples, and optional DSB/drive board ROMs, all contained within per-game
|
||||||
MAME-format ZIP archives. Supermodel loads all required data from these game
|
MAME-format ZIP archives. Supermodel loads all required data from these game
|
||||||
ZIPs via CRC32-based identification defined in Games.xml. No standalone BIOS
|
ZIPs via CRC32-based identification defined in Games.xml. The files listed
|
||||||
or firmware files are referenced by the emulator source code.
|
above are the emulator's own data, not system ROMs.
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
emulator: "Swan.emu"
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/Rakashazi/emu-ex-plus-alpha"
|
||||||
|
upstream: "https://mednafen.github.io/"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "1c12fac5ce49badaadff2e2f210dcc30b89f4943"
|
||||||
|
core_version: "1.5.85"
|
||||||
|
display_name: "Bandai - WonderSwan / Color (Swan.emu)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "swan-emu"
|
||||||
|
- "Swan.emu"
|
||||||
|
- "SWAN-EMU"
|
||||||
|
systems:
|
||||||
|
- bandai-wswan
|
||||||
|
- bandai-wswanc
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Member of the EX Emulator series by Robert Broglia, which targets Android and
|
||||||
|
Linux (README.md:1,3-4,12-13) and keeps iOS and Pandora build shortcuts in the
|
||||||
|
tree (Swan.emu/ios.mk, Swan.emu/pandora.mk). Published as
|
||||||
|
com.explusalpha.SwanEmu (Swan.emu/metadata/conf.mk:2,6,7) and reached by ES-DE
|
||||||
|
through its SWAN-EMU find rule, which only the Android rule set carries.
|
||||||
|
Mednafen's WonderSwan module, itself descended from Cygne, is vendored under
|
||||||
|
Swan.emu/src/wswan (Swan.emu/metadata/conf.mk:8,
|
||||||
|
Swan.emu/src/main/AppMeta.cc:27) on the 1.32 line
|
||||||
|
(EmuFramework/include/shared/mednafen/mednafen-config.h:167) and driven by the
|
||||||
|
app's own video, audio, input and save layers. Three files differ from the
|
||||||
|
Mednafen 1.32.1 release: the pixel format and sound rate hooks move to the app
|
||||||
|
and the button latch is dropped for a value the input layer writes directly,
|
||||||
|
the save file calls are removed from loading and closing, and the SRAM and
|
||||||
|
EEPROM writes signal the app's backup memory
|
||||||
|
(Swan.emu/src/wswan/main.cpp:91,95, Swan.emu/src/main/Main.cc:96,104,119,
|
||||||
|
Swan.emu/src/main/input.cc:97,102, Swan.emu/src/wswan/memory.cpp:160-164,
|
||||||
|
Swan.emu/src/wswan/eeprom.cpp:164-169). The debugger and the disassembler are
|
||||||
|
left out of the build (Swan.emu/src/CMakeLists.txt:6-22). Content is read from
|
||||||
|
.ws, .wsc and .bin files (Swan.emu/metadata/conf.mk:5,
|
||||||
|
Swan.emu/src/main/AppMeta.cc:30); an archive is opened by the framework, which
|
||||||
|
keeps the first entry passing that same filter
|
||||||
|
(EmuFramework/src/EmuSystem.cc:394-412).
|
||||||
|
|
||||||
|
The content image is the only one the app loads. It is read into a 64 MiB
|
||||||
|
buffer, refused under 64 KiB or over 64 MiB, rounded up to 64 KiB then to a
|
||||||
|
power of two with the image sitting at the end of the buffer, and hashed for
|
||||||
|
the save file names (Swan.emu/src/main/Main.cc:91-97,
|
||||||
|
EmuFramework/src/shared/mednafen-emuex/MDFNUtils.hh:133-146,
|
||||||
|
Swan.emu/src/wswan/main.cpp:236-257,294-299). Byte 5 of the footer selects
|
||||||
|
either an EEPROM of 128, 1024 or 2048 bytes or battery RAM of 8 KiB to 512 KiB
|
||||||
|
(Swan.emu/src/wswan/main.cpp:317-333). A 512 KiB image carrying ELISA at
|
||||||
|
0x70000 whose last 16 bytes hash to crc32 0x0d05ed64, minus three blacklisted
|
||||||
|
images, is taken for WonderWitch firmware and read as content
|
||||||
|
(Swan.emu/src/wswan/main.cpp:273-291,351-352).
|
||||||
|
|
||||||
|
No boot ROM is read. Reset writes a built-in table of 200 power-on values to
|
||||||
|
the I/O ports, less the four EEPROM data ports
|
||||||
|
(Swan.emu/src/wswan/start.inc:12,
|
||||||
|
Swan.emu/src/wswan/main.cpp:66-70) and the memory reset writes at 0x75AC the
|
||||||
|
eight identifier bytes the boot ROM would have left
|
||||||
|
(Swan.emu/src/wswan/memory.cpp:801-808). The internal EEPROM is a built-in
|
||||||
|
0x400 byte image copied at init, then personalized in place with the name,
|
||||||
|
birth date, sex and blood type of the WonderSwan User Profile menu; the
|
||||||
|
language flag reaches the hardware the same way
|
||||||
|
(Swan.emu/src/wswan/eeprom.cpp:31,33,183-214,
|
||||||
|
Swan.emu/src/wswan/memory.cpp:748-772, Swan.emu/src/wswan/main.cpp:377,
|
||||||
|
Swan.emu/src/main/EmuMenuViews.cc:34-155,
|
||||||
|
Swan.emu/src/main/options.cc:117-165).
|
||||||
|
|
||||||
|
No firmware path exists by construction: the app answers Mednafen's file name
|
||||||
|
request for save states, saves and save backups only, and any other kind ends
|
||||||
|
in unreachable() (Swan.emu/src/main/options.cc:179-189). The module's own save
|
||||||
|
reader and writer, which would open a .sav and, for WonderWitch, a 524288 byte
|
||||||
|
.flash image, are unreachable, both call sites of the Mednafen release having
|
||||||
|
been removed from loading and closing (Swan.emu/src/wswan/memory.cpp:674-740,
|
||||||
|
Swan.emu/src/wswan/main.cpp:223-226,377-379). The comms setting is answered
|
||||||
|
false and its program path empty, so the serial link never forks a helper
|
||||||
|
(Swan.emu/src/main/options.cc:159-160,173-174,
|
||||||
|
Swan.emu/src/wswan/main.cpp:379, Swan.emu/src/wswan/comm.cpp:40-71). Cheat
|
||||||
|
loading and IPS patching are compiled in from the shared Mednafen sources and
|
||||||
|
called from nowhere (EmuFramework/src/shared/CMakeLists.txt:11-12,
|
||||||
|
EmuFramework/src/shared/mednafen/mempatcher.cpp:251-254,
|
||||||
|
EmuFramework/src/shared/mednafen/file.cpp:38-53), and the music rip player
|
||||||
|
routines are stubs (EmuFramework/src/shared/mednafen-emuex/MDFNApi.cc:87-88,
|
||||||
|
Swan.emu/src/wswan/main.cpp:259-268).
|
||||||
|
|
||||||
|
Per content the app writes and reads back one .sav holding the EEPROM followed
|
||||||
|
by the battery RAM, plus save states and SwanEmu.config
|
||||||
|
(Swan.emu/src/main/Main.cc:47-54,56-82, Swan.emu/src/main/system.ccm:155,
|
||||||
|
Swan.emu/src/main/AppMeta.cc:28,
|
||||||
|
EmuFramework/src/shared/mednafen-emuex/MDFNUtils.hh:76-122,
|
||||||
|
EmuFramework/src/EmuSystem.cc:168-172). ui.png, gpOverlay.png and the shader
|
||||||
|
sources are drawn from the application bundle
|
||||||
|
(EmuFramework/include/emuframework/AssetManager.hh:61-66,
|
||||||
|
EmuFramework/src/AssetManager.cc:58-70,
|
||||||
|
EmuFramework/src/VideoImageEffect.cc:163-173), as is the interface font on a
|
||||||
|
build without fontconfig (imagine/src/font/FreetypeFont.cc:271-289). The app
|
||||||
|
declares no bundled content, the framework definition defaulting to an empty
|
||||||
|
span (EmuFramework/src/AppMeta.cc:40,
|
||||||
|
EmuFramework/include/emuframework/AppMeta.hh:66-68).
|
||||||
|
|
||||||
|
files: []
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
emulator: "SWF Player"
|
||||||
|
type: standalone
|
||||||
|
core_classification: launcher
|
||||||
|
source: "https://play.google.com/store/apps/details?id=com.issess.flashplayer"
|
||||||
|
upstream: closed-source
|
||||||
|
author: "issess.net"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
core_version: "1.90 free (build 507)"
|
||||||
|
display_name: "Adobe Flash (SWF Player)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- "swf-player"
|
||||||
|
- "SWF Player"
|
||||||
|
- "SWF-PLAYER"
|
||||||
|
systems:
|
||||||
|
- flash
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Android package com.issess.flashplayer, closed source, published on Google Play and
|
||||||
|
reached by ES-DE through its SWF-PLAYER find rule. The build read here is 1.90 free
|
||||||
|
(build 507), versionCode 507, arm64-v8a and armeabi-v7a, sha256
|
||||||
|
0a56e74d0f8bfdfbd984ce1b8aa2a700203fdd051f3aece3c95fb17f45d4383b, signed v1 and v2 with
|
||||||
|
the developer certificate O=issess.com, CN=issess, sha256
|
||||||
|
c3a222b4339f9dde3a770bc1d0ceb551fa96e554679cdbd2056aadd0f1b843c8. Line numbers below are
|
||||||
|
those of that package: jadx output for the classes, the shipped file itself for
|
||||||
|
contents.html. The paid package com.issess.flashplayerpro, the other entry of the same
|
||||||
|
find rule, is built from this class tree, its activity being spelled
|
||||||
|
com.issess.flashplayer.player.FlashPlayerActivity. No genuine copy of it was obtainable:
|
||||||
|
apkpure and apkcombo bounce the download of a paid app, apkvision holds none, mi9 serves
|
||||||
|
zero bytes and archive.org has no item for either package.
|
||||||
|
|
||||||
|
Two engines ship in the package, one activity each, both exported and both answering
|
||||||
|
android.intent.action.VIEW for application/swf, application/x-shockwave-flash and
|
||||||
|
video/x-flv. FlashPlayerActivity is labelled "SWF Player by Ruffle" and runs the movie
|
||||||
|
in a WebView; AirPlayerActivity is labelled "SWF Player by AdobeAIR", lives in a :air
|
||||||
|
process and drives a captive Adobe AIR runtime. ES-DE names the first one and passes the
|
||||||
|
movie as the content URI of its own provider, so it always gets the Ruffle engine.
|
||||||
|
ref: AndroidManifest.xml activity com.issess.flashplayer.player.FlashPlayerActivity and
|
||||||
|
.AirPlayerActivity, string play_ruffle_player, play_air_player, using_ruffle_plugin,
|
||||||
|
using_air_plugin
|
||||||
|
|
||||||
|
The movie itself never stays where the user put it. BaseActivity.E reads the intent Uri
|
||||||
|
through the content resolver, or opens the path directly for a file:// intent, and writes
|
||||||
|
the bytes twice: to <cache>/assetLoader/cached.swf for the WebView engine and to
|
||||||
|
<cache>/app/<uniqueappversionid>/assets/cached.swf for the AIR engine, next to a copy of
|
||||||
|
the bundled AIR descriptor. The AIR name is fixed because the descriptor declares
|
||||||
|
cached.swf as its initial window content. A run with no Uri falls back to the last_swf
|
||||||
|
preference.
|
||||||
|
ref: BaseActivity.java:607-654, BaseActivity.java:594-605 (uniqueappversionid),
|
||||||
|
a2/b.java:86-92 (asset copy), a2/b.java:115 (stream copy),
|
||||||
|
assets/META-INF/AIR/application.xml:28
|
||||||
|
|
||||||
|
The Ruffle engine serves everything over a virtual host. FlashPlayerActivity.g0 writes
|
||||||
|
<cache>/assetLoader/swf.html from the bundled contents.html template, substituting the
|
||||||
|
movie URL and the wmode, scale, quality, background and density preferences;
|
||||||
|
FlashPlayerActivity.h0 builds a WebViewAssetLoader on the domain localhost.issess.net
|
||||||
|
mapping /ruffle/ to the package assets and / to that cache directory; i0 then loads
|
||||||
|
https://localhost.issess.net/swf.html one second later. The template pulls
|
||||||
|
/ruffle/ruffle/ruffle.js, which resolves to assets/ruffle/ruffle.js, and declares the
|
||||||
|
movie as a plain <object type="application/x-shockwave-flash">, which the Ruffle polyfill
|
||||||
|
takes over. Ruffle is the web build, nightly 2024-08-26, commit
|
||||||
|
c869505e88f792b1b6691cd8d6f0185bde4c21b9. The player controls are JavaScript calls on
|
||||||
|
that object and the frame counter comes back through the CallJava bridge.
|
||||||
|
ref: FlashPlayerActivity.java:262-291, 293-310, 312-346, 154, 349-386,
|
||||||
|
a2/b.java:327-373, c1/i.java:22-40 (assets handler), c1/i.java:77-95 (cache handler),
|
||||||
|
assets/contents.html:28,35-49, assets/ruffle/ruffle.js versionName field
|
||||||
|
|
||||||
|
Nothing is read from outside the package. The one mention of Adobe's own player is a main
|
||||||
|
list row that opens market://details?id=com.adobe.flashplayer, a store link that loads no
|
||||||
|
file, and the "Flash Player Not Found!" branch with its CallJava.notInstalled callback is
|
||||||
|
the fallback content of the object element, reached only when neither a plugin nor the
|
||||||
|
polyfill claims it. No plugin binary, BIOS, firmware or key is named anywhere in the
|
||||||
|
class tree, and ES-DE's own table records no BIOS for this system.
|
||||||
|
ref: MainListFragment.java:360, a2/b.java:452-468 (market intent),
|
||||||
|
assets/contents.html:50-60, FlashPlayerActivity.java:179-183,
|
||||||
|
ES-DE ANDROID.md:928
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: ruffle.js
|
||||||
|
path: "assets/ruffle/ruffle.js"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 344533
|
||||||
|
md5: c0263e609d1aef85891d56d6467a429c
|
||||||
|
sha1: c58c63e0ae8396018fd71f0fa7ebd4f8eb4f139f
|
||||||
|
description: "Ruffle web loader and polyfill, nightly 2024-08-26"
|
||||||
|
note: >-
|
||||||
|
The only script the generated page includes. It replaces the shockwave-flash object
|
||||||
|
with a Ruffle player and selects one of the two cores below by WebAssembly feature
|
||||||
|
detection. Absent, nothing claims the object element and the page renders its fallback
|
||||||
|
content instead, which reports back through CallJava.notInstalled.
|
||||||
|
source_ref: "assets/contents.html:28, FlashPlayerActivity.java:305 (/ruffle/ mapped to the package assets)"
|
||||||
|
|
||||||
|
- name: "core.ruffle.1c418e86b251861b5eca.js"
|
||||||
|
path: "assets/ruffle/core.ruffle.1c418e86b251861b5eca.js"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
variant_group: "ruffle-core"
|
||||||
|
size: 90386
|
||||||
|
md5: 5b1d64812875a1341ebd2a611e9324a1
|
||||||
|
sha1: 0eabbed786f3b8e5656d123e9f4573f918ba63d8
|
||||||
|
description: "Ruffle core bindings, WebAssembly extensions build"
|
||||||
|
note: >-
|
||||||
|
Glue for the SIMD core, webpack module 791. Loaded on a device whose WebAssembly
|
||||||
|
engine carries the extensions, which is what is_wasm_simd_used reports back.
|
||||||
|
source_ref: "assets/ruffle/ruffle.js webpack module 791, assets/ruffle/core.ruffle.1c418e86b251861b5eca.js is_wasm_simd_used"
|
||||||
|
|
||||||
|
- name: "75a2b30a5d3fb1a3431d.wasm"
|
||||||
|
path: "assets/ruffle/75a2b30a5d3fb1a3431d.wasm"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
variant_group: "ruffle-core"
|
||||||
|
size: 13107470
|
||||||
|
md5: 834f85979115fd740943a782887d0ab0
|
||||||
|
sha1: d27da38e4d37727a44bf04d7690a09135fad7115
|
||||||
|
description: "Ruffle core, WebAssembly extensions build"
|
||||||
|
note: >-
|
||||||
|
The player itself for devices with the extensions. Its target features record simd128,
|
||||||
|
which the baseline build below does not carry.
|
||||||
|
source_ref: "assets/ruffle/ruffle.js webpack module 791"
|
||||||
|
|
||||||
|
- name: "core.ruffle.9fa2f1e6feaba5f6767a.js"
|
||||||
|
path: "assets/ruffle/core.ruffle.9fa2f1e6feaba5f6767a.js"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
variant_group: "ruffle-core"
|
||||||
|
size: 94169
|
||||||
|
md5: 5aee868a91c066cc15f8b06999af690b
|
||||||
|
sha1: 45815723a1bdf4229e289906bf4e52dbfd78da56
|
||||||
|
description: "Ruffle core bindings, baseline build"
|
||||||
|
note: >-
|
||||||
|
Glue for the core without WebAssembly extensions, webpack module 797. Loaded when the
|
||||||
|
device does not report them.
|
||||||
|
source_ref: "assets/ruffle/ruffle.js webpack module 797, assets/ruffle/core.ruffle.9fa2f1e6feaba5f6767a.js is_wasm_simd_used"
|
||||||
|
|
||||||
|
- name: "9541e862775deeb49470.wasm"
|
||||||
|
path: "assets/ruffle/9541e862775deeb49470.wasm"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
variant_group: "ruffle-core"
|
||||||
|
size: 13323601
|
||||||
|
md5: fe843bd0152c714f0449493b0193108f
|
||||||
|
sha1: fea8e60e86cba7a63258626b13e6adb69ed110f9
|
||||||
|
description: "Ruffle core, baseline build"
|
||||||
|
note: >-
|
||||||
|
The player itself for devices without the WebAssembly extensions.
|
||||||
|
source_ref: "assets/ruffle/ruffle.js webpack module 797"
|
||||||
|
|
||||||
|
- name: contents.html
|
||||||
|
path: "assets/contents.html"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 2421
|
||||||
|
md5: 39c997db73db15a6807b35f148fcc85a
|
||||||
|
sha1: 0aaf20633888d2d0a2da38e82773cb5d44e840eb
|
||||||
|
description: "Template of the page the WebView loads"
|
||||||
|
note: >-
|
||||||
|
Read from the assets on every launch and rewritten into
|
||||||
|
<cache>/assetLoader/swf.html with the movie URL and the display preferences
|
||||||
|
substituted. It carries the ruffle.js include and the object element. Unreadable, the
|
||||||
|
generator returns null and the WebView is pointed at a page with no movie in it.
|
||||||
|
source_ref: "a2/b.java:327-333, FlashPlayerActivity.java:276-291"
|
||||||
|
|
||||||
|
- name: application.xml
|
||||||
|
path: "assets/META-INF/AIR/application.xml"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 1377
|
||||||
|
md5: de36d0dc1b74a39be2313749138d4d00
|
||||||
|
sha1: bc283d9ad8ad3bb99b632ca5b194a5bf27df1c22
|
||||||
|
description: "Adobe AIR application descriptor, namespace 3.8"
|
||||||
|
note: >-
|
||||||
|
Copied out of the assets into <cache>/app/<uniqueappversionid>/assets/META-INF/AIR/
|
||||||
|
before the AIR engine starts, and read from there by the runtime. It declares
|
||||||
|
cached.swf as the initial window content, which is the name the movie is copied under,
|
||||||
|
plus fullscreen, gpu rendering and auto orientation.
|
||||||
|
source_ref: "BaseActivity.java:616-630, assets/META-INF/AIR/application.xml:19,27-35"
|
||||||
|
|
||||||
|
- name: libCore.so
|
||||||
|
path: "lib/arm64-v8a/libCore.so"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 20951456
|
||||||
|
md5: 7fa4474455635584fa683167ee7e948f
|
||||||
|
sha1: d6d91ca32cbceda054851e9aa78c2e9286bd8812
|
||||||
|
description: "Adobe AIR 51.1.1.3 captive runtime"
|
||||||
|
note: >-
|
||||||
|
The AIR player, loaded by path first and then by name from the package. The runtime is
|
||||||
|
captive: the wrapper classes live in the application's own dex and the library beside
|
||||||
|
them, so no separate AIR package is consulted. The armeabi-v7a build of the same
|
||||||
|
version is 14808220 bytes. Version read back from the library as "AND 51,1,1,3".
|
||||||
|
source_ref: "AndroidActivityWrapper.java:455-481, AirPlayerBaseActivity.java:59-70"
|
||||||
|
|
||||||
|
- name: libc++_shared.so
|
||||||
|
path: "lib/arm64-v8a/libc++_shared.so"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 1058904
|
||||||
|
md5: 77f7b0c9bba5c0b4c4339bc655d5613a
|
||||||
|
sha1: 8db47ede06074dec3fbc05b69eb75f8c1c5e71a8
|
||||||
|
description: "NDK C++ runtime for the AIR runtime"
|
||||||
|
note: >-
|
||||||
|
Named by the wrapper ahead of the runtime itself, by path and then by name, and listed
|
||||||
|
as a DT_NEEDED of libCore.so. The armeabi-v7a build is 657000 bytes.
|
||||||
|
source_ref: "AndroidActivityWrapper.java:459,472-478"
|
||||||
|
|
||||||
|
- name: libswfplayer.so
|
||||||
|
path: "lib/arm64-v8a/libswfplayer.so"
|
||||||
|
system: flash
|
||||||
|
required: true
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 3896
|
||||||
|
md5: 1301640830c754d20384243c97bd7854
|
||||||
|
sha1: 6118faa7947eb7abf4326f08f5ba94ab61e42808
|
||||||
|
description: "JNI library of the application"
|
||||||
|
note: >-
|
||||||
|
Loaded from the static initializer of the AIR activity's base class, so its absence
|
||||||
|
stops that activity from being created. It exports one symbol,
|
||||||
|
Java_com_issess_flashplayer_stringFromJNI, which nothing calls. The armeabi-v7a build
|
||||||
|
is 2688 bytes.
|
||||||
|
source_ref: "AirPlayerBaseActivity.java:31-33"
|
||||||
|
|
||||||
|
- name: sample1.swf
|
||||||
|
path: "assets/sample1.swf"
|
||||||
|
system: flash
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 5889
|
||||||
|
md5: 3d801b57e0b9e1a84d9cf28ef7505b3c
|
||||||
|
sha1: 5194da518b3bbc77204e481c2cfed0381cf5df41
|
||||||
|
description: "Sample movie"
|
||||||
|
note: >-
|
||||||
|
Unpacked into <cache>/assetLoader on the sample list screen, then opened through a
|
||||||
|
chooser like any other movie so either engine can take it.
|
||||||
|
source_ref: "SampleListFragment.java:65-81, 109-117"
|
||||||
|
|
||||||
|
- name: sample2.swf
|
||||||
|
path: "assets/sample2.swf"
|
||||||
|
system: flash
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 54675
|
||||||
|
md5: c583c7db1c5456c0d9307d5f510a63f0
|
||||||
|
sha1: bef0ab96169418441f43b9dae2ec92a990b89ade
|
||||||
|
description: "Sample movie"
|
||||||
|
note: >-
|
||||||
|
Unpacked and opened on the same path as sample1.swf.
|
||||||
|
source_ref: "SampleListFragment.java:65-81, 109-117"
|
||||||
|
|
||||||
|
- name: sample3.swf
|
||||||
|
path: "assets/sample3.swf"
|
||||||
|
system: flash
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "ships inside the application package"
|
||||||
|
size: 23563
|
||||||
|
md5: 505834e937b0bd061695ff34f40301cb
|
||||||
|
sha1: f5992aebd3ba298f6564681592be8b4626e89158
|
||||||
|
description: "Sample movie"
|
||||||
|
note: >-
|
||||||
|
Unpacked and opened on the same path as sample1.swf.
|
||||||
|
source_ref: "SampleListFragment.java:65-81, 109-117"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
Four files the package carries are left out because no code path opens them. The assets
|
||||||
|
cached.swf, Hello2.swf and empty.html are named in no class; the cached.swf the AIR
|
||||||
|
runtime reads is the copy of the user's movie written into the cache, not the one in the
|
||||||
|
assets. libysshared.so, which exports only ysEncrypt and ysDecrypt, is loaded by nothing:
|
||||||
|
the three loadLibrary calls in the package name swfplayer, c++_shared and Core, no
|
||||||
|
library declares it as a DT_NEEDED, and its soname appears nowhere in the class tree. The
|
||||||
|
market link to com.adobe.flashplayer is not a dependency either, being an intent to the
|
||||||
|
store page rather than a load of Adobe's plugin.
|
||||||
@@ -0,0 +1,226 @@
|
|||||||
|
emulator: Virtual Virtual Boy
|
||||||
|
type: standalone
|
||||||
|
core_classification: other
|
||||||
|
source: "https://github.com/SupernaviX/vvb"
|
||||||
|
upstream: "https://github.com/SupernaviX/vvb"
|
||||||
|
author: "Simon Gellis"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "0bf230bced628d78ff2c149baaf16f6fb8388cec"
|
||||||
|
upstream_commit: "0bf230bced628d78ff2c149baaf16f6fb8388cec"
|
||||||
|
core_version: "1.18.2"
|
||||||
|
display_name: "Nintendo - Virtual Boy (Virtual Virtual Boy)"
|
||||||
|
mode: standalone
|
||||||
|
cores:
|
||||||
|
- virtual-virtual-boy
|
||||||
|
- VIRTUAL-VIRTUAL-BOY
|
||||||
|
- vvb
|
||||||
|
- com.simongellis.vvb
|
||||||
|
- com.simongellis.vvb.leia
|
||||||
|
systems:
|
||||||
|
- nintendo-virtualboy
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Virtual Boy emulator for Android, published as com.simongellis.vvb
|
||||||
|
(app/build.gradle:62,65-66) and reached by ES-DE through its
|
||||||
|
VIRTUAL-VIRTUAL-BOY find rule, which hands the game over as an ACTION_VIEW
|
||||||
|
intent on a content URI (MainActivity.kt:126-131, MainActivity.kt:40-45). The
|
||||||
|
hardware sits in a Rust library packaged as libvvb.so and loaded when the
|
||||||
|
application starts (VvbApplication.kt:69, Cargo.toml [lib]); the Kotlin side
|
||||||
|
owns the menus, the input mapping and every file access. Display goes through
|
||||||
|
mono, anaglyph, stereo, Google Cardboard and Leia CNSDK renderers, each
|
||||||
|
carrying its GLSL as string constants in the Rust sources
|
||||||
|
(src/video/renderers/mono.rs:10-26, src/video/renderers/stereo.rs:13-29).
|
||||||
|
|
||||||
|
The console has no boot ROM and the emulator loads none. The memory map
|
||||||
|
declares Vram, Audio, Hardware, Dram, Sram and Rom, and load_game_pak takes
|
||||||
|
the cartridge image and its SRAM, leaving the Rom region unpopulated until a
|
||||||
|
game arrives (src/emulator/memory.rs:8-14, src/emulator/memory.rs:115,
|
||||||
|
src/emulator/memory.rs:134-149).
|
||||||
|
|
||||||
|
Games are read from .vb, .vboy and .bin, or from the first member of a zip
|
||||||
|
answering the same test (GamePakLoader.kt:20-27, GamePakLoader.kt:97-98). The
|
||||||
|
image has to be a power of two and at most 0x01000000 bytes, either test
|
||||||
|
aborting the load (GamePakLoader.kt:39-45, GamePakLoader.kt:57), and the core
|
||||||
|
applies the same two limits again when the image reaches it
|
||||||
|
(src/emulator/memory.rs:136-141). The MD5 of the image names the directory
|
||||||
|
that holds the save data, where the app writes .srm and
|
||||||
|
save_states/<slot>.sav as it runs (GamePakLoader.kt:30-32,
|
||||||
|
GamePak.kt:8-9,30, src/emulator/state.rs:30-38). Cardboard lens parameters
|
||||||
|
come from scanning the viewer QR code and are kept by the SDK, the app asking
|
||||||
|
for them and starting a scan when none are saved
|
||||||
|
(src/video/renderers/cardboard.rs:29-34).
|
||||||
|
|
||||||
|
One tree ships two flavours: playStore, and leia, which appends .leia to the
|
||||||
|
application id and renders through the CNSDK (app/build.gradle:92-100). Both
|
||||||
|
carry the same nine homebrew titles, stored uncompressed so they can be opened
|
||||||
|
by descriptor (app/build.gradle:117).
|
||||||
|
|
||||||
|
files:
|
||||||
|
# -- Bundled homebrew, assets/games, listed by res/raw/bundledgames.json --
|
||||||
|
# Each title is served over content://com.simongellis.vvb.assets and then read
|
||||||
|
# through the same path as a user game, so the power of two and 0x01000000
|
||||||
|
# tests apply to it. The id an entry declares is the MD5 of the image.
|
||||||
|
# Common refs: BundledGameRepository.kt:9-13, AssetsProvider.kt:18-19,
|
||||||
|
# GamePakLoader.kt:35-49.
|
||||||
|
|
||||||
|
- name: "BLOX.vb"
|
||||||
|
path: "games/BLOX.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: f82d4c9fdd81518537d88f70c6602bb5
|
||||||
|
sha1: f2105349dff09bdc00e4548460991dde9ac7c2af
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by KR155E"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:2-7, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "BLOX 2.vb"
|
||||||
|
path: "games/BLOX 2.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: cc91d6389df2c9777919e8e8ab2c0e66
|
||||||
|
sha1: 66b2a25ef8e1af74bed4bbba4785951a9d6edce0
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by KR155E"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:8-13, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "Elevated Speed.vb"
|
||||||
|
path: "games/Elevated Speed.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 8f7bcfdd0f412d9060b06a97a89fe202
|
||||||
|
sha1: 8b08f08f37127621483aa4e204a3e3b2312af196
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by PizzaRollsRoyce"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:14-19, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "Fishbone.vb"
|
||||||
|
path: "games/Fishbone.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 61e38e4e0c43aa8d6274a89ebedd3063
|
||||||
|
sha1: b1e5d5ab7e49f91050d3593bbcf48ff609c1c979
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by thunderstruck"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:20-25, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "Formula V Public Demo.vb"
|
||||||
|
path: "games/Formula V Public Demo.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 34e9a2ffd60f7ea565caada82d57f29f
|
||||||
|
sha1: 533672b887ec16aa50a5508488d1ab125dd5e749
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by KR155E"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:26-31, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "Red Square.vb"
|
||||||
|
path: "games/Red Square.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 9c372321204b9fa65f9324f98aae53ff
|
||||||
|
sha1: a12529a0d7cf7f0711b913b8ae72fea193cebc17
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by Kresna and Nyrator"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:32-37, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "The Red Castle.vb"
|
||||||
|
path: "games/The Red Castle.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: cdb404ff3e1df7b3c13214ac5409d512
|
||||||
|
sha1: 34e90abaa3ffc706882fd8a0d1a8101abc185734
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by Timothy Beck"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:38-43, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "VUE Snake.vb"
|
||||||
|
path: "games/VUE Snake.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: ccfa400a0ff3d717dad36a3f736fd34d
|
||||||
|
sha1: 77ebaf5dbe667d8347d098b6749b6f3be09f5814
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by KR155E"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:44-49, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: "VUEngine Platformer Demo.vb"
|
||||||
|
path: "games/VUEngine Platformer Demo.vb"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: c96d91fb97572a0af7d53f63b292e0f2
|
||||||
|
sha1: b1b9893629bbec74e8b58d7b5983e7d35e202fe0
|
||||||
|
max_size: 16777216
|
||||||
|
validation: [size]
|
||||||
|
description: "Bundled homebrew game by KR155E"
|
||||||
|
source_ref: "app/src/main/res/raw/bundledgames.json:50-55, app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/AssetsProvider.kt:18-19, app/src/main/java/com/simongellis/vvb/game/GamePakLoader.kt:35-49"
|
||||||
|
|
||||||
|
- name: bundledgames.json
|
||||||
|
path: "res/raw/bundledgames.json"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 04ecc37b70b23fdcc3f5207040f4d178
|
||||||
|
sha1: 2ae5b46e78afb1bb95d11fa103d6176321573b91
|
||||||
|
size: 1677
|
||||||
|
description: "Index of the bundled homebrew titles"
|
||||||
|
note: >-
|
||||||
|
Read whole as a raw resource when the repository is built, and decoded
|
||||||
|
into the list the load menu offers. Each record names the title, the
|
||||||
|
content URI serving it, the authors and the MD5 of the image. The leia
|
||||||
|
flavour replaces the file with one pointing at its own authority.
|
||||||
|
source_ref: "app/src/main/java/com/simongellis/vvb/data/BundledGameRepository.kt:9-13, app/src/main/java/com/simongellis/vvb/data/BundledGame.kt:7-13, app/src/leia/res/raw/bundledgames.json:5"
|
||||||
|
|
||||||
|
# -- Preview frames, decoded unscaled and pushed into the eye buffers --
|
||||||
|
# Both are 384x224 in four shades, the shape the display expects, and they
|
||||||
|
# stand in for a running game while the video settings are being adjusted.
|
||||||
|
|
||||||
|
- name: vbtitlescreen_left.png
|
||||||
|
path: "res/drawable-nodpi/vbtitlescreen_left.png"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 793565cb6af20eb02c78322899e54172
|
||||||
|
sha1: 480e9872ab20d8a137004e45486985608882983f
|
||||||
|
size: 619
|
||||||
|
description: "Left eye of the settings preview image"
|
||||||
|
source_ref: "app/src/main/java/com/simongellis/vvb/game/GameViewModel.kt:41-51, app/src/main/java/com/simongellis/vvb/game/PreviewActivity.kt:32,56"
|
||||||
|
|
||||||
|
- name: vbtitlescreen_right.png
|
||||||
|
path: "res/drawable-nodpi/vbtitlescreen_right.png"
|
||||||
|
system: nintendo-virtualboy
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
category: game_data
|
||||||
|
md5: 6df7af05e6b0cb19a37615c2b29116d9
|
||||||
|
sha1: fc6c5857a0c298d9d6a73449044d1ef3c57fe050
|
||||||
|
size: 620
|
||||||
|
description: "Right eye of the settings preview image"
|
||||||
|
source_ref: "app/src/main/java/com/simongellis/vvb/game/GameViewModel.kt:41-51, app/src/main/java/com/simongellis/vvb/game/PreviewActivity.kt:32,56"
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
emulator: X1 BOX
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/izzy2lost/xemu"
|
||||||
|
upstream: "https://github.com/xemu-project/xemu"
|
||||||
|
author: "izzy2lost"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "3ed53f6843ac41147287468d996dfa939b40ad00"
|
||||||
|
upstream_commit: "26fcbe54f17e496bdf530dad9f237e74e2f943fc"
|
||||||
|
core_version: "1.2.6"
|
||||||
|
display_name: "Microsoft - Xbox (X1 BOX)"
|
||||||
|
cores:
|
||||||
|
- "x1-box"
|
||||||
|
- "x1box"
|
||||||
|
systems:
|
||||||
|
- microsoft-xbox
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Original Xbox emulator for Android, package com.izzy2lost.x1box, arm64-v8a.
|
||||||
|
A Kotlin front end carries the launcher, setup wizard, game library, settings
|
||||||
|
and per-title overrides, and drives a whole xemu tree built through CMake
|
||||||
|
against SDL2 and QEMU 10.2.0. The imgui interface, the monitor and the
|
||||||
|
snapshot entry points are stubbed, so that front end is the only interface.
|
||||||
|
.LauncherActivity answers VIEW with a content or file URI, and that URI
|
||||||
|
becomes the disc slot before emulation opens.
|
||||||
|
ref: QEMU_VERSION,
|
||||||
|
android/app/build.gradle.kts:49, 55, 64-65, 68,
|
||||||
|
android/app/src/main/AndroidManifest.xml:13-30,
|
||||||
|
android/app/src/main/cpp/CMakeLists.txt:858, 867-868,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/LauncherActivity.kt:37,
|
||||||
|
92-121
|
||||||
|
|
||||||
|
The wizard walks four steps and each Next stays disabled until its own step
|
||||||
|
resolves: the MCPX boot ROM, the flash ROM, the disk image and a games
|
||||||
|
folder. The two ROM pickers keep .bin, .rom and .img, the disk picker .qcow2
|
||||||
|
and .img. A pick is fingerprinted before anything is written, and only a file
|
||||||
|
that passes is copied into x1box under the external files directory as
|
||||||
|
mcpx.bin, flash.bin or hdd.img; a file chosen as a path in place is kept as
|
||||||
|
that path instead. Those names, the eeprom the wizard never asks for and the
|
||||||
|
disc are written to x1box/xemu.toml under sys.files. The disc is handed to
|
||||||
|
QEMU as a file descriptor through -add-fd and only copied to x1box/dvd.iso
|
||||||
|
when that fails.
|
||||||
|
ref: android/app/src/main/java/com/izzy2lost/x1box/SetupWizardActivity.kt:63-139,
|
||||||
|
243-278, 411-459,
|
||||||
|
android/app/src/main/cpp/xemu_android.cpp:717-721, 757-870, 1315-1325
|
||||||
|
|
||||||
|
The three images are what the app gates on. The launcher sends the user back
|
||||||
|
through the wizard whenever the MCPX, the flash, the disk or the games folder
|
||||||
|
stops resolving, and an intent from a frontend reaches the emulator only once
|
||||||
|
the three images resolve. The core underneath is looser: an empty MCPX path
|
||||||
|
simply leaves the machine property off, an empty disk path attaches no drive
|
||||||
|
at index 0, and only the flash clears autostart on its own.
|
||||||
|
ref: android/app/src/main/java/com/izzy2lost/x1box/LauncherActivity.kt:117-135,
|
||||||
|
system/vl.c:3000-3022, 3057-3072, 3078-3092
|
||||||
|
|
||||||
|
Settings imports a dashboard tree from a ZIP or a folder into the FATX
|
||||||
|
partitions of the configured disk image, C at 0x8CA80000 and E at 0xABE80000,
|
||||||
|
keeping what it overwrites in a dated backup folder. The tree is searched for
|
||||||
|
a boot XBE beforehand and the best candidate is copied to C/xboxdash.xbe when
|
||||||
|
that name is missing, xboxdash.xbe, default.xbe, evoxdash.xbe, avalaunch.xbe,
|
||||||
|
unleashx.xbe, xbmc.xbe and nexgen.xbe scoring in that order, with a name
|
||||||
|
carrying dash and a path under dashboard scoring above one under apps or
|
||||||
|
games. The status line probes C for xboxdash.xbe, msdash.xbe, xbox.xtf and
|
||||||
|
the directories xodash, audio, fonts and xboxdashdata.*, and calls the
|
||||||
|
install complete when the boot XBE sits beside at least one of the others.
|
||||||
|
ref: android/app/src/main/cpp/xemu_fatx_import.c:51-54, 1786-1801, 1842-1847,
|
||||||
|
1864-1911,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/XboxInsigniaHelper.kt:10-53,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt:2370-2445
|
||||||
|
|
||||||
|
Preparing Insignia turns the NAT backend on and writes the DNS 46.101.64.175
|
||||||
|
into the config sector of the disk image and into the EEPROM at 0xAC.
|
||||||
|
Registration boots a Setup Assistant image the user picks, which goes in the
|
||||||
|
disc slot like any other game. The disk tools format an image that already
|
||||||
|
exists and never create one: a retail layout needs at least 0x1DD156000
|
||||||
|
bytes and the extended F and G layouts need room past that boundary. The
|
||||||
|
EEPROM editor rewrites language, video standard, resolution flags, aspect
|
||||||
|
ratio and refresh rate in place and recomputes both checksums. The five
|
||||||
|
managed files travel together through an x1box-files-*.zip archive that
|
||||||
|
settings both writes and reads back.
|
||||||
|
ref: android/app/src/main/java/com/izzy2lost/x1box/XboxInsigniaHelper.kt:7-8,
|
||||||
|
62-77,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/XboxEepromEditor.kt:17,
|
||||||
|
159-213,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/XboxHddFormatter.kt:7-16,
|
||||||
|
46-50,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt:48-56,
|
||||||
|
1030-1086, 1432-1445
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: mcpx_1.0.bin
|
||||||
|
required: true
|
||||||
|
path: "x1box/mcpx.bin"
|
||||||
|
config_key: "sys.files.bootrom_path"
|
||||||
|
size: 512
|
||||||
|
md5: "d49c52a4102f6df7bcf8d0617ac475ed"
|
||||||
|
validation: [size, md5]
|
||||||
|
description: "MCPX southbridge boot ROM"
|
||||||
|
note: >-
|
||||||
|
The only file the app verifies by content. A pick is accepted just when
|
||||||
|
its MD5 equals the value hardcoded in the wizard, which is the v1.0 boot
|
||||||
|
ROM; anything else is refused with the expected hash quoted, and the
|
||||||
|
512-byte dump whose MD5 is 196a5f59a13382c185636e691d6c323d is named
|
||||||
|
separately as a known bad dump to re-dump. The check runs again over the
|
||||||
|
stored copy every time the wizard opens, so a file that stops matching
|
||||||
|
is dropped. The loader then checks the size a second time and ends the
|
||||||
|
process when it is not 512 bytes. The bytes are read over the last 512
|
||||||
|
of the flash image and the region stays writable so early retail kernels
|
||||||
|
keep their cache quirk.
|
||||||
|
source_ref: "android/app/src/main/java/com/izzy2lost/x1box/SetupWizardActivity.kt:23-25, 67-91, 411-459, 461-500, android/app/src/main/res/values/strings.xml:19-21, system/vl.c:2998-3022, hw/xbox/xbox.c:143-172"
|
||||||
|
|
||||||
|
- name: Complex_4627.bin
|
||||||
|
required: true
|
||||||
|
path: "x1box/flash.bin"
|
||||||
|
config_key: "sys.files.flashrom_path"
|
||||||
|
size_options: [262144, 524288, 1048576]
|
||||||
|
size_note: "Any non-zero multiple of 65536; 256 KB is assumed when the image cannot be read."
|
||||||
|
validation: [size]
|
||||||
|
description: "Xbox flash ROM"
|
||||||
|
note: >-
|
||||||
|
Passed as -bios, and the one image whose absence stops the run on its
|
||||||
|
own: a path that cannot be opened queues an error and clears autostart.
|
||||||
|
The picker only refuses what looks like the boot ROM, a 512-byte file or
|
||||||
|
either MCPX hash, and asks for a BIOS instead; there is no positive hash
|
||||||
|
to match. The image is mapped at 0xFF000000 and mirrored to the top of
|
||||||
|
the address space; a size that is zero or not a multiple of 64 KB, or a
|
||||||
|
short read, falls back to 256 KB filled with 0xFF. A retail image cannot
|
||||||
|
launch unsigned code, so a debug or modified image is what boots a title.
|
||||||
|
source_ref: "system/vl.c:3057-3072, hw/xbox/xbox.c:64-102, android/app/src/main/java/com/izzy2lost/x1box/SetupWizardActivity.kt:64, 93-116, 487-495"
|
||||||
|
|
||||||
|
- name: xbox_hdd.qcow2
|
||||||
|
required: true
|
||||||
|
path: "x1box/hdd.img"
|
||||||
|
config_key: "sys.files.hdd_path"
|
||||||
|
description: "Xbox hard disk image"
|
||||||
|
note: >-
|
||||||
|
Taken in qcow2 or raw form and attached as index 0 with locked=on and
|
||||||
|
cache=writethrough. An empty setting attaches no drive at all and an
|
||||||
|
unopenable one only queues a message, but the launcher refuses to leave
|
||||||
|
the wizard until the file resolves. The formatter builds FATX partitions
|
||||||
|
inside an image that already exists and needs at least 0x1DD156000 bytes
|
||||||
|
for the retail layout; it never creates the image. Partitions C and E of
|
||||||
|
this image are what the dashboard import writes into.
|
||||||
|
source_ref: "system/vl.c:3078-3092, android/app/src/main/java/com/izzy2lost/x1box/SetupWizardActivity.kt:65, 118-139, android/app/src/main/java/com/izzy2lost/x1box/XboxHddFormatter.kt:7-16, 46-50, android/app/src/main/cpp/xemu_android.cpp:822-843"
|
||||||
|
|
||||||
|
- name: eeprom.bin
|
||||||
|
required: false
|
||||||
|
path: "x1box/eeprom.bin"
|
||||||
|
config_key: "sys.files.eeprom_path"
|
||||||
|
size: 256
|
||||||
|
validation: [size]
|
||||||
|
description: "Xbox EEPROM image"
|
||||||
|
note: >-
|
||||||
|
Always pointed at x1box/eeprom.bin, a path the wizard never asks for.
|
||||||
|
Generated as XBOX_EEPROM_VERSION_R1 when it does not exist, so a dump is
|
||||||
|
needed only to carry over a console serial, region or HDD key. It is
|
||||||
|
attached through the smbus-storage device; a size other than 256 bytes,
|
||||||
|
or a generation that fails, clears autostart. Preparing Insignia and the
|
||||||
|
EEPROM editor write to it in place.
|
||||||
|
source_ref: "system/vl.c:2921-2964, 3045-3055, android/app/src/main/cpp/xemu_android.cpp:757-759, 719, android/app/src/main/cpp/xemu_settings_android.cc:246-286, android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt:2748-2751"
|
||||||
|
|
||||||
|
- name: xboxdash.xbe
|
||||||
|
required: false
|
||||||
|
load_from: hdd_image
|
||||||
|
path: "C/xboxdash.xbe"
|
||||||
|
description: "Retail dashboard boot executable"
|
||||||
|
note: >-
|
||||||
|
Imported to the root of partition C from the C directory of a user
|
||||||
|
dashboard tree. The import treats this name as the boot entry: when it is
|
||||||
|
absent the best scoring .xbe of the tree is copied to it, and the retail
|
||||||
|
boot counts as ready only once the name exists. The start path of the
|
||||||
|
emulator never reads partition C, and preparing Insignia finishes with a
|
||||||
|
warning when the name is missing.
|
||||||
|
source_ref: "android/app/src/main/cpp/xemu_fatx_import.c:1796-1797, 1842-1843, 1864-1911, android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt:2370-2401, 2436-2445, 2518, 2536-2538"
|
||||||
|
|
||||||
|
- name: msdash.xbe
|
||||||
|
required: false
|
||||||
|
load_from: hdd_image
|
||||||
|
path: "C/msdash.xbe"
|
||||||
|
description: "Retail dashboard executable kept beside the boot copy"
|
||||||
|
note: >-
|
||||||
|
Probed at the root of partition C and imported with the rest of the tree.
|
||||||
|
Its presence beside the boot XBE is one of the marks the status line
|
||||||
|
reads to call a dashboard install complete, and it is one of the names
|
||||||
|
that decide which directory of a picked tree is taken as the source root.
|
||||||
|
source_ref: "android/app/src/main/cpp/xemu_fatx_import.c:1798-1799, 1844-1845, android/app/src/main/java/com/izzy2lost/x1box/XboxInsigniaHelper.kt:13, 42-50, android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt:2518, 2539-2541"
|
||||||
|
|
||||||
|
- name: xbox.xtf
|
||||||
|
required: false
|
||||||
|
load_from: hdd_image
|
||||||
|
path: "C/xbox.xtf"
|
||||||
|
description: "Dashboard typeface"
|
||||||
|
note: >-
|
||||||
|
Probed at the root of partition C and imported with the rest of the tree,
|
||||||
|
alongside the xodash, audio, fonts and xboxdashdata.* directories the
|
||||||
|
root scan looks for.
|
||||||
|
source_ref: "android/app/src/main/cpp/xemu_fatx_import.c:1786-1794, 1800-1801, 1846-1847, android/app/src/main/java/com/izzy2lost/x1box/XboxInsigniaHelper.kt:12, 14-16, android/app/src/main/java/com/izzy2lost/x1box/SettingsActivity.kt:2518, 2542-2543"
|
||||||
|
|
||||||
|
- name: "<driver>.zip"
|
||||||
|
required: false
|
||||||
|
unsourceable: "third-party Vulkan driver built for one GPU family, not an emulator artefact"
|
||||||
|
description: "Replacement Vulkan driver package"
|
||||||
|
note: >-
|
||||||
|
Imported through a picker into gpu_drivers under the external files
|
||||||
|
directory, renamed after the name field of the meta.json it carries, then
|
||||||
|
unpacked whole into gpu_driver in internal storage, entries that would
|
||||||
|
escape that directory being refused. The minApi field is compared against
|
||||||
|
the device before the archive is kept. Loading is offered only when
|
||||||
|
/dev/kgsl-3d0 exists, and clearing the install directory returns the app
|
||||||
|
to the system driver.
|
||||||
|
source_ref: "android/app/src/main/java/com/izzy2lost/x1box/GpuDriverHelper.kt:15, 19-35, 41-89, 91-131, 133-136, 170-197"
|
||||||
|
|
||||||
|
- name: gamecontrollerdb.txt
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
unsourceable: "opened through the asset manager inside the package, so no file on disk reaches this load"
|
||||||
|
description: "SDL controller mapping database"
|
||||||
|
note: >-
|
||||||
|
Read from the assets of the package as the game controller subsystem
|
||||||
|
comes up and handed to SDL as a memory stream. The asset manager reads
|
||||||
|
inside the archive and the path is a constant, so there is no search
|
||||||
|
order and nothing outside the package replaces this copy; an added pad
|
||||||
|
mapping goes in through controller_map.txt instead. The revision shipped
|
||||||
|
here is 589031 bytes and is not the one other releases carry under this
|
||||||
|
name.
|
||||||
|
source_ref: "android/app/src/main/cpp/xemu_android.cpp:205-206, 236-275, 1192-1197"
|
||||||
|
|
||||||
|
- name: X1_Covers.txt
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
description: "Cover art index for the game library"
|
||||||
|
note: >-
|
||||||
|
Read from the assets and turned into a lookup from normalised game name
|
||||||
|
to a URL under the X1_Covers repository, which the library fetches and
|
||||||
|
caches per title. Only lines ending in .png are kept.
|
||||||
|
source_ref: "android/app/src/main/java/com/izzy2lost/x1box/GameLibraryActivity.kt:103, 895-935"
|
||||||
|
|
||||||
|
- name: controller_map.txt
|
||||||
|
required: false
|
||||||
|
load_from: internal_storage
|
||||||
|
description: "Extra SDL controller mappings"
|
||||||
|
note: >-
|
||||||
|
SDL builds this path from the internal storage directory of the package
|
||||||
|
when SDL_GAMECONTROLLERCONFIG_FILE is unset, which it is here, and reads
|
||||||
|
it while the game controller subsystem starts, after the mappings
|
||||||
|
compiled in. It is the one mapping file a user can add without
|
||||||
|
rebuilding the package. The SDL2 tree in thirdparty is what the build
|
||||||
|
compiles, the local checkout taking precedence over the release archive
|
||||||
|
CMake would otherwise fetch.
|
||||||
|
source_ref: "thirdparty/SDL2/src/joystick/SDL_gamecontroller.c:1873-1885, 1890-1907, android/app/src/main/cpp/CMakeLists.txt:61-72"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
Two file loads present in the tree are not reached by this build and are not
|
||||||
|
listed. hw/xbox/chihiro.c falls back to the media board ROM when no path is
|
||||||
|
given and maps a media board filesystem image beside it, but the whole driver
|
||||||
|
is filtered out of the source list, so no Chihiro machine exists here.
|
||||||
|
X1_Covers.xml ships in the assets and no code opens it, the library reading
|
||||||
|
X1_Covers.txt instead.
|
||||||
|
ref: hw/xbox/chihiro.c,
|
||||||
|
android/app/src/main/cpp/CMakeLists.txt:705,
|
||||||
|
android/app/src/main/assets/X1_Covers.xml,
|
||||||
|
android/app/src/main/java/com/izzy2lost/x1box/GameLibraryActivity.kt:901
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
emulator: XenDroid
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/rfandango/XenDroid"
|
||||||
|
upstream: "https://github.com/has207/xenia-edge"
|
||||||
|
author: "rfandango"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "b70d64374f8733645e8ea63f50430165b7dbd684"
|
||||||
|
upstream_commit: "84cf209221160590768f615a0369a9c4a1456bbf"
|
||||||
|
core_version: "b70d643"
|
||||||
|
display_name: "Microsoft - Xbox 360 (XenDroid)"
|
||||||
|
cores:
|
||||||
|
- "xendroid"
|
||||||
|
- "XENDROID"
|
||||||
|
systems:
|
||||||
|
- microsoft-xbox-360
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Xbox 360 emulator for Android, package xendroid.compose, arm64-v8a only.
|
||||||
|
Xenia Edge is vendored whole under emulator-core/src/main/cpp/xenia and a
|
||||||
|
Kotlin and Compose frontend replaces the desktop front end: its own windowed
|
||||||
|
app, AAudio and OpenSLES audio systems, an Android input driver, and Android
|
||||||
|
providers for the guest keyboard, the message box and disc swap. The library
|
||||||
|
recognises ISO, ZAR, GOD, extracted XEX folders and STFS containers, and the
|
||||||
|
boot path reads the file signature before mounting.
|
||||||
|
ref: emulator-core/src/main/cpp/CMakeLists.txt:30-56, 112-152,
|
||||||
|
emulator-core/src/main/cpp/xendroid_emu.cpp:333-346, 671-676,
|
||||||
|
app/src/main/java/xendroid/compose/data/GameFormat.kt:6, 26-32
|
||||||
|
|
||||||
|
Releases are tagged XenDroid-<short commit> and the version name is the git
|
||||||
|
hash handed to the build, so b70d643 is both the head of main and the current
|
||||||
|
release. version.h names canary_experimental dc561e4df, carried over from the
|
||||||
|
ax360e tree the project started as, and it does not describe the vendored
|
||||||
|
code. The Edge revision is named by the periodic merge pull request instead,
|
||||||
|
and Edge rebases its branch, so that commit is no longer reachable there.
|
||||||
|
ref: app/build.gradle:34, emulator-core/src/main/cpp/version.h:4-5,
|
||||||
|
.github/workflows/XenDroid.yml:185-187
|
||||||
|
|
||||||
|
No Xbox 360 system file is read. xboxkrnl, xam and xbdm are HLE modules
|
||||||
|
registered at startup, the XEX1 retail, XEX2 retail and XEX2 devkit keys are
|
||||||
|
constant arrays tried in turn when an image is read, and every XConfig setting
|
||||||
|
is answered from cvars and constants rather than from a flash image. When the
|
||||||
|
launched title is itself a system title the kernel resolves xam.xex, then
|
||||||
|
$flash_xam.xex, through the guest filesystem under the \SystemRoot symlink
|
||||||
|
pointing at that title's own directory.
|
||||||
|
ref: emulator-core/src/main/cpp/xenia/src/xenia/emulator.cc:421-428, 757-772,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/cpu/xex_module.cc:55-63, 925-935,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/kernel/xconfig.cc:89-159
|
||||||
|
|
||||||
|
The storage root is the compose external files directory of the package and is
|
||||||
|
passed as a launch argument beside the config path and the log path. content,
|
||||||
|
cache, cache0, cache1, patches and plugins hang off it, the global
|
||||||
|
configuration is xenia-canary.config.toml and per title overrides live in
|
||||||
|
config/<TITLE_ID>.config.toml. The custom driver directory sits in internal
|
||||||
|
storage instead, because the external filesystem cannot carry an executable
|
||||||
|
mapping.
|
||||||
|
ref: emulator-core/src/main/java/xendroid/compose/Application.java:14-33, 84-88,
|
||||||
|
app/src/main/java/xendroid/compose/EmulatorHostActivity.kt:231-236,
|
||||||
|
emulator-core/src/main/cpp/xendroid_emu.cpp:312-317, 355-381
|
||||||
|
|
||||||
|
479 game patches ship inside the APK, synced at build time from the
|
||||||
|
xenia-canary game-patches submodule pinned at 3553a5ae. The patch database
|
||||||
|
reads the patches directory only, so a bundled patch reaches the emulator once
|
||||||
|
the user toggles it, which writes the asset out under the same name.
|
||||||
|
ref: app/build.gradle:12-19,
|
||||||
|
app/src/main/java/xendroid/compose/patches/PatchAssets.kt:17-23,
|
||||||
|
app/src/main/java/xendroid/compose/patches/PatchStore.kt:23-33,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/patcher/patch_db.cc:34-60
|
||||||
|
|
||||||
|
ES-DE finds the emulator by the xendroid.compose/.EmulatorHostActivity package
|
||||||
|
rule and hands the game over as the intent data URI.
|
||||||
|
ref: app/src/main/AndroidManifest.xml:54-73, docs/frontend-integration.md
|
||||||
|
|
||||||
|
files:
|
||||||
|
- name: "<driver>.zip"
|
||||||
|
required: false
|
||||||
|
config_key: "Vulkan|vulkan_lib_path"
|
||||||
|
unsourceable: "third-party Vulkan driver built for one GPU family, not an emulator artefact"
|
||||||
|
description: "Replacement Vulkan driver package"
|
||||||
|
note: >-
|
||||||
|
Imported through a picker restricted to application/zip. The archive is
|
||||||
|
read whole, meta.json names the library to keep, and a single .so is taken
|
||||||
|
instead when no meta.json is present; the .so files and meta.json are
|
||||||
|
unpacked into a directory named after the archive, in internal storage.
|
||||||
|
The configured path is read before the instance is created and opened
|
||||||
|
through adrenotools when the file exists, otherwise the system libvulkan.so
|
||||||
|
is used. The row is hidden on devices without /dev/kgsl-3d0.
|
||||||
|
source_ref: "app/src/main/java/xendroid/compose/ui/settings/SettingRows.kt:175-200, app/src/main/java/xendroid/compose/settings/SettingsRepository.kt:34-35, 140, emulator-core/src/main/java/xendroid/compose/Utils.java:164-236, emulator-core/src/main/java/xendroid/compose/Application.java:21-24, emulator-core/src/main/cpp/xenia/src/xenia/ui/vulkan/vulkan_instance.cc:49, 168-192, 203"
|
||||||
|
|
||||||
|
- name: "<font>.ttf"
|
||||||
|
required: false
|
||||||
|
config_key: "UI|custom_font_path"
|
||||||
|
unsourceable: "any TrueType face the user points the setting at, with no name or version the code expects"
|
||||||
|
description: "Replacement face for the overlay text"
|
||||||
|
note: >-
|
||||||
|
Loaded when the configured path exists, over the glyph ranges the atlas is
|
||||||
|
built with. A path that does not resolve, or a face that fails to build,
|
||||||
|
leaves the embedded Inter face in place, so the absence is covered.
|
||||||
|
source_ref: "emulator-core/src/main/cpp/xenia/src/xenia/ui/imgui_drawer.cc:39-44, 353-366, 367-376"
|
||||||
|
|
||||||
|
- name: "<sound>.wav"
|
||||||
|
required: false
|
||||||
|
config_key: "UI|achievement_sound_path"
|
||||||
|
unsourceable: "any sound file the user points the setting at, with no name or version the code expects"
|
||||||
|
description: "Sound played when an achievement unlocks"
|
||||||
|
note: >-
|
||||||
|
Read through miniaudio, which accepts WAV, MP3, OGG and FLAC. The engine is
|
||||||
|
built the first time an achievement fires, and an empty or missing path
|
||||||
|
leaves the notification silent. Config written under the older key
|
||||||
|
General|notification_sound_path is carried to this cvar when the file is
|
||||||
|
read, and that is the key the shipped template still carries.
|
||||||
|
source_ref: "emulator-core/src/main/cpp/xenia/src/xenia/ui/audio_helper.cc:21-24, 38-80, 97-101, emulator-core/src/main/cpp/xenia/src/xenia/kernel/xam/achievement_manager.cc:163-166, emulator-core/src/main/cpp/xenia/src/xenia/config.cc:174-190, emulator-core/src/main/cpp/xenia/src/xenia/ui/config_helpers.h:47"
|
||||||
|
|
||||||
|
- name: "<title_id> - <title>.patch.toml"
|
||||||
|
required: false
|
||||||
|
bundled: true
|
||||||
|
config_key: "General|apply_patches"
|
||||||
|
description: "Memory patch set for one title"
|
||||||
|
note: >-
|
||||||
|
Read from the patches directory under the storage root, keeping names that
|
||||||
|
open with eight hexadecimal digits and close with .patch.toml. The title id
|
||||||
|
and title name fields and a hash node are mandatory, the file is dropped
|
||||||
|
without them, and each entry of the patch array is applied only when its
|
||||||
|
is_enabled flag is set and the module hash matches. Patching is on by
|
||||||
|
default.
|
||||||
|
source_ref: "emulator-core/src/main/cpp/xenia/src/xenia/patcher/patch_db.h:124-125, emulator-core/src/main/cpp/xenia/src/xenia/patcher/patch_db.cc:34-60, 63-105, emulator-core/src/main/cpp/xenia/src/xenia/patcher/patcher.cc:22-37, emulator-core/src/main/cpp/xenia/src/xenia/emulator.cc:415"
|
||||||
|
|
||||||
|
- name: plugins.toml
|
||||||
|
required: false
|
||||||
|
config_key: "General|allow_plugins"
|
||||||
|
unsourceable: "per-title manifest written by whoever authors the mod, with no distributed form"
|
||||||
|
description: "Plugin manifest for one title"
|
||||||
|
note: >-
|
||||||
|
Read from plugins/<TITLE_ID>/ under the storage root, where the directory
|
||||||
|
name is eight hexadecimal digits. Each entry of the plugin array needs a
|
||||||
|
hash node, and an entry without one is skipped. Plugin loading is off by
|
||||||
|
default, so nothing under plugins is scanned until it is turned on.
|
||||||
|
source_ref: "emulator-core/src/main/cpp/xenia/src/xenia/patcher/plugin_loader.cc:16-21, 27-37, 40-56, 58-125, emulator-core/src/main/cpp/xenia/src/xenia/emulator.cc:431-432"
|
||||||
|
|
||||||
|
- name: "<plugin>.xex"
|
||||||
|
required: false
|
||||||
|
unsourceable: "homebrew module built for one title, distributed with the mod it belongs to"
|
||||||
|
description: "Plugin module named by a plugin manifest"
|
||||||
|
note: >-
|
||||||
|
The title directory is mounted as the plugins device and each enabled entry
|
||||||
|
whose hash matches the running module is loaded as a user module on its own
|
||||||
|
thread.
|
||||||
|
source_ref: "emulator-core/src/main/cpp/xenia/src/xenia/patcher/plugin_loader.cc:175-233, 235-252, emulator-core/src/main/cpp/xenia/src/xenia/emulator.cc:2625-2630"
|
||||||
|
|
||||||
|
- name: Account
|
||||||
|
required: false
|
||||||
|
load_from: content_dir
|
||||||
|
path: "content/<XUID>/FFFE07D1/00010000/<XUID>/Account"
|
||||||
|
unsourceable: "per-user blob the emulator encrypts with the console key on first run"
|
||||||
|
description: "Encrypted profile account blob"
|
||||||
|
note: >-
|
||||||
|
A 0x10 hash, an 8 byte confounder and an encrypted X_XAMACCOUNTINFO. Read
|
||||||
|
from the profile directory when the content tree is enumerated and from the
|
||||||
|
mounted profile when a XUID is logged in, decrypted with the retail key
|
||||||
|
first and the devkit key second, against the HMAC the first sixteen bytes
|
||||||
|
carry. The frontend creates one for the gamertag XenDroid on first run when
|
||||||
|
the tree holds none, and writes its XUID to the slot 0 setting.
|
||||||
|
source_ref: "emulator-core/src/main/cpp/xenia/src/xenia/kernel/xam/profile_standalone.cc:24-52, 72-99, 129-141, emulator-core/src/main/cpp/xenia/src/xenia/kernel/xam/profile_manager.cc:256-296, app/src/main/java/xendroid/compose/core/ProfileBootstrap.kt:13-28, app/src/main/java/xendroid/compose/core/ProfilePaths.kt:6-13"
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
The file loads present in the vendored tree that this build does not reach are
|
||||||
|
not listed. tahoma.ttf and msgothic.ttc are read by the Windows font paths
|
||||||
|
only, and the two fontconfig matches are compiled out by
|
||||||
|
XE_PLATFORM_LINUX && !(XE_PLATFORM_ANDROID || XE_PLATFORM_xendroid), because
|
||||||
|
platform.h defines XE_PLATFORM_xendroid and XE_PLATFORM_LINUX for this target
|
||||||
|
and leaves XE_PLATFORM_ANDROID commented out. gamecontrollerdb.txt belongs to the SDL
|
||||||
|
input driver, and xenia-hid-sdl is absent from the link list, which carries
|
||||||
|
xenia-hid-nop and the fork's own Android driver. portable.txt is read by
|
||||||
|
xenia_main.cc, which is not compiled, the application supplying its own
|
||||||
|
windowed app. The profile picture the gamercard dialog reads through
|
||||||
|
ReadPngFromFile is never reached: the Android file picker returns false without
|
||||||
|
showing anything, so no path is ever selected. librenderdoc.so is opened with
|
||||||
|
RTLD_NOLOAD, which returns a handle only when the library is already mapped and
|
||||||
|
never reads the file. Edge's in-binary patch bundle, its game compatibility
|
||||||
|
bundle and its game title database are packed from build/data_repos, which
|
||||||
|
xenia-build.py fetches and the Gradle build never runs, so the bundle compiled
|
||||||
|
in is empty and the APK assets are the only patch source; the locale bundle is
|
||||||
|
guarded off when the CMake system name is Android. Two profile files sit beside
|
||||||
|
the Account and are not listed: tile_32.png is written and never read back, and
|
||||||
|
tile_64.png is written by the frontend from a picture the user picks and read
|
||||||
|
only to draw the avatar, the core testing its existence and nothing more.
|
||||||
|
ref: emulator-core/src/main/cpp/xenia/src/xenia/ui/imgui_drawer.cc:389-405, 418-465, 474-490, 500-536,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/base/platform.h:34-40,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/hid/sdl/CMakeLists.txt:7-8,
|
||||||
|
emulator-core/src/main/cpp/CMakeLists.txt:112-152,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/app/xenia_main.cc:95-99,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/app/xenia_main.cc:561,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/kernel/xam/ui/gamercard_ui.cc:339-368,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/ui/file_picker_android.cc:27-34,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/ui/renderdoc_api.cc:33-41,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/patcher/CMakeLists.txt:6-7,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/app/CMakeLists.txt:213-219,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/ui/CMakeLists.txt:66-84,
|
||||||
|
emulator-core/src/main/cpp/xenia/tools/build/embed_bundle.py:55-57,
|
||||||
|
app/src/main/java/xendroid/compose/ui/profile/ProfileManagerViewModel.kt:173-181,
|
||||||
|
emulator-core/src/main/cpp/xenia/src/xenia/kernel/xam/profile_standalone.cc:140-141
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
emulator: XeniOS
|
||||||
|
type: standalone
|
||||||
|
core_classification: community_fork
|
||||||
|
source: "https://github.com/xenios-jp/XeniOS"
|
||||||
|
upstream: "https://github.com/has207/xenia-edge"
|
||||||
|
profiled_date: "2026-08-12"
|
||||||
|
source_commit: "87b176a078c316fde3adf67a217f0c44615b0e0d"
|
||||||
|
upstream_commit: "07021f019cf55105bc26c0474e0b0835808353e2"
|
||||||
|
core_version: "2.0.1"
|
||||||
|
display_name: "Microsoft - Xbox 360 (XeniOS)"
|
||||||
|
cores:
|
||||||
|
- "xenios"
|
||||||
|
- "XENIOS"
|
||||||
|
systems:
|
||||||
|
- microsoft-xbox-360
|
||||||
|
mode: standalone
|
||||||
|
|
||||||
|
notes: |
|
||||||
|
Xbox 360 emulator for macOS and iOS, forked from Xenia Edge by xenios-jp and
|
||||||
|
published as xenios_macos_apple_silicon.dmg, xenios_macos_intel.dmg,
|
||||||
|
xenios_macos_universal.dmg and xenios_ios_iphone_ipad.ipa. The 2.0.1 disk
|
||||||
|
image holds a single bundle, Xenia-edge.app, carrying the executable, an
|
||||||
|
icon, a compiled asset catalog and two dylibs under Contents/Frameworks.
|
||||||
|
|
||||||
|
Rendering runs on Metal. Guest DXBC is converted to DXIL through
|
||||||
|
libdxilconv.dylib, built from the fork's own DirectX Shader Compiler branch,
|
||||||
|
then to Metal IR through Apple's Metal Shader Converter
|
||||||
|
(libmetalirconverter.dylib), which the build requires present before it will
|
||||||
|
configure. Both are linked as imported shared libraries and copied into the
|
||||||
|
bundle before it is signed (third_party/CMakeLists.txt:432-448, 489-579,
|
||||||
|
src/xenia/app/CMakeLists.txt:347-363, 371-378), so the code calls IRCompilerCreate
|
||||||
|
and DxcCreateInstance as ordinary symbols and never names either file
|
||||||
|
(gpu/metal/metal_shader_converter.cc:83, gpu/metal/dxbc_to_dxil_converter.cc:103).
|
||||||
|
MoltenVK is statically linked and its entry points resolve as real symbols,
|
||||||
|
so the Vulkan backend loads no loader library
|
||||||
|
(ui/vulkan/vulkan_instance.cc:30-33, 81-82).
|
||||||
|
|
||||||
|
No Xbox 360 system file is read. xboxkrnl, xam and xbdm are C++ HLE modules
|
||||||
|
registered at startup (emulator.cc:425-427), the XEX1 and XEX2 retail keys
|
||||||
|
and the zeroed devkit key are constexpr arrays in the binary
|
||||||
|
(cpu/xex_module.cc:55-63, used at 344 and 503), and every XConfig setting is
|
||||||
|
assembled from cvars and constants by BuildSetting, in a file that makes no
|
||||||
|
filesystem call at all (kernel/xconfig.cc:87-246). Launching a system title
|
||||||
|
symlinks \SystemRoot to that title's own mount and resolves xam.xex, then
|
||||||
|
$flash_xam.xex, through the guest filesystem (emulator.cc:744-762): a
|
||||||
|
companion module inside the dump the user launched, not a host lookup.
|
||||||
|
|
||||||
|
The fork's data ships inside the executable. assets/font and assets/icon are
|
||||||
|
linked in by xe_embed_binary_assets and the 33 assets/locale catalogues are
|
||||||
|
compiled to .mo at configure time and bundled, with no .mo written beside the
|
||||||
|
binary (ui/CMakeLists.txt:55-58, 64-83). The UI font is read from that buffer
|
||||||
|
with AddFontFromMemoryTTF (ui/imgui_drawer.cc:367-377), and xe::EmbeddedBundle
|
||||||
|
decodes the SDL controller mappings (hid/sdl/sdl_input_driver.cc:148-165), the
|
||||||
|
canary game patches (patcher/patch_db.cc:303-318) and the canary.json and
|
||||||
|
stable.json compatibility lists (app/game_compat_db.cc:65-79).
|
||||||
|
|
||||||
|
Three cvars accept a file and name none by default, so nothing is expected at
|
||||||
|
a fixed path: custom_font_path falls back to the embedded font
|
||||||
|
(ui/imgui_drawer.cc:39-44, 353-377), mappings_file to the embedded controller
|
||||||
|
DB (hid/sdl/sdl_input_driver.cc:35-39, 148-152), achievement_sound_path leaves
|
||||||
|
the achievement sound silent (ui/audio_helper.cc:21-25, 44-48). Each carries an
|
||||||
|
UPDATE_from_path rule that clears the earlier default out of an existing config.
|
||||||
|
|
||||||
|
Everything under the storage root is written by the emulator or dropped in by
|
||||||
|
the user: xenia-edge.config.toml and per-title config/<title id>.config.toml
|
||||||
|
(config.cc:44-52), patches/*.patch.toml read on top of the embedded set
|
||||||
|
(patcher/patch_db.cc:29-60, app/xenia_main_ios.mm:275-300), plugins/<title id>/plugins.toml
|
||||||
|
behind allow_plugins, which defaults false (patcher/plugin_loader.cc:16-18, 40-62),
|
||||||
|
content, cache_host and the per-module executable_addr_flags.bin analysis cache
|
||||||
|
(app/xenia_main.cc:588-613, cpu/xex_module.cc:1336-1343). portable.txt next to
|
||||||
|
the executable keeps the storage root there instead of the user folder
|
||||||
|
(app/xenia_main.cc:556-570). On iOS the touch layouts live as
|
||||||
|
Documents/touch-layouts/<id>.toml, written by the layout editor
|
||||||
|
(ui/ios/touch/touch_layout_store_ios.mm:117-139).
|
||||||
|
|
||||||
|
files: []
|
||||||
|
|
||||||
|
exclusion_note: >
|
||||||
|
XeniOS emulates the Xbox 360 by high-level emulation and reads no BIOS,
|
||||||
|
firmware, NAND image, flash dump or keyvault at any point: the kernel, XAM
|
||||||
|
and XBDM are compiled-in modules, the XEX AES keys are constant arrays and
|
||||||
|
XConfig is synthesised. Its own data (UI font, icons, locale catalogues, SDL
|
||||||
|
controller mappings, game patches, compatibility lists) is compressed into
|
||||||
|
the executable through xe_embed_binary_assets and xe_embed_compressed_bundle,
|
||||||
|
so none of it exists as a file beside the binary. The three cvars that accept
|
||||||
|
a path default to empty and fall back to those embedded copies. The two
|
||||||
|
dylibs under Contents/Frameworks, libmetalirconverter.dylib and
|
||||||
|
libdxilconv.dylib, are shader translation components linked at build time and
|
||||||
|
resolved by the loader through @rpath; no code path names them, and they are
|
||||||
|
obtained by the same download that provides the executable.
|
||||||
Reference in new issue
Block a user