Compare commits

...

25 Commits

Author SHA1 Message Date
Logan McNaughton 84dcc6c154 fix image scale when using upscaling (#317) 2025-03-10 22:53:16 +01:00
Logan McNaughton 8aa23e1665 bump to 1.0.12 (#316) 2025-03-10 17:22:51 +01:00
Logan McNaughton f2b75a2dcc update cargo packages 2025-03-10 17:14:04 +01:00
Logan McNaughton 5bac846bda update shaders (#315) 2025-03-10 17:13:45 +01:00
Logan McNaughton e93c275795 Add option for CRT shader (#314)
* add CRT shader

* more

* more

* update type

* more

* more

* more

* more
2025-03-10 16:52:25 +01:00
Logan McNaughton 67a8bb5e4c show VRU dialog in main window (#311) 2025-03-09 22:20:16 +01:00
Logan McNaughton 2828accee1 re-arrange UI struct (#310)
* re-arrange UI struct

* format
2025-03-09 10:30:43 +01:00
Logan McNaughton 16a9754bda GB MBC1 support (#309) 2025-03-08 21:48:51 +01:00
Logan McNaughton fbe95767f5 update zip 2025-03-07 18:40:11 +01:00
Logan McNaughton 0989be1e0f update cargo packages 2025-03-07 18:36:08 +01:00
Logan McNaughton e73816541e condense code (#308) 2025-03-07 18:35:48 +01:00
Logan McNaughton f6b2342e0e always make the window resizeable (#305) 2025-03-07 10:43:35 +01:00
Logan McNaughton 7ab57d592b bump to 1.0.11 (#301) 2025-03-05 15:20:42 +01:00
Logan McNaughton a2cda03c8d update cargo packages 2025-03-05 15:12:05 +01:00
Logan McNaughton a07237aa64 set netplay buffer target (#300) 2025-03-04 21:23:33 +01:00
Logan McNaughton fdc17f4ae5 make is viewer optional (#299)
* make is viewer optional

* more
2025-03-04 18:52:47 +01:00
Logan McNaughton 4802f3b71a remove pub 2025-03-04 12:03:30 +01:00
Logan McNaughton a4c505c72d remove some code duplication (#298) 2025-03-04 10:12:56 +01:00
Logan McNaughton 30cb3f8339 add some randomness (#297) 2025-03-04 09:45:25 +01:00
Logan McNaughton a5f5867ebb update cargo packages 2025-03-03 10:03:44 +01:00
Logan McNaughton ee8e34e17c Add audio file 2025-03-01 21:59:35 +01:00
Logan McNaughton da1e686c1a Add option for overclocking (#293)
* add option to overclock CPU

* netplay

* more

* more

* more

* more

* more
2025-02-28 21:34:33 +01:00
Logan McNaughton 5a3609d501 add option to crop out letterbox (#292) 2025-02-28 09:47:34 +01:00
Logan McNaughton 7b51ca82eb add widescreen stretch option (#291) 2025-02-27 22:05:19 +01:00
Logan McNaughton ee77e75855 bump to 1.0.10 (#290) 2025-02-27 17:22:19 +01:00
46 changed files with 2290 additions and 696 deletions
Generated
+252 -217
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -1,6 +1,6 @@
[package]
name = "gopher64"
version = "1.0.9"
version = "1.0.12"
edition = "2024"
rust-version = "1.85"
@@ -8,7 +8,7 @@ rust-version = "1.85"
[dependencies]
dirs = "6.0"
zip = "2.1"
zip = "2.2"
governor = "0.8"
sevenz-rust = "0.6"
chrono = "0.4"
@@ -27,6 +27,7 @@ mimalloc = "0.1"
regex = "1.11"
tungstenite = "0.26"
socket2 = "0.5"
rand_chacha = "0.9"
fatfs = "0.3"
semver = "1.0"
postcard = { version = "1.1", features = ["use-std"] }
Binary file not shown.
+135
View File
@@ -0,0 +1,135 @@
#version 450
/*
CRT Shader by EasyMode
License: GPL
*/
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OutputSize;
} params;
#define SHARPNESS_IMAGE 1.0
#define SHARPNESS_EDGES 3.0
#define GLOW_WIDTH 0.5
#define GLOW_HEIGHT 0.5
#define GLOW_HALATION 0.1
#define GLOW_DIFFUSION 0.05
#define MASK_COLORS 2.0
#define MASK_STRENGTH 0.3
#define MASK_SIZE 1.0
#define SCANLINE_SIZE_MIN 0.5
#define SCANLINE_SIZE_MAX 1.5
#define SCANLINE_SHAPE 2.5
#define SCANLINE_OFFSET 1.0
#define GAMMA_INPUT 2.4
#define GAMMA_OUTPUT 2.4
#define BRIGHTNESS 1.5
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#define FIX(c) max(abs(c), 1e-5)
#define PI 3.141592653589
#define TEX2D(c) pow(texture(tex, c).rgb, vec3(GAMMA_INPUT))
#define saturate(c) clamp(c, 0.0, 1.0)
mat3x3 get_color_matrix(sampler2D tex, vec2 co, vec2 dx)
{
return mat3x3(TEX2D(co - dx), TEX2D(co), TEX2D(co + dx));
}
vec3 blur(mat3 m, float dist, float rad)
{
vec3 x = vec3(dist - 1.0, dist, dist + 1.0) / rad;
vec3 w = exp2(x * x * -1.0);
return (m[0] * w.x + m[1] * w.y + m[2] * w.z) / (w.x + w.y + w.z);
}
vec3 filter_gaussian(sampler2D tex, vec2 co, vec2 tex_size)
{
vec2 dx = vec2(1.0 / tex_size.x, 0.0);
vec2 dy = vec2(0.0, 1.0 / tex_size.y);
vec2 pix_co = co * tex_size;
vec2 tex_co = (floor(pix_co) + 0.5) / tex_size;
vec2 dist = (fract(pix_co) - 0.5) * -1.0;
mat3x3 line0 = get_color_matrix(tex, tex_co - dy, dx);
mat3x3 line1 = get_color_matrix(tex, tex_co, dx);
mat3x3 line2 = get_color_matrix(tex, tex_co + dy, dx);
mat3x3 column = mat3x3(blur(line0, dist.x, GLOW_WIDTH),
blur(line1, dist.x, GLOW_WIDTH),
blur(line2, dist.x, GLOW_WIDTH));
return blur(column, dist.y, GLOW_HEIGHT);
}
vec3 filter_lanczos(sampler2D tex, vec2 co, vec2 tex_size, float sharp)
{
tex_size.x *= sharp;
vec2 dx = vec2(1.0 / tex_size.x, 0.0);
vec2 pix_co = co * tex_size - vec2(0.5, 0.0);
vec2 tex_co = (floor(pix_co) + vec2(0.5, 0.001)) / tex_size;
vec2 dist = fract(pix_co);
vec4 coef = PI * vec4(dist.x + 1.0, dist.x, dist.x - 1.0, dist.x - 2.0);
coef = FIX(coef);
coef = 2.0 * sin(coef) * sin(coef / 2.0) / (coef * coef);
coef /= dot(coef, vec4(1.0));
vec4 col1 = vec4(TEX2D(tex_co), 1.0);
vec4 col2 = vec4(TEX2D(tex_co + dx), 1.0);
return (mat4x4(col1, col1, col2, col2) * coef).rgb;
}
vec3 get_scanline_weight(float x, vec3 col)
{
vec3 beam = mix(vec3(SCANLINE_SIZE_MIN), vec3(SCANLINE_SIZE_MAX), pow(col, vec3(1.0 / SCANLINE_SHAPE)));
vec3 x_mul = 2.0 / beam;
vec3 x_offset = x_mul * 0.5;
return smoothstep(0.0, 1.0, 1.0 - abs(x * x_mul - x_offset)) * x_offset;
}
vec3 get_mask_weight(float x)
{
float i = mod(floor(x * params.OutputSize.x * params.SourceSize.x / (params.SourceSize.x * MASK_SIZE)), MASK_COLORS);
if (i == 0.0) return mix(vec3(1.0, 0.0, 1.0), vec3(1.0, 0.0, 0.0), MASK_COLORS - 2.0);
else if (i == 1.0) return vec3(0.0, 1.0, 0.0);
else return vec3(0.0, 0.0, 1.0);
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 0) uniform sampler2D Source;
void main()
{
float scale = floor(params.OutputSize.y * params.SourceSize.w);
float offset = 1.0 / scale * 0.5;
if (bool(mod(scale, 2.0))) offset = 0.0;
vec2 co = (vTexCoord * params.SourceSize.xy - vec2(0.0, offset * SCANLINE_OFFSET)) * params.SourceSize.zw;
vec3 col_glow = filter_gaussian(Source, co, params.SourceSize.xy);
vec3 col_soft = filter_lanczos(Source, co, params.SourceSize.xy, SHARPNESS_IMAGE);
vec3 col_sharp = filter_lanczos(Source, co, params.SourceSize.xy, SHARPNESS_EDGES);
vec3 col = sqrt(col_sharp * col_soft);
col *= get_scanline_weight(fract(co.y * params.SourceSize.y), col_soft);
col_glow = saturate(col_glow - col);
col += col_glow * col_glow * GLOW_HALATION;
col = mix(col, col * get_mask_weight(vTexCoord.x) * MASK_COLORS, MASK_STRENGTH);
col += col_glow * GLOW_DIFFUSION;
col = pow(col * BRIGHTNESS, vec3(1.0 / GAMMA_OUTPUT));
FragColor = vec4(col, 1.0);
}
+453
View File
@@ -0,0 +1,453 @@
{0x07230203,0x00010300,0x000d000b,0x000004fd,
0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,
0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000004,0x00000004,0x6e69616d,
0x00000000,0x000001ba,0x0000021a,0x00030010,
0x00000004,0x00000007,0x00030047,0x00000185,
0x00000002,0x00050048,0x00000185,0x00000000,
0x00000023,0x00000000,0x00050048,0x00000185,
0x00000001,0x00000023,0x00000010,0x00040047,
0x000001ba,0x0000001e,0x00000000,0x00040047,
0x000001ca,0x00000021,0x00000000,0x00040047,
0x000001ca,0x00000022,0x00000000,0x00040047,
0x0000021a,0x0000001e,0x00000000,0x00020013,
0x00000002,0x00030021,0x00000003,0x00000002,
0x00030016,0x00000006,0x00000020,0x00090019,
0x00000007,0x00000006,0x00000001,0x00000000,
0x00000000,0x00000000,0x00000001,0x00000000,
0x0003001b,0x00000008,0x00000007,0x00040020,
0x00000009,0x00000000,0x00000008,0x00040017,
0x0000000a,0x00000006,0x00000002,0x00040017,
0x0000000c,0x00000006,0x00000003,0x00040017,
0x00000037,0x00000006,0x00000004,0x0004002b,
0x00000006,0x0000003a,0x4019999a,0x0006002c,
0x0000000c,0x0000003b,0x0000003a,0x0000003a,
0x0000003a,0x0004002b,0x00000006,0x00000049,
0x3f800000,0x0004002b,0x00000006,0x0000004a,
0x00000000,0x0004002b,0x00000006,0x00000068,
0xbf800000,0x00040015,0x0000006b,0x00000020,
0x00000001,0x0004002b,0x0000006b,0x0000006c,
0x00000000,0x00040015,0x0000006f,0x00000020,
0x00000000,0x0004002b,0x0000006f,0x00000070,
0x00000000,0x0004002b,0x0000006b,0x00000074,
0x00000001,0x0004002b,0x0000006f,0x00000077,
0x00000001,0x0004002b,0x00000006,0x000000a1,
0x3f000000,0x0005002c,0x0000000a,0x000000fc,
0x000000a1,0x0000004a,0x0004002b,0x00000006,
0x00000101,0x3a83126f,0x0005002c,0x0000000a,
0x00000102,0x000000a1,0x00000101,0x0004002b,
0x00000006,0x0000010b,0x40490fdb,0x0004002b,
0x00000006,0x00000116,0x40000000,0x0004002b,
0x00000006,0x0000011c,0x3727c5ac,0x0007002c,
0x00000037,0x0000012c,0x00000049,0x00000049,
0x00000049,0x00000049,0x00040018,0x00000149,
0x00000037,0x00000004,0x0006002c,0x0000000c,
0x00000165,0x000000a1,0x000000a1,0x000000a1,
0x0004002b,0x00000006,0x00000166,0x3fc00000,
0x0006002c,0x0000000c,0x00000167,0x00000166,
0x00000166,0x00000166,0x0004002b,0x00000006,
0x00000169,0x3ecccccd,0x0006002c,0x0000000c,
0x0000016a,0x00000169,0x00000169,0x00000169,
0x0004001e,0x00000185,0x00000037,0x00000037,
0x00040020,0x00000186,0x00000009,0x00000185,
0x0004003b,0x00000186,0x00000187,0x00000009,
0x00040020,0x00000188,0x00000009,0x00000006,
0x00020014,0x00000196,0x0006002c,0x0000000c,
0x0000019a,0x00000049,0x0000004a,0x00000049,
0x0006002c,0x0000000c,0x000001a1,0x0000004a,
0x00000049,0x0000004a,0x0006002c,0x0000000c,
0x000001a4,0x0000004a,0x0000004a,0x00000049,
0x0004002b,0x0000006f,0x000001aa,0x00000003,
0x00040020,0x000001b9,0x00000001,0x0000000a,
0x0004003b,0x000001b9,0x000001ba,0x00000001,
0x00040020,0x000001bc,0x00000009,0x00000037,
0x0004003b,0x00000009,0x000001ca,0x00000000,
0x0004002b,0x00000006,0x000001dc,0x40400000,
0x0004002b,0x00000006,0x000001ff,0x3dcccccd,
0x00040020,0x00000206,0x00000001,0x00000006,
0x0004002b,0x00000006,0x0000020c,0x3e99999a,
0x0004002b,0x00000006,0x00000210,0x3d4ccccd,
0x0004002b,0x00000006,0x00000216,0x3ed55555,
0x0006002c,0x0000000c,0x00000217,0x00000216,
0x00000216,0x00000216,0x00040020,0x00000219,
0x00000003,0x00000037,0x0004003b,0x00000219,
0x0000021a,0x00000003,0x0005002c,0x0000000a,
0x000004f3,0x000000a1,0x000000a1,0x0007002c,
0x00000037,0x000004f4,0x0000011c,0x0000011c,
0x0000011c,0x0000011c,0x0006002c,0x0000000c,
0x000004f6,0x00000116,0x00000116,0x00000116,
0x0006002c,0x0000000c,0x000004f7,0x00000049,
0x00000049,0x00000049,0x0006002c,0x0000000c,
0x000004f8,0x0000004a,0x0000004a,0x0000004a,
0x0006002c,0x0000000c,0x000004f9,0x0000020c,
0x0000020c,0x0000020c,0x0007002c,0x00000037,
0x000004fa,0x000000a1,0x000000a1,0x000000a1,
0x000000a1,0x0004002b,0x00000006,0x000004fb,
0x3eaaaaab,0x00050036,0x00000002,0x00000004,
0x00000000,0x00000003,0x000200f8,0x00000005,
0x00060041,0x00000188,0x000001a8,0x00000187,
0x00000074,0x00000077,0x0004003d,0x00000006,
0x000001a9,0x000001a8,0x00060041,0x00000188,
0x000001ab,0x00000187,0x0000006c,0x000001aa,
0x0004003d,0x00000006,0x000001ac,0x000001ab,
0x00050085,0x00000006,0x000001ad,0x000001a9,
0x000001ac,0x0006000c,0x00000006,0x000001ae,
0x00000001,0x00000008,0x000001ad,0x00050088,
0x00000006,0x000001b2,0x000000a1,0x000001ae,
0x0005008d,0x00000006,0x000001b4,0x000001ae,
0x00000116,0x000500b7,0x00000196,0x000001b5,
0x000001b4,0x0000004a,0x000600a9,0x00000006,
0x000004fc,0x000001b5,0x0000004a,0x000001b2,
0x0004003d,0x0000000a,0x000001bb,0x000001ba,
0x00050041,0x000001bc,0x000001bd,0x00000187,
0x0000006c,0x0004003d,0x00000037,0x000001be,
0x000001bd,0x0007004f,0x0000000a,0x000001bf,
0x000001be,0x000001be,0x00000000,0x00000001,
0x00050085,0x0000000a,0x000001c0,0x000001bb,
0x000001bf,0x00050050,0x0000000a,0x000001c3,
0x0000004a,0x000004fc,0x00050083,0x0000000a,
0x000001c4,0x000001c0,0x000001c3,0x0007004f,
0x0000000a,0x000001c7,0x000001be,0x000001be,
0x00000002,0x00000003,0x00050085,0x0000000a,
0x000001c8,0x000001c4,0x000001c7,0x00050051,
0x00000006,0x00000249,0x000001be,0x00000000,
0x00050088,0x00000006,0x0000024a,0x00000049,
0x00000249,0x00050050,0x0000000a,0x0000024b,
0x0000024a,0x0000004a,0x00050051,0x00000006,
0x0000024d,0x000001be,0x00000001,0x00050088,
0x00000006,0x0000024e,0x00000049,0x0000024d,
0x00050050,0x0000000a,0x0000024f,0x0000004a,
0x0000024e,0x00050085,0x0000000a,0x00000252,
0x000001c8,0x000001bf,0x0006000c,0x0000000a,
0x00000254,0x00000001,0x00000008,0x00000252,
0x00050081,0x0000000a,0x00000256,0x00000254,
0x000004f3,0x00050088,0x0000000a,0x00000258,
0x00000256,0x000001bf,0x0006000c,0x0000000a,
0x0000025a,0x00000001,0x0000000a,0x00000252,
0x00050083,0x0000000a,0x0000025c,0x0000025a,
0x000004f3,0x0005008e,0x0000000a,0x0000025d,
0x0000025c,0x00000068,0x00050083,0x0000000a,
0x00000260,0x00000258,0x0000024f,0x0004003d,
0x00000008,0x0000028a,0x000001ca,0x00050083,
0x0000000a,0x0000028d,0x00000260,0x0000024b,
0x00050057,0x00000037,0x0000028e,0x0000028a,
0x0000028d,0x0008004f,0x0000000c,0x0000028f,
0x0000028e,0x0000028e,0x00000000,0x00000001,
0x00000002,0x0007000c,0x0000000c,0x00000290,
0x00000001,0x0000001a,0x0000028f,0x0000003b,
0x00050057,0x00000037,0x00000293,0x0000028a,
0x00000260,0x0008004f,0x0000000c,0x00000294,
0x00000293,0x00000293,0x00000000,0x00000001,
0x00000002,0x0007000c,0x0000000c,0x00000295,
0x00000001,0x0000001a,0x00000294,0x0000003b,
0x00050081,0x0000000a,0x00000299,0x00000260,
0x0000024b,0x00050057,0x00000037,0x0000029a,
0x0000028a,0x00000299,0x0008004f,0x0000000c,
0x0000029b,0x0000029a,0x0000029a,0x00000000,
0x00000001,0x00000002,0x0007000c,0x0000000c,
0x0000029c,0x00000001,0x0000001a,0x0000029b,
0x0000003b,0x00050083,0x0000000a,0x000002af,
0x00000258,0x0000024b,0x00050057,0x00000037,
0x000002b0,0x0000028a,0x000002af,0x0008004f,
0x0000000c,0x000002b1,0x000002b0,0x000002b0,
0x00000000,0x00000001,0x00000002,0x0007000c,
0x0000000c,0x000002b2,0x00000001,0x0000001a,
0x000002b1,0x0000003b,0x00050057,0x00000037,
0x000002b5,0x0000028a,0x00000258,0x0008004f,
0x0000000c,0x000002b6,0x000002b5,0x000002b5,
0x00000000,0x00000001,0x00000002,0x0007000c,
0x0000000c,0x000002b7,0x00000001,0x0000001a,
0x000002b6,0x0000003b,0x00050081,0x0000000a,
0x000002bb,0x00000258,0x0000024b,0x00050057,
0x00000037,0x000002bc,0x0000028a,0x000002bb,
0x0008004f,0x0000000c,0x000002bd,0x000002bc,
0x000002bc,0x00000000,0x00000001,0x00000002,
0x0007000c,0x0000000c,0x000002be,0x00000001,
0x0000001a,0x000002bd,0x0000003b,0x00050081,
0x0000000a,0x00000268,0x00000258,0x0000024f,
0x00050083,0x0000000a,0x000002d1,0x00000268,
0x0000024b,0x00050057,0x00000037,0x000002d2,
0x0000028a,0x000002d1,0x0008004f,0x0000000c,
0x000002d3,0x000002d2,0x000002d2,0x00000000,
0x00000001,0x00000002,0x0007000c,0x0000000c,
0x000002d4,0x00000001,0x0000001a,0x000002d3,
0x0000003b,0x00050057,0x00000037,0x000002d7,
0x0000028a,0x00000268,0x0008004f,0x0000000c,
0x000002d8,0x000002d7,0x000002d7,0x00000000,
0x00000001,0x00000002,0x0007000c,0x0000000c,
0x000002d9,0x00000001,0x0000001a,0x000002d8,
0x0000003b,0x00050081,0x0000000a,0x000002dd,
0x00000268,0x0000024b,0x00050057,0x00000037,
0x000002de,0x0000028a,0x000002dd,0x0008004f,
0x0000000c,0x000002df,0x000002de,0x000002de,
0x00000000,0x00000001,0x00000002,0x0007000c,
0x0000000c,0x000002e0,0x00000001,0x0000001a,
0x000002df,0x0000003b,0x00050051,0x00000006,
0x0000026d,0x0000025d,0x00000000,0x00050083,
0x00000006,0x000002f3,0x0000026d,0x00000049,
0x00050081,0x00000006,0x000002f6,0x0000026d,
0x00000049,0x00060050,0x0000000c,0x000002f7,
0x000002f3,0x0000026d,0x000002f6,0x00050085,
0x0000000c,0x000002fa,0x000002f7,0x000004f6,
0x00050085,0x0000000c,0x000002fd,0x000002fa,
0x000002fa,0x0005008e,0x0000000c,0x000002fe,
0x000002fd,0x00000068,0x0006000c,0x0000000c,
0x000002ff,0x00000001,0x0000001d,0x000002fe,
0x00050051,0x00000006,0x00000303,0x000002ff,
0x00000000,0x0005008e,0x0000000c,0x00000304,
0x00000290,0x00000303,0x00050051,0x00000006,
0x00000308,0x000002ff,0x00000001,0x0005008e,
0x0000000c,0x00000309,0x00000295,0x00000308,
0x00050081,0x0000000c,0x0000030a,0x00000304,
0x00000309,0x00050051,0x00000006,0x0000030e,
0x000002ff,0x00000002,0x0005008e,0x0000000c,
0x0000030f,0x0000029c,0x0000030e,0x00050081,
0x0000000c,0x00000310,0x0000030a,0x0000030f,
0x00050081,0x00000006,0x00000315,0x00000303,
0x00000308,0x00050081,0x00000006,0x00000318,
0x00000315,0x0000030e,0x00060050,0x0000000c,
0x00000319,0x00000318,0x00000318,0x00000318,
0x00050088,0x0000000c,0x0000031a,0x00000310,
0x00000319,0x0005008e,0x0000000c,0x00000331,
0x000002b2,0x00000303,0x0005008e,0x0000000c,
0x00000336,0x000002b7,0x00000308,0x00050081,
0x0000000c,0x00000337,0x00000331,0x00000336,
0x0005008e,0x0000000c,0x0000033c,0x000002be,
0x0000030e,0x00050081,0x0000000c,0x0000033d,
0x00000337,0x0000033c,0x00050088,0x0000000c,
0x00000347,0x0000033d,0x00000319,0x0005008e,
0x0000000c,0x0000035e,0x000002d4,0x00000303,
0x0005008e,0x0000000c,0x00000363,0x000002d9,
0x00000308,0x00050081,0x0000000c,0x00000364,
0x0000035e,0x00000363,0x0005008e,0x0000000c,
0x00000369,0x000002e0,0x0000030e,0x00050081,
0x0000000c,0x0000036a,0x00000364,0x00000369,
0x00050088,0x0000000c,0x00000374,0x0000036a,
0x00000319,0x00050051,0x00000006,0x00000286,
0x0000025d,0x00000001,0x00050083,0x00000006,
0x0000037a,0x00000286,0x00000049,0x00050081,
0x00000006,0x0000037d,0x00000286,0x00000049,
0x00060050,0x0000000c,0x0000037e,0x0000037a,
0x00000286,0x0000037d,0x00050085,0x0000000c,
0x00000381,0x0000037e,0x000004f6,0x00050085,
0x0000000c,0x00000384,0x00000381,0x00000381,
0x0005008e,0x0000000c,0x00000385,0x00000384,
0x00000068,0x0006000c,0x0000000c,0x00000386,
0x00000001,0x0000001d,0x00000385,0x00050051,
0x00000006,0x0000038a,0x00000386,0x00000000,
0x0005008e,0x0000000c,0x0000038b,0x0000031a,
0x0000038a,0x00050051,0x00000006,0x0000038f,
0x00000386,0x00000001,0x0005008e,0x0000000c,
0x00000390,0x00000347,0x0000038f,0x00050081,
0x0000000c,0x00000391,0x0000038b,0x00000390,
0x00050051,0x00000006,0x00000395,0x00000386,
0x00000002,0x0005008e,0x0000000c,0x00000396,
0x00000374,0x00000395,0x00050081,0x0000000c,
0x00000397,0x00000391,0x00000396,0x00050081,
0x00000006,0x0000039c,0x0000038a,0x0000038f,
0x00050081,0x00000006,0x0000039f,0x0000039c,
0x00000395,0x00060050,0x0000000c,0x000003a0,
0x0000039f,0x0000039f,0x0000039f,0x00050088,
0x0000000c,0x000003a1,0x00000397,0x000003a0,
0x00060052,0x0000000a,0x000004e1,0x00000249,
0x000001bf,0x00000000,0x00050085,0x0000000a,
0x000003b6,0x000001c8,0x000004e1,0x00050083,
0x0000000a,0x000003b7,0x000003b6,0x000000fc,
0x0006000c,0x0000000a,0x000003b9,0x00000001,
0x00000008,0x000003b7,0x00050081,0x0000000a,
0x000003ba,0x000003b9,0x00000102,0x00050088,
0x0000000a,0x000003bc,0x000003ba,0x000004e1,
0x0006000c,0x0000000a,0x000003be,0x00000001,
0x0000000a,0x000003b7,0x00050051,0x00000006,
0x000003c0,0x000003be,0x00000000,0x00050081,
0x00000006,0x000003c1,0x000003c0,0x00000049,
0x00050083,0x00000006,0x000003c6,0x000003c0,
0x00000049,0x00050083,0x00000006,0x000003c9,
0x000003c0,0x00000116,0x00070050,0x00000037,
0x000003ca,0x000003c1,0x000003c0,0x000003c6,
0x000003c9,0x0005008e,0x00000037,0x000003cb,
0x000003ca,0x0000010b,0x0006000c,0x00000037,
0x000003cd,0x00000001,0x00000004,0x000003cb,
0x0007000c,0x00000037,0x000003cf,0x00000001,
0x00000028,0x000003cd,0x000004f4,0x0006000c,
0x00000037,0x000003d1,0x00000001,0x0000000d,
0x000003cf,0x0005008e,0x00000037,0x000003d2,
0x000003d1,0x00000116,0x00050085,0x00000037,
0x000003d5,0x000003cf,0x000004fa,0x0006000c,
0x00000037,0x000003d6,0x00000001,0x0000000d,
0x000003d5,0x00050085,0x00000037,0x000003d7,
0x000003d2,0x000003d6,0x00050085,0x00000037,
0x000003da,0x000003cf,0x000003cf,0x00050088,
0x00000037,0x000003db,0x000003d7,0x000003da,
0x00050094,0x00000006,0x000003dd,0x000003db,
0x0000012c,0x00070050,0x00000037,0x000003df,
0x000003dd,0x000003dd,0x000003dd,0x000003dd,
0x00050088,0x00000037,0x000003e0,0x000003db,
0x000003df,0x00050057,0x00000037,0x000003e3,
0x0000028a,0x000003bc,0x0008004f,0x0000000c,
0x000003e4,0x000003e3,0x000003e3,0x00000000,
0x00000001,0x00000002,0x0007000c,0x0000000c,
0x000003e5,0x00000001,0x0000001a,0x000003e4,
0x0000003b,0x00050051,0x00000006,0x000003e6,
0x000003e5,0x00000000,0x00050051,0x00000006,
0x000003e7,0x000003e5,0x00000001,0x00050051,
0x00000006,0x000003e8,0x000003e5,0x00000002,
0x00050081,0x0000000a,0x000003ed,0x000003bc,
0x0000024b,0x00050057,0x00000037,0x000003ee,
0x0000028a,0x000003ed,0x0008004f,0x0000000c,
0x000003ef,0x000003ee,0x000003ee,0x00000000,
0x00000001,0x00000002,0x0007000c,0x0000000c,
0x000003f0,0x00000001,0x0000001a,0x000003ef,
0x0000003b,0x00050051,0x00000006,0x000003f1,
0x000003f0,0x00000000,0x00050051,0x00000006,
0x000003f2,0x000003f0,0x00000001,0x00050051,
0x00000006,0x000003f3,0x000003f0,0x00000002,
0x00070050,0x00000037,0x00000407,0x000003e6,
0x000003e7,0x000003e8,0x00000049,0x00070050,
0x00000037,0x00000409,0x000003f1,0x000003f2,
0x000003f3,0x00000049,0x00070050,0x00000149,
0x0000040b,0x00000407,0x00000407,0x00000409,
0x00000409,0x00050091,0x00000037,0x0000040d,
0x0000040b,0x000003e0,0x0008004f,0x0000000c,
0x0000040e,0x0000040d,0x0000040d,0x00000000,
0x00000001,0x00000002,0x00050085,0x00000006,
0x0000041b,0x00000249,0x000001dc,0x00060052,
0x0000000a,0x000004e9,0x0000041b,0x000001bf,
0x00000000,0x00050088,0x00000006,0x0000041f,
0x000004fb,0x00000249,0x00050050,0x0000000a,
0x00000420,0x0000041f,0x0000004a,0x00050085,
0x0000000a,0x00000423,0x000001c8,0x000004e9,
0x00050083,0x0000000a,0x00000424,0x00000423,
0x000000fc,0x0006000c,0x0000000a,0x00000426,
0x00000001,0x00000008,0x00000424,0x00050081,
0x0000000a,0x00000427,0x00000426,0x00000102,
0x00050088,0x0000000a,0x00000429,0x00000427,
0x000004e9,0x0006000c,0x0000000a,0x0000042b,
0x00000001,0x0000000a,0x00000424,0x00050051,
0x00000006,0x0000042d,0x0000042b,0x00000000,
0x00050081,0x00000006,0x0000042e,0x0000042d,
0x00000049,0x00050083,0x00000006,0x00000433,
0x0000042d,0x00000049,0x00050083,0x00000006,
0x00000436,0x0000042d,0x00000116,0x00070050,
0x00000037,0x00000437,0x0000042e,0x0000042d,
0x00000433,0x00000436,0x0005008e,0x00000037,
0x00000438,0x00000437,0x0000010b,0x0006000c,
0x00000037,0x0000043a,0x00000001,0x00000004,
0x00000438,0x0007000c,0x00000037,0x0000043c,
0x00000001,0x00000028,0x0000043a,0x000004f4,
0x0006000c,0x00000037,0x0000043e,0x00000001,
0x0000000d,0x0000043c,0x0005008e,0x00000037,
0x0000043f,0x0000043e,0x00000116,0x00050085,
0x00000037,0x00000442,0x0000043c,0x000004fa,
0x0006000c,0x00000037,0x00000443,0x00000001,
0x0000000d,0x00000442,0x00050085,0x00000037,
0x00000444,0x0000043f,0x00000443,0x00050085,
0x00000037,0x00000447,0x0000043c,0x0000043c,
0x00050088,0x00000037,0x00000448,0x00000444,
0x00000447,0x00050094,0x00000006,0x0000044a,
0x00000448,0x0000012c,0x00070050,0x00000037,
0x0000044c,0x0000044a,0x0000044a,0x0000044a,
0x0000044a,0x00050088,0x00000037,0x0000044d,
0x00000448,0x0000044c,0x00050057,0x00000037,
0x00000450,0x0000028a,0x00000429,0x0008004f,
0x0000000c,0x00000451,0x00000450,0x00000450,
0x00000000,0x00000001,0x00000002,0x0007000c,
0x0000000c,0x00000452,0x00000001,0x0000001a,
0x00000451,0x0000003b,0x00050051,0x00000006,
0x00000453,0x00000452,0x00000000,0x00050051,
0x00000006,0x00000454,0x00000452,0x00000001,
0x00050051,0x00000006,0x00000455,0x00000452,
0x00000002,0x00050081,0x0000000a,0x0000045a,
0x00000429,0x00000420,0x00050057,0x00000037,
0x0000045b,0x0000028a,0x0000045a,0x0008004f,
0x0000000c,0x0000045c,0x0000045b,0x0000045b,
0x00000000,0x00000001,0x00000002,0x0007000c,
0x0000000c,0x0000045d,0x00000001,0x0000001a,
0x0000045c,0x0000003b,0x00050051,0x00000006,
0x0000045e,0x0000045d,0x00000000,0x00050051,
0x00000006,0x0000045f,0x0000045d,0x00000001,
0x00050051,0x00000006,0x00000460,0x0000045d,
0x00000002,0x00070050,0x00000037,0x00000474,
0x00000453,0x00000454,0x00000455,0x00000049,
0x00070050,0x00000037,0x00000476,0x0000045e,
0x0000045f,0x00000460,0x00000049,0x00070050,
0x00000149,0x00000478,0x00000474,0x00000474,
0x00000476,0x00000476,0x00050091,0x00000037,
0x0000047a,0x00000478,0x0000044d,0x0008004f,
0x0000000c,0x0000047b,0x0000047a,0x0000047a,
0x00000000,0x00000001,0x00000002,0x00050085,
0x0000000c,0x000001e8,0x0000047b,0x0000040e,
0x0006000c,0x0000000c,0x000001e9,0x00000001,
0x0000001f,0x000001e8,0x00050051,0x00000006,
0x000001eb,0x000001c8,0x00000001,0x00060041,
0x00000188,0x000001ec,0x00000187,0x0000006c,
0x00000077,0x0004003d,0x00000006,0x000001ed,
0x000001ec,0x00050085,0x00000006,0x000001ee,
0x000001eb,0x000001ed,0x0006000c,0x00000006,
0x000001ef,0x00000001,0x0000000a,0x000001ee,
0x0007000c,0x0000000c,0x00000482,0x00000001,
0x0000001a,0x0000040e,0x0000016a,0x0008000c,
0x0000000c,0x00000483,0x00000001,0x0000002e,
0x00000165,0x00000167,0x00000482,0x00050088,
0x0000000c,0x00000486,0x000004f6,0x00000483,
0x0005008e,0x0000000c,0x00000488,0x00000486,
0x000000a1,0x0005008e,0x0000000c,0x0000048b,
0x00000486,0x000001ef,0x00050083,0x0000000c,
0x0000048d,0x0000048b,0x00000488,0x0006000c,
0x0000000c,0x0000048e,0x00000001,0x00000004,
0x0000048d,0x00050083,0x0000000c,0x00000490,
0x000004f7,0x0000048e,0x0008000c,0x0000000c,
0x00000493,0x00000001,0x00000031,0x000004f8,
0x000004f7,0x00000490,0x00050085,0x0000000c,
0x00000495,0x00000493,0x00000488,0x00050085,
0x0000000c,0x000001f5,0x000001e9,0x00000495,
0x00050083,0x0000000c,0x000001f8,0x000003a1,
0x000001f5,0x0008000c,0x0000000c,0x000001fb,
0x00000001,0x0000002b,0x000001f8,0x000004f8,
0x000004f7,0x00050085,0x0000000c,0x000001fe,
0x000001fb,0x000001fb,0x0005008e,0x0000000c,
0x00000200,0x000001fe,0x000001ff,0x00050081,
0x0000000c,0x00000202,0x000001f5,0x00000200,
0x00050041,0x00000206,0x00000207,0x000001ba,
0x00000070,0x0004003d,0x00000006,0x00000208,
0x00000207,0x000300f7,0x000004b3,0x00000000,
0x000300fb,0x00000070,0x0000049b,0x000200f8,
0x0000049b,0x00060041,0x00000188,0x0000049d,
0x00000187,0x00000074,0x00000070,0x0004003d,
0x00000006,0x0000049e,0x0000049d,0x00050085,
0x00000006,0x0000049f,0x00000208,0x0000049e,
0x0006000c,0x00000006,0x000004a7,0x00000001,
0x00000008,0x0000049f,0x0005008d,0x00000006,
0x000004a8,0x000004a7,0x00000116,0x000500b4,
0x00000196,0x000004aa,0x000004a8,0x0000004a,
0x000300f7,0x000004b2,0x00000000,0x000400fa,
0x000004aa,0x000004ab,0x000004ac,0x000200f8,
0x000004ac,0x000500b4,0x00000196,0x000004ae,
0x000004a8,0x00000049,0x000300f7,0x000004b1,
0x00000000,0x000400fa,0x000004ae,0x000004af,
0x000004b0,0x000200f8,0x000004b0,0x000200f9,
0x000004b3,0x000200f8,0x000004af,0x000200f9,
0x000004b3,0x000200f8,0x000004b1,0x000100ff,
0x000200f8,0x000004ab,0x000200f9,0x000004b3,
0x000200f8,0x000004b2,0x000100ff,0x000200f8,
0x000004b3,0x000900f5,0x0000000c,0x000004f1,
0x0000019a,0x000004ab,0x000001a1,0x000004af,
0x000001a4,0x000004b0,0x00050085,0x0000000c,
0x0000020a,0x00000202,0x000004f1,0x0005008e,
0x0000000c,0x0000020b,0x0000020a,0x00000116,
0x0008000c,0x0000000c,0x0000020e,0x00000001,
0x0000002e,0x00000202,0x0000020b,0x000004f9,
0x0005008e,0x0000000c,0x00000211,0x000001fb,
0x00000210,0x00050081,0x0000000c,0x00000213,
0x0000020e,0x00000211,0x0005008e,0x0000000c,
0x00000215,0x00000213,0x00000166,0x0007000c,
0x0000000c,0x00000218,0x00000001,0x0000001a,
0x00000215,0x00000217,0x00050051,0x00000006,
0x0000021c,0x00000218,0x00000000,0x00050051,
0x00000006,0x0000021d,0x00000218,0x00000001,
0x00050051,0x00000006,0x0000021e,0x00000218,
0x00000002,0x00070050,0x00000037,0x0000021f,
0x0000021c,0x0000021d,0x0000021e,0x00000049,
0x0003003e,0x0000021a,0x0000021f,0x000100fd,
0x00010038}
+10
View File
@@ -0,0 +1,10 @@
#version 450
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 0) uniform sampler2D uTexture;
layout(location = 0) in vec2 vUV;
void main()
{
FragColor = textureLod(uTexture, vUV, 0.0);
}
+21
View File
@@ -0,0 +1,21 @@
#version 450
layout(location = 0) out vec2 vUV;
void main()
{
if (gl_VertexIndex == 0)
{
gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);
}
else if (gl_VertexIndex == 1)
{
gl_Position = vec4(-1.0, +3.0, 0.0, 1.0);
}
else
{
gl_Position = vec4(+3.0, -1.0, 0.0, 1.0);
}
vUV = gl_Position.xy * 0.5 + 0.5;
}
+32
View File
@@ -0,0 +1,32 @@
{0x07230203,0x00010300,0x000d000b,0x00000015,
0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,
0x00000000,0x0003000e,0x00000000,0x00000001,
0x0007000f,0x00000004,0x00000004,0x6e69616d,
0x00000000,0x00000009,0x00000011,0x00030010,
0x00000004,0x00000007,0x00040047,0x00000009,
0x0000001e,0x00000000,0x00040047,0x0000000d,
0x00000021,0x00000000,0x00040047,0x0000000d,
0x00000022,0x00000000,0x00040047,0x00000011,
0x0000001e,0x00000000,0x00020013,0x00000002,
0x00030021,0x00000003,0x00000002,0x00030016,
0x00000006,0x00000020,0x00040017,0x00000007,
0x00000006,0x00000004,0x00040020,0x00000008,
0x00000003,0x00000007,0x0004003b,0x00000008,
0x00000009,0x00000003,0x00090019,0x0000000a,
0x00000006,0x00000001,0x00000000,0x00000000,
0x00000000,0x00000001,0x00000000,0x0003001b,
0x0000000b,0x0000000a,0x00040020,0x0000000c,
0x00000000,0x0000000b,0x0004003b,0x0000000c,
0x0000000d,0x00000000,0x00040017,0x0000000f,
0x00000006,0x00000002,0x00040020,0x00000010,
0x00000001,0x0000000f,0x0004003b,0x00000010,
0x00000011,0x00000001,0x0004002b,0x00000006,
0x00000013,0x00000000,0x00050036,0x00000002,
0x00000004,0x00000000,0x00000003,0x000200f8,
0x00000005,0x0004003d,0x0000000b,0x0000000e,
0x0000000d,0x0004003d,0x0000000f,0x00000012,
0x00000011,0x00070058,0x00000007,0x00000014,
0x0000000e,0x00000012,0x00000002,0x00000013,
0x0003003e,0x00000009,0x00000014,0x000100fd,
0x00010038}
+72
View File
@@ -0,0 +1,72 @@
{0x07230203,0x00010300,0x000d000b,0x00000034,
0x00000000,0x00020011,0x00000001,0x0006000b,
0x00000001,0x4c534c47,0x6474732e,0x3035342e,
0x00000000,0x0003000e,0x00000000,0x00000001,
0x0008000f,0x00000000,0x00000004,0x6e69616d,
0x00000000,0x00000008,0x00000016,0x0000002b,
0x00040047,0x00000008,0x0000000b,0x0000002a,
0x00030047,0x00000014,0x00000002,0x00050048,
0x00000014,0x00000000,0x0000000b,0x00000000,
0x00050048,0x00000014,0x00000001,0x0000000b,
0x00000001,0x00050048,0x00000014,0x00000002,
0x0000000b,0x00000003,0x00050048,0x00000014,
0x00000003,0x0000000b,0x00000004,0x00040047,
0x0000002b,0x0000001e,0x00000000,0x00020013,
0x00000002,0x00030021,0x00000003,0x00000002,
0x00040015,0x00000006,0x00000020,0x00000001,
0x00040020,0x00000007,0x00000001,0x00000006,
0x0004003b,0x00000007,0x00000008,0x00000001,
0x0004002b,0x00000006,0x0000000a,0x00000000,
0x00020014,0x0000000b,0x00030016,0x0000000f,
0x00000020,0x00040017,0x00000010,0x0000000f,
0x00000004,0x00040015,0x00000011,0x00000020,
0x00000000,0x0004002b,0x00000011,0x00000012,
0x00000001,0x0004001c,0x00000013,0x0000000f,
0x00000012,0x0006001e,0x00000014,0x00000010,
0x0000000f,0x00000013,0x00000013,0x00040020,
0x00000015,0x00000003,0x00000014,0x0004003b,
0x00000015,0x00000016,0x00000003,0x0004002b,
0x0000000f,0x00000017,0xbf800000,0x0004002b,
0x0000000f,0x00000018,0x00000000,0x0004002b,
0x0000000f,0x00000019,0x3f800000,0x0007002c,
0x00000010,0x0000001a,0x00000017,0x00000017,
0x00000018,0x00000019,0x00040020,0x0000001b,
0x00000003,0x00000010,0x0004002b,0x00000006,
0x0000001f,0x00000001,0x0004002b,0x0000000f,
0x00000023,0x40400000,0x0007002c,0x00000010,
0x00000024,0x00000017,0x00000023,0x00000018,
0x00000019,0x0007002c,0x00000010,0x00000027,
0x00000023,0x00000017,0x00000018,0x00000019,
0x00040017,0x00000029,0x0000000f,0x00000002,
0x00040020,0x0000002a,0x00000003,0x00000029,
0x0004003b,0x0000002a,0x0000002b,0x00000003,
0x0004002b,0x0000000f,0x0000002f,0x3f000000,
0x0005002c,0x00000029,0x00000033,0x0000002f,
0x0000002f,0x00050036,0x00000002,0x00000004,
0x00000000,0x00000003,0x000200f8,0x00000005,
0x0004003d,0x00000006,0x00000009,0x00000008,
0x000500aa,0x0000000b,0x0000000c,0x00000009,
0x0000000a,0x000300f7,0x0000000e,0x00000000,
0x000400fa,0x0000000c,0x0000000d,0x0000001d,
0x000200f8,0x0000000d,0x00050041,0x0000001b,
0x0000001c,0x00000016,0x0000000a,0x0003003e,
0x0000001c,0x0000001a,0x000200f9,0x0000000e,
0x000200f8,0x0000001d,0x000500aa,0x0000000b,
0x00000020,0x00000009,0x0000001f,0x000300f7,
0x00000022,0x00000000,0x000400fa,0x00000020,
0x00000021,0x00000026,0x000200f8,0x00000021,
0x00050041,0x0000001b,0x00000025,0x00000016,
0x0000000a,0x0003003e,0x00000025,0x00000024,
0x000200f9,0x00000022,0x000200f8,0x00000026,
0x00050041,0x0000001b,0x00000028,0x00000016,
0x0000000a,0x0003003e,0x00000028,0x00000027,
0x000200f9,0x00000022,0x000200f8,0x00000022,
0x000200f9,0x0000000e,0x000200f8,0x0000000e,
0x00050041,0x0000001b,0x0000002c,0x00000016,
0x0000000a,0x0004003d,0x00000010,0x0000002d,
0x0000002c,0x0007004f,0x00000029,0x0000002e,
0x0000002d,0x0000002d,0x00000000,0x00000001,
0x0005008e,0x00000029,0x00000030,0x0000002e,
0x0000002f,0x00050081,0x00000029,0x00000032,
0x00000030,0x00000033,0x0003003e,0x0000002b,
0x00000032,0x000100fd,0x00010038}
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
glslc -O crt-aperture.frag -o crt_frag.spv --target-env=vulkan1.1 -mfmt=c
glslc -O main.frag -o main_frag.spv --target-env=vulkan1.1 -mfmt=c
glslc -O main.vert -o main_vert.spv --target-env=vulkan1.1 -mfmt=c
+80 -25
View File
@@ -3,6 +3,7 @@
#include "rdp_device.hpp"
#include "interface.hpp"
#include "spirv.hpp"
#include "spirv_crt.hpp"
#include <SDL3/SDL_vulkan.h>
using namespace Vulkan;
@@ -51,8 +52,6 @@ enum vi_registers
VI_REGS_COUNT
};
static bool fullscreen;
static bool integer_scaling;
static SDL_Window *window;
static RDP::CommandProcessor *processor;
static SDL_WSIPlatform *wsi_platform;
@@ -63,6 +62,9 @@ static int cmd_ptr;
static CALL_BACK callback;
static GFX_INFO gfx_info;
static uint32_t region;
static bool crop_letterbox;
static const uint32_t *fragment_spirv;
static size_t fragment_size;
typedef struct
{
@@ -76,6 +78,12 @@ typedef struct
uint8_t depthbuffer_enabled;
} FrameBufferInfo;
typedef struct
{
float SourceSize[4];
float OutputSize[4];
} Push;
static uint8_t *rdram_dirty;
static uint64_t sync_signal;
static FrameBufferInfo frame_buffer_info;
@@ -164,8 +172,8 @@ bool sdl_event_filter(void *userdata, SDL_Event *event)
case SDL_SCANCODE_RETURN:
if (event->key.mod & SDL_KMOD_ALT)
{
fullscreen = !fullscreen;
SDL_SetWindowFullscreen(window, fullscreen);
gfx_info.fullscreen = !gfx_info.fullscreen;
SDL_SetWindowFullscreen(window, gfx_info.fullscreen);
}
break;
case SDL_SCANCODE_F:
@@ -175,9 +183,12 @@ bool sdl_event_filter(void *userdata, SDL_Event *event)
}
break;
case SDL_SCANCODE_ESCAPE:
if (fullscreen)
if (gfx_info.fullscreen)
callback.emu_running = false;
break;
case SDL_SCANCODE_F4:
crop_letterbox = !crop_letterbox;
break;
case SDL_SCANCODE_F5:
callback.save_state = true;
break;
@@ -192,7 +203,7 @@ bool sdl_event_filter(void *userdata, SDL_Event *event)
return 0;
}
void rdp_new_processor(GFX_INFO _gfx_info, uint32_t upscale)
void rdp_new_processor(GFX_INFO _gfx_info)
{
memset(&frame_buffer_info, 0, sizeof(FrameBufferInfo));
sync_signal = 0;
@@ -205,12 +216,12 @@ void rdp_new_processor(GFX_INFO _gfx_info, uint32_t upscale)
}
RDP::CommandProcessorFlags flags = 0;
if (upscale == 2)
if (gfx_info.upscale == 2)
{
flags |= RDP::COMMAND_PROCESSOR_FLAG_SUPER_SAMPLED_DITHER_BIT;
flags |= RDP::COMMAND_PROCESSOR_FLAG_UPSCALING_2X_BIT;
}
else if (upscale == 4)
else if (gfx_info.upscale == 4)
{
flags |= RDP::COMMAND_PROCESSOR_FLAG_SUPER_SAMPLED_DITHER_BIT;
flags |= RDP::COMMAND_PROCESSOR_FLAG_UPSCALING_4X_BIT;
@@ -219,7 +230,7 @@ void rdp_new_processor(GFX_INFO _gfx_info, uint32_t upscale)
processor = new RDP::CommandProcessor(wsi->get_device(), gfx_info.RDRAM, 0, gfx_info.RDRAM_SIZE, gfx_info.RDRAM_SIZE / 2, flags);
}
void rdp_init(void *_window, GFX_INFO _gfx_info, uint32_t _upscale, bool _integer_scaling, bool _fullscreen)
void rdp_init(void *_window, GFX_INFO _gfx_info)
{
window = (SDL_Window *)_window;
bool result = SDL_AddEventWatch(sdl_event_filter, nullptr);
@@ -230,8 +241,18 @@ void rdp_init(void *_window, GFX_INFO _gfx_info, uint32_t _upscale, bool _intege
}
gfx_info = _gfx_info;
fullscreen = _fullscreen;
integer_scaling = _integer_scaling;
if (gfx_info.crt)
{
fragment_spirv = crt_fragment_spirv;
fragment_size = sizeof(crt_fragment_spirv);
}
else
{
fragment_spirv = plain_fragment_spirv;
fragment_size = sizeof(plain_fragment_spirv);
}
bool window_vsync = 0;
wsi = new WSI;
wsi_platform = new SDL_WSIPlatform;
@@ -250,7 +271,7 @@ void rdp_init(void *_window, GFX_INFO _gfx_info, uint32_t _upscale, bool _intege
}
rdram_dirty = (uint8_t *)malloc(gfx_info.RDRAM_SIZE / 8);
rdp_new_processor(gfx_info, _upscale);
rdp_new_processor(gfx_info);
if (!processor->device_is_supported())
{
@@ -263,6 +284,7 @@ void rdp_init(void *_window, GFX_INFO _gfx_info, uint32_t _upscale, bool _intege
callback.emu_running = true;
callback.enable_speedlimiter = true;
crop_letterbox = false;
}
void rdp_close()
@@ -292,15 +314,14 @@ void rdp_close()
}
}
static void calculate_viewport(float *x, float *y, float *width, float *height)
static void calculate_viewport(float *x, float *y, float *width, float *height, uint32_t display_height)
{
const int32_t display_width = gfx_info.PAL ? 384 : 320;
const int32_t display_height = gfx_info.PAL ? 288 : 240;
uint32_t display_width = gfx_info.widescreen ? display_height * 16 / 9 : display_height * 4 / 3;
int w, h;
SDL_GetWindowSize(window, &w, &h);
if (integer_scaling)
if (gfx_info.integer_scaling)
{
// Integer scaling path
int scale_x = w / display_width;
@@ -315,6 +336,13 @@ static void calculate_viewport(float *x, float *y, float *width, float *height)
*width = scaled_width;
*height = scaled_height;
// Center the viewport
int integer_x = (w - *width) / 2.0f;
int integer_y = (h - *height) / 2.0f;
*x = integer_x;
*y = integer_y;
}
else
{
@@ -325,11 +353,11 @@ static void calculate_viewport(float *x, float *y, float *width, float *height)
*width = display_width * scale;
*height = display_height * scale;
}
// Center the viewport
*x = (w - *width) / 2.0f;
*y = (h - *height) / 2.0f;
// Center the viewport
*x = (w - *width) / 2.0f;
*y = (h - *height) / 2.0f;
}
}
static void render_frame(Vulkan::Device &device)
@@ -338,17 +366,34 @@ static void render_frame(Vulkan::Device &device)
options.persist_frame_on_invalid_input = true;
options.blend_previous_frame = true;
options.upscale_deinterlacing = false;
if (crop_letterbox && gfx_info.widescreen)
{
options.crop_rect.enable = true;
if (gfx_info.PAL)
{
options.crop_rect.top = 36;
options.crop_rect.bottom = 36;
}
else
{
options.crop_rect.top = 30;
options.crop_rect.bottom = 30;
}
}
Vulkan::ImageHandle image = processor->scanout(options);
// Normally reflection is automated.
Vulkan::ResourceLayout vertex_layout = {};
Vulkan::ResourceLayout fragment_layout = {};
fragment_layout.output_mask = 1 << 0;
fragment_layout.sets[0].sampled_image_mask = 1 << 0;
if (gfx_info.crt)
fragment_layout.push_constant_size = sizeof(Push);
// This request is cached.
auto *program = device.request_program(vertex_spirv, sizeof(vertex_spirv),
fragment_spirv, sizeof(fragment_spirv),
fragment_spirv, fragment_size,
&vertex_layout,
&fragment_layout);
@@ -358,9 +403,6 @@ static void render_frame(Vulkan::Device &device)
auto rp = device.get_swapchain_render_pass(Vulkan::SwapchainRenderPass::ColorOnly);
cmd->begin_render_pass(rp);
VkViewport vp = cmd->get_viewport();
calculate_viewport(&vp.x, &vp.y, &vp.width, &vp.height);
cmd->set_program(program);
// Basic default render state.
@@ -371,6 +413,19 @@ static void render_frame(Vulkan::Device &device)
// If we don't have an image, we just get a cleared screen in the render pass.
if (image)
{
VkViewport vp = cmd->get_viewport();
calculate_viewport(&vp.x, &vp.y, &vp.width, &vp.height, image->get_height() / gfx_info.upscale);
if (gfx_info.crt)
{
// Set shader parameters
Push push = {
{float(image->get_width()), float(image->get_height()), 1.0f / float(image->get_width()), 1.0f / float(image->get_height())},
{vp.width, vp.height, 1.0f / vp.width, 1.0f / vp.height},
};
cmd->push_constants(&push, 0, sizeof(push));
}
cmd->set_texture(0, 0, image->get_view(), Vulkan::StockSampler::LinearClamp);
cmd->set_viewport(vp);
// The vertices are constants in the shader.
+7 -2
View File
@@ -17,6 +17,11 @@ extern "C"
uint32_t *DPC_END_REG;
uint32_t *DPC_STATUS_REG;
bool PAL;
bool widescreen;
bool fullscreen;
bool integer_scaling;
uint32_t upscale;
bool crt;
} GFX_INFO;
typedef struct
@@ -27,13 +32,13 @@ extern "C"
bool enable_speedlimiter;
} CALL_BACK;
void rdp_init(void *_window, GFX_INFO _gfx_info, uint32_t _upscale, bool _integer_scaling, bool _fullscreen);
void rdp_init(void *_window, GFX_INFO _gfx_info);
void rdp_close();
void rdp_set_vi_register(uint32_t reg, uint32_t value);
void rdp_update_screen();
CALL_BACK rdp_check_callback();
uint64_t rdp_process_commands();
void rdp_new_processor(GFX_INFO _gfx_info, uint32_t _upscale);
void rdp_new_processor(GFX_INFO _gfx_info);
void rdp_check_framebuffers(uint32_t address);
void rdp_full_sync();
+11 -11
View File
@@ -1,19 +1,19 @@
#pragma once
static const uint32_t vertex_spirv[] =
{0x07230203, 0x00010000, 0x000d000a, 0x00000034,
{0x07230203, 0x00010300, 0x000d000b, 0x00000034,
0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
0x00000000, 0x0003000e, 0x00000000, 0x00000001,
0x0008000f, 0x00000000, 0x00000004, 0x6e69616d,
0x00000000, 0x00000008, 0x00000016, 0x0000002b,
0x00040047, 0x00000008, 0x0000000b, 0x0000002a,
0x00050048, 0x00000014, 0x00000000, 0x0000000b,
0x00000000, 0x00050048, 0x00000014, 0x00000001,
0x0000000b, 0x00000001, 0x00050048, 0x00000014,
0x00000002, 0x0000000b, 0x00000003, 0x00050048,
0x00000014, 0x00000003, 0x0000000b, 0x00000004,
0x00030047, 0x00000014, 0x00000002, 0x00040047,
0x00030047, 0x00000014, 0x00000002, 0x00050048,
0x00000014, 0x00000000, 0x0000000b, 0x00000000,
0x00050048, 0x00000014, 0x00000001, 0x0000000b,
0x00000001, 0x00050048, 0x00000014, 0x00000002,
0x0000000b, 0x00000003, 0x00050048, 0x00000014,
0x00000003, 0x0000000b, 0x00000004, 0x00040047,
0x0000002b, 0x0000001e, 0x00000000, 0x00020013,
0x00000002, 0x00030021, 0x00000003, 0x00000002,
0x00040015, 0x00000006, 0x00000020, 0x00000001,
@@ -74,8 +74,8 @@ static const uint32_t vertex_spirv[] =
0x00000030, 0x00000033, 0x0003003e, 0x0000002b,
0x00000032, 0x000100fd, 0x00010038};
static const uint32_t fragment_spirv[] =
{0x07230203, 0x00010000, 0x000d000a, 0x00000015,
static const uint32_t plain_fragment_spirv[] =
{0x07230203, 0x00010300, 0x000d000b, 0x00000015,
0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
0x00000000, 0x0003000e, 0x00000000, 0x00000001,
@@ -83,8 +83,8 @@ static const uint32_t fragment_spirv[] =
0x00000000, 0x00000009, 0x00000011, 0x00030010,
0x00000004, 0x00000007, 0x00040047, 0x00000009,
0x0000001e, 0x00000000, 0x00040047, 0x0000000d,
0x00000022, 0x00000000, 0x00040047, 0x0000000d,
0x00000021, 0x00000000, 0x00040047, 0x00000011,
0x00000021, 0x00000000, 0x00040047, 0x0000000d,
0x00000022, 0x00000000, 0x00040047, 0x00000011,
0x0000001e, 0x00000000, 0x00020013, 0x00000002,
0x00030021, 0x00000003, 0x00000002, 0x00030016,
0x00000006, 0x00000020, 0x00040017, 0x00000007,
+456
View File
@@ -0,0 +1,456 @@
#pragma once
static const uint32_t crt_fragment_spirv[] =
{0x07230203, 0x00010300, 0x000d000b, 0x000004fd,
0x00000000, 0x00020011, 0x00000001, 0x0006000b,
0x00000001, 0x4c534c47, 0x6474732e, 0x3035342e,
0x00000000, 0x0003000e, 0x00000000, 0x00000001,
0x0007000f, 0x00000004, 0x00000004, 0x6e69616d,
0x00000000, 0x000001ba, 0x0000021a, 0x00030010,
0x00000004, 0x00000007, 0x00030047, 0x00000185,
0x00000002, 0x00050048, 0x00000185, 0x00000000,
0x00000023, 0x00000000, 0x00050048, 0x00000185,
0x00000001, 0x00000023, 0x00000010, 0x00040047,
0x000001ba, 0x0000001e, 0x00000000, 0x00040047,
0x000001ca, 0x00000021, 0x00000000, 0x00040047,
0x000001ca, 0x00000022, 0x00000000, 0x00040047,
0x0000021a, 0x0000001e, 0x00000000, 0x00020013,
0x00000002, 0x00030021, 0x00000003, 0x00000002,
0x00030016, 0x00000006, 0x00000020, 0x00090019,
0x00000007, 0x00000006, 0x00000001, 0x00000000,
0x00000000, 0x00000000, 0x00000001, 0x00000000,
0x0003001b, 0x00000008, 0x00000007, 0x00040020,
0x00000009, 0x00000000, 0x00000008, 0x00040017,
0x0000000a, 0x00000006, 0x00000002, 0x00040017,
0x0000000c, 0x00000006, 0x00000003, 0x00040017,
0x00000037, 0x00000006, 0x00000004, 0x0004002b,
0x00000006, 0x0000003a, 0x4019999a, 0x0006002c,
0x0000000c, 0x0000003b, 0x0000003a, 0x0000003a,
0x0000003a, 0x0004002b, 0x00000006, 0x00000049,
0x3f800000, 0x0004002b, 0x00000006, 0x0000004a,
0x00000000, 0x0004002b, 0x00000006, 0x00000068,
0xbf800000, 0x00040015, 0x0000006b, 0x00000020,
0x00000001, 0x0004002b, 0x0000006b, 0x0000006c,
0x00000000, 0x00040015, 0x0000006f, 0x00000020,
0x00000000, 0x0004002b, 0x0000006f, 0x00000070,
0x00000000, 0x0004002b, 0x0000006b, 0x00000074,
0x00000001, 0x0004002b, 0x0000006f, 0x00000077,
0x00000001, 0x0004002b, 0x00000006, 0x000000a1,
0x3f000000, 0x0005002c, 0x0000000a, 0x000000fc,
0x000000a1, 0x0000004a, 0x0004002b, 0x00000006,
0x00000101, 0x3a83126f, 0x0005002c, 0x0000000a,
0x00000102, 0x000000a1, 0x00000101, 0x0004002b,
0x00000006, 0x0000010b, 0x40490fdb, 0x0004002b,
0x00000006, 0x00000116, 0x40000000, 0x0004002b,
0x00000006, 0x0000011c, 0x3727c5ac, 0x0007002c,
0x00000037, 0x0000012c, 0x00000049, 0x00000049,
0x00000049, 0x00000049, 0x00040018, 0x00000149,
0x00000037, 0x00000004, 0x0006002c, 0x0000000c,
0x00000165, 0x000000a1, 0x000000a1, 0x000000a1,
0x0004002b, 0x00000006, 0x00000166, 0x3fc00000,
0x0006002c, 0x0000000c, 0x00000167, 0x00000166,
0x00000166, 0x00000166, 0x0004002b, 0x00000006,
0x00000169, 0x3ecccccd, 0x0006002c, 0x0000000c,
0x0000016a, 0x00000169, 0x00000169, 0x00000169,
0x0004001e, 0x00000185, 0x00000037, 0x00000037,
0x00040020, 0x00000186, 0x00000009, 0x00000185,
0x0004003b, 0x00000186, 0x00000187, 0x00000009,
0x00040020, 0x00000188, 0x00000009, 0x00000006,
0x00020014, 0x00000196, 0x0006002c, 0x0000000c,
0x0000019a, 0x00000049, 0x0000004a, 0x00000049,
0x0006002c, 0x0000000c, 0x000001a1, 0x0000004a,
0x00000049, 0x0000004a, 0x0006002c, 0x0000000c,
0x000001a4, 0x0000004a, 0x0000004a, 0x00000049,
0x0004002b, 0x0000006f, 0x000001aa, 0x00000003,
0x00040020, 0x000001b9, 0x00000001, 0x0000000a,
0x0004003b, 0x000001b9, 0x000001ba, 0x00000001,
0x00040020, 0x000001bc, 0x00000009, 0x00000037,
0x0004003b, 0x00000009, 0x000001ca, 0x00000000,
0x0004002b, 0x00000006, 0x000001dc, 0x40400000,
0x0004002b, 0x00000006, 0x000001ff, 0x3dcccccd,
0x00040020, 0x00000206, 0x00000001, 0x00000006,
0x0004002b, 0x00000006, 0x0000020c, 0x3e99999a,
0x0004002b, 0x00000006, 0x00000210, 0x3d4ccccd,
0x0004002b, 0x00000006, 0x00000216, 0x3ed55555,
0x0006002c, 0x0000000c, 0x00000217, 0x00000216,
0x00000216, 0x00000216, 0x00040020, 0x00000219,
0x00000003, 0x00000037, 0x0004003b, 0x00000219,
0x0000021a, 0x00000003, 0x0005002c, 0x0000000a,
0x000004f3, 0x000000a1, 0x000000a1, 0x0007002c,
0x00000037, 0x000004f4, 0x0000011c, 0x0000011c,
0x0000011c, 0x0000011c, 0x0006002c, 0x0000000c,
0x000004f6, 0x00000116, 0x00000116, 0x00000116,
0x0006002c, 0x0000000c, 0x000004f7, 0x00000049,
0x00000049, 0x00000049, 0x0006002c, 0x0000000c,
0x000004f8, 0x0000004a, 0x0000004a, 0x0000004a,
0x0006002c, 0x0000000c, 0x000004f9, 0x0000020c,
0x0000020c, 0x0000020c, 0x0007002c, 0x00000037,
0x000004fa, 0x000000a1, 0x000000a1, 0x000000a1,
0x000000a1, 0x0004002b, 0x00000006, 0x000004fb,
0x3eaaaaab, 0x00050036, 0x00000002, 0x00000004,
0x00000000, 0x00000003, 0x000200f8, 0x00000005,
0x00060041, 0x00000188, 0x000001a8, 0x00000187,
0x00000074, 0x00000077, 0x0004003d, 0x00000006,
0x000001a9, 0x000001a8, 0x00060041, 0x00000188,
0x000001ab, 0x00000187, 0x0000006c, 0x000001aa,
0x0004003d, 0x00000006, 0x000001ac, 0x000001ab,
0x00050085, 0x00000006, 0x000001ad, 0x000001a9,
0x000001ac, 0x0006000c, 0x00000006, 0x000001ae,
0x00000001, 0x00000008, 0x000001ad, 0x00050088,
0x00000006, 0x000001b2, 0x000000a1, 0x000001ae,
0x0005008d, 0x00000006, 0x000001b4, 0x000001ae,
0x00000116, 0x000500b7, 0x00000196, 0x000001b5,
0x000001b4, 0x0000004a, 0x000600a9, 0x00000006,
0x000004fc, 0x000001b5, 0x0000004a, 0x000001b2,
0x0004003d, 0x0000000a, 0x000001bb, 0x000001ba,
0x00050041, 0x000001bc, 0x000001bd, 0x00000187,
0x0000006c, 0x0004003d, 0x00000037, 0x000001be,
0x000001bd, 0x0007004f, 0x0000000a, 0x000001bf,
0x000001be, 0x000001be, 0x00000000, 0x00000001,
0x00050085, 0x0000000a, 0x000001c0, 0x000001bb,
0x000001bf, 0x00050050, 0x0000000a, 0x000001c3,
0x0000004a, 0x000004fc, 0x00050083, 0x0000000a,
0x000001c4, 0x000001c0, 0x000001c3, 0x0007004f,
0x0000000a, 0x000001c7, 0x000001be, 0x000001be,
0x00000002, 0x00000003, 0x00050085, 0x0000000a,
0x000001c8, 0x000001c4, 0x000001c7, 0x00050051,
0x00000006, 0x00000249, 0x000001be, 0x00000000,
0x00050088, 0x00000006, 0x0000024a, 0x00000049,
0x00000249, 0x00050050, 0x0000000a, 0x0000024b,
0x0000024a, 0x0000004a, 0x00050051, 0x00000006,
0x0000024d, 0x000001be, 0x00000001, 0x00050088,
0x00000006, 0x0000024e, 0x00000049, 0x0000024d,
0x00050050, 0x0000000a, 0x0000024f, 0x0000004a,
0x0000024e, 0x00050085, 0x0000000a, 0x00000252,
0x000001c8, 0x000001bf, 0x0006000c, 0x0000000a,
0x00000254, 0x00000001, 0x00000008, 0x00000252,
0x00050081, 0x0000000a, 0x00000256, 0x00000254,
0x000004f3, 0x00050088, 0x0000000a, 0x00000258,
0x00000256, 0x000001bf, 0x0006000c, 0x0000000a,
0x0000025a, 0x00000001, 0x0000000a, 0x00000252,
0x00050083, 0x0000000a, 0x0000025c, 0x0000025a,
0x000004f3, 0x0005008e, 0x0000000a, 0x0000025d,
0x0000025c, 0x00000068, 0x00050083, 0x0000000a,
0x00000260, 0x00000258, 0x0000024f, 0x0004003d,
0x00000008, 0x0000028a, 0x000001ca, 0x00050083,
0x0000000a, 0x0000028d, 0x00000260, 0x0000024b,
0x00050057, 0x00000037, 0x0000028e, 0x0000028a,
0x0000028d, 0x0008004f, 0x0000000c, 0x0000028f,
0x0000028e, 0x0000028e, 0x00000000, 0x00000001,
0x00000002, 0x0007000c, 0x0000000c, 0x00000290,
0x00000001, 0x0000001a, 0x0000028f, 0x0000003b,
0x00050057, 0x00000037, 0x00000293, 0x0000028a,
0x00000260, 0x0008004f, 0x0000000c, 0x00000294,
0x00000293, 0x00000293, 0x00000000, 0x00000001,
0x00000002, 0x0007000c, 0x0000000c, 0x00000295,
0x00000001, 0x0000001a, 0x00000294, 0x0000003b,
0x00050081, 0x0000000a, 0x00000299, 0x00000260,
0x0000024b, 0x00050057, 0x00000037, 0x0000029a,
0x0000028a, 0x00000299, 0x0008004f, 0x0000000c,
0x0000029b, 0x0000029a, 0x0000029a, 0x00000000,
0x00000001, 0x00000002, 0x0007000c, 0x0000000c,
0x0000029c, 0x00000001, 0x0000001a, 0x0000029b,
0x0000003b, 0x00050083, 0x0000000a, 0x000002af,
0x00000258, 0x0000024b, 0x00050057, 0x00000037,
0x000002b0, 0x0000028a, 0x000002af, 0x0008004f,
0x0000000c, 0x000002b1, 0x000002b0, 0x000002b0,
0x00000000, 0x00000001, 0x00000002, 0x0007000c,
0x0000000c, 0x000002b2, 0x00000001, 0x0000001a,
0x000002b1, 0x0000003b, 0x00050057, 0x00000037,
0x000002b5, 0x0000028a, 0x00000258, 0x0008004f,
0x0000000c, 0x000002b6, 0x000002b5, 0x000002b5,
0x00000000, 0x00000001, 0x00000002, 0x0007000c,
0x0000000c, 0x000002b7, 0x00000001, 0x0000001a,
0x000002b6, 0x0000003b, 0x00050081, 0x0000000a,
0x000002bb, 0x00000258, 0x0000024b, 0x00050057,
0x00000037, 0x000002bc, 0x0000028a, 0x000002bb,
0x0008004f, 0x0000000c, 0x000002bd, 0x000002bc,
0x000002bc, 0x00000000, 0x00000001, 0x00000002,
0x0007000c, 0x0000000c, 0x000002be, 0x00000001,
0x0000001a, 0x000002bd, 0x0000003b, 0x00050081,
0x0000000a, 0x00000268, 0x00000258, 0x0000024f,
0x00050083, 0x0000000a, 0x000002d1, 0x00000268,
0x0000024b, 0x00050057, 0x00000037, 0x000002d2,
0x0000028a, 0x000002d1, 0x0008004f, 0x0000000c,
0x000002d3, 0x000002d2, 0x000002d2, 0x00000000,
0x00000001, 0x00000002, 0x0007000c, 0x0000000c,
0x000002d4, 0x00000001, 0x0000001a, 0x000002d3,
0x0000003b, 0x00050057, 0x00000037, 0x000002d7,
0x0000028a, 0x00000268, 0x0008004f, 0x0000000c,
0x000002d8, 0x000002d7, 0x000002d7, 0x00000000,
0x00000001, 0x00000002, 0x0007000c, 0x0000000c,
0x000002d9, 0x00000001, 0x0000001a, 0x000002d8,
0x0000003b, 0x00050081, 0x0000000a, 0x000002dd,
0x00000268, 0x0000024b, 0x00050057, 0x00000037,
0x000002de, 0x0000028a, 0x000002dd, 0x0008004f,
0x0000000c, 0x000002df, 0x000002de, 0x000002de,
0x00000000, 0x00000001, 0x00000002, 0x0007000c,
0x0000000c, 0x000002e0, 0x00000001, 0x0000001a,
0x000002df, 0x0000003b, 0x00050051, 0x00000006,
0x0000026d, 0x0000025d, 0x00000000, 0x00050083,
0x00000006, 0x000002f3, 0x0000026d, 0x00000049,
0x00050081, 0x00000006, 0x000002f6, 0x0000026d,
0x00000049, 0x00060050, 0x0000000c, 0x000002f7,
0x000002f3, 0x0000026d, 0x000002f6, 0x00050085,
0x0000000c, 0x000002fa, 0x000002f7, 0x000004f6,
0x00050085, 0x0000000c, 0x000002fd, 0x000002fa,
0x000002fa, 0x0005008e, 0x0000000c, 0x000002fe,
0x000002fd, 0x00000068, 0x0006000c, 0x0000000c,
0x000002ff, 0x00000001, 0x0000001d, 0x000002fe,
0x00050051, 0x00000006, 0x00000303, 0x000002ff,
0x00000000, 0x0005008e, 0x0000000c, 0x00000304,
0x00000290, 0x00000303, 0x00050051, 0x00000006,
0x00000308, 0x000002ff, 0x00000001, 0x0005008e,
0x0000000c, 0x00000309, 0x00000295, 0x00000308,
0x00050081, 0x0000000c, 0x0000030a, 0x00000304,
0x00000309, 0x00050051, 0x00000006, 0x0000030e,
0x000002ff, 0x00000002, 0x0005008e, 0x0000000c,
0x0000030f, 0x0000029c, 0x0000030e, 0x00050081,
0x0000000c, 0x00000310, 0x0000030a, 0x0000030f,
0x00050081, 0x00000006, 0x00000315, 0x00000303,
0x00000308, 0x00050081, 0x00000006, 0x00000318,
0x00000315, 0x0000030e, 0x00060050, 0x0000000c,
0x00000319, 0x00000318, 0x00000318, 0x00000318,
0x00050088, 0x0000000c, 0x0000031a, 0x00000310,
0x00000319, 0x0005008e, 0x0000000c, 0x00000331,
0x000002b2, 0x00000303, 0x0005008e, 0x0000000c,
0x00000336, 0x000002b7, 0x00000308, 0x00050081,
0x0000000c, 0x00000337, 0x00000331, 0x00000336,
0x0005008e, 0x0000000c, 0x0000033c, 0x000002be,
0x0000030e, 0x00050081, 0x0000000c, 0x0000033d,
0x00000337, 0x0000033c, 0x00050088, 0x0000000c,
0x00000347, 0x0000033d, 0x00000319, 0x0005008e,
0x0000000c, 0x0000035e, 0x000002d4, 0x00000303,
0x0005008e, 0x0000000c, 0x00000363, 0x000002d9,
0x00000308, 0x00050081, 0x0000000c, 0x00000364,
0x0000035e, 0x00000363, 0x0005008e, 0x0000000c,
0x00000369, 0x000002e0, 0x0000030e, 0x00050081,
0x0000000c, 0x0000036a, 0x00000364, 0x00000369,
0x00050088, 0x0000000c, 0x00000374, 0x0000036a,
0x00000319, 0x00050051, 0x00000006, 0x00000286,
0x0000025d, 0x00000001, 0x00050083, 0x00000006,
0x0000037a, 0x00000286, 0x00000049, 0x00050081,
0x00000006, 0x0000037d, 0x00000286, 0x00000049,
0x00060050, 0x0000000c, 0x0000037e, 0x0000037a,
0x00000286, 0x0000037d, 0x00050085, 0x0000000c,
0x00000381, 0x0000037e, 0x000004f6, 0x00050085,
0x0000000c, 0x00000384, 0x00000381, 0x00000381,
0x0005008e, 0x0000000c, 0x00000385, 0x00000384,
0x00000068, 0x0006000c, 0x0000000c, 0x00000386,
0x00000001, 0x0000001d, 0x00000385, 0x00050051,
0x00000006, 0x0000038a, 0x00000386, 0x00000000,
0x0005008e, 0x0000000c, 0x0000038b, 0x0000031a,
0x0000038a, 0x00050051, 0x00000006, 0x0000038f,
0x00000386, 0x00000001, 0x0005008e, 0x0000000c,
0x00000390, 0x00000347, 0x0000038f, 0x00050081,
0x0000000c, 0x00000391, 0x0000038b, 0x00000390,
0x00050051, 0x00000006, 0x00000395, 0x00000386,
0x00000002, 0x0005008e, 0x0000000c, 0x00000396,
0x00000374, 0x00000395, 0x00050081, 0x0000000c,
0x00000397, 0x00000391, 0x00000396, 0x00050081,
0x00000006, 0x0000039c, 0x0000038a, 0x0000038f,
0x00050081, 0x00000006, 0x0000039f, 0x0000039c,
0x00000395, 0x00060050, 0x0000000c, 0x000003a0,
0x0000039f, 0x0000039f, 0x0000039f, 0x00050088,
0x0000000c, 0x000003a1, 0x00000397, 0x000003a0,
0x00060052, 0x0000000a, 0x000004e1, 0x00000249,
0x000001bf, 0x00000000, 0x00050085, 0x0000000a,
0x000003b6, 0x000001c8, 0x000004e1, 0x00050083,
0x0000000a, 0x000003b7, 0x000003b6, 0x000000fc,
0x0006000c, 0x0000000a, 0x000003b9, 0x00000001,
0x00000008, 0x000003b7, 0x00050081, 0x0000000a,
0x000003ba, 0x000003b9, 0x00000102, 0x00050088,
0x0000000a, 0x000003bc, 0x000003ba, 0x000004e1,
0x0006000c, 0x0000000a, 0x000003be, 0x00000001,
0x0000000a, 0x000003b7, 0x00050051, 0x00000006,
0x000003c0, 0x000003be, 0x00000000, 0x00050081,
0x00000006, 0x000003c1, 0x000003c0, 0x00000049,
0x00050083, 0x00000006, 0x000003c6, 0x000003c0,
0x00000049, 0x00050083, 0x00000006, 0x000003c9,
0x000003c0, 0x00000116, 0x00070050, 0x00000037,
0x000003ca, 0x000003c1, 0x000003c0, 0x000003c6,
0x000003c9, 0x0005008e, 0x00000037, 0x000003cb,
0x000003ca, 0x0000010b, 0x0006000c, 0x00000037,
0x000003cd, 0x00000001, 0x00000004, 0x000003cb,
0x0007000c, 0x00000037, 0x000003cf, 0x00000001,
0x00000028, 0x000003cd, 0x000004f4, 0x0006000c,
0x00000037, 0x000003d1, 0x00000001, 0x0000000d,
0x000003cf, 0x0005008e, 0x00000037, 0x000003d2,
0x000003d1, 0x00000116, 0x00050085, 0x00000037,
0x000003d5, 0x000003cf, 0x000004fa, 0x0006000c,
0x00000037, 0x000003d6, 0x00000001, 0x0000000d,
0x000003d5, 0x00050085, 0x00000037, 0x000003d7,
0x000003d2, 0x000003d6, 0x00050085, 0x00000037,
0x000003da, 0x000003cf, 0x000003cf, 0x00050088,
0x00000037, 0x000003db, 0x000003d7, 0x000003da,
0x00050094, 0x00000006, 0x000003dd, 0x000003db,
0x0000012c, 0x00070050, 0x00000037, 0x000003df,
0x000003dd, 0x000003dd, 0x000003dd, 0x000003dd,
0x00050088, 0x00000037, 0x000003e0, 0x000003db,
0x000003df, 0x00050057, 0x00000037, 0x000003e3,
0x0000028a, 0x000003bc, 0x0008004f, 0x0000000c,
0x000003e4, 0x000003e3, 0x000003e3, 0x00000000,
0x00000001, 0x00000002, 0x0007000c, 0x0000000c,
0x000003e5, 0x00000001, 0x0000001a, 0x000003e4,
0x0000003b, 0x00050051, 0x00000006, 0x000003e6,
0x000003e5, 0x00000000, 0x00050051, 0x00000006,
0x000003e7, 0x000003e5, 0x00000001, 0x00050051,
0x00000006, 0x000003e8, 0x000003e5, 0x00000002,
0x00050081, 0x0000000a, 0x000003ed, 0x000003bc,
0x0000024b, 0x00050057, 0x00000037, 0x000003ee,
0x0000028a, 0x000003ed, 0x0008004f, 0x0000000c,
0x000003ef, 0x000003ee, 0x000003ee, 0x00000000,
0x00000001, 0x00000002, 0x0007000c, 0x0000000c,
0x000003f0, 0x00000001, 0x0000001a, 0x000003ef,
0x0000003b, 0x00050051, 0x00000006, 0x000003f1,
0x000003f0, 0x00000000, 0x00050051, 0x00000006,
0x000003f2, 0x000003f0, 0x00000001, 0x00050051,
0x00000006, 0x000003f3, 0x000003f0, 0x00000002,
0x00070050, 0x00000037, 0x00000407, 0x000003e6,
0x000003e7, 0x000003e8, 0x00000049, 0x00070050,
0x00000037, 0x00000409, 0x000003f1, 0x000003f2,
0x000003f3, 0x00000049, 0x00070050, 0x00000149,
0x0000040b, 0x00000407, 0x00000407, 0x00000409,
0x00000409, 0x00050091, 0x00000037, 0x0000040d,
0x0000040b, 0x000003e0, 0x0008004f, 0x0000000c,
0x0000040e, 0x0000040d, 0x0000040d, 0x00000000,
0x00000001, 0x00000002, 0x00050085, 0x00000006,
0x0000041b, 0x00000249, 0x000001dc, 0x00060052,
0x0000000a, 0x000004e9, 0x0000041b, 0x000001bf,
0x00000000, 0x00050088, 0x00000006, 0x0000041f,
0x000004fb, 0x00000249, 0x00050050, 0x0000000a,
0x00000420, 0x0000041f, 0x0000004a, 0x00050085,
0x0000000a, 0x00000423, 0x000001c8, 0x000004e9,
0x00050083, 0x0000000a, 0x00000424, 0x00000423,
0x000000fc, 0x0006000c, 0x0000000a, 0x00000426,
0x00000001, 0x00000008, 0x00000424, 0x00050081,
0x0000000a, 0x00000427, 0x00000426, 0x00000102,
0x00050088, 0x0000000a, 0x00000429, 0x00000427,
0x000004e9, 0x0006000c, 0x0000000a, 0x0000042b,
0x00000001, 0x0000000a, 0x00000424, 0x00050051,
0x00000006, 0x0000042d, 0x0000042b, 0x00000000,
0x00050081, 0x00000006, 0x0000042e, 0x0000042d,
0x00000049, 0x00050083, 0x00000006, 0x00000433,
0x0000042d, 0x00000049, 0x00050083, 0x00000006,
0x00000436, 0x0000042d, 0x00000116, 0x00070050,
0x00000037, 0x00000437, 0x0000042e, 0x0000042d,
0x00000433, 0x00000436, 0x0005008e, 0x00000037,
0x00000438, 0x00000437, 0x0000010b, 0x0006000c,
0x00000037, 0x0000043a, 0x00000001, 0x00000004,
0x00000438, 0x0007000c, 0x00000037, 0x0000043c,
0x00000001, 0x00000028, 0x0000043a, 0x000004f4,
0x0006000c, 0x00000037, 0x0000043e, 0x00000001,
0x0000000d, 0x0000043c, 0x0005008e, 0x00000037,
0x0000043f, 0x0000043e, 0x00000116, 0x00050085,
0x00000037, 0x00000442, 0x0000043c, 0x000004fa,
0x0006000c, 0x00000037, 0x00000443, 0x00000001,
0x0000000d, 0x00000442, 0x00050085, 0x00000037,
0x00000444, 0x0000043f, 0x00000443, 0x00050085,
0x00000037, 0x00000447, 0x0000043c, 0x0000043c,
0x00050088, 0x00000037, 0x00000448, 0x00000444,
0x00000447, 0x00050094, 0x00000006, 0x0000044a,
0x00000448, 0x0000012c, 0x00070050, 0x00000037,
0x0000044c, 0x0000044a, 0x0000044a, 0x0000044a,
0x0000044a, 0x00050088, 0x00000037, 0x0000044d,
0x00000448, 0x0000044c, 0x00050057, 0x00000037,
0x00000450, 0x0000028a, 0x00000429, 0x0008004f,
0x0000000c, 0x00000451, 0x00000450, 0x00000450,
0x00000000, 0x00000001, 0x00000002, 0x0007000c,
0x0000000c, 0x00000452, 0x00000001, 0x0000001a,
0x00000451, 0x0000003b, 0x00050051, 0x00000006,
0x00000453, 0x00000452, 0x00000000, 0x00050051,
0x00000006, 0x00000454, 0x00000452, 0x00000001,
0x00050051, 0x00000006, 0x00000455, 0x00000452,
0x00000002, 0x00050081, 0x0000000a, 0x0000045a,
0x00000429, 0x00000420, 0x00050057, 0x00000037,
0x0000045b, 0x0000028a, 0x0000045a, 0x0008004f,
0x0000000c, 0x0000045c, 0x0000045b, 0x0000045b,
0x00000000, 0x00000001, 0x00000002, 0x0007000c,
0x0000000c, 0x0000045d, 0x00000001, 0x0000001a,
0x0000045c, 0x0000003b, 0x00050051, 0x00000006,
0x0000045e, 0x0000045d, 0x00000000, 0x00050051,
0x00000006, 0x0000045f, 0x0000045d, 0x00000001,
0x00050051, 0x00000006, 0x00000460, 0x0000045d,
0x00000002, 0x00070050, 0x00000037, 0x00000474,
0x00000453, 0x00000454, 0x00000455, 0x00000049,
0x00070050, 0x00000037, 0x00000476, 0x0000045e,
0x0000045f, 0x00000460, 0x00000049, 0x00070050,
0x00000149, 0x00000478, 0x00000474, 0x00000474,
0x00000476, 0x00000476, 0x00050091, 0x00000037,
0x0000047a, 0x00000478, 0x0000044d, 0x0008004f,
0x0000000c, 0x0000047b, 0x0000047a, 0x0000047a,
0x00000000, 0x00000001, 0x00000002, 0x00050085,
0x0000000c, 0x000001e8, 0x0000047b, 0x0000040e,
0x0006000c, 0x0000000c, 0x000001e9, 0x00000001,
0x0000001f, 0x000001e8, 0x00050051, 0x00000006,
0x000001eb, 0x000001c8, 0x00000001, 0x00060041,
0x00000188, 0x000001ec, 0x00000187, 0x0000006c,
0x00000077, 0x0004003d, 0x00000006, 0x000001ed,
0x000001ec, 0x00050085, 0x00000006, 0x000001ee,
0x000001eb, 0x000001ed, 0x0006000c, 0x00000006,
0x000001ef, 0x00000001, 0x0000000a, 0x000001ee,
0x0007000c, 0x0000000c, 0x00000482, 0x00000001,
0x0000001a, 0x0000040e, 0x0000016a, 0x0008000c,
0x0000000c, 0x00000483, 0x00000001, 0x0000002e,
0x00000165, 0x00000167, 0x00000482, 0x00050088,
0x0000000c, 0x00000486, 0x000004f6, 0x00000483,
0x0005008e, 0x0000000c, 0x00000488, 0x00000486,
0x000000a1, 0x0005008e, 0x0000000c, 0x0000048b,
0x00000486, 0x000001ef, 0x00050083, 0x0000000c,
0x0000048d, 0x0000048b, 0x00000488, 0x0006000c,
0x0000000c, 0x0000048e, 0x00000001, 0x00000004,
0x0000048d, 0x00050083, 0x0000000c, 0x00000490,
0x000004f7, 0x0000048e, 0x0008000c, 0x0000000c,
0x00000493, 0x00000001, 0x00000031, 0x000004f8,
0x000004f7, 0x00000490, 0x00050085, 0x0000000c,
0x00000495, 0x00000493, 0x00000488, 0x00050085,
0x0000000c, 0x000001f5, 0x000001e9, 0x00000495,
0x00050083, 0x0000000c, 0x000001f8, 0x000003a1,
0x000001f5, 0x0008000c, 0x0000000c, 0x000001fb,
0x00000001, 0x0000002b, 0x000001f8, 0x000004f8,
0x000004f7, 0x00050085, 0x0000000c, 0x000001fe,
0x000001fb, 0x000001fb, 0x0005008e, 0x0000000c,
0x00000200, 0x000001fe, 0x000001ff, 0x00050081,
0x0000000c, 0x00000202, 0x000001f5, 0x00000200,
0x00050041, 0x00000206, 0x00000207, 0x000001ba,
0x00000070, 0x0004003d, 0x00000006, 0x00000208,
0x00000207, 0x000300f7, 0x000004b3, 0x00000000,
0x000300fb, 0x00000070, 0x0000049b, 0x000200f8,
0x0000049b, 0x00060041, 0x00000188, 0x0000049d,
0x00000187, 0x00000074, 0x00000070, 0x0004003d,
0x00000006, 0x0000049e, 0x0000049d, 0x00050085,
0x00000006, 0x0000049f, 0x00000208, 0x0000049e,
0x0006000c, 0x00000006, 0x000004a7, 0x00000001,
0x00000008, 0x0000049f, 0x0005008d, 0x00000006,
0x000004a8, 0x000004a7, 0x00000116, 0x000500b4,
0x00000196, 0x000004aa, 0x000004a8, 0x0000004a,
0x000300f7, 0x000004b2, 0x00000000, 0x000400fa,
0x000004aa, 0x000004ab, 0x000004ac, 0x000200f8,
0x000004ac, 0x000500b4, 0x00000196, 0x000004ae,
0x000004a8, 0x00000049, 0x000300f7, 0x000004b1,
0x00000000, 0x000400fa, 0x000004ae, 0x000004af,
0x000004b0, 0x000200f8, 0x000004b0, 0x000200f9,
0x000004b3, 0x000200f8, 0x000004af, 0x000200f9,
0x000004b3, 0x000200f8, 0x000004b1, 0x000100ff,
0x000200f8, 0x000004ab, 0x000200f9, 0x000004b3,
0x000200f8, 0x000004b2, 0x000100ff, 0x000200f8,
0x000004b3, 0x000900f5, 0x0000000c, 0x000004f1,
0x0000019a, 0x000004ab, 0x000001a1, 0x000004af,
0x000001a4, 0x000004b0, 0x00050085, 0x0000000c,
0x0000020a, 0x00000202, 0x000004f1, 0x0005008e,
0x0000000c, 0x0000020b, 0x0000020a, 0x00000116,
0x0008000c, 0x0000000c, 0x0000020e, 0x00000001,
0x0000002e, 0x00000202, 0x0000020b, 0x000004f9,
0x0005008e, 0x0000000c, 0x00000211, 0x000001fb,
0x00000210, 0x00050081, 0x0000000c, 0x00000213,
0x0000020e, 0x00000211, 0x0005008e, 0x0000000c,
0x00000215, 0x00000213, 0x00000166, 0x0007000c,
0x0000000c, 0x00000218, 0x00000001, 0x0000001a,
0x00000215, 0x00000217, 0x00050051, 0x00000006,
0x0000021c, 0x00000218, 0x00000000, 0x00050051,
0x00000006, 0x0000021d, 0x00000218, 0x00000001,
0x00050051, 0x00000006, 0x0000021e, 0x00000218,
0x00000002, 0x00070050, 0x00000037, 0x0000021f,
0x0000021c, 0x0000021d, 0x0000021e, 0x00000049,
0x0003003e, 0x0000021a, 0x0000021f, 0x000100fd,
0x00010038};
+29 -1
View File
@@ -10,6 +10,8 @@ include!(concat!(env!("OUT_DIR"), "/simd_bindings.rs"));
#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
use rand_chacha::rand_core::{RngCore, SeedableRng};
use crate::{netplay, ui};
use std::{collections::HashMap, fs, io::Read};
@@ -42,7 +44,12 @@ pub mod tlb;
pub mod unmapped;
pub mod vi;
pub fn run_game(rom_contents: Vec<u8>, device: &mut Device) {
pub fn run_game(device: &mut Device, rom_contents: Vec<u8>, fullscreen: bool, overclock: bool) {
device.ui.video.fullscreen = fullscreen;
device.cpu.overclock = overclock;
init_rng(device);
cart::rom::init(device, rom_contents); // cart needs to come before rdram
// rdram pointer is shared with parallel-rdp
@@ -75,6 +82,23 @@ pub fn run_game(rom_contents: Vec<u8>, device: &mut Device) {
ui::storage::write_saves(device);
}
fn set_rng() -> rand_chacha::ChaCha8Rng {
rand_chacha::ChaCha8Rng::from_os_rng()
}
fn init_rng(device: &mut Device) {
let mut rng_seed = set_rng().next_u64();
if device.netplay.is_some() {
let netplay = device.netplay.as_mut().unwrap();
if netplay.player_number == 0 {
netplay::send_rng(netplay, rng_seed);
} else {
rng_seed = netplay::receive_rng(netplay);
}
}
device.rng = rand_chacha::ChaCha8Rng::seed_from_u64(rng_seed);
}
fn swap_rom(contents: Vec<u8>) -> Vec<u8> {
let test = u32::from_be_bytes(contents[0..4].try_into().unwrap());
if test == 0x80371240 {
@@ -174,6 +198,8 @@ pub struct Device {
pub ai: ai::Ai,
pub si: si::Si,
pub ri: ri::Ri,
#[serde(skip, default = "set_rng")]
pub rng: rand_chacha::ChaCha8Rng,
pub vru: controller::vru::Vru,
pub vru_window: controller::vru::VruWindow,
pub transferpaks: [controller::transferpak::TransferPak; 4],
@@ -270,6 +296,7 @@ impl Device {
pc: 0xBFC00000,
pc_phys: 0,
llbit: false,
overclock: false,
lo: 0,
hi: 0,
running: false,
@@ -461,6 +488,7 @@ impl Device {
talking: false,
word_mappings: HashMap::new(),
},
rng: set_rng(),
transferpaks: [
controller::transferpak::TransferPak::default(),
controller::transferpak::TransferPak::default(),
+1 -1
View File
@@ -66,7 +66,7 @@ fn do_dma(device: &mut device::Device) {
device::events::create_event(
device,
device::events::EVENT_TYPE_AI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + device.ai.fifo[0].duration,
device.ai.fifo[0].duration,
);
device::mi::set_rcp_interrupt(device, device::mi::MI_INTR_AI);
}
+15 -6
View File
@@ -63,12 +63,14 @@ pub fn process(device: &mut device::Device, channel: usize) {
let eeprom_type;
if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Eeprom16k)
{
eeprom_type = JDT_EEPROM_16K;
} else if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Eeprom4k)
{
@@ -124,8 +126,14 @@ pub fn process(device: &mut device::Device, channel: usize) {
}
pub fn format_eeprom(device: &mut device::Device) {
if device.ui.saves.eeprom.data.len() < EEPROM_MAX_SIZE {
device.ui.saves.eeprom.data.resize(EEPROM_MAX_SIZE, 0xFF)
if device.ui.storage.saves.eeprom.data.len() < EEPROM_MAX_SIZE {
device
.ui
.storage
.saves
.eeprom
.data
.resize(EEPROM_MAX_SIZE, 0xFF)
}
}
@@ -134,8 +142,9 @@ fn eeprom_read_block(device: &mut device::Device, block: usize, offset: usize) {
format_eeprom(device);
device.pif.ram[offset..offset + EEPROM_BLOCK_SIZE]
.copy_from_slice(&device.ui.saves.eeprom.data[address..address + EEPROM_BLOCK_SIZE]);
device.pif.ram[offset..offset + EEPROM_BLOCK_SIZE].copy_from_slice(
&device.ui.storage.saves.eeprom.data[address..address + EEPROM_BLOCK_SIZE],
);
}
fn eeprom_write_block(device: &mut device::Device, block: usize, offset: usize, status: usize) {
@@ -143,12 +152,12 @@ fn eeprom_write_block(device: &mut device::Device, block: usize, offset: usize,
format_eeprom(device);
device.ui.saves.eeprom.data[address..address + EEPROM_BLOCK_SIZE]
device.ui.storage.saves.eeprom.data[address..address + EEPROM_BLOCK_SIZE]
.copy_from_slice(&device.pif.ram[offset..offset + EEPROM_BLOCK_SIZE]);
device.pif.ram[status] = 0x00;
device.ui.saves.eeprom.written = true
device.ui.storage.saves.eeprom.written = true
}
fn time2data(device: &mut device::Device, offset: usize) {
+15 -11
View File
@@ -7,7 +7,14 @@ const CART_MASK: usize = 0xFFFFFFF;
fn read_cart_word(device: &mut device::Device, address: usize) -> u32 {
let mut data: [u8; 4] = [0; 4];
for i in 0..4 {
if let Some(value) = device.ui.saves.romsave.data.get(&(address as u32 + i)) {
if let Some(value) = device
.ui
.storage
.saves
.romsave
.data
.get(&(address as u32 + i))
{
data[i as usize] = *value;
} else {
data[i as usize] = *device.cart.rom.get(address + i as usize).unwrap_or(&0);
@@ -52,12 +59,13 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
for (i, item) in data.to_be_bytes().iter().enumerate() {
device
.ui
.storage
.saves
.romsave
.data
.insert((masked_address + i) as u32, *item);
}
device.ui.saves.romsave.written = true;
device.ui.storage.saves.romsave.written = true;
}
device.cart.latch = value & mask;
@@ -65,11 +73,7 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
device.pi.regs[device::pi::PI_STATUS_REG as usize] |= device::pi::PI_STATUS_IO_BUSY;
let cycles = device::pi::calculate_cycles(device, 1, 4);
device::events::create_event(
device,
device::events::EVENT_TYPE_PI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + cycles,
);
device::events::create_event(device, device::events::EVENT_TYPE_PI, cycles);
}
pub fn dma_read(
@@ -85,12 +89,12 @@ pub fn dma_read(
cart_addr &= CART_MASK as u32;
for i in 0..length {
device.ui.saves.romsave.data.insert(
device.ui.storage.saves.romsave.data.insert(
cart_addr + i,
device.rdram.mem[(dram_addr + i) as usize ^ device.byte_swap],
);
}
device.ui.saves.romsave.written = true;
device.ui.storage.saves.romsave.written = true;
}
device::pi::calculate_cycles(device, 1, length)
@@ -108,8 +112,8 @@ pub fn dma_write(
let mut i = dram_addr;
let mut j = cart_addr;
while i < dram_addr + length {
if device.ui.saves.romsave.data.contains_key(&j) {
device.rdram.mem[i as usize ^ device.byte_swap] = device.ui.saves.romsave.data[&j];
if let Some(value) = device.ui.storage.saves.romsave.data.get(&j) {
device.rdram.mem[i as usize ^ device.byte_swap] = *value;
} else {
device.rdram.mem[i as usize ^ device.byte_swap] =
*device.cart.rom.get(j as usize).unwrap_or(&0);
+18 -17
View File
@@ -31,9 +31,9 @@ pub struct Sc64 {
}
fn format_sdcard(device: &mut device::Device) {
if device.ui.saves.sdcard.data.is_empty() {
device.ui.saves.sdcard.data.resize(SDCARD_SIZE, 0);
let buf = std::io::Cursor::new(&mut device.ui.saves.sdcard.data);
if device.ui.storage.saves.sdcard.data.is_empty() {
device.ui.storage.saves.sdcard.data.resize(SDCARD_SIZE, 0);
let buf = std::io::Cursor::new(&mut device.ui.storage.saves.sdcard.data);
fatfs::format_volume(buf, fatfs::FormatVolumeOptions::new()).unwrap();
}
}
@@ -93,8 +93,8 @@ pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u
if device.cart.sc64.regs[SC64_DATA0_REG as usize] == SC64_SAVE_TYPE {
// if save type is being written, we are probably booting a game using the flash cart menu
// we shouldn't write saves to disk in this case (they are written to the SD card)
device.ui.saves.write_to_disk = false;
device.ui.save_type =
device.ui.storage.saves.write_to_disk = false;
device.ui.storage.save_type =
match device.cart.sc64.regs[SC64_DATA1_REG as usize] {
0 => {
vec![]
@@ -155,9 +155,10 @@ pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u
let mut i = 0;
while i < length {
if offset + i < device.ui.saves.sdcard.data.len() {
if offset + i < device.ui.storage.saves.sdcard.data.len() {
let data = u32::from_be_bytes(
device.ui.saves.sdcard.data[(offset + i)..(offset + i + 4)]
device.ui.storage.saves.sdcard.data
[(offset + i)..(offset + i + 4)]
.try_into()
.unwrap(),
);
@@ -186,7 +187,7 @@ pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u
let mut i = 0;
while i < length {
if offset + i < device.ui.saves.sdcard.data.len() {
if offset + i < device.ui.storage.saves.sdcard.data.len() {
let data = device::memory::data_read(
device,
address + i as u64,
@@ -194,14 +195,14 @@ pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u
false,
)
.to_be_bytes();
device.ui.saves.sdcard.data[(offset + i)..(offset + i + 4)]
device.ui.storage.saves.sdcard.data[(offset + i)..(offset + i + 4)]
.copy_from_slice(&data);
} else {
panic!("sd card write out of bounds")
}
i += 4;
}
device.ui.saves.sdcard.written = true;
device.ui.storage.saves.sdcard.written = true;
}
'U' | 'u' => {} // USB status, ignored
'M' | 'm' => {} // USB read/write, ignored
@@ -248,7 +249,7 @@ pub fn read_mem(
device::cart::format_eeprom(device);
let masked_address = address as usize & SC64_EEPROM_MASK;
u32::from_be_bytes(
device.ui.saves.eeprom.data[masked_address..masked_address + 4]
device.ui.storage.saves.eeprom.data[masked_address..masked_address + 4]
.try_into()
.unwrap(),
)
@@ -267,14 +268,14 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
device::cart::format_eeprom(device);
let masked_address = address as usize & SC64_EEPROM_MASK;
let mut data = u32::from_be_bytes(
device.ui.saves.eeprom.data[masked_address..masked_address + 4]
device.ui.storage.saves.eeprom.data[masked_address..masked_address + 4]
.try_into()
.unwrap(),
);
device::memory::masked_write_32(&mut data, value, mask);
device.ui.saves.eeprom.data[masked_address..masked_address + 4]
device.ui.storage.saves.eeprom.data[masked_address..masked_address + 4]
.copy_from_slice(&data.to_be_bytes());
device.ui.saves.eeprom.written = true
device.ui.storage.saves.eeprom.written = true
} else {
let masked_address = address as usize & SC64_BUFFER_MASK;
let mut data = u32::from_be_bytes(
@@ -298,8 +299,8 @@ pub fn dma_read(
let buffer = if cart_addr & 0x2000 != 0 {
device::cart::format_eeprom(device);
cart_addr &= SC64_EEPROM_MASK as u32;
device.ui.saves.eeprom.written = true;
&mut device.ui.saves.eeprom.data
device.ui.storage.saves.eeprom.written = true;
&mut device.ui.storage.saves.eeprom.data
} else {
cart_addr &= SC64_BUFFER_MASK as u32;
&mut device.cart.sc64.buffer
@@ -326,7 +327,7 @@ pub fn dma_write(
let buffer = if cart_addr & 0x2000 != 0 {
device::cart::format_eeprom(device);
cart_addr &= SC64_EEPROM_MASK as u32;
&device.ui.saves.eeprom.data
&device.ui.storage.saves.eeprom.data
} else {
cart_addr &= SC64_BUFFER_MASK as u32;
&device.cart.sc64.buffer
+51 -27
View File
@@ -29,14 +29,20 @@ pub struct Flashram {
}
fn format_sram(device: &mut device::Device) {
if device.ui.saves.sram.data.len() < SRAM_SIZE {
device.ui.saves.sram.data.resize(SRAM_SIZE, 0xFF)
if device.ui.storage.saves.sram.data.len() < SRAM_SIZE {
device.ui.storage.saves.sram.data.resize(SRAM_SIZE, 0xFF)
}
}
fn format_flash(device: &mut device::Device) {
if device.ui.saves.flash.data.len() < FLASHRAM_SIZE {
device.ui.saves.flash.data.resize(FLASHRAM_SIZE, 0xFF)
if device.ui.storage.saves.flash.data.len() < FLASHRAM_SIZE {
device
.ui
.storage
.saves
.flash
.data
.resize(FLASHRAM_SIZE, 0xFF)
}
}
@@ -46,7 +52,7 @@ fn read_mem_sram(device: &mut device::Device, address: u64) -> u32 {
format_sram(device);
u32::from_be_bytes(
device.ui.saves.sram.data[masked_address..masked_address + 4]
device.ui.storage.saves.sram.data[masked_address..masked_address + 4]
.try_into()
.unwrap(),
)
@@ -75,7 +81,12 @@ pub fn read_mem(
let cycles = device::pi::calculate_cycles(device, 2, 4);
device::cop0::add_cycles(device, cycles);
if device.ui.save_type.contains(&ui::storage::SaveTypes::Sram) {
if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Sram)
{
read_mem_sram(device, address)
} else {
read_mem_flash(device, address)
@@ -88,15 +99,15 @@ fn write_mem_sram(device: &mut device::Device, address: u64, value: u32, mask: u
format_sram(device);
let mut data = u32::from_be_bytes(
device.ui.saves.sram.data[masked_address..masked_address + 4]
device.ui.storage.saves.sram.data[masked_address..masked_address + 4]
.try_into()
.unwrap(),
);
device::memory::masked_write_32(&mut data, value, mask);
device.ui.saves.sram.data[masked_address..masked_address + 4]
device.ui.storage.saves.sram.data[masked_address..masked_address + 4]
.copy_from_slice(&data.to_be_bytes());
device.ui.saves.sram.written = true
device.ui.storage.saves.sram.written = true
}
fn write_mem_flash(device: &mut device::Device, address: u64, value: u32, mask: u32) {
@@ -114,7 +125,12 @@ fn write_mem_flash(device: &mut device::Device, address: u64, value: u32, mask:
}
pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u32) {
if device.ui.save_type.contains(&ui::storage::SaveTypes::Sram) {
if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Sram)
{
write_mem_sram(device, address, value, mask)
} else {
write_mem_flash(device, address, value, mask)
@@ -123,11 +139,7 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
device.pi.regs[device::pi::PI_STATUS_REG as usize] |= device::pi::PI_STATUS_IO_BUSY;
let cycles = device::pi::calculate_cycles(device, 2, 4);
device::events::create_event(
device,
device::events::EVENT_TYPE_PI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + cycles,
);
device::events::create_event(device, device::events::EVENT_TYPE_PI, cycles);
}
fn dma_read_sram(device: &mut device::Device, mut cart_addr: u32, mut dram_addr: u32, length: u32) {
@@ -139,12 +151,13 @@ fn dma_read_sram(device: &mut device::Device, mut cart_addr: u32, mut dram_addr:
format_sram(device);
while i < dram_addr + length && i < device.rdram.size {
device.ui.saves.sram.data[j as usize] = device.rdram.mem[i as usize ^ device.byte_swap];
device.ui.storage.saves.sram.data[j as usize] =
device.rdram.mem[i as usize ^ device.byte_swap];
i += 1;
j += 1;
}
device.ui.saves.sram.written = true
device.ui.storage.saves.sram.written = true
}
fn dma_read_flash(device: &mut device::Device, cart_addr: u32, dram_addr: u32, length: u32) {
@@ -167,7 +180,12 @@ fn dma_read_flash(device: &mut device::Device, cart_addr: u32, dram_addr: u32, l
// cart is big endian, rdram is native endian
pub fn dma_read(device: &mut device::Device, cart_addr: u32, dram_addr: u32, length: u32) -> u64 {
if device.ui.save_type.contains(&ui::storage::SaveTypes::Sram) {
if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Sram)
{
dma_read_sram(device, cart_addr, dram_addr, length)
} else {
dma_read_flash(device, cart_addr, dram_addr, length)
@@ -189,7 +207,8 @@ fn dma_write_sram(
format_sram(device);
while i < dram_addr + length && i < device.rdram.size {
device.rdram.mem[i as usize ^ device.byte_swap] = device.ui.saves.sram.data[j as usize];
device.rdram.mem[i as usize ^ device.byte_swap] =
device.ui.storage.saves.sram.data[j as usize];
i += 1;
j += 1;
}
@@ -232,7 +251,7 @@ fn dma_write_flash(
/* do actual DMA */
for i in 0..length {
device.rdram.mem[(dram_addr + i) as usize ^ device.byte_swap] =
device.ui.saves.flash.data[(cart_addr + i) as usize];
device.ui.storage.saves.flash.data[(cart_addr + i) as usize];
}
} else {
/* other accesses are not implemented */
@@ -242,7 +261,12 @@ fn dma_write_flash(
// cart is big endian, rdram is native endian
pub fn dma_write(device: &mut device::Device, cart_addr: u32, dram_addr: u32, length: u32) -> u64 {
if device.ui.save_type.contains(&ui::storage::SaveTypes::Sram) {
if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Sram)
{
dma_write_sram(device, cart_addr, dram_addr, length)
} else {
dma_write_flash(device, cart_addr, dram_addr, length)
@@ -271,14 +295,14 @@ fn flashram_command(device: &mut device::Device, command: u32) {
if device.cart.flashram.mode == FlashramMode::SectorErase {
let offset: usize = (device.cart.flashram.erase_page & 0xff80) as usize * 128;
for i in 0..128 * 128 {
device.ui.saves.flash.data[offset + i] = 0xFF;
device.ui.storage.saves.flash.data[offset + i] = 0xFF;
}
device.ui.saves.flash.written = true
device.ui.storage.saves.flash.written = true
} else if device.cart.flashram.mode == FlashramMode::ChipErase {
for i in 0..FLASHRAM_SIZE {
device.ui.saves.flash.data[i] = 0xFF;
device.ui.storage.saves.flash.data[i] = 0xFF;
}
device.ui.saves.flash.written = true
device.ui.storage.saves.flash.written = true
} else {
panic!("Unexpected flash erase command")
}
@@ -296,9 +320,9 @@ fn flashram_command(device: &mut device::Device, command: u32) {
/* program selected page */
let offset: usize = (command & 0xffff) as usize * 128;
for i in 0..128 {
device.ui.saves.flash.data[offset + i] = device.cart.flashram.page_buf[i];
device.ui.storage.saves.flash.data[offset + i] = device.cart.flashram.page_buf[i];
}
device.ui.saves.flash.written = true;
device.ui.storage.saves.flash.written = true;
/* clear program busy flag, set program success flag, transition to status mode */
device.cart.flashram.status &= !0x01;
+1 -2
View File
@@ -77,8 +77,7 @@ pub fn process(device: &mut device::Device, channel: usize) {
device::events::create_event(
device,
device::events::EVENT_TYPE_PAK,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize]
+ (device.cpu.clock_rate), // 1 second
device.cpu.clock_rate, // 1 second
)
}
}
+76
View File
@@ -8,6 +8,7 @@ pub struct GbCart {
pub ram: Vec<u8>,
pub cart_type: device::controller::gbcart::CartType,
pub ram_enabled: bool,
pub mbc1_mode: bool,
pub ram_bank: u16,
pub rom_bank: u32,
pub set_latch: bool,
@@ -21,11 +22,83 @@ pub struct GbCart {
pub enum CartType {
#[default]
None,
MBC1RamBatt,
MBC3RamBatt,
MBC3RamBattRtc,
MBC5RamBatt,
}
fn write_mbc1(
pif_ram: &mut [u8],
cart: &mut device::controller::gbcart::GbCart,
address: u16,
data: usize,
size: usize,
) {
let value = pif_ram[data + size - 1];
if address < 0x2000 {
cart.ram_enabled = value & 0xf == 0xa;
} else if address < 0x4000 {
let bank = value & 0x1f;
cart.rom_bank = bank as u32;
if cart.rom_bank == 0 {
cart.rom_bank = 1;
}
} else if address < 0x6000 {
cart.ram_bank = (value & 0x3) as u16;
} else if address < 0x8000 {
cart.mbc1_mode = (value & 0x1) != 0;
} else if (0xa000..0xc000).contains(&address) {
if !cart.ram_enabled {
return;
}
if cart.mbc1_mode {
let banked_address = address - 0xA000 + (cart.ram_bank * 0x2000);
cart.ram[banked_address as usize..banked_address as usize + size]
.copy_from_slice(&pif_ram[data..data + size]);
} else {
let banked_address = address - 0xA000;
cart.ram[banked_address as usize..banked_address as usize + size]
.copy_from_slice(&pif_ram[data..data + size]);
}
}
}
fn read_mbc1(
pif_ram: &mut [u8],
cart: &mut device::controller::gbcart::GbCart,
address: u16,
data: usize,
size: usize,
) {
if address < 0x4000 {
let banked_address = address & 0x3FFF;
pif_ram[data..data + size]
.copy_from_slice(&cart.rom[banked_address as usize..banked_address as usize + size]);
} else if address < 0x8000 {
let banked_address = address as u32 - 0x4000 + (cart.rom_bank * 0x4000);
pif_ram[data..data + size]
.copy_from_slice(&cart.rom[banked_address as usize..banked_address as usize + size]);
} else if (0xa000..0xc000).contains(&address) {
if !cart.ram_enabled {
for i in 0..size {
pif_ram[data + i] = 0xff;
}
return;
}
if cart.ram_bank > 3 {
for i in 0..size {
pif_ram[data + i] = 0;
}
} else {
let banked_address = address - 0xA000 + (cart.ram_bank * 0x2000);
pif_ram[data..data + size].copy_from_slice(
&cart.ram[banked_address as usize..banked_address as usize + size],
);
}
}
}
fn write_mbc3(
pif_ram: &mut [u8],
cart: &mut device::controller::gbcart::GbCart,
@@ -217,6 +290,7 @@ pub fn read(
return;
}
match cart.cart_type {
CartType::MBC1RamBatt => read_mbc1(pif_ram, cart, address, data, size),
CartType::MBC3RamBatt => read_mbc3(pif_ram, cart, address, data, size),
CartType::MBC3RamBattRtc => read_mbc3(pif_ram, cart, address, data, size),
CartType::MBC5RamBatt => read_mbc5(pif_ram, cart, address, data, size),
@@ -235,6 +309,7 @@ pub fn write(
return;
}
match cart.cart_type {
CartType::MBC1RamBatt => write_mbc1(pif_ram, cart, address, data, size),
CartType::MBC3RamBatt => write_mbc3(pif_ram, cart, address, data, size),
CartType::MBC3RamBattRtc => write_mbc3(pif_ram, cart, address, data, size),
CartType::MBC5RamBatt => write_mbc5(pif_ram, cart, address, data, size),
@@ -244,6 +319,7 @@ pub fn write(
pub fn get_cart_type(data: u8) -> CartType {
match data {
0x03 => CartType::MBC1RamBatt,
0x10 => CartType::MBC3RamBattRtc,
0x13 => CartType::MBC3RamBatt,
0x1b => CartType::MBC5RamBatt,
+22 -13
View File
@@ -4,8 +4,14 @@ pub const MEMPAK_SIZE: usize = 0x8000;
const MPK_PAGE_SIZE: usize = 256;
fn format_mempak(device: &mut device::Device) {
if device.ui.saves.mempak.data.len() < MEMPAK_SIZE * 4 {
device.ui.saves.mempak.data.resize(MEMPAK_SIZE * 4, 0);
if device.ui.storage.saves.mempak.data.len() < MEMPAK_SIZE * 4 {
device
.ui
.storage
.saves
.mempak
.data
.resize(MEMPAK_SIZE * 4, 0);
let page_0: [u8; MPK_PAGE_SIZE] = [
/* Label area */
@@ -38,28 +44,31 @@ fn format_mempak(device: &mut device::Device) {
let offset = i * MEMPAK_SIZE;
/* Fill Page 0 with pre-initialized content */
device.ui.saves.mempak.data[offset..offset + MPK_PAGE_SIZE].copy_from_slice(&page_0);
device.ui.storage.saves.mempak.data[offset..offset + MPK_PAGE_SIZE]
.copy_from_slice(&page_0);
/* Fill INODE page 1 and update it's checkum */
let start_page = 5;
for i in MPK_PAGE_SIZE..2 * start_page {
device.ui.saves.mempak.data[offset + i] = 0;
device.ui.storage.saves.mempak.data[offset + i] = 0;
}
for i in (MPK_PAGE_SIZE + 2 * start_page..2 * MPK_PAGE_SIZE).step_by(2) {
device.ui.saves.mempak.data[offset + i] = 0x00;
device.ui.saves.mempak.data[offset + i + 1] = 0x03;
device.ui.storage.saves.mempak.data[offset + i] = 0x00;
device.ui.storage.saves.mempak.data[offset + i + 1] = 0x03;
}
device.ui.saves.mempak.data[offset + (MPK_PAGE_SIZE + 1)] = 0x71;
device.ui.storage.saves.mempak.data[offset + (MPK_PAGE_SIZE + 1)] = 0x71;
/* Page 2 is identical to page 1 */
let page1 = offset + MPK_PAGE_SIZE;
let page2 = offset + 2 * MPK_PAGE_SIZE;
let page1data = device.ui.saves.mempak.data[page1..page1 + MPK_PAGE_SIZE].to_vec();
device.ui.saves.mempak.data[page2..page2 + MPK_PAGE_SIZE].copy_from_slice(&page1data);
let page1data =
device.ui.storage.saves.mempak.data[page1..page1 + MPK_PAGE_SIZE].to_vec();
device.ui.storage.saves.mempak.data[page2..page2 + MPK_PAGE_SIZE]
.copy_from_slice(&page1data);
/* Remaining pages DIR+DATA (3...) are initialized with 0x00 */
for i in 3 * MPK_PAGE_SIZE..MEMPAK_SIZE - 3 * MPK_PAGE_SIZE {
device.ui.saves.mempak.data[offset + i] = 0;
device.ui.storage.saves.mempak.data[offset + i] = 0;
}
}
}
@@ -71,7 +80,7 @@ pub fn read(device: &mut device::Device, channel: usize, address: u16, data: usi
let offset = (channel * MEMPAK_SIZE) + address as usize;
device.pif.ram[data..data + size]
.copy_from_slice(&device.ui.saves.mempak.data[offset..offset + size])
.copy_from_slice(&device.ui.storage.saves.mempak.data[offset..offset + size])
} else {
for i in 0..size {
device.pif.ram[data + i] = 0;
@@ -84,9 +93,9 @@ pub fn write(device: &mut device::Device, channel: usize, address: u16, data: us
format_mempak(device);
let offset = (channel * MEMPAK_SIZE) + address as usize;
device.ui.saves.mempak.data[offset..offset + size]
device.ui.storage.saves.mempak.data[offset..offset + size]
.copy_from_slice(&device.pif.ram[data..data + size]);
device.ui.saves.mempak.written = true
device.ui.storage.saves.mempak.written = true
}
}
+1 -2
View File
@@ -170,8 +170,7 @@ pub fn process(device: &mut device::Device, channel: usize) {
device::events::create_event(
device,
device::events::EVENT_TYPE_VRU,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize]
+ (device.cpu.clock_rate * 2), // 2 seconds
device.cpu.clock_rate * 2, // 2 seconds
)
} else if device.pif.ram[device.pif.channels[channel].rx_buf.unwrap()] == 0xEF {
device.vru.talking = false;
+2 -2
View File
@@ -215,7 +215,7 @@ fn set_control_registers(device: &mut device::Device, index: u32, mut data: u64)
device::events::create_event(
device,
device::events::EVENT_TYPE_COMPARE,
device.cpu.cop0.regs[COP0_COUNT_REG as usize] + ((compare_event_diff as u64) << 1),
(compare_event_diff as u64) << 1,
);
device.cpu.cop0.regs[COP0_CAUSE_REG as usize] &= !COP0_CAUSE_IP7;
device.cpu.cop0.pending_compare_interrupt = false;
@@ -237,7 +237,7 @@ fn set_control_registers(device: &mut device::Device, index: u32, mut data: u64)
pub fn compare_event(device: &mut device::Device) {
device.cpu.cop0.pending_compare_interrupt = true;
device::events::create_event(
device::events::create_event_at(
device,
device::events::EVENT_TYPE_COMPARE,
device.cpu.next_event_count + (u32::MAX as u64),
+6 -1
View File
@@ -30,6 +30,7 @@ pub struct Cpu {
pub hi: u64,
pub running: bool,
pub llbit: bool,
pub overclock: bool,
pub clock_rate: u64,
#[serde(skip, default = "savestates::default_instructions")]
pub instrs: [fn(&mut device::Device, u32); 64],
@@ -223,7 +224,11 @@ pub fn map_instructions(device: &mut device::Device) {
}
pub fn init(device: &mut device::Device) {
device.cpu.clock_rate = 93750000;
device.cpu.clock_rate = if !device.cpu.overclock {
93750000
} else {
125000000
};
map_instructions(device);
+8
View File
@@ -21,6 +21,14 @@ pub struct Event {
}
pub fn create_event(device: &mut device::Device, name: usize, when: u64) {
device.cpu.events[name] = Event {
enabled: true,
count: device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + when,
};
set_next_event(device);
}
pub fn create_event_at(device: &mut device::Device, name: usize, when: u64) {
device.cpu.events[name] = Event {
enabled: true,
count: when,
+1 -5
View File
@@ -33,11 +33,7 @@ pub fn check_pending_interrupts(device: &mut device::Device) {
if device.cpu.cop0.is_event {
interrupt_exception(device);
} else {
device::events::create_event(
device,
device::events::EVENT_TYPE_INT,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize],
);
device::events::create_event(device, device::events::EVENT_TYPE_INT, 0);
}
}
+4 -1
View File
@@ -153,7 +153,10 @@ pub fn init(device: &mut device::Device) {
} else if (MM_DOM2_ADDR2 >> 16..=(MM_DOM2_ADDR2 + 0x1FFFF) >> 16).contains(&i) {
device.memory.memory_map_read[i] = device::cart::sram::read_mem;
device.memory.memory_map_write[i] = device::cart::sram::write_mem;
} else if i >= MM_IS_VIEWER >> 16 && i <= (MM_IS_VIEWER + 0xFFFF) >> 16 {
} else if device.cart.rom.len() <= MM_IS_VIEWER - MM_CART_ROM
&& i >= MM_IS_VIEWER >> 16
&& i <= (MM_IS_VIEWER + 0xFFFF) >> 16
{
device.memory.memory_map_read[i] = device::is_viewer::read_mem;
device.memory.memory_map_write[i] = device::is_viewer::write_mem;
} else if (MM_CART_ROM >> 16..=(MM_CART_ROM + 0x0FBFFFFF) >> 16).contains(&i) {
+9 -11
View File
@@ -1,4 +1,5 @@
use crate::{device, ui};
use rand_chacha::rand_core::RngCore;
const PI_DRAM_ADDR_REG: u32 = 0;
const PI_CART_ADDR_REG: u32 = 1;
@@ -65,11 +66,7 @@ fn dma_read(device: &mut device::Device) {
let cycles = (handler.read)(device, cart_addr, dram_addr, length);
device::events::create_event(
device,
device::events::EVENT_TYPE_PI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + cycles,
);
device::events::create_event(device, device::events::EVENT_TYPE_PI, cycles);
/* Update PI_DRAM_ADDR_REG and PI_CART_ADDR_REG */
device.pi.regs[PI_DRAM_ADDR_REG as usize] =
@@ -98,11 +95,7 @@ fn dma_write(device: &mut device::Device) {
let cycles = (handler.write)(device, cart_addr, dram_addr, length);
device::events::create_event(
device,
device::events::EVENT_TYPE_PI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + cycles,
);
device::events::create_event(device, device::events::EVENT_TYPE_PI, cycles);
/* Update PI_DRAM_ADDR_REG and PI_CART_ADDR_REG */
device.pi.regs[PI_DRAM_ADDR_REG as usize] =
@@ -173,7 +166,11 @@ pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u
}
}
pub fn calculate_cycles(device: &device::Device, domain: i32, length: u32) -> u64 {
fn randomize_interrupt_time(rng: &mut rand_chacha::ChaCha8Rng) -> u64 {
rng.next_u64() % 0x10
}
pub fn calculate_cycles(device: &mut device::Device, domain: i32, length: u32) -> u64 {
let mut cycles: f64 = 0.0;
let (page_size, latency, pulse_width, release, pages);
let page_size_base: f64 = 2.0;
@@ -196,6 +193,7 @@ pub fn calculate_cycles(device: &device::Device, domain: i32, length: u32) -> u6
cycles += (14.0 + latency) * pages;
cycles += (pulse_width + release) * (length as f64 / 2.0);
cycles += 5.0 * pages;
cycles += randomize_interrupt_time(&mut device.rng) as f64;
(cycles * 1.5) as u64 // Converting RCP clock speed to CPU clock speed
}
+1 -5
View File
@@ -67,11 +67,7 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
device.pif.ram[masked_address..masked_address + 4].copy_from_slice(&data.to_be_bytes());
device.si.dma_dir = device::si::DmaDir::Write;
device::events::create_event(
device,
device::events::EVENT_TYPE_SI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + 3200,
); //based on https://github.com/rasky/n64-systembench
device::events::create_event(device, device::events::EVENT_TYPE_SI, 3200); //based on https://github.com/rasky/n64-systembench
device.si.regs[device::si::SI_STATUS_REG as usize] |=
device::si::SI_STATUS_DMA_BUSY | device::si::SI_STATUS_IO_BUSY
}
+1 -5
View File
@@ -130,11 +130,7 @@ fn run_rdp(device: &mut device::Device) {
device.load_state = false;
savestates::load_savestate(device);
}
device::events::create_event(
device,
device::events::EVENT_TYPE_DP,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + timer,
)
device::events::create_event(device, device::events::EVENT_TYPE_DP, timer)
}
}
+2 -8
View File
@@ -206,9 +206,7 @@ fn do_dma(device: &mut device::Device, dma: RspDma) {
device::events::create_event(
device,
device::events::EVENT_TYPE_SPDMA,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize]
+ device::rdram::rdram_calculate_cycles((count * length) as u64)
+ 9,
device::rdram::rdram_calculate_cycles((count * length) as u64) + 9,
);
}
@@ -467,11 +465,7 @@ fn do_task(device: &mut device::Device) {
} else {
let timer = device::rsp_cpu::run(device);
device::events::create_event(
device,
device::events::EVENT_TYPE_SP,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + timer,
)
device::events::create_event(device, device::events::EVENT_TYPE_SP, timer)
}
}
+12 -10
View File
@@ -1,3 +1,5 @@
use rand_chacha::rand_core::RngCore;
use crate::device;
const SI_DRAM_ADDR_REG: u32 = 0;
@@ -36,6 +38,10 @@ pub fn read_regs(
device.si.regs[((address & 0xFFFF) >> 2) as usize]
}
fn randomize_interrupt_time(rng: &mut rand_chacha::ChaCha8Rng) -> u64 {
rng.next_u64() % 0x100
}
fn dma_read(device: &mut device::Device) {
device.si.dma_dir = DmaDir::Read;
@@ -43,11 +49,9 @@ fn dma_read(device: &mut device::Device) {
device.si.regs[SI_STATUS_REG as usize] |= SI_STATUS_DMA_BUSY;
device::events::create_event(
device,
device::events::EVENT_TYPE_SI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + duration,
)
let length = duration + randomize_interrupt_time(&mut device.rng);
device::events::create_event(device, device::events::EVENT_TYPE_SI, length)
}
fn dma_write(device: &mut device::Device) {
@@ -57,11 +61,9 @@ fn dma_write(device: &mut device::Device) {
device.si.regs[SI_STATUS_REG as usize] |= SI_STATUS_DMA_BUSY;
device::events::create_event(
device,
device::events::EVENT_TYPE_SI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + 6000, //based on https://github.com/rasky/n64-systembench
)
let length = 6000 + randomize_interrupt_time(&mut device.rng); //based on https://github.com/rasky/n64-systembench
device::events::create_event(device, device::events::EVENT_TYPE_SI, length)
}
pub fn write_regs(device: &mut device::Device, address: u64, value: u32, mask: u32) {
+2 -6
View File
@@ -65,11 +65,7 @@ fn create_limiter(device: &mut device::Device) {
fn set_vertical_interrupt(device: &mut device::Device) {
if device::events::get_event(device, device::events::EVENT_TYPE_VI).is_none() {
device::events::create_event(
device,
device::events::EVENT_TYPE_VI,
device.cpu.cop0.regs[device::cop0::COP0_COUNT_REG as usize] + device.vi.delay,
)
device::events::create_event(device, device::events::EVENT_TYPE_VI, device.vi.delay)
}
}
@@ -164,7 +160,7 @@ pub fn vertical_interrupt_event(device: &mut device::Device) {
device::mi::set_rcp_interrupt(device, device::mi::MI_INTR_VI);
device::events::create_event(
device::events::create_event_at(
device,
device::events::EVENT_TYPE_VI,
device.cpu.next_event_count + device.vi.delay,
+2 -2
View File
@@ -161,8 +161,8 @@ async fn main() {
.stack_size(env!("N64_STACK_SIZE").parse().unwrap())
.spawn(move || {
let mut device = device::Device::new();
device.ui.fullscreen = args.fullscreen;
device::run_game(rom_contents, &mut device);
let overclock = device.ui.config.emulation.overclock;
device::run_game(&mut device, rom_contents, args.fullscreen, overclock);
})
.unwrap();
+18
View File
@@ -18,6 +18,8 @@ const TCP_DISCONNECT_NOTICE: u8 = 7;
const TCP_RECEIVE_SAVE_WITH_SIZE: u8 = 8;
const TCP_SEND_RTC: u8 = 64;
const TCP_RECEIVE_RTC: u8 = 128;
const TCP_SEND_RNG: u8 = 65;
const TCP_RECEIVE_RNG: u8 = 129;
const CS4: u32 = 32;
@@ -68,6 +70,22 @@ pub fn receive_rtc(netplay: &mut Netplay) -> i64 {
i64::from_be_bytes(rtc)
}
pub fn send_rng(netplay: &mut Netplay, seed: u64) {
let mut request: Vec<u8> = [TCP_SEND_RNG].to_vec();
let size: u32 = 8;
request.extend_from_slice(&size.to_be_bytes());
request.extend_from_slice(&seed.to_be_bytes());
netplay.tcp_stream.write_all(&request).unwrap();
}
pub fn receive_rng(netplay: &mut Netplay) -> u64 {
let request: Vec<u8> = [TCP_RECEIVE_RNG].to_vec();
netplay.tcp_stream.write_all(&request).unwrap();
let mut seed: [u8; 8] = [0; 8];
netplay.tcp_stream.read_exact(&mut seed).unwrap();
u64::from_be_bytes(seed)
}
pub fn send_save(netplay: &mut Netplay, save_type: &str, save_data: &[u8], size: usize) {
let mut request: Vec<u8> = [TCP_SEND_SAVE].to_vec();
request.extend_from_slice(save_type.as_bytes());
+11 -4
View File
@@ -74,20 +74,27 @@ pub fn create_savestate(device: &device::Device) {
let data: &[(&[u8], &str)] = &[
(&postcard::to_stdvec(device).unwrap(), "device"),
(&postcard::to_stdvec(&device.ui.saves).unwrap(), "saves"),
(
&postcard::to_stdvec(&device.ui.storage.saves).unwrap(),
"saves",
),
];
let compressed_file = ui::storage::compress_file(data);
std::fs::write(device.ui.paths.savestate_file_path.clone(), compressed_file).unwrap();
std::fs::write(
device.ui.storage.paths.savestate_file_path.clone(),
compressed_file,
)
.unwrap();
}
pub fn load_savestate(device: &mut device::Device) {
let savestate = std::fs::read(&mut device.ui.paths.savestate_file_path);
let savestate = std::fs::read(&mut device.ui.storage.paths.savestate_file_path);
if savestate.is_ok() {
let device_bytes = ui::storage::decompress_file(savestate.as_ref().unwrap(), "device");
let save_bytes = ui::storage::decompress_file(savestate.as_ref().unwrap(), "saves");
let state: device::Device = postcard::from_bytes(&device_bytes).unwrap();
device.ui.saves = postcard::from_bytes(&save_bytes).unwrap();
device.ui.storage.saves = postcard::from_bytes(&save_bytes).unwrap();
device.cpu = state.cpu;
device.pif = state.pif;
+115 -91
View File
@@ -12,32 +12,48 @@ pub struct Dirs {
pub data_dir: std::path::PathBuf,
}
pub struct Ui {
pub dirs: Dirs,
pub keyboard_state: *const bool,
pub controllers: [input::Controllers; 4],
pub config: config::Config,
pub save_type: Vec<storage::SaveTypes>,
pub game_id: String,
pub game_hash: String,
pub paths: storage::Paths,
pub saves: storage::Saves,
pub event_audio: audio::EventAudio,
pub window: *mut sdl3_sys::video::SDL_Window,
pub struct Audio {
pub audio_stream: *mut sdl3_sys::audio::SDL_AudioStream,
pub event_audio_stream: *mut sdl3_sys::audio::SDL_AudioStream,
pub audio_device: u32,
pub event_audio: audio::EventAudio,
}
pub struct Input {
pub num_joysticks: i32,
pub fullscreen: bool,
pub joysticks: *mut sdl3_sys::joystick::SDL_JoystickID,
pub keyboard_state: *const bool,
pub controllers: [input::Controllers; 4],
}
pub struct Storage {
pub save_type: Vec<storage::SaveTypes>,
pub paths: storage::Paths,
pub saves: storage::Saves,
}
pub struct Video {
pub window: *mut sdl3_sys::video::SDL_Window,
pub fullscreen: bool,
}
pub struct Ui {
pub dirs: Dirs,
pub config: config::Config,
pub game_id: String,
pub game_hash: String,
pub with_sdl: bool,
pub audio: Audio,
pub input: Input,
pub storage: Storage,
pub video: Video,
}
impl Drop for Ui {
fn drop(&mut self) {
if self.with_sdl {
unsafe {
sdl3_sys::stdinc::SDL_free(self.joysticks as *mut std::ffi::c_void);
sdl3_sys::stdinc::SDL_free(self.input.joysticks as *mut std::ffi::c_void);
sdl3_sys::init::SDL_Quit();
}
}
@@ -85,90 +101,98 @@ impl Ui {
let dirs = get_dirs();
Ui {
controllers: [
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
input: Input {
controllers: [
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
},
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
},
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
},
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
},
],
keyboard_state: std::ptr::null_mut(),
num_joysticks,
joysticks,
},
storage: Storage {
save_type: vec![],
paths: storage::Paths {
eep_file_path: std::path::PathBuf::new(),
fla_file_path: std::path::PathBuf::new(),
sra_file_path: std::path::PathBuf::new(),
pak_file_path: std::path::PathBuf::new(),
sdcard_file_path: std::path::PathBuf::new(),
romsave_file_path: std::path::PathBuf::new(),
savestate_file_path: std::path::PathBuf::new(),
},
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
saves: storage::Saves {
write_to_disk: true,
eeprom: storage::Save {
data: Vec::new(),
written: false,
},
sram: storage::Save {
data: Vec::new(),
written: false,
},
flash: storage::Save {
data: Vec::new(),
written: false,
},
mempak: storage::Save {
data: Vec::new(),
written: false,
},
sdcard: storage::Save {
data: Vec::new(),
written: false,
},
romsave: storage::RomSave {
data: std::collections::HashMap::new(),
written: false,
},
},
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
},
input::Controllers {
game_controller: std::ptr::null_mut(),
joystick: std::ptr::null_mut(),
rumble: false,
},
],
keyboard_state: std::ptr::null_mut(),
},
config: config::Config::new(),
save_type: vec![],
game_id: String::new(),
game_hash: String::new(),
paths: storage::Paths {
eep_file_path: std::path::PathBuf::new(),
fla_file_path: std::path::PathBuf::new(),
sra_file_path: std::path::PathBuf::new(),
pak_file_path: std::path::PathBuf::new(),
sdcard_file_path: std::path::PathBuf::new(),
romsave_file_path: std::path::PathBuf::new(),
savestate_file_path: std::path::PathBuf::new(),
audio: Audio {
event_audio: audio::EventAudio {
mempak: include_bytes!("../data/mempak.wav").to_vec(),
rumblepak: include_bytes!("../data/rumblepak.wav").to_vec(),
transferpak: include_bytes!("../data/transferpak.wav").to_vec(),
netplay_desync: include_bytes!("../data/netplay_desync.wav").to_vec(),
netplay_lost_connection: include_bytes!("../data/netplay_lost_connection.wav")
.to_vec(),
netplay_disconnected: [
include_bytes!("../data/netplay_p1_disconnected.wav").to_vec(),
include_bytes!("../data/netplay_p2_disconnected.wav").to_vec(),
include_bytes!("../data/netplay_p3_disconnected.wav").to_vec(),
include_bytes!("../data/netplay_p4_disconnected.wav").to_vec(),
],
},
audio_stream: std::ptr::null_mut(),
event_audio_stream: std::ptr::null_mut(),
audio_device: 0,
},
saves: storage::Saves {
write_to_disk: true,
eeprom: storage::Save {
data: Vec::new(),
written: false,
},
sram: storage::Save {
data: Vec::new(),
written: false,
},
flash: storage::Save {
data: Vec::new(),
written: false,
},
mempak: storage::Save {
data: Vec::new(),
written: false,
},
sdcard: storage::Save {
data: Vec::new(),
written: false,
},
romsave: storage::RomSave {
data: std::collections::HashMap::new(),
written: false,
},
video: Video {
window: std::ptr::null_mut(),
fullscreen: false,
},
event_audio: audio::EventAudio {
mempak: include_bytes!("../data/mempak.wav").to_vec(),
rumblepak: include_bytes!("../data/rumblepak.wav").to_vec(),
transferpak: include_bytes!("../data/transferpak.wav").to_vec(),
netplay_desync: include_bytes!("../data/netplay_desync.wav").to_vec(),
netplay_lost_connection: include_bytes!("../data/netplay_lost_connection.wav")
.to_vec(),
netplay_disconnected: [
include_bytes!("../data/netplay_p1_disconnected.wav").to_vec(),
include_bytes!("../data/netplay_p2_disconnected.wav").to_vec(),
include_bytes!("../data/netplay_p3_disconnected.wav").to_vec(),
include_bytes!("../data/netplay_p4_disconnected.wav").to_vec(),
],
},
window: std::ptr::null_mut(),
audio_stream: std::ptr::null_mut(),
event_audio_stream: std::ptr::null_mut(),
audio_device: 0,
fullscreen: false,
num_joysticks,
joysticks,
dirs,
with_sdl,
}
+50 -33
View File
@@ -24,28 +24,35 @@ pub fn init(ui: &mut ui::Ui, frequency: u64) {
freq: 48000,
channels: 2,
};
ui.audio_device = unsafe {
ui.audio.audio_device = unsafe {
sdl3_sys::audio::SDL_OpenAudioDevice(
sdl3_sys::audio::SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK,
&device_audio_spec,
)
};
if ui.audio_device == 0 {
if ui.audio.audio_device == 0 {
panic!("Could not open audio device");
}
let mut dst = Default::default();
if !unsafe {
sdl3_sys::audio::SDL_GetAudioDeviceFormat(ui.audio_device, &mut dst, std::ptr::null_mut())
sdl3_sys::audio::SDL_GetAudioDeviceFormat(
ui.audio.audio_device,
&mut dst,
std::ptr::null_mut(),
)
} {
panic!("Could not get audio device format");
}
ui.audio_stream = unsafe { sdl3_sys::audio::SDL_CreateAudioStream(&game_audio_spec, &dst) };
if ui.audio_stream.is_null() {
ui.audio.audio_stream =
unsafe { sdl3_sys::audio::SDL_CreateAudioStream(&game_audio_spec, &dst) };
if ui.audio.audio_stream.is_null() {
return;
}
if !unsafe { sdl3_sys::audio::SDL_BindAudioStream(ui.audio_device, ui.audio_stream) } {
if !unsafe {
sdl3_sys::audio::SDL_BindAudioStream(ui.audio.audio_device, ui.audio.audio_stream)
} {
panic!("Could not bind audio stream");
}
@@ -55,44 +62,54 @@ pub fn init(ui: &mut ui::Ui, frequency: u64) {
channels: 1,
};
ui.event_audio_stream =
ui.audio.event_audio_stream =
unsafe { sdl3_sys::audio::SDL_CreateAudioStream(&wav_audio_spec, &dst) };
if !unsafe { sdl3_sys::audio::SDL_BindAudioStream(ui.audio_device, ui.event_audio_stream) } {
if !unsafe {
sdl3_sys::audio::SDL_BindAudioStream(ui.audio.audio_device, ui.audio.event_audio_stream)
} {
panic!("Could not bind audio stream");
}
}
pub fn close(ui: &mut ui::Ui) {
unsafe {
if !ui.audio_stream.is_null() {
sdl3_sys::audio::SDL_DestroyAudioStream(ui.audio_stream);
ui.audio_stream = std::ptr::null_mut();
if !ui.audio.audio_stream.is_null() {
sdl3_sys::audio::SDL_DestroyAudioStream(ui.audio.audio_stream);
ui.audio.audio_stream = std::ptr::null_mut();
}
if !ui.event_audio_stream.is_null() {
sdl3_sys::audio::SDL_DestroyAudioStream(ui.event_audio_stream);
ui.event_audio_stream = std::ptr::null_mut();
if !ui.audio.event_audio_stream.is_null() {
sdl3_sys::audio::SDL_DestroyAudioStream(ui.audio.event_audio_stream);
ui.audio.event_audio_stream = std::ptr::null_mut();
}
sdl3_sys::audio::SDL_CloseAudioDevice(ui.audio_device);
ui.audio_device = 0;
sdl3_sys::audio::SDL_CloseAudioDevice(ui.audio.audio_device);
ui.audio.audio_device = 0;
}
}
pub fn play_netplay_audio(ui: &mut ui::Ui, error: u32) {
if ui.event_audio_stream.is_null() {
if ui.audio.event_audio_stream.is_null() {
return;
}
let sound = match error {
netplay::NETPLAY_ERROR_DESYNC => &ui.event_audio.netplay_desync,
netplay::NETPLAY_ERROR_LOST_CONNECTION => &ui.event_audio.netplay_lost_connection,
netplay::NETPLAY_ERROR_PLAYER_1_DISCONNECTED => &ui.event_audio.netplay_disconnected[0],
netplay::NETPLAY_ERROR_PLAYER_2_DISCONNECTED => &ui.event_audio.netplay_disconnected[1],
netplay::NETPLAY_ERROR_PLAYER_3_DISCONNECTED => &ui.event_audio.netplay_disconnected[2],
netplay::NETPLAY_ERROR_PLAYER_4_DISCONNECTED => &ui.event_audio.netplay_disconnected[3],
netplay::NETPLAY_ERROR_DESYNC => &ui.audio.event_audio.netplay_desync,
netplay::NETPLAY_ERROR_LOST_CONNECTION => &ui.audio.event_audio.netplay_lost_connection,
netplay::NETPLAY_ERROR_PLAYER_1_DISCONNECTED => {
&ui.audio.event_audio.netplay_disconnected[0]
}
netplay::NETPLAY_ERROR_PLAYER_2_DISCONNECTED => {
&ui.audio.event_audio.netplay_disconnected[1]
}
netplay::NETPLAY_ERROR_PLAYER_3_DISCONNECTED => {
&ui.audio.event_audio.netplay_disconnected[2]
}
netplay::NETPLAY_ERROR_PLAYER_4_DISCONNECTED => {
&ui.audio.event_audio.netplay_disconnected[3]
}
_ => panic!("Invalid netplay error"),
};
if !unsafe {
sdl3_sys::audio::SDL_PutAudioStreamData(
ui.event_audio_stream,
ui.audio.event_audio_stream,
sound.as_ptr() as *const std::ffi::c_void,
sound.len() as i32,
)
@@ -102,19 +119,19 @@ pub fn play_netplay_audio(ui: &mut ui::Ui, error: u32) {
}
pub fn play_pak_switch(ui: &mut ui::Ui, pak: device::controller::PakType) {
if ui.event_audio_stream.is_null() {
if ui.audio.event_audio_stream.is_null() {
return;
}
let sound = match pak {
device::controller::PakType::RumblePak => &ui.event_audio.rumblepak,
device::controller::PakType::MemPak => &ui.event_audio.mempak,
device::controller::PakType::TransferPak => &ui.event_audio.transferpak,
device::controller::PakType::RumblePak => &ui.audio.event_audio.rumblepak,
device::controller::PakType::MemPak => &ui.audio.event_audio.mempak,
device::controller::PakType::TransferPak => &ui.audio.event_audio.transferpak,
_ => panic!("Invalid pak type"),
};
if !unsafe {
sdl3_sys::audio::SDL_PutAudioStreamData(
ui.event_audio_stream,
ui.audio.event_audio_stream,
sound.as_ptr() as *const std::ffi::c_void,
sound.len() as i32,
)
@@ -124,7 +141,7 @@ pub fn play_pak_switch(ui: &mut ui::Ui, pak: device::controller::PakType) {
}
pub fn play_audio(device: &mut device::Device, dram_addr: usize, length: u64) {
if device.ui.audio_stream.is_null() {
if device.ui.audio.audio_stream.is_null() {
return;
}
@@ -142,7 +159,7 @@ pub fn play_audio(device: &mut device::Device, dram_addr: usize, length: u64) {
}
let audio_queued =
unsafe { sdl3_sys::audio::SDL_GetAudioStreamQueued(device.ui.audio_stream) } as f64;
unsafe { sdl3_sys::audio::SDL_GetAudioStreamQueued(device.ui.audio.audio_stream) } as f64;
let acceptable_latency = (device.ai.freq as f64 * 0.2) * 4.0;
let min_latency = (device.ai.freq as f64 * 0.02) * 4.0;
@@ -150,7 +167,7 @@ pub fn play_audio(device: &mut device::Device, dram_addr: usize, length: u64) {
let silence_buffer: Vec<u8> = vec![0; min_latency as usize & !3];
if !unsafe {
sdl3_sys::audio::SDL_PutAudioStreamData(
device.ui.audio_stream,
device.ui.audio.audio_stream,
silence_buffer.as_ptr() as *const std::ffi::c_void,
silence_buffer.len() as i32,
)
@@ -162,7 +179,7 @@ pub fn play_audio(device: &mut device::Device, dram_addr: usize, length: u64) {
if audio_queued < acceptable_latency
&& !unsafe {
sdl3_sys::audio::SDL_PutAudioStreamData(
device.ui.audio_stream,
device.ui.audio.audio_stream,
primary_buffer.as_ptr() as *const std::ffi::c_void,
primary_buffer.len() as i32 * 2,
)
+13
View File
@@ -40,16 +40,26 @@ pub struct Input {
pub transfer_pak: [bool; 4],
pub emulate_vru: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Video {
pub upscale: u32,
pub integer_scaling: bool,
pub fullscreen: bool,
pub widescreen: bool,
pub crt: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Emulation {
pub overclock: bool,
}
#[derive(serde::Serialize, serde::Deserialize)]
pub struct Config {
pub input: Input,
pub video: Video,
pub emulation: Emulation,
}
impl Drop for Config {
@@ -96,7 +106,10 @@ impl Config {
upscale: 1,
integer_scaling: false,
fullscreen: false,
widescreen: false,
crt: false,
},
emulation: Emulation { overclock: false },
}
}
}
+76 -54
View File
@@ -17,6 +17,9 @@ pub struct GopherEguiApp {
upscale: u32,
integer_scaling: bool,
fullscreen: bool,
widescreen: bool,
crt: bool,
overclock: bool,
emulate_vru: bool,
dinput: bool,
show_vru_dialog: bool,
@@ -25,7 +28,7 @@ pub struct GopherEguiApp {
vru_word_list: Vec<String>,
latest_version: Option<semver::Version>,
update_receiver: Option<tokio::sync::mpsc::Receiver<GithubData>>,
pub netplay: gui_netplay::GuiNetplay,
netplay: gui_netplay::GuiNetplay,
}
#[derive(serde::Deserialize)]
@@ -41,7 +44,10 @@ struct SaveConfig {
upscale: u32,
integer_scaling: bool,
fullscreen: bool,
widescreen: bool,
crt: bool,
emulate_vru: bool,
overclock: bool,
}
fn get_input_profiles(config: &ui::config::Config) -> Vec<String> {
@@ -55,10 +61,10 @@ fn get_input_profiles(config: &ui::config::Config) -> Vec<String> {
pub fn get_controller_names(game_ui: &ui::Ui) -> Vec<String> {
let mut controllers: Vec<String> = vec![];
for offset in 0..game_ui.num_joysticks as isize {
for offset in 0..game_ui.input.num_joysticks as isize {
let name = unsafe {
std::ffi::CStr::from_ptr(sdl3_sys::joystick::SDL_GetJoystickNameForID(
*(game_ui.joysticks.offset(offset)),
*(game_ui.input.joysticks.offset(offset)),
))
};
controllers.push(name.to_string_lossy().to_string());
@@ -70,10 +76,10 @@ pub fn get_controller_names(game_ui: &ui::Ui) -> Vec<String> {
pub fn get_controller_paths(game_ui: &ui::Ui) -> Vec<String> {
let mut controller_paths: Vec<String> = vec![];
for offset in 0..game_ui.num_joysticks as isize {
for offset in 0..game_ui.input.num_joysticks as isize {
let path = unsafe {
std::ffi::CStr::from_ptr(sdl3_sys::joystick::SDL_GetJoystickPathForID(
*(game_ui.joysticks.offset(offset)),
*(game_ui.input.joysticks.offset(offset)),
))
.to_string_lossy()
.to_string()
@@ -116,7 +122,10 @@ impl GopherEguiApp {
upscale: config.video.upscale,
integer_scaling: config.video.integer_scaling,
fullscreen: config.video.fullscreen,
widescreen: config.video.widescreen,
crt: config.video.crt,
emulate_vru: config.input.emulate_vru,
overclock: config.emulation.overclock,
show_vru_dialog: false,
dinput: false,
controller_paths,
@@ -152,7 +161,11 @@ fn save_config(
config.video.upscale = save_config_items.upscale;
config.video.integer_scaling = save_config_items.integer_scaling;
config.video.fullscreen = save_config_items.fullscreen;
config.video.widescreen = save_config_items.widescreen;
config.video.crt = save_config_items.crt;
config.input.emulate_vru = save_config_items.emulate_vru;
config.emulation.overclock = save_config_items.overclock;
}
impl Drop for GopherEguiApp {
@@ -165,7 +178,10 @@ impl Drop for GopherEguiApp {
upscale: self.upscale,
integer_scaling: self.integer_scaling,
fullscreen: self.fullscreen,
widescreen: self.widescreen,
crt: self.crt,
emulate_vru: self.emulate_vru,
overclock: self.overclock,
};
let mut config = ui::config::Config::new();
save_config(
@@ -211,44 +227,35 @@ fn configure_profile(app: &mut GopherEguiApp, ctx: &egui::Context) {
}
fn show_vru_dialog(app: &mut GopherEguiApp, ctx: &egui::Context) {
ctx.show_viewport_immediate(
egui::ViewportId::from_hash_of("vru_dialog"),
egui::ViewportBuilder::default()
.with_title("What would you like to say?")
.with_always_on_top(),
|ctx, class| {
assert!(
class == egui::ViewportClass::Immediate,
"This egui backend doesn't support multiple viewports"
);
egui::CentralPanel::default().show(ctx, |ui| {
egui::Grid::new("vru_words").show(ui, |ui| {
for (i, v) in app.vru_word_list.iter().enumerate() {
if i % 5 == 0 {
ui.end_row();
}
if ui.button((*v).to_string()).clicked() {
app.vru_word_notifier
.as_ref()
.unwrap()
.try_send(v.clone())
.unwrap();
app.show_vru_dialog = false;
}
}
});
});
if ctx.input(|i| i.viewport().close_requested()) {
app.vru_word_notifier
.as_ref()
.unwrap()
.try_send(String::from(""))
.unwrap();
app.show_vru_dialog = false;
egui::CentralPanel::default().show(ctx, |ui| {
ui.label("What would you like to say?");
egui::Grid::new("vru_words").show(ui, |ui| {
for (i, v) in app.vru_word_list.iter().enumerate() {
if i % 5 == 0 {
ui.end_row();
}
if ui.button((*v).to_string()).clicked() {
app.vru_word_notifier
.as_ref()
.unwrap()
.try_send(v.clone())
.unwrap();
app.show_vru_dialog = false;
}
}
},
);
});
ui.add_space(16.0);
if ui.button("Close without saying anything").clicked() {
app.vru_word_notifier
.as_ref()
.unwrap()
.try_send(String::from(""))
.unwrap();
app.show_vru_dialog = false;
};
});
}
fn get_latest_version(app: &mut GopherEguiApp, ctx: &egui::Context) {
@@ -290,7 +297,7 @@ fn get_latest_version(app: &mut GopherEguiApp, ctx: &egui::Context) {
}
}
pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context, enable_overclock: bool) {
let netplay;
let selected_controller = app.selected_controller;
@@ -300,7 +307,10 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
let upscale = app.upscale;
let integer_scaling = app.integer_scaling;
let fullscreen = app.fullscreen;
let widescreen = app.widescreen;
let crt = app.crt;
let emulate_vru = app.emulate_vru;
let overclock = app.overclock;
let peer_addr;
let session;
let player_number;
@@ -394,7 +404,10 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
upscale,
integer_scaling,
fullscreen,
widescreen,
crt,
emulate_vru,
overclock,
};
if file.is_some() || netplay {
@@ -417,8 +430,7 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
session.unwrap(),
player_number.unwrap(),
));
device.ui.fullscreen = fullscreen;
device::run_game(rom_contents, &mut device);
device::run_game(&mut device, rom_contents, fullscreen, enable_overclock);
netplay::close(&mut device);
} else {
for i in 0..4 {
@@ -441,8 +453,12 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
if rom_contents.is_empty() {
println!("Could not read rom file");
} else {
device.ui.fullscreen = fullscreen;
device::run_game(rom_contents, &mut device);
device::run_game(
&mut device,
rom_contents,
fullscreen,
enable_overclock,
);
}
}
let result = std::fs::remove_file(running_file);
@@ -457,6 +473,11 @@ pub fn open_rom(app: &mut GopherEguiApp, ctx: &egui::Context) {
impl eframe::App for GopherEguiApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if self.show_vru_dialog {
show_vru_dialog(self, ctx);
return;
}
if self.netplay.create {
gui_netplay::netplay_create(self, ctx);
}
@@ -485,7 +506,7 @@ impl eframe::App for GopherEguiApp {
.min_col_width(200.0)
.show(ui, |ui| {
if ui.button("Open ROM").clicked() {
open_rom(self, ctx);
open_rom(self, ctx, self.overclock);
}
if ui.button("Netplay: Create Session").clicked()
&& !self.dirs.cache_dir.join("game_running").exists()
@@ -521,7 +542,7 @@ impl eframe::App for GopherEguiApp {
}
});
ui.add_space(32.0);
ui.add_space(16.0);
ui.label("Controller Config:");
egui::Grid::new("controller_config").show(ui, |ui| {
ui.label("Port");
@@ -585,7 +606,7 @@ impl eframe::App for GopherEguiApp {
ui.end_row();
}
});
ui.add_space(32.0);
ui.add_space(16.0);
let upscale_values = [1, 2, 4];
let mut slider_value = match self.upscale {
1 => 0,
@@ -606,8 +627,13 @@ impl eframe::App for GopherEguiApp {
};
ui.checkbox(&mut self.integer_scaling, "Integer Scaling");
ui.checkbox(&mut self.fullscreen, "Fullscreen (Esc closes game)");
ui.checkbox(&mut self.widescreen, "Widescreen (stretch)");
ui.checkbox(&mut self.crt, "Apply CRT shader");
ui.add_space(16.0);
ui.checkbox(&mut self.overclock, "Overclock N64 CPU (may cause bugs)");
ui.add_space(16.0);
ui.hyperlink_to("Wiki", "https://github.com/gopher64/gopher64/wiki");
ui.hyperlink_to("Discord Server", "https://discord.gg/9RGXq8W8JQ");
ui.add_space(16.0);
@@ -632,10 +658,6 @@ impl eframe::App for GopherEguiApp {
}
}
if self.show_vru_dialog {
show_vru_dialog(self, ctx);
}
get_latest_version(self, ctx);
}
}
+26 -1
View File
@@ -68,6 +68,8 @@ pub struct NetplayRoom {
md5: Option<String>,
game_name: Option<String>,
pub port: Option<i32>,
features: Option<std::collections::HashMap<String, String>>,
buffer_target: Option<i32>,
}
#[derive(serde::Serialize, serde::Deserialize)]
@@ -310,6 +312,8 @@ pub fn netplay_create(app: &mut GopherEguiApp, ctx: &egui::Context) {
// If the ROM doesn't report a name, use the filename
game_name = app.netplay.create_rom_label.clone();
}
let mut features = std::collections::HashMap::new();
features.insert("overclock".to_string(), app.overclock.to_string());
let netplay_message = NetplayMessage {
message_type: "request_create_room".to_string(),
player_name: Some(app.netplay.player_name.clone()),
@@ -329,6 +333,8 @@ pub fn netplay_create(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: Some(app.netplay.game_info.md5.clone()),
protected: None,
port: None,
features: Some(features),
buffer_target: Some(2),
}),
};
let (mut socket, _response) =
@@ -502,6 +508,8 @@ pub fn netplay_join(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: Some(app.netplay.game_info.md5.clone()),
protected: None,
port: app.netplay.selected_session.as_ref().unwrap().port,
features: None,
buffer_target: None,
}),
};
let socket = app.netplay.socket.as_mut().unwrap();
@@ -651,6 +659,17 @@ pub fn netplay_join(app: &mut GopherEguiApp, ctx: &egui::Context) {
}
pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
let overclock = app
.netplay
.waiting_session
.as_ref()
.unwrap()
.features
.as_ref()
.unwrap()
.get("overclock")
.unwrap();
let motd_message = NetplayMessage {
message_type: "request_motd".to_string(),
player_name: None,
@@ -684,6 +703,8 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: None,
protected: None,
port: app.netplay.waiting_session.as_ref().unwrap().port,
features: None,
buffer_target: None,
}),
};
@@ -722,6 +743,8 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: None,
protected: None,
port: app.netplay.waiting_session.as_ref().unwrap().port,
features: None,
buffer_target: None,
}),
};
let socket = app.netplay.socket.as_mut().unwrap();
@@ -753,6 +776,8 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
md5: None,
protected: None,
port: app.netplay.waiting_session.as_ref().unwrap().port,
features: None,
buffer_target: None,
}),
};
app.netplay.chat_message.clear();
@@ -801,7 +826,7 @@ pub fn netplay_wait(app: &mut GopherEguiApp, ctx: &egui::Context) {
};
}
gui::open_rom(app, ctx);
gui::open_rom(app, ctx, *overclock == "true");
app.netplay = Default::default();
return;
} else {
+29 -24
View File
@@ -277,11 +277,11 @@ fn set_buttons_from_controller(
}
pub fn set_rumble(ui: &mut ui::Ui, channel: usize, rumble: u8) {
if !ui.controllers[channel].rumble {
if !ui.input.controllers[channel].rumble {
return;
}
let controller = ui.controllers[channel].game_controller;
let joystick = ui.controllers[channel].joystick;
let controller = ui.input.controllers[channel].game_controller;
let joystick = ui.input.controllers[channel].joystick;
if !controller.is_null() {
unsafe {
sdl3_sys::gamepad::SDL_RumbleGamepad(
@@ -338,14 +338,16 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData {
let profile_name = ui.config.input.input_profile_binding[channel].clone();
let profile = ui.config.input.input_profiles.get(&profile_name).unwrap();
let mut keys = 0;
let controller = ui.controllers[channel].game_controller;
let joystick = ui.controllers[channel].joystick;
let controller = ui.input.controllers[channel].game_controller;
let joystick = ui.input.controllers[channel].joystick;
let alt_pressed = unsafe {
// ignore key presses if ALT is pressed
*ui.keyboard_state
*ui.input
.keyboard_state
.offset(i32::from(sdl3_sys::scancode::SDL_SCANCODE_LALT) as isize)
|| *ui
.input
.keyboard_state
.offset(i32::from(sdl3_sys::scancode::SDL_SCANCODE_RALT) as isize)
};
@@ -354,7 +356,9 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData {
if profile_name != "default" || channel == 0 {
let profile_key = profile.keys[i];
if profile_key.enabled && !alt_pressed {
keys |= (unsafe { *ui.keyboard_state.offset(profile_key.id as isize) } as u32) << i;
keys |= (unsafe { *ui.input.keyboard_state.offset(profile_key.id as isize) }
as u32)
<< i;
}
}
@@ -369,7 +373,7 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData {
let mut y: f64 = 0.0;
if profile_name != "default" || channel == 0 {
(x, y) = set_axis_from_keys(profile, ui.keyboard_state);
(x, y) = set_axis_from_keys(profile, ui.input.keyboard_state);
}
if !controller.is_null() {
@@ -384,15 +388,15 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> InputData {
InputData {
data: keys,
pak_change_pressed: change_paks(profile, joystick, controller, ui.keyboard_state),
pak_change_pressed: change_paks(profile, joystick, controller, ui.input.keyboard_state),
}
}
pub fn assign_controller(ui: &mut ui::Ui, controller: i32, port: usize) {
if controller < ui.num_joysticks {
if controller < ui.input.num_joysticks {
let path = unsafe {
std::ffi::CStr::from_ptr(sdl3_sys::joystick::SDL_GetJoystickPathForID(
*(ui.joysticks.offset(controller as isize)),
*(ui.input.joysticks.offset(controller as isize)),
))
.to_string_lossy()
.to_string()
@@ -444,16 +448,16 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String, dinput: bool) {
let mut open_joysticks: Vec<*mut sdl3_sys::joystick::SDL_Joystick> = Vec::new();
let mut open_controllers: Vec<*mut sdl3_sys::gamepad::SDL_Gamepad> = Vec::new();
for offset in 0..ui.num_joysticks as isize {
for offset in 0..ui.input.num_joysticks as isize {
if !dinput {
let controller =
unsafe { sdl3_sys::gamepad::SDL_OpenGamepad(*ui.joysticks.offset(offset)) };
unsafe { sdl3_sys::gamepad::SDL_OpenGamepad(*ui.input.joysticks.offset(offset)) };
if !controller.is_null() {
open_controllers.push(controller);
}
} else {
let joystick =
unsafe { sdl3_sys::joystick::SDL_OpenJoystick(*ui.joysticks.offset(offset)) };
unsafe { sdl3_sys::joystick::SDL_OpenJoystick(*ui.input.joysticks.offset(offset)) };
if !joystick.is_null() {
open_joysticks.push(joystick);
}
@@ -849,8 +853,9 @@ pub fn get_default_profile() -> ui::config::InputProfile {
}
pub fn init(ui: &mut ui::Ui) {
ui.keyboard_state = unsafe { sdl3_sys::keyboard::SDL_GetKeyboardState(std::ptr::null_mut()) };
if ui.keyboard_state.is_null() {
ui.input.keyboard_state =
unsafe { sdl3_sys::keyboard::SDL_GetKeyboardState(std::ptr::null_mut()) };
if ui.input.keyboard_state.is_null() {
panic!("Could not get keyboard state");
}
@@ -861,16 +866,16 @@ pub fn init(ui: &mut ui::Ui) {
let mut joystick_id = 0;
let assigned_path = controller_assignment.as_ref().unwrap();
for offset in 0..ui.num_joysticks as isize {
for offset in 0..ui.input.num_joysticks as isize {
let path = unsafe {
std::ffi::CStr::from_ptr(sdl3_sys::joystick::SDL_GetJoystickPathForID(
*(ui.joysticks.offset(offset)),
*(ui.input.joysticks.offset(offset)),
))
.to_string_lossy()
.to_string()
};
if path == *assigned_path && !taken[offset as usize] {
joystick_id = unsafe { *(ui.joysticks.offset(offset)) };
joystick_id = unsafe { *(ui.input.joysticks.offset(offset)) };
taken[offset as usize] = true;
break;
}
@@ -885,13 +890,13 @@ pub fn init(ui: &mut ui::Ui) {
if gamepad.is_null() {
println!("could not connect gamepad: {}", joystick_id)
} else {
ui.controllers[i].game_controller = gamepad;
ui.input.controllers[i].game_controller = gamepad;
let properties =
unsafe { sdl3_sys::gamepad::SDL_GetGamepadProperties(gamepad) };
if properties == 0 {
println!("could not get gamepad properties");
}
ui.controllers[i].rumble = unsafe {
ui.input.controllers[i].rumble = unsafe {
sdl3_sys::properties::SDL_GetBooleanProperty(
properties,
sdl3_sys::gamepad::SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN,
@@ -904,13 +909,13 @@ pub fn init(ui: &mut ui::Ui) {
if joystick.is_null() {
println!("could not connect joystick: {}", joystick_id)
} else {
ui.controllers[i].joystick = joystick;
ui.input.controllers[i].joystick = joystick;
let properties =
unsafe { sdl3_sys::joystick::SDL_GetJoystickProperties(joystick) };
if properties == 0 {
println!("could not get joystick properties");
}
ui.controllers[i].rumble = unsafe {
ui.input.controllers[i].rumble = unsafe {
sdl3_sys::properties::SDL_GetBooleanProperty(
properties,
sdl3_sys::joystick::SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN,
@@ -927,7 +932,7 @@ pub fn init(ui: &mut ui::Ui) {
}
pub fn close(ui: &mut ui::Ui) {
for controller in ui.controllers.iter_mut() {
for controller in ui.input.controllers.iter_mut() {
if !controller.joystick.is_null() {
unsafe { sdl3_sys::joystick::SDL_CloseJoystick(controller.joystick) }
controller.joystick = std::ptr::null_mut();
+102 -74
View File
@@ -134,7 +134,7 @@ pub fn get_game_name(rom: &[u8]) -> String {
}
pub fn init(ui: &mut ui::Ui, rom: &[u8]) {
ui.save_type = get_save_type(rom, &ui.game_id);
ui.storage.save_type = get_save_type(rom, &ui.game_id);
let saves_path = ui.dirs.data_dir.join("saves");
@@ -148,67 +148,78 @@ pub fn init(ui: &mut ui::Ui, rom: &[u8]) {
&game_name
};
ui.paths.eep_file_path.clone_from(&saves_path);
ui.paths
ui.storage.paths.eep_file_path.clone_from(&saves_path);
ui.storage
.paths
.eep_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".eep");
ui.paths.sra_file_path.clone_from(&saves_path);
ui.paths
ui.storage.paths.sra_file_path.clone_from(&saves_path);
ui.storage
.paths
.sra_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".sra");
ui.paths.fla_file_path.clone_from(&saves_path);
ui.paths
ui.storage.paths.fla_file_path.clone_from(&saves_path);
ui.storage
.paths
.fla_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".fla");
ui.paths.pak_file_path.clone_from(&saves_path);
ui.paths
ui.storage.paths.pak_file_path.clone_from(&saves_path);
ui.storage
.paths
.pak_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".mpk");
ui.paths.sdcard_file_path.clone_from(&saves_path);
ui.paths
ui.storage.paths.sdcard_file_path.clone_from(&saves_path);
ui.storage
.paths
.sdcard_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".img");
ui.paths.romsave_file_path.clone_from(&saves_path);
ui.paths
ui.storage.paths.romsave_file_path.clone_from(&saves_path);
ui.storage
.paths
.romsave_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".romsave");
ui.paths.savestate_file_path.clone_from(&states_path);
ui.paths
ui.storage
.paths
.savestate_file_path
.clone_from(&states_path);
ui.storage
.paths
.savestate_file_path
.push(prefix.to_owned() + "-" + &ui.game_hash + ".state");
}
pub fn load_saves(ui: &mut ui::Ui, netplay: &mut Option<netplay::Netplay>) {
if netplay.is_none() || netplay.as_ref().unwrap().player_number == 0 {
let eep = std::fs::read(&mut ui.paths.eep_file_path);
let eep = std::fs::read(&mut ui.storage.paths.eep_file_path);
if eep.is_ok() {
ui.saves.eeprom.data = eep.unwrap();
ui.storage.saves.eeprom.data = eep.unwrap();
}
let sra = std::fs::read(&mut ui.paths.sra_file_path);
let sra = std::fs::read(&mut ui.storage.paths.sra_file_path);
if sra.is_ok() {
ui.saves.sram.data = sra.unwrap();
ui.storage.saves.sram.data = sra.unwrap();
}
let fla = std::fs::read(&mut ui.paths.fla_file_path);
let fla = std::fs::read(&mut ui.storage.paths.fla_file_path);
if fla.is_ok() {
ui.saves.flash.data = fla.unwrap();
ui.storage.saves.flash.data = fla.unwrap();
}
let mempak = std::fs::read(&mut ui.paths.pak_file_path);
let mempak = std::fs::read(&mut ui.storage.paths.pak_file_path);
if mempak.is_ok() {
ui.saves.mempak.data = mempak.unwrap();
ui.storage.saves.mempak.data = mempak.unwrap();
}
let sdcard = std::fs::read(&mut ui.paths.sdcard_file_path);
let sdcard = std::fs::read(&mut ui.storage.paths.sdcard_file_path);
if sdcard.is_ok() {
ui.saves.sdcard.data = sdcard.unwrap();
ui.storage.saves.sdcard.data = sdcard.unwrap();
}
let romsave = std::fs::read(&mut ui.paths.romsave_file_path);
let romsave = std::fs::read(&mut ui.storage.paths.romsave_file_path);
if romsave.is_ok() {
ui.saves.romsave.data = postcard::from_bytes(romsave.unwrap().as_ref()).unwrap();
ui.storage.saves.romsave.data =
postcard::from_bytes(romsave.unwrap().as_ref()).unwrap();
}
}
@@ -217,31 +228,31 @@ pub fn load_saves(ui: &mut ui::Ui, netplay: &mut Option<netplay::Netplay>) {
netplay::send_save(
netplay.as_mut().unwrap(),
"eep",
&ui.saves.eeprom.data,
ui.saves.eeprom.data.len(),
&ui.storage.saves.eeprom.data,
ui.storage.saves.eeprom.data.len(),
);
netplay::send_save(
netplay.as_mut().unwrap(),
"sra",
&ui.saves.sram.data,
ui.saves.sram.data.len(),
&ui.storage.saves.sram.data,
ui.storage.saves.sram.data.len(),
);
netplay::send_save(
netplay.as_mut().unwrap(),
"fla",
&ui.saves.flash.data,
ui.saves.flash.data.len(),
&ui.storage.saves.flash.data,
ui.storage.saves.flash.data.len(),
);
netplay::send_save(
netplay.as_mut().unwrap(),
"mpk",
&ui.saves.mempak.data,
ui.saves.mempak.data.len(),
&ui.storage.saves.mempak.data,
ui.storage.saves.mempak.data.len(),
);
let mut compressed_sd = Vec::new();
if !ui.saves.sdcard.data.is_empty() {
compressed_sd = compress_file(&[(&ui.saves.sdcard.data, "save")]);
if !ui.storage.saves.sdcard.data.is_empty() {
compressed_sd = compress_file(&[(&ui.storage.saves.sdcard.data, "save")]);
}
netplay::send_save(
netplay.as_mut().unwrap(),
@@ -251,9 +262,9 @@ pub fn load_saves(ui: &mut ui::Ui, netplay: &mut Option<netplay::Netplay>) {
);
let mut compressed_romsave = Vec::new();
if !ui.saves.romsave.data.is_empty() {
if !ui.storage.saves.romsave.data.is_empty() {
compressed_romsave = compress_file(&[(
&postcard::to_stdvec(&ui.saves.romsave.data).unwrap(),
&postcard::to_stdvec(&ui.storage.saves.romsave.data).unwrap(),
"save",
)]);
}
@@ -264,22 +275,38 @@ pub fn load_saves(ui: &mut ui::Ui, netplay: &mut Option<netplay::Netplay>) {
compressed_romsave.len(),
);
} else {
netplay::receive_save(netplay.as_mut().unwrap(), "eep", &mut ui.saves.eeprom.data);
netplay::receive_save(netplay.as_mut().unwrap(), "sra", &mut ui.saves.sram.data);
netplay::receive_save(netplay.as_mut().unwrap(), "fla", &mut ui.saves.flash.data);
netplay::receive_save(netplay.as_mut().unwrap(), "mpk", &mut ui.saves.mempak.data);
netplay::receive_save(
netplay.as_mut().unwrap(),
"eep",
&mut ui.storage.saves.eeprom.data,
);
netplay::receive_save(
netplay.as_mut().unwrap(),
"sra",
&mut ui.storage.saves.sram.data,
);
netplay::receive_save(
netplay.as_mut().unwrap(),
"fla",
&mut ui.storage.saves.flash.data,
);
netplay::receive_save(
netplay.as_mut().unwrap(),
"mpk",
&mut ui.storage.saves.mempak.data,
);
let mut compressed_sd = Vec::new();
netplay::receive_save(netplay.as_mut().unwrap(), "img", &mut compressed_sd);
if !compressed_sd.is_empty() {
ui.saves.sdcard.data = decompress_file(&compressed_sd, "save");
ui.storage.saves.sdcard.data = decompress_file(&compressed_sd, "save");
}
let mut compressed_romsave = Vec::new();
netplay::receive_save(netplay.as_mut().unwrap(), "rom", &mut compressed_romsave);
if !compressed_romsave.is_empty() {
let romsave_bytes = decompress_file(&compressed_romsave, "save");
ui.saves.romsave.data = postcard::from_bytes(&romsave_bytes).unwrap();
ui.storage.saves.romsave.data = postcard::from_bytes(&romsave_bytes).unwrap();
}
}
}
@@ -314,16 +341,17 @@ pub fn compress_file(data: &[(&[u8], &str)]) -> Vec<u8> {
}
fn write_rom_save(ui: &ui::Ui) {
let data = postcard::to_stdvec(&ui.saves.romsave.data).unwrap();
std::fs::write(ui.paths.romsave_file_path.clone(), data).unwrap();
let data = postcard::to_stdvec(&ui.storage.saves.romsave.data).unwrap();
std::fs::write(ui.storage.paths.romsave_file_path.clone(), data).unwrap();
}
fn writeback_sdcard(device: &mut device::Device) {
let length;
let save_data: &[u8];
if device.ui.saves.eeprom.written {
if device.ui.storage.saves.eeprom.written {
if device
.ui
.storage
.save_type
.contains(&ui::storage::SaveTypes::Eeprom4k)
{
@@ -331,47 +359,47 @@ fn writeback_sdcard(device: &mut device::Device) {
} else {
length = 4;
}
save_data = device.ui.saves.eeprom.data.as_ref();
} else if device.ui.saves.sram.written {
length = device.ui.saves.sram.data.len() / 512;
save_data = device.ui.saves.sram.data.as_ref();
} else if device.ui.saves.flash.written {
length = device.ui.saves.flash.data.len() / 512;
save_data = device.ui.saves.flash.data.as_ref();
save_data = device.ui.storage.saves.eeprom.data.as_ref();
} else if device.ui.storage.saves.sram.written {
length = device.ui.storage.saves.sram.data.len() / 512;
save_data = device.ui.storage.saves.sram.data.as_ref();
} else if device.ui.storage.saves.flash.written {
length = device.ui.storage.saves.flash.data.len() / 512;
save_data = device.ui.storage.saves.flash.data.as_ref();
} else {
return;
}
for i in 0..length {
let offset = device.cart.sc64.writeback_sector[i] as usize * 512;
device.ui.saves.sdcard.data[offset..offset + 512]
device.ui.storage.saves.sdcard.data[offset..offset + 512]
.copy_from_slice(&save_data[i * 512..(i + 1) * 512]);
}
device.ui.saves.sdcard.written = true;
device.ui.storage.saves.sdcard.written = true;
}
pub fn write_saves(device: &mut device::Device) {
if device.netplay.is_none() || device.netplay.as_ref().unwrap().player_number == 0 {
if device.ui.saves.write_to_disk {
if device.ui.saves.eeprom.written {
if device.ui.storage.saves.write_to_disk {
if device.ui.storage.saves.eeprom.written {
write_save(&device.ui, SaveTypes::Eeprom16k)
}
if device.ui.saves.sram.written {
if device.ui.storage.saves.sram.written {
write_save(&device.ui, SaveTypes::Sram)
}
if device.ui.saves.flash.written {
if device.ui.storage.saves.flash.written {
write_save(&device.ui, SaveTypes::Flash)
}
if device.ui.saves.romsave.written {
if device.ui.storage.saves.romsave.written {
write_save(&device.ui, SaveTypes::Romsave)
}
} else {
writeback_sdcard(device)
}
if device.ui.saves.mempak.written {
if device.ui.storage.saves.mempak.written {
write_save(&device.ui, SaveTypes::Mempak)
}
if device.ui.saves.sdcard.written {
if device.ui.storage.saves.sdcard.written {
write_save(&device.ui, SaveTypes::Sdcard)
}
}
@@ -382,24 +410,24 @@ fn write_save(ui: &ui::Ui, save_type: SaveTypes) {
let data: &Vec<u8>;
match save_type {
SaveTypes::Eeprom4k | SaveTypes::Eeprom16k => {
path = ui.paths.eep_file_path.as_ref();
data = ui.saves.eeprom.data.as_ref();
path = ui.storage.paths.eep_file_path.as_ref();
data = ui.storage.saves.eeprom.data.as_ref();
}
SaveTypes::Sram => {
path = ui.paths.sra_file_path.as_ref();
data = ui.saves.sram.data.as_ref();
path = ui.storage.paths.sra_file_path.as_ref();
data = ui.storage.saves.sram.data.as_ref();
}
SaveTypes::Flash => {
path = ui.paths.fla_file_path.as_ref();
data = ui.saves.flash.data.as_ref();
path = ui.storage.paths.fla_file_path.as_ref();
data = ui.storage.saves.flash.data.as_ref();
}
SaveTypes::Mempak => {
path = ui.paths.pak_file_path.as_ref();
data = ui.saves.mempak.data.as_ref();
path = ui.storage.paths.pak_file_path.as_ref();
data = ui.storage.saves.mempak.data.as_ref();
}
SaveTypes::Sdcard => {
path = ui.paths.sdcard_file_path.as_ref();
data = ui.saves.sdcard.data.as_ref();
path = ui.storage.paths.sdcard_file_path.as_ref();
data = ui.storage.saves.sdcard.data.as_ref();
}
SaveTypes::Romsave => {
write_rom_save(ui);
+34 -22
View File
@@ -7,28 +7,38 @@ pub fn init(device: &mut device::Device) {
let title = std::ffi::CString::new("gopher64").unwrap();
let mut flags = sdl3_sys::video::SDL_WINDOW_VULKAN;
let mut flags = sdl3_sys::video::SDL_WINDOW_VULKAN
| sdl3_sys::video::SDL_WINDOW_RESIZABLE
| sdl3_sys::video::SDL_WINDOW_INPUT_FOCUS;
if device.ui.fullscreen {
if device.ui.video.fullscreen {
flags |= sdl3_sys::video::SDL_WINDOW_FULLSCREEN;
} else {
flags |= sdl3_sys::video::SDL_WINDOW_RESIZABLE;
}
flags |= sdl3_sys::video::SDL_WINDOW_INPUT_FOCUS;
let mut window_width = 640;
let mut window_height = 480;
let window_width;
let window_height;
if device.cart.pal {
window_width = 768;
window_width = if device.ui.config.video.widescreen {
1024
} else {
768
};
window_height = 576;
} else {
window_width = if device.ui.config.video.widescreen {
852
} else {
640
};
window_height = 480;
}
device.ui.window = unsafe {
device.ui.video.window = unsafe {
sdl3_sys::video::SDL_CreateWindow(title.as_ptr(), window_width, window_height, flags)
};
if device.ui.window.is_null() {
if device.ui.video.window.is_null() {
panic!("Could not create window");
}
if !unsafe { sdl3_sys::video::SDL_ShowWindow(device.ui.window) } {
if !unsafe { sdl3_sys::video::SDL_ShowWindow(device.ui.video.window) } {
panic!("Could not show window");
}
unsafe { sdl3_sys::everything::SDL_HideCursor() };
@@ -42,23 +52,20 @@ pub fn init(device: &mut device::Device) {
DPC_END_REG: &mut device.rdp.regs_dpc[device::rdp::DPC_END_REG as usize],
DPC_STATUS_REG: &mut device.rdp.regs_dpc[device::rdp::DPC_STATUS_REG as usize],
PAL: device.cart.pal,
widescreen: device.ui.config.video.widescreen,
fullscreen: device.ui.video.fullscreen,
integer_scaling: device.ui.config.video.integer_scaling,
upscale: device.ui.config.video.upscale,
crt: device.ui.config.video.crt,
};
unsafe {
rdp_init(
device.ui.window as *mut std::ffi::c_void,
gfx_info,
device.ui.config.video.upscale,
device.ui.config.video.integer_scaling,
device.ui.fullscreen,
)
}
unsafe { rdp_init(device.ui.video.window as *mut std::ffi::c_void, gfx_info) }
}
pub fn close(ui: &ui::Ui) {
unsafe {
rdp_close();
sdl3_sys::video::SDL_DestroyWindow(ui.window);
sdl3_sys::video::SDL_DestroyWindow(ui.video.window);
}
}
@@ -85,9 +92,14 @@ pub fn load_state(device: &mut device::Device) {
DPC_END_REG: &mut device.rdp.regs_dpc[device::rdp::DPC_END_REG as usize],
DPC_STATUS_REG: &mut device.rdp.regs_dpc[device::rdp::DPC_STATUS_REG as usize],
PAL: device.cart.pal,
widescreen: device.ui.config.video.widescreen,
fullscreen: device.ui.video.fullscreen,
integer_scaling: device.ui.config.video.integer_scaling,
upscale: device.ui.config.video.upscale,
crt: device.ui.config.video.crt,
};
unsafe {
rdp_new_processor(gfx_info, device.ui.config.video.upscale);
rdp_new_processor(gfx_info);
}
}