mirror of
https://github.com/gopher64/gopher64.git
synced 2026-07-11 09:35:21 +02:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d3c26fb359 | |||
| cd106345c9 | |||
| f75636f7e5 | |||
| 97e4921b6a | |||
| 21300ab7db | |||
| 8fd7688aa7 | |||
| a013e72fda | |||
| f2812b0434 | |||
| 5f84c18b39 | |||
| 9058cd1715 | |||
| 5d00eccb19 | |||
| e821626f2b | |||
| 63b8b79dd7 | |||
| 90c9bfbf09 | |||
| 9a3a56d0c6 | |||
| e71d5a1b2d | |||
| a731b870da | |||
| c54356e6f4 | |||
| b2d2089d95 | |||
| a47801b9cb | |||
| 9a76bcd303 |
@@ -1,2 +1,5 @@
|
||||
[target.'cfg(target_arch = "x86_64")']
|
||||
rustflags = ["-C", "target-cpu=x86-64-v3"]
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")']
|
||||
rustflags = ["-C", "target-cpu=cortex-a76"]
|
||||
|
||||
+68
-19
@@ -12,64 +12,113 @@ env:
|
||||
jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
TARGET: x86_64-unknown-linux-gnu
|
||||
strategy:
|
||||
matrix:
|
||||
target: [x86_64-unknown-linux-gnu, aarch64-unknown-linux-gnu]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install sdl2 headers
|
||||
run: |
|
||||
sudo apt -y install libsdl2-dev
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
rustflags: ""
|
||||
- name: Install SDL2
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
run: |
|
||||
cat <<EOF > deb822sources
|
||||
Types: deb
|
||||
URIs: http://archive.ubuntu.com/ubuntu/
|
||||
Suites: noble
|
||||
Components: main restricted universe
|
||||
Architectures: amd64
|
||||
|
||||
Types: deb
|
||||
URIs: http://security.ubuntu.com/ubuntu/
|
||||
Suites: noble-security
|
||||
Components: main restricted universe
|
||||
Architectures: amd64
|
||||
|
||||
Types: deb
|
||||
URIs: http://archive.ubuntu.com/ubuntu/
|
||||
Suites: noble-updates
|
||||
Components: main restricted universe
|
||||
Architectures: amd64
|
||||
|
||||
Types: deb
|
||||
URIs: http://azure.ports.ubuntu.com/ubuntu-ports/
|
||||
Suites: noble
|
||||
Components: main restricted multiverse universe
|
||||
Architectures: arm64
|
||||
|
||||
Types: deb
|
||||
URIs: http://azure.ports.ubuntu.com/ubuntu-ports/
|
||||
Suites: noble-updates
|
||||
Components: main restricted multiverse universe
|
||||
Architectures: arm64
|
||||
EOF
|
||||
|
||||
sudo mv deb822sources /etc/apt/sources.list.d/ubuntu.sources
|
||||
sudo dpkg --add-architecture arm64
|
||||
sudo apt update
|
||||
sudo apt -y install libsdl2-dev:arm64 g++-aarch64-linux-gnu
|
||||
- name: Install SDL2
|
||||
if: matrix.target == 'x86_64-unknown-linux-gnu'
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt -y install libsdl2-dev
|
||||
- name: Set aarch64 linker
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
run: echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV
|
||||
- name: Build
|
||||
run: |
|
||||
cargo build --release -v --target=${{ env.TARGET }}
|
||||
cargo build --release -v --target=${{ matrix.target }}
|
||||
- name: Upload file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gopher64-linux
|
||||
path: target/${{ env.TARGET }}/release/gopher64
|
||||
name: gopher64-${{ matrix.target }}
|
||||
path: target/${{ matrix.target }}/release/gopher64
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
TARGET: x86_64-pc-windows-msvc
|
||||
strategy:
|
||||
matrix:
|
||||
target: [x86_64-pc-windows-msvc]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
target: ${{ matrix.target }}
|
||||
rustflags: ""
|
||||
- name: Build
|
||||
run: |
|
||||
cargo build --release -v --target=${{ env.TARGET }}
|
||||
cargo build --release -v --target=${{ matrix.target }}
|
||||
- name: Upload file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gopher64-windows
|
||||
path: target/${{ env.TARGET }}/release/gopher64.exe
|
||||
name: gopher64-${{ matrix.target }}
|
||||
path: target/${{ matrix.target }}/release/gopher64.exe
|
||||
|
||||
build-macos:
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
TARGET: x86_64-apple-darwin
|
||||
strategy:
|
||||
matrix:
|
||||
target: [x86_64-apple-darwin, aarch64-apple-darwin]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
||||
with:
|
||||
target: ${{ env.TARGET }}
|
||||
target: ${{ matrix.target }}
|
||||
rustflags: ""
|
||||
- name: Build
|
||||
run: |
|
||||
cargo build --release -v --target=${{ env.TARGET }}
|
||||
cargo build --release -v --target=${{ matrix.target }}
|
||||
- name: Upload file
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: gopher64-mac
|
||||
path: target/${{ env.TARGET }}/release/gopher64
|
||||
name: gopher64-${{ matrix.target }}
|
||||
path: target/${{ matrix.target }}/release/gopher64
|
||||
|
||||
+4
-4
@@ -1,12 +1,12 @@
|
||||
[package]
|
||||
name = "gopher64"
|
||||
version = "0.1.14"
|
||||
version = "0.1.17"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
dirs = "5.0"
|
||||
dirs = "6.0"
|
||||
zip = "2.1"
|
||||
governor = "0.8"
|
||||
sevenz-rust = "0.6"
|
||||
@@ -14,7 +14,6 @@ chrono = "0.4"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
eframe = "0.30"
|
||||
epaint = "0.30"
|
||||
rfd = "0.15"
|
||||
sha2 = "0.10"
|
||||
rusttype = "0.9"
|
||||
@@ -31,7 +30,8 @@ features = ["static-link","bundled"]
|
||||
|
||||
[build-dependencies]
|
||||
winres = "0.1"
|
||||
cc = { version = "1.0", features = ["parallel"] }
|
||||
bindgen = "0.71"
|
||||
cc = { version = "1.2", features = ["parallel"] }
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
@@ -46,6 +46,10 @@ You can create you own mappings by running `./gopher64 --configure-input-profile
|
||||
|
||||
In order to use a controller (for example, an Xbox controller), run `./gopher64 --list-controllers` to get a list of attached controllers, and then assign it by doing `./gopher64 --assign-controller <controller_number> --port 1`
|
||||
|
||||
## portable mode
|
||||
|
||||
If you would like to keep all the game data in the same folder as executable, you just need to create a file called "portable.txt" in the same directory as the executable.
|
||||
|
||||
## contributing
|
||||
|
||||
I am very open to contributions! Please reach out to me via a GitHub issue, or via discord (loganmc10) before doing substantial work on a PR.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
fn main() {
|
||||
println!("cargo::rerun-if-changed=parallel-rdp");
|
||||
println!("cargo::rerun-if-changed=src/compat");
|
||||
|
||||
let mut simd_build = cc::Build::new();
|
||||
let mut build = cc::Build::new();
|
||||
build
|
||||
.cpp(true)
|
||||
@@ -52,11 +54,15 @@ fn main() {
|
||||
.include("parallel-rdp/parallel-rdp-standalone/util")
|
||||
.includes(std::env::var("DEP_SDL2_INCLUDE"));
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
|
||||
let arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
||||
if os == "windows" {
|
||||
if arch == "x86_64" {
|
||||
build.flag("/arch:AVX2");
|
||||
} else if arch == "aarch64" {
|
||||
panic!("unsupported platform")
|
||||
} else {
|
||||
panic!("unknown arch")
|
||||
}
|
||||
build.flag("-DVK_USE_PLATFORM_WIN32_KHR");
|
||||
|
||||
@@ -64,14 +70,90 @@ fn main() {
|
||||
.set_icon("data/icon.ico")
|
||||
.compile()
|
||||
.unwrap();
|
||||
}
|
||||
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||
{
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
} else if os == "linux" || os == "macos" {
|
||||
if arch == "x86_64" {
|
||||
build.flag("-march=x86-64-v3");
|
||||
} else if arch == "aarch64" {
|
||||
build.flag("-march=armv8.2-a");
|
||||
simd_build.flag("-march=armv8.2-a");
|
||||
simd_build.flag("-DSSE2NEON_SUPPRESS_WARNINGS");
|
||||
simd_build.file("src/compat/aarch64.c");
|
||||
} else {
|
||||
panic!("unknown arch")
|
||||
}
|
||||
} else {
|
||||
panic!("unknown OS")
|
||||
}
|
||||
|
||||
build.compile("parallel-rdp");
|
||||
|
||||
let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
|
||||
|
||||
let parallel_bindings = bindgen::Builder::default()
|
||||
.header("parallel-rdp/interface.hpp")
|
||||
.allowlist_function("rdp_init")
|
||||
.allowlist_function("rdp_close")
|
||||
.allowlist_function("rdp_set_vi_register")
|
||||
.allowlist_function("rdp_update_screen")
|
||||
.allowlist_function("rdp_process_commands")
|
||||
.allowlist_function("rdp_full_sync")
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
parallel_bindings
|
||||
.write_to_file(out_path.join("parallel_bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
|
||||
if arch == "aarch64" {
|
||||
let simd_bindings = bindgen::Builder::default()
|
||||
.header("src/compat/sse2neon.h")
|
||||
.allowlist_function("_mm_setzero_si128")
|
||||
.allowlist_function("_mm_set_epi8")
|
||||
.allowlist_function("_mm_movemask_epi8")
|
||||
.allowlist_function("_mm_shuffle_epi8")
|
||||
.allowlist_function("_mm_packs_epi16")
|
||||
.allowlist_function("_mm_set_epi16")
|
||||
.allowlist_function("_mm_cmpeq_epi8")
|
||||
.allowlist_function("_mm_and_si128")
|
||||
.allowlist_function("_mm_set1_epi8")
|
||||
.allowlist_function("_mm_mullo_epi16")
|
||||
.allowlist_function("_mm_cmpeq_epi16")
|
||||
.allowlist_function("_mm_add_epi16")
|
||||
.allowlist_function("_mm_slli_epi16")
|
||||
.allowlist_function("_mm_mulhi_epi16")
|
||||
.allowlist_function("_mm_srai_epi16")
|
||||
.allowlist_function("_mm_andnot_si128")
|
||||
.allowlist_function("_mm_or_si128")
|
||||
.allowlist_function("_mm_mulhi_epu16")
|
||||
.allowlist_function("_mm_sub_epi16")
|
||||
.allowlist_function("_mm_unpacklo_epi16")
|
||||
.allowlist_function("_mm_unpackhi_epi16")
|
||||
.allowlist_function("_mm_packs_epi32")
|
||||
.allowlist_function("_mm_adds_epu16")
|
||||
.allowlist_function("_mm_cmpgt_epi16")
|
||||
.allowlist_function("_mm_blendv_epi8")
|
||||
.allowlist_function("_mm_min_epi16")
|
||||
.allowlist_function("_mm_max_epi16")
|
||||
.allowlist_function("_mm_subs_epi16")
|
||||
.allowlist_function("_mm_adds_epi16")
|
||||
.allowlist_function("_mm_xor_si128")
|
||||
.allowlist_function("_mm_cmplt_epi16")
|
||||
.allowlist_function("_mm_subs_epu16")
|
||||
.allowlist_function("_mm_set1_epi32")
|
||||
.blocklist_type("__m128i")
|
||||
.blocklist_type("int64x2_t")
|
||||
.wrap_static_fns(true)
|
||||
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
|
||||
.generate()
|
||||
.expect("Unable to generate bindings");
|
||||
|
||||
simd_bindings
|
||||
.write_to_file(out_path.join("simd_bindings.rs"))
|
||||
.expect("Couldn't write bindings!");
|
||||
|
||||
simd_build.file(std::env::temp_dir().join("bindgen").join("extern.c"));
|
||||
simd_build.include(".");
|
||||
simd_build.compile("simd");
|
||||
}
|
||||
}
|
||||
|
||||
+34
-31
@@ -132,6 +132,37 @@ static const unsigned cmd_len_lut[64] = {
|
||||
1,
|
||||
};
|
||||
|
||||
int sdl_event_filter(void *userdata, SDL_Event *event)
|
||||
{
|
||||
if (event->type == SDL_WINDOWEVENT)
|
||||
{
|
||||
switch (event->window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
emu_running = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
wsi_platform->do_resize();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (fullscreen && event->type == SDL_KEYDOWN)
|
||||
{
|
||||
switch (event->key.keysym.scancode)
|
||||
{
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
emu_running = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void rdp_init(void *_window, GFX_INFO _gfx_info, bool _fullscreen, bool _upscale)
|
||||
{
|
||||
window = (SDL_Window *)_window;
|
||||
@@ -198,37 +229,6 @@ void rdp_close()
|
||||
}
|
||||
}
|
||||
|
||||
int sdl_event_filter(void *userdata, SDL_Event *event)
|
||||
{
|
||||
if (event->type == SDL_WINDOWEVENT)
|
||||
{
|
||||
switch (event->window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_CLOSE:
|
||||
emu_running = false;
|
||||
break;
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
wsi_platform->do_resize();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (fullscreen && event->type == SDL_KEYDOWN)
|
||||
{
|
||||
switch (event->key.keysym.scancode)
|
||||
{
|
||||
case SDL_SCANCODE_ESCAPE:
|
||||
emu_running = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void calculate_viewport(float *x, float *y, float *width, float *height)
|
||||
{
|
||||
bool window_widescreen = false;
|
||||
@@ -264,6 +264,9 @@ static void calculate_viewport(float *x, float *y, float *width, float *height)
|
||||
static void render_frame(Vulkan::Device &device)
|
||||
{
|
||||
RDP::ScanoutOptions options = {};
|
||||
options.persist_frame_on_invalid_input = true;
|
||||
options.blend_previous_frame = true;
|
||||
options.upscale_deinterlacing = false;
|
||||
Vulkan::ImageHandle image = processor->scanout(options);
|
||||
|
||||
// Normally reflection is automated.
|
||||
|
||||
@@ -29,7 +29,6 @@ extern "C"
|
||||
bool rdp_update_screen();
|
||||
uint64_t rdp_process_commands();
|
||||
void rdp_full_sync();
|
||||
int sdl_event_filter(void *userdata, SDL_Event *event);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
#include "src/compat/sse2neon.h"
|
||||
|
||||
// Static wrappers
|
||||
|
||||
__m128i _mm_srli_epi16__extern(__m128i __a, int __imm8) { return _mm_srli_epi16(__a, __imm8); }
|
||||
|
||||
__m128i _mm_insert_epi8__extern(__m128i __a, int __i, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_insert_epi8(__a, __i, 0);
|
||||
case 1:
|
||||
return _mm_insert_epi8(__a, __i, 1);
|
||||
case 2:
|
||||
return _mm_insert_epi8(__a, __i, 2);
|
||||
case 3:
|
||||
return _mm_insert_epi8(__a, __i, 3);
|
||||
case 4:
|
||||
return _mm_insert_epi8(__a, __i, 4);
|
||||
case 5:
|
||||
return _mm_insert_epi8(__a, __i, 5);
|
||||
case 6:
|
||||
return _mm_insert_epi8(__a, __i, 6);
|
||||
case 7:
|
||||
return _mm_insert_epi8(__a, __i, 7);
|
||||
case 8:
|
||||
return _mm_insert_epi8(__a, __i, 8);
|
||||
case 9:
|
||||
return _mm_insert_epi8(__a, __i, 9);
|
||||
case 10:
|
||||
return _mm_insert_epi8(__a, __i, 10);
|
||||
case 11:
|
||||
return _mm_insert_epi8(__a, __i, 11);
|
||||
case 12:
|
||||
return _mm_insert_epi8(__a, __i, 12);
|
||||
case 13:
|
||||
return _mm_insert_epi8(__a, __i, 13);
|
||||
case 14:
|
||||
return _mm_insert_epi8(__a, __i, 14);
|
||||
case 15:
|
||||
return _mm_insert_epi8(__a, __i, 15);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int _mm_extract_epi8__extern(__m128i __a, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_extract_epi8(__a, 0);
|
||||
case 1:
|
||||
return _mm_extract_epi8(__a, 1);
|
||||
case 2:
|
||||
return _mm_extract_epi8(__a, 2);
|
||||
case 3:
|
||||
return _mm_extract_epi8(__a, 3);
|
||||
case 4:
|
||||
return _mm_extract_epi8(__a, 4);
|
||||
case 5:
|
||||
return _mm_extract_epi8(__a, 5);
|
||||
case 6:
|
||||
return _mm_extract_epi8(__a, 6);
|
||||
case 7:
|
||||
return _mm_extract_epi8(__a, 7);
|
||||
case 8:
|
||||
return _mm_extract_epi8(__a, 8);
|
||||
case 9:
|
||||
return _mm_extract_epi8(__a, 9);
|
||||
case 10:
|
||||
return _mm_extract_epi8(__a, 10);
|
||||
case 11:
|
||||
return _mm_extract_epi8(__a, 11);
|
||||
case 12:
|
||||
return _mm_extract_epi8(__a, 12);
|
||||
case 13:
|
||||
return _mm_extract_epi8(__a, 13);
|
||||
case 14:
|
||||
return _mm_extract_epi8(__a, 14);
|
||||
case 15:
|
||||
return _mm_extract_epi8(__a, 15);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
__m128i _mm_insert_epi16__extern(__m128i __a, int __i, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_insert_epi16(__a, __i, 0);
|
||||
case 1:
|
||||
return _mm_insert_epi16(__a, __i, 1);
|
||||
case 2:
|
||||
return _mm_insert_epi16(__a, __i, 2);
|
||||
case 3:
|
||||
return _mm_insert_epi16(__a, __i, 3);
|
||||
case 4:
|
||||
return _mm_insert_epi16(__a, __i, 4);
|
||||
case 5:
|
||||
return _mm_insert_epi16(__a, __i, 5);
|
||||
case 6:
|
||||
return _mm_insert_epi16(__a, __i, 6);
|
||||
case 7:
|
||||
return _mm_insert_epi16(__a, __i, 7);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int _mm_extract_epi16__extern(__m128i __a, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_extract_epi16(__a, 0);
|
||||
case 1:
|
||||
return _mm_extract_epi16(__a, 1);
|
||||
case 2:
|
||||
return _mm_extract_epi16(__a, 2);
|
||||
case 3:
|
||||
return _mm_extract_epi16(__a, 3);
|
||||
case 4:
|
||||
return _mm_extract_epi16(__a, 4);
|
||||
case 5:
|
||||
return _mm_extract_epi16(__a, 5);
|
||||
case 6:
|
||||
return _mm_extract_epi16(__a, 6);
|
||||
case 7:
|
||||
return _mm_extract_epi16(__a, 7);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
__m128i _mm_insert_epi32__extern(__m128i __a, int __i, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_insert_epi32(__a, __i, 0);
|
||||
case 1:
|
||||
return _mm_insert_epi32(__a, __i, 1);
|
||||
case 2:
|
||||
return _mm_insert_epi32(__a, __i, 2);
|
||||
case 3:
|
||||
return _mm_insert_epi32(__a, __i, 3);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int _mm_extract_epi32__extern(__m128i __a, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_extract_epi32(__a, 0);
|
||||
case 1:
|
||||
return _mm_extract_epi32(__a, 1);
|
||||
case 2:
|
||||
return _mm_extract_epi32(__a, 2);
|
||||
case 3:
|
||||
return _mm_extract_epi32(__a, 3);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
__m128i _mm_insert_epi64__extern(__m128i __a, int64_t __i, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_insert_epi64(__a, __i, 0);
|
||||
case 1:
|
||||
return _mm_insert_epi64(__a, __i, 1);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
int64_t _mm_extract_epi64__extern(__m128i __a, const int __imm8)
|
||||
{
|
||||
switch (__imm8)
|
||||
{
|
||||
case 0:
|
||||
return _mm_extract_epi64(__a, 0);
|
||||
case 1:
|
||||
return _mm_extract_epi64(__a, 1);
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
unsafe extern "C" {
|
||||
#[link_name = "_mm_srli_epi16__extern"]
|
||||
pub fn _mm_srli_epi16(__a: __m128i, __imm8: ::std::os::raw::c_int) -> __m128i;
|
||||
|
||||
#[link_name = "_mm_insert_epi8__extern"]
|
||||
pub fn _mm_insert_epi8(
|
||||
__a: __m128i,
|
||||
__i: ::std::os::raw::c_int,
|
||||
__imm8: ::std::os::raw::c_int,
|
||||
) -> __m128i;
|
||||
|
||||
#[link_name = "_mm_extract_epi8__extern"]
|
||||
pub fn _mm_extract_epi8(__a: __m128i, __imm8: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
|
||||
|
||||
#[link_name = "_mm_insert_epi16__extern"]
|
||||
pub fn _mm_insert_epi16(
|
||||
__a: __m128i,
|
||||
__i: ::std::os::raw::c_int,
|
||||
__imm8: ::std::os::raw::c_int,
|
||||
) -> __m128i;
|
||||
|
||||
#[link_name = "_mm_extract_epi16__extern"]
|
||||
pub fn _mm_extract_epi16(__a: __m128i, __imm8: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
|
||||
|
||||
#[link_name = "_mm_insert_epi32__extern"]
|
||||
pub fn _mm_insert_epi32(
|
||||
__a: __m128i,
|
||||
__i: ::std::os::raw::c_int,
|
||||
__imm8: ::std::os::raw::c_int,
|
||||
) -> __m128i;
|
||||
|
||||
#[link_name = "_mm_extract_epi32__extern"]
|
||||
pub fn _mm_extract_epi32(__a: __m128i, __imm8: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
|
||||
|
||||
#[link_name = "_mm_insert_epi64__extern"]
|
||||
pub fn _mm_insert_epi64(
|
||||
__a: __m128i,
|
||||
__i: ::std::os::raw::c_longlong,
|
||||
__imm8: ::std::os::raw::c_int,
|
||||
) -> __m128i;
|
||||
|
||||
#[link_name = "_mm_extract_epi64__extern"]
|
||||
pub fn _mm_extract_epi64(
|
||||
__a: __m128i,
|
||||
__imm8: ::std::os::raw::c_int,
|
||||
) -> ::std::os::raw::c_longlong;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+33
-15
@@ -1,3 +1,15 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(improper_ctypes)]
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct __m128i(std::arch::aarch64::int64x2_t);
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
include!(concat!(env!("OUT_DIR"), "/simd_bindings.rs"));
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
use crate::ui;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
@@ -36,7 +48,12 @@ pub mod unmapped;
|
||||
pub mod vi;
|
||||
pub mod vru;
|
||||
|
||||
pub fn run_game(file_path: &std::path::Path, device: &mut Device, fullscreen: bool) {
|
||||
pub fn run_game(
|
||||
file_path: &std::path::Path,
|
||||
data_dir: std::path::PathBuf,
|
||||
device: &mut Device,
|
||||
fullscreen: bool,
|
||||
) {
|
||||
let rom_contents = get_rom_contents(file_path);
|
||||
|
||||
cart_rom::init(device, rom_contents); // cart needs to come before rdram
|
||||
@@ -59,7 +76,7 @@ pub fn run_game(file_path: &std::path::Path, device: &mut Device, fullscreen: bo
|
||||
vi::init(device);
|
||||
cpu::init(device);
|
||||
|
||||
ui::storage::init(&mut device.ui);
|
||||
ui::storage::init(&mut device.ui, data_dir);
|
||||
ui::storage::load_saves(&mut device.ui);
|
||||
cart_rom::load_rom_save(device);
|
||||
|
||||
@@ -166,7 +183,7 @@ pub struct Device {
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn new() -> Device {
|
||||
pub fn new(config_dir: std::path::PathBuf) -> Device {
|
||||
let mut byte_swap: usize = 0;
|
||||
let test: [u8; 4] = [1, 2, 3, 4];
|
||||
// if the host computer is little endian, that means the RDRAM will be stored as little endian
|
||||
@@ -175,7 +192,7 @@ impl Device {
|
||||
byte_swap = 3;
|
||||
}
|
||||
Device {
|
||||
ui: ui::Ui::new(),
|
||||
ui: ui::Ui::new(config_dir),
|
||||
byte_swap,
|
||||
cpu: cpu::Cpu {
|
||||
cop0: cop0::Cop0 {
|
||||
@@ -223,7 +240,8 @@ impl Device {
|
||||
cop1: cop1::Cop1 {
|
||||
fcr0: 0,
|
||||
fcr31: 0,
|
||||
flush_mode: 0,
|
||||
//#[cfg(target_arch = "x86_64")]
|
||||
//flush_mode: 0,
|
||||
fgr32: [[0; 4]; 32],
|
||||
fgr64: [[0; 8]; 32],
|
||||
instrs: [cop1::reserved; 32],
|
||||
@@ -323,21 +341,21 @@ impl Device {
|
||||
sync_point: false,
|
||||
cycle_counter: 0,
|
||||
gpr: [0; 32],
|
||||
vpr: [0; 32],
|
||||
vpr: unsafe { [_mm_setzero_si128(); 32] },
|
||||
reciprocals: [0; 512],
|
||||
inverse_square_roots: [0; 512],
|
||||
divdp: false,
|
||||
divin: 0,
|
||||
divout: 0,
|
||||
shuffle: unsafe { [std::arch::x86_64::_mm_setzero_si128(); 16] },
|
||||
vcol: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
vcoh: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
vccl: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
vcch: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
vce: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
accl: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
accm: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
acch: unsafe { std::arch::x86_64::_mm_setzero_si128() },
|
||||
shuffle: unsafe { [_mm_setzero_si128(); 16] },
|
||||
vcol: unsafe { _mm_setzero_si128() },
|
||||
vcoh: unsafe { _mm_setzero_si128() },
|
||||
vccl: unsafe { _mm_setzero_si128() },
|
||||
vcch: unsafe { _mm_setzero_si128() },
|
||||
vce: unsafe { _mm_setzero_si128() },
|
||||
accl: unsafe { _mm_setzero_si128() },
|
||||
accm: unsafe { _mm_setzero_si128() },
|
||||
acch: unsafe { _mm_setzero_si128() },
|
||||
special_instrs: [rsp_su_instructions::reserved; 64],
|
||||
regimm_instrs: [rsp_su_instructions::reserved; 32],
|
||||
cop0_instrs: [rsp_su_instructions::reserved; 32],
|
||||
|
||||
+11
-5
@@ -17,7 +17,8 @@ use crate::device;
|
||||
//const FCR31_CAUSE_INVALID_BIT: u32 = 1 << 16;
|
||||
const FCR31_CAUSE_UNIMP_BIT: u32 = 1 << 17;
|
||||
pub const FCR31_CMP_BIT: u32 = 1 << 23;
|
||||
const FCR31_FS_BIT: u32 = 1 << 24;
|
||||
//#[cfg(target_arch = "x86_64")]
|
||||
//const FCR31_FS_BIT: u32 = 1 << 24;
|
||||
|
||||
const FCR31_CAUSE_MASK: u32 = 0b00000000000000111111000000000000;
|
||||
const FCR31_ENABLE_MASK: u32 = 0b00000000000000000000111110000000;
|
||||
@@ -26,7 +27,8 @@ const FCR31_WRITE_MASK: u32 = 0b00000001100000111111111111111111;
|
||||
pub struct Cop1 {
|
||||
pub fcr0: u32,
|
||||
pub fcr31: u32,
|
||||
pub flush_mode: u32,
|
||||
//#[cfg(target_arch = "x86_64")]
|
||||
//pub flush_mode: u32,
|
||||
pub fgr32: [[u8; 4]; 32],
|
||||
pub fgr64: [[u8; 8]; 32],
|
||||
pub instrs: [fn(&mut device::Device, u32); 32],
|
||||
@@ -366,8 +368,9 @@ pub fn set_control_registers_fpu(device: &mut device::Device, index: u32, data:
|
||||
{
|
||||
device::exceptions::floating_point_exception(device)
|
||||
}
|
||||
|
||||
unsafe {
|
||||
/*
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let flush_mode;
|
||||
if (device.cpu.cop1.fcr31 & 2) != 0 {
|
||||
if (device.cpu.cop1.fcr31 & FCR31_FS_BIT) != 0 {
|
||||
@@ -380,10 +383,13 @@ pub fn set_control_registers_fpu(device: &mut device::Device, index: u32, data:
|
||||
}
|
||||
if flush_mode != device.cpu.cop1.flush_mode {
|
||||
#[allow(deprecated)]
|
||||
std::arch::x86_64::_MM_SET_FLUSH_ZERO_MODE(flush_mode);
|
||||
unsafe {
|
||||
std::arch::x86_64::_MM_SET_FLUSH_ZERO_MODE(flush_mode)
|
||||
};
|
||||
device.cpu.cop1.flush_mode = flush_mode;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
_ => {
|
||||
panic!("unknown FCR register")
|
||||
|
||||
+2
-1
@@ -13,7 +13,8 @@ const PI_BSD_DOM2_LAT_REG: u32 = 9;
|
||||
const PI_BSD_DOM2_PWD_REG: u32 = 10;
|
||||
const PI_BSD_DOM2_PGS_REG: u32 = 11;
|
||||
const PI_BSD_DOM2_RLS_REG: u32 = 12;
|
||||
pub const PI_REGS_COUNT: u32 = 13;
|
||||
//const UNKNOWN_REG: u32 = 13; //LibDragon
|
||||
pub const PI_REGS_COUNT: u32 = 14;
|
||||
|
||||
/* PI_STATUS - read */
|
||||
const PI_STATUS_DMA_BUSY: u32 = 1 << 0;
|
||||
|
||||
+3
-2
@@ -57,10 +57,11 @@ pub fn write_mem(device: &mut device::Device, address: u64, value: u32, mask: u3
|
||||
|
||||
pub fn read_regs(
|
||||
_device: &mut device::Device,
|
||||
_address: u64,
|
||||
address: u64,
|
||||
_access_size: device::memory::AccessSize,
|
||||
) -> u32 {
|
||||
panic!("rdram read reg");
|
||||
println!("Warning: read from RDRAM reg {:#x}", address);
|
||||
0
|
||||
}
|
||||
|
||||
pub fn write_regs(_device: &mut device::Device, _address: u64, _value: u32, _mask: u32) {
|
||||
|
||||
+14
-9
@@ -1,4 +1,9 @@
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use device::__m128i;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
include!(concat!(env!("OUT_DIR"), "/simd_bindings.rs"));
|
||||
use crate::device;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
pub struct BranchState {
|
||||
@@ -30,17 +35,17 @@ pub struct Cpu {
|
||||
pub cycle_counter: u64,
|
||||
pub shuffle: [__m128i; 16],
|
||||
pub gpr: [u32; 32],
|
||||
pub vpr: [u128; 32],
|
||||
pub vpr: [__m128i; 32],
|
||||
pub reciprocals: [u16; 512],
|
||||
pub inverse_square_roots: [u16; 512],
|
||||
pub vcol: std::arch::x86_64::__m128i,
|
||||
pub vcoh: std::arch::x86_64::__m128i,
|
||||
pub vccl: std::arch::x86_64::__m128i,
|
||||
pub vcch: std::arch::x86_64::__m128i,
|
||||
pub vce: std::arch::x86_64::__m128i,
|
||||
pub accl: std::arch::x86_64::__m128i,
|
||||
pub accm: std::arch::x86_64::__m128i,
|
||||
pub acch: std::arch::x86_64::__m128i,
|
||||
pub vcol: __m128i,
|
||||
pub vcoh: __m128i,
|
||||
pub vccl: __m128i,
|
||||
pub vcch: __m128i,
|
||||
pub vce: __m128i,
|
||||
pub accl: __m128i,
|
||||
pub accm: __m128i,
|
||||
pub acch: __m128i,
|
||||
pub divdp: bool,
|
||||
pub divin: i16,
|
||||
pub divout: i16,
|
||||
|
||||
+433
-152
@@ -1,4 +1,11 @@
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use device::__m128i;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
include!(concat!(env!("OUT_DIR"), "/simd_bindings.rs"));
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
include!("../compat/aarch64.rs");
|
||||
use crate::device;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::arch::x86_64::*;
|
||||
|
||||
pub fn rd(opcode: u32) -> u32 {
|
||||
@@ -39,28 +46,136 @@ pub fn sign_extend_7bit_offset(offset: u8, shift_amount: u32) -> u32 {
|
||||
(((soffset) as i32) as u32) << shift_amount
|
||||
}
|
||||
|
||||
pub fn modify_vpr_byte(vpr: &mut u128, value: u8, element: u8) {
|
||||
let pos = 15 - (element & 15);
|
||||
let mask = 0xFF << (pos * 8);
|
||||
*vpr &= !mask;
|
||||
*vpr |= (value as u128) << (pos * 8);
|
||||
pub fn modify_vpr8(vpr: &mut __m128i, element: u8, value: u8) {
|
||||
unsafe {
|
||||
*vpr = match element & 15 {
|
||||
0 => _mm_insert_epi8(*vpr, value as i32, 15),
|
||||
1 => _mm_insert_epi8(*vpr, value as i32, 14),
|
||||
2 => _mm_insert_epi8(*vpr, value as i32, 13),
|
||||
3 => _mm_insert_epi8(*vpr, value as i32, 12),
|
||||
4 => _mm_insert_epi8(*vpr, value as i32, 11),
|
||||
5 => _mm_insert_epi8(*vpr, value as i32, 10),
|
||||
6 => _mm_insert_epi8(*vpr, value as i32, 9),
|
||||
7 => _mm_insert_epi8(*vpr, value as i32, 8),
|
||||
8 => _mm_insert_epi8(*vpr, value as i32, 7),
|
||||
9 => _mm_insert_epi8(*vpr, value as i32, 6),
|
||||
10 => _mm_insert_epi8(*vpr, value as i32, 5),
|
||||
11 => _mm_insert_epi8(*vpr, value as i32, 4),
|
||||
12 => _mm_insert_epi8(*vpr, value as i32, 3),
|
||||
13 => _mm_insert_epi8(*vpr, value as i32, 2),
|
||||
14 => _mm_insert_epi8(*vpr, value as i32, 1),
|
||||
15 => _mm_insert_epi8(*vpr, value as i32, 0),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vpr_byte(vpr: u128, element: u8) -> u8 {
|
||||
let pos = 15 - (element & 15);
|
||||
(vpr >> (pos * 8)) as u8
|
||||
pub fn get_vpr8(vpr: __m128i, element: u8) -> u8 {
|
||||
unsafe {
|
||||
match element & 15 {
|
||||
0 => _mm_extract_epi8(vpr, 15) as u8,
|
||||
1 => _mm_extract_epi8(vpr, 14) as u8,
|
||||
2 => _mm_extract_epi8(vpr, 13) as u8,
|
||||
3 => _mm_extract_epi8(vpr, 12) as u8,
|
||||
4 => _mm_extract_epi8(vpr, 11) as u8,
|
||||
5 => _mm_extract_epi8(vpr, 10) as u8,
|
||||
6 => _mm_extract_epi8(vpr, 9) as u8,
|
||||
7 => _mm_extract_epi8(vpr, 8) as u8,
|
||||
8 => _mm_extract_epi8(vpr, 7) as u8,
|
||||
9 => _mm_extract_epi8(vpr, 6) as u8,
|
||||
10 => _mm_extract_epi8(vpr, 5) as u8,
|
||||
11 => _mm_extract_epi8(vpr, 4) as u8,
|
||||
12 => _mm_extract_epi8(vpr, 3) as u8,
|
||||
13 => _mm_extract_epi8(vpr, 2) as u8,
|
||||
14 => _mm_extract_epi8(vpr, 1) as u8,
|
||||
15 => _mm_extract_epi8(vpr, 0) as u8,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_vpr_element(vpr: &mut u128, value: u16, element: u8) {
|
||||
let pos = 7 - (element & 7);
|
||||
let mask = 0xFFFF << (pos * 16);
|
||||
*vpr &= !mask;
|
||||
*vpr |= (value as u128) << (pos * 16);
|
||||
pub fn modify_vpr16(vpr: &mut __m128i, element: u8, value: u16) {
|
||||
unsafe {
|
||||
*vpr = match element & 7 {
|
||||
0 => _mm_insert_epi16(*vpr, value as i32, 7),
|
||||
1 => _mm_insert_epi16(*vpr, value as i32, 6),
|
||||
2 => _mm_insert_epi16(*vpr, value as i32, 5),
|
||||
3 => _mm_insert_epi16(*vpr, value as i32, 4),
|
||||
4 => _mm_insert_epi16(*vpr, value as i32, 3),
|
||||
5 => _mm_insert_epi16(*vpr, value as i32, 2),
|
||||
6 => _mm_insert_epi16(*vpr, value as i32, 1),
|
||||
7 => _mm_insert_epi16(*vpr, value as i32, 0),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vpr_element(vpr: u128, element: u8) -> u16 {
|
||||
let pos = 7 - (element & 7);
|
||||
(vpr >> (pos * 16)) as u16
|
||||
pub fn get_vpr16(vpr: __m128i, element: u8) -> u16 {
|
||||
unsafe {
|
||||
match element & 7 {
|
||||
0 => _mm_extract_epi16(vpr, 7) as u16,
|
||||
1 => _mm_extract_epi16(vpr, 6) as u16,
|
||||
2 => _mm_extract_epi16(vpr, 5) as u16,
|
||||
3 => _mm_extract_epi16(vpr, 4) as u16,
|
||||
4 => _mm_extract_epi16(vpr, 3) as u16,
|
||||
5 => _mm_extract_epi16(vpr, 2) as u16,
|
||||
6 => _mm_extract_epi16(vpr, 1) as u16,
|
||||
7 => _mm_extract_epi16(vpr, 0) as u16,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_vpr32(vpr: &mut __m128i, element: u8, value: u32) {
|
||||
unsafe {
|
||||
*vpr = match element & 3 {
|
||||
0 => _mm_insert_epi32(*vpr, value as i32, 3),
|
||||
1 => _mm_insert_epi32(*vpr, value as i32, 2),
|
||||
2 => _mm_insert_epi32(*vpr, value as i32, 1),
|
||||
3 => _mm_insert_epi32(*vpr, value as i32, 0),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vpr32(vpr: __m128i, element: u8) -> u32 {
|
||||
unsafe {
|
||||
match element & 3 {
|
||||
0 => _mm_extract_epi32(vpr, 3) as u32,
|
||||
1 => _mm_extract_epi32(vpr, 2) as u32,
|
||||
2 => _mm_extract_epi32(vpr, 1) as u32,
|
||||
3 => _mm_extract_epi32(vpr, 0) as u32,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_vpr64(vpr: &mut __m128i, element: u8, value: u64) {
|
||||
unsafe {
|
||||
*vpr = match element & 1 {
|
||||
0 => _mm_insert_epi64(*vpr, value as i64, 1),
|
||||
1 => _mm_insert_epi64(*vpr, value as i64, 0),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_vpr64(vpr: __m128i, element: u8) -> u64 {
|
||||
unsafe {
|
||||
match element & 1 {
|
||||
0 => _mm_extract_epi64(vpr, 1) as u64,
|
||||
1 => _mm_extract_epi64(vpr, 0) as u64,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_vpr128(vpr: &mut __m128i, value: u128) {
|
||||
unsafe { *vpr = std::mem::transmute::<u128, __m128i>(value) }
|
||||
}
|
||||
|
||||
pub fn get_vpr128(vpr: __m128i) -> u128 {
|
||||
unsafe { std::mem::transmute::<__m128i, u128>(vpr) }
|
||||
}
|
||||
|
||||
pub fn j(device: &mut device::Device, opcode: u32) {
|
||||
@@ -481,8 +596,8 @@ pub fn mtc0(device: &mut device::Device, opcode: u32) {
|
||||
}
|
||||
|
||||
pub fn mfc2(device: &mut device::Device, opcode: u32) {
|
||||
let hi = get_vpr_byte(device.rsp.cpu.vpr[rd(opcode) as usize], velement(opcode));
|
||||
let lo = get_vpr_byte(
|
||||
let hi = get_vpr8(device.rsp.cpu.vpr[rd(opcode) as usize], velement(opcode));
|
||||
let lo = get_vpr8(
|
||||
device.rsp.cpu.vpr[rd(opcode) as usize],
|
||||
velement(opcode) + 1,
|
||||
);
|
||||
@@ -508,7 +623,7 @@ pub fn cfc2(device: &mut device::Device, opcode: u32) {
|
||||
lo = &mut device.rsp.cpu.vce;
|
||||
}
|
||||
_ => {
|
||||
panic!("unknown ctc2")
|
||||
panic!("unknown cfc2")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,16 +635,16 @@ pub fn cfc2(device: &mut device::Device, opcode: u32) {
|
||||
}
|
||||
|
||||
pub fn mtc2(device: &mut device::Device, opcode: u32) {
|
||||
modify_vpr_byte(
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rd(opcode) as usize],
|
||||
(device.rsp.cpu.gpr[rt(opcode) as usize] >> 8) as u8,
|
||||
velement(opcode),
|
||||
(device.rsp.cpu.gpr[rt(opcode) as usize] >> 8) as u8,
|
||||
);
|
||||
if velement(opcode) != 15 {
|
||||
modify_vpr_byte(
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rd(opcode) as usize],
|
||||
device.rsp.cpu.gpr[rt(opcode) as usize] as u8,
|
||||
velement(opcode) + 1,
|
||||
device.rsp.cpu.gpr[rt(opcode) as usize] as u8,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -574,7 +689,7 @@ pub fn ctc2(device: &mut device::Device, opcode: u32) {
|
||||
),
|
||||
_mm_setzero_si128(),
|
||||
);
|
||||
*hi = std::arch::x86_64::_mm_cmpeq_epi8(
|
||||
*hi = _mm_cmpeq_epi8(
|
||||
_mm_and_si128(
|
||||
_mm_set1_epi8(!(device.rsp.cpu.gpr[rt(opcode) as usize] >> 8) as i8),
|
||||
mask,
|
||||
@@ -589,10 +704,10 @@ pub fn lbv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 0));
|
||||
|
||||
let element = velement(opcode);
|
||||
modify_vpr_byte(
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
element,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -601,15 +716,25 @@ pub fn lsv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 1));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = std::cmp::min(element + 2, 16);
|
||||
while element < end {
|
||||
modify_vpr_byte(
|
||||
|
||||
if element % 2 == 0 {
|
||||
modify_vpr16(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
element,
|
||||
element / 2,
|
||||
(device.rsp.mem[(address & 0xFFF) as usize] as u16) << 8
|
||||
| (device.rsp.mem[((address + 1) & 0xFFF) as usize] as u16),
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
} else {
|
||||
let end = std::cmp::min(element + 2, 16);
|
||||
while element < end {
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
element,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,15 +743,27 @@ pub fn llv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 2));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = std::cmp::min(element + 4, 16);
|
||||
while element < end {
|
||||
modify_vpr_byte(
|
||||
|
||||
if element % 4 == 0 {
|
||||
modify_vpr32(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
element,
|
||||
element / 4,
|
||||
(device.rsp.mem[(address & 0xFFF) as usize] as u32) << (8 * 3)
|
||||
| (device.rsp.mem[((address + 1) & 0xFFF) as usize] as u32) << (8 * 2)
|
||||
| (device.rsp.mem[((address + 2) & 0xFFF) as usize] as u32) << 8
|
||||
| (device.rsp.mem[((address + 3) & 0xFFF) as usize] as u32),
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
} else {
|
||||
let end = std::cmp::min(element + 4, 16);
|
||||
while element < end {
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
element,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,15 +772,31 @@ pub fn ldv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 3));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = std::cmp::min(element + 8, 16);
|
||||
while element < end {
|
||||
modify_vpr_byte(
|
||||
|
||||
if element % 8 == 0 {
|
||||
modify_vpr64(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
element,
|
||||
element / 8,
|
||||
(device.rsp.mem[(address & 0xFFF) as usize] as u64) << (8 * 7)
|
||||
| (device.rsp.mem[((address + 1) & 0xFFF) as usize] as u64) << (8 * 6)
|
||||
| (device.rsp.mem[((address + 2) & 0xFFF) as usize] as u64) << (8 * 5)
|
||||
| (device.rsp.mem[((address + 3) & 0xFFF) as usize] as u64) << (8 * 4)
|
||||
| (device.rsp.mem[((address + 4) & 0xFFF) as usize] as u64) << (8 * 3)
|
||||
| (device.rsp.mem[((address + 5) & 0xFFF) as usize] as u64) << (8 * 2)
|
||||
| (device.rsp.mem[((address + 6) & 0xFFF) as usize] as u64) << 8
|
||||
| (device.rsp.mem[((address + 7) & 0xFFF) as usize] as u64),
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
} else {
|
||||
let end = std::cmp::min(element + 8, 16);
|
||||
while element < end {
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
element,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,15 +805,38 @@ pub fn lqv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 4));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = std::cmp::min(16 + element - ((address & 15) as u8), 16);
|
||||
while element < end {
|
||||
modify_vpr_byte(
|
||||
|
||||
if element == 0 && address % 16 == 0 {
|
||||
modify_vpr128(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
element,
|
||||
(device.rsp.mem[(address & 0xFFF) as usize] as u128) << (8 * 15)
|
||||
| (device.rsp.mem[((address + 1) & 0xFFF) as usize] as u128) << (8 * 14)
|
||||
| (device.rsp.mem[((address + 2) & 0xFFF) as usize] as u128) << (8 * 13)
|
||||
| (device.rsp.mem[((address + 3) & 0xFFF) as usize] as u128) << (8 * 12)
|
||||
| (device.rsp.mem[((address + 4) & 0xFFF) as usize] as u128) << (8 * 11)
|
||||
| (device.rsp.mem[((address + 5) & 0xFFF) as usize] as u128) << (8 * 10)
|
||||
| (device.rsp.mem[((address + 6) & 0xFFF) as usize] as u128) << (8 * 9)
|
||||
| (device.rsp.mem[((address + 7) & 0xFFF) as usize] as u128) << (8 * 8)
|
||||
| (device.rsp.mem[((address + 8) & 0xFFF) as usize] as u128) << (8 * 7)
|
||||
| (device.rsp.mem[((address + 9) & 0xFFF) as usize] as u128) << (8 * 6)
|
||||
| (device.rsp.mem[((address + 10) & 0xFFF) as usize] as u128) << (8 * 5)
|
||||
| (device.rsp.mem[((address + 11) & 0xFFF) as usize] as u128) << (8 * 4)
|
||||
| (device.rsp.mem[((address + 12) & 0xFFF) as usize] as u128) << (8 * 3)
|
||||
| (device.rsp.mem[((address + 13) & 0xFFF) as usize] as u128) << (8 * 2)
|
||||
| (device.rsp.mem[((address + 14) & 0xFFF) as usize] as u128) << 8
|
||||
| (device.rsp.mem[((address + 15) & 0xFFF) as usize] as u128),
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
} else {
|
||||
let end = std::cmp::min(16 + element - ((address & 15) as u8), 16);
|
||||
while element < end {
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
element,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,14 +846,36 @@ pub fn lrv(device: &mut device::Device, opcode: u32) {
|
||||
|
||||
let mut element = 16u8.wrapping_sub(((address & 15) as u8).wrapping_sub(velement(opcode)));
|
||||
address &= !15;
|
||||
while element < 16 {
|
||||
modify_vpr_byte(
|
||||
if element == 0 {
|
||||
modify_vpr128(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
element,
|
||||
(device.rsp.mem[(address & 0xFFF) as usize] as u128) << (8 * 15)
|
||||
| (device.rsp.mem[((address + 1) & 0xFFF) as usize] as u128) << (8 * 14)
|
||||
| (device.rsp.mem[((address + 2) & 0xFFF) as usize] as u128) << (8 * 13)
|
||||
| (device.rsp.mem[((address + 3) & 0xFFF) as usize] as u128) << (8 * 12)
|
||||
| (device.rsp.mem[((address + 4) & 0xFFF) as usize] as u128) << (8 * 11)
|
||||
| (device.rsp.mem[((address + 5) & 0xFFF) as usize] as u128) << (8 * 10)
|
||||
| (device.rsp.mem[((address + 6) & 0xFFF) as usize] as u128) << (8 * 9)
|
||||
| (device.rsp.mem[((address + 7) & 0xFFF) as usize] as u128) << (8 * 8)
|
||||
| (device.rsp.mem[((address + 8) & 0xFFF) as usize] as u128) << (8 * 7)
|
||||
| (device.rsp.mem[((address + 9) & 0xFFF) as usize] as u128) << (8 * 6)
|
||||
| (device.rsp.mem[((address + 10) & 0xFFF) as usize] as u128) << (8 * 5)
|
||||
| (device.rsp.mem[((address + 11) & 0xFFF) as usize] as u128) << (8 * 4)
|
||||
| (device.rsp.mem[((address + 12) & 0xFFF) as usize] as u128) << (8 * 3)
|
||||
| (device.rsp.mem[((address + 13) & 0xFFF) as usize] as u128) << (8 * 2)
|
||||
| (device.rsp.mem[((address + 14) & 0xFFF) as usize] as u128) << 8
|
||||
| (device.rsp.mem[((address + 15) & 0xFFF) as usize] as u128),
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
} else {
|
||||
while element < 16 {
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
element,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -687,16 +885,34 @@ pub fn lpv(device: &mut device::Device, opcode: u32) {
|
||||
|
||||
let index = ((address & 7) as u8).wrapping_sub(velement(opcode));
|
||||
address &= !7;
|
||||
let mut offset: u8 = 0;
|
||||
while offset < 8 {
|
||||
modify_vpr_element(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(offset)) & 15) as u32))
|
||||
& 0xFFF) as usize] as u16)
|
||||
<< 8,
|
||||
offset,
|
||||
);
|
||||
offset += 1;
|
||||
unsafe {
|
||||
device.rsp.cpu.vpr[rt(opcode) as usize] =
|
||||
_mm_set_epi16(
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(0)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(1)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(2)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(3)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(4)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(5)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(6)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(7)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 8,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -706,16 +922,34 @@ pub fn luv(device: &mut device::Device, opcode: u32) {
|
||||
|
||||
let index = ((address & 7) as u8).wrapping_sub(velement(opcode));
|
||||
address &= !7;
|
||||
let mut offset: u8 = 0;
|
||||
while offset < 8 {
|
||||
modify_vpr_element(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(offset)) & 15) as u32))
|
||||
& 0xFFF) as usize] as u16)
|
||||
<< 7,
|
||||
offset,
|
||||
);
|
||||
offset += 1;
|
||||
unsafe {
|
||||
device.rsp.cpu.vpr[rt(opcode) as usize] =
|
||||
_mm_set_epi16(
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(0)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(1)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(2)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(3)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(4)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(5)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(6)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(7)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -725,16 +959,34 @@ pub fn lhv(device: &mut device::Device, opcode: u32) {
|
||||
|
||||
let index = ((address & 7) as u8).wrapping_sub(velement(opcode));
|
||||
address &= !7;
|
||||
let mut offset: u8 = 0;
|
||||
while offset < 8 {
|
||||
modify_vpr_element(
|
||||
&mut device.rsp.cpu.vpr[rt(opcode) as usize],
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(offset * 2)) & 15) as u32))
|
||||
& 0xFFF) as usize] as u16)
|
||||
<< 7,
|
||||
offset,
|
||||
);
|
||||
offset += 1;
|
||||
unsafe {
|
||||
device.rsp.cpu.vpr[rt(opcode) as usize] =
|
||||
_mm_set_epi16(
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(0)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(2)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(4)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(6)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(8)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(10)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(12)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(14)) & 15) as u32))
|
||||
& 0xFFF) as usize] as i16)
|
||||
<< 7,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -746,30 +998,30 @@ pub fn lfv(device: &mut device::Device, opcode: u32) {
|
||||
address &= !7;
|
||||
let start = velement(opcode);
|
||||
let end = std::cmp::min(start + 8, 16);
|
||||
let mut tmp: u128 = 0;
|
||||
let mut tmp: __m128i = unsafe { _mm_setzero_si128() };
|
||||
let mut offset: u8 = 0;
|
||||
while offset < 4 {
|
||||
modify_vpr_element(
|
||||
modify_vpr16(
|
||||
&mut tmp,
|
||||
offset,
|
||||
(device.rsp.mem[((address.wrapping_add(((index.wrapping_add(offset * 4)) & 15) as u32))
|
||||
& 0xFFF) as usize] as u16)
|
||||
<< 7,
|
||||
offset,
|
||||
);
|
||||
modify_vpr_element(
|
||||
modify_vpr16(
|
||||
&mut tmp,
|
||||
offset + 4,
|
||||
(device.rsp.mem[((address
|
||||
.wrapping_add(((index.wrapping_add(offset * 4).wrapping_add(8)) & 15) as u32))
|
||||
& 0xFFF) as usize] as u16)
|
||||
<< 7,
|
||||
offset + 4,
|
||||
);
|
||||
offset += 1;
|
||||
}
|
||||
offset = start;
|
||||
while offset < end {
|
||||
let value = get_vpr_byte(tmp, offset);
|
||||
modify_vpr_byte(&mut device.rsp.cpu.vpr[rt(opcode) as usize], value, offset);
|
||||
let value = get_vpr8(tmp, offset);
|
||||
modify_vpr8(&mut device.rsp.cpu.vpr[rt(opcode) as usize], offset, value);
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
@@ -784,28 +1036,26 @@ pub fn ltv(device: &mut device::Device, opcode: u32) {
|
||||
address = begin + (((velement(opcode)) as u32 + (address & 8)) & 15);
|
||||
let vtbase = rt(opcode) & !7;
|
||||
let mut vtoff = (velement(opcode)) as u32 >> 1;
|
||||
let mut i = 0;
|
||||
while i < 8 {
|
||||
modify_vpr_byte(
|
||||
for i in 0..8 {
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[(vtbase + vtoff) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
i * 2,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
if address == begin + 16 {
|
||||
address = begin
|
||||
}
|
||||
modify_vpr_byte(
|
||||
modify_vpr8(
|
||||
&mut device.rsp.cpu.vpr[(vtbase + vtoff) as usize],
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
i * 2 + 1,
|
||||
device.rsp.mem[(address & 0xFFF) as usize],
|
||||
);
|
||||
address += 1;
|
||||
if address == begin + 16 {
|
||||
address = begin
|
||||
}
|
||||
vtoff = (vtoff + 1) & 7;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,7 +1064,7 @@ pub fn sbv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 0));
|
||||
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], velement(opcode))
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], velement(opcode))
|
||||
}
|
||||
|
||||
pub fn ssv(device: &mut device::Device, opcode: u32) {
|
||||
@@ -822,12 +1072,20 @@ pub fn ssv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 1));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = element + 2;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
|
||||
if element % 2 == 0 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize..((address + 2) & 0xFFF) as usize]
|
||||
.copy_from_slice(
|
||||
&get_vpr16(device.rsp.cpu.vpr[rt(opcode) as usize], element / 2).to_be_bytes(),
|
||||
);
|
||||
} else {
|
||||
let end = element + 2;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -836,12 +1094,20 @@ pub fn slv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 2));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = element + 4;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
|
||||
if element % 4 == 0 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize..((address + 4) & 0xFFF) as usize]
|
||||
.copy_from_slice(
|
||||
&get_vpr32(device.rsp.cpu.vpr[rt(opcode) as usize], element / 4).to_be_bytes(),
|
||||
);
|
||||
} else {
|
||||
let end = element + 4;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -850,12 +1116,20 @@ pub fn sdv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 3));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = element + 8;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
|
||||
if element % 8 == 0 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize..((address + 8) & 0xFFF) as usize]
|
||||
.copy_from_slice(
|
||||
&get_vpr64(device.rsp.cpu.vpr[rt(opcode) as usize], element / 8).to_be_bytes(),
|
||||
);
|
||||
} else {
|
||||
let end = element + 8;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,12 +1138,18 @@ pub fn sqv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 4));
|
||||
|
||||
let mut element = velement(opcode);
|
||||
let end = element + (16 - (address & 15)) as u8;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
|
||||
if element == 0 && address % 16 == 0 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize..((address + 16) & 0xFFF) as usize]
|
||||
.copy_from_slice(&get_vpr128(device.rsp.cpu.vpr[rt(opcode) as usize]).to_be_bytes());
|
||||
} else {
|
||||
let end = element + (16 - (address & 15)) as u8;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -881,11 +1161,17 @@ pub fn srv(device: &mut device::Device, opcode: u32) {
|
||||
let end = element + (address & 15) as u8;
|
||||
let base = (16 - (address & 15)) as u8;
|
||||
address &= !15;
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], element + base);
|
||||
address += 1;
|
||||
element += 1;
|
||||
|
||||
if element == 0 && base == 0 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize..((address + 16) & 0xFFF) as usize]
|
||||
.copy_from_slice(&get_vpr128(device.rsp.cpu.vpr[rt(opcode) as usize]).to_be_bytes());
|
||||
} else {
|
||||
while element < end {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], element + base);
|
||||
address += 1;
|
||||
element += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,10 +1184,10 @@ pub fn spv(device: &mut device::Device, opcode: u32) {
|
||||
while element < end {
|
||||
if (element & 15) < 8 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], (element & 7) << 1);
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], (element & 7) << 1);
|
||||
} else {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
(get_vpr_element(device.rsp.cpu.vpr[rt(opcode) as usize], element) >> 7) as u8;
|
||||
(get_vpr16(device.rsp.cpu.vpr[rt(opcode) as usize], element) >> 7) as u8;
|
||||
}
|
||||
address += 1;
|
||||
element += 1;
|
||||
@@ -917,10 +1203,10 @@ pub fn suv(device: &mut device::Device, opcode: u32) {
|
||||
while element < end {
|
||||
if (element & 15) < 8 {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
(get_vpr_element(device.rsp.cpu.vpr[rt(opcode) as usize], element) >> 7) as u8;
|
||||
(get_vpr16(device.rsp.cpu.vpr[rt(opcode) as usize], element) >> 7) as u8;
|
||||
} else {
|
||||
device.rsp.mem[(address & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], (element & 7) << 1);
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], (element & 7) << 1);
|
||||
}
|
||||
address += 1;
|
||||
element += 1;
|
||||
@@ -934,13 +1220,11 @@ pub fn shv(device: &mut device::Device, opcode: u32) {
|
||||
let element = velement(opcode);
|
||||
let index = (address & 7) as u8;
|
||||
address &= !7;
|
||||
let mut offset = 0;
|
||||
while offset < 8 {
|
||||
for offset in 0..8 {
|
||||
let byte_val = element + offset * 2;
|
||||
let value = (get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], byte_val) << 1)
|
||||
| (get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], byte_val + 1) >> 7);
|
||||
let value = (get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], byte_val) << 1)
|
||||
| (get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], byte_val + 1) >> 7);
|
||||
device.rsp.mem[((address + ((index + offset * 2) & 15) as u32) & 0xFFF) as usize] = value;
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,8 +1233,7 @@ pub fn sfv(device: &mut device::Device, opcode: u32) {
|
||||
.wrapping_add(sign_extend_7bit_offset(voffset(opcode), 4));
|
||||
let base = address & 7;
|
||||
address &= !7;
|
||||
let element = velement(opcode);
|
||||
let elements = match element {
|
||||
let elements = match velement(opcode) {
|
||||
0 | 15 => [0, 1, 2, 3],
|
||||
1 => [6, 7, 4, 5],
|
||||
4 => [1, 2, 3, 0],
|
||||
@@ -967,12 +1250,10 @@ pub fn sfv(device: &mut device::Device, opcode: u32) {
|
||||
}
|
||||
};
|
||||
let mut offset = 0;
|
||||
let mut i = 0;
|
||||
while i < 4 {
|
||||
for element in elements {
|
||||
device.rsp.mem[((address + ((base + offset) & 15)) & 0xFFF) as usize] =
|
||||
(get_vpr_element(device.rsp.cpu.vpr[rt(opcode) as usize], elements[i]) >> 7) as u8;
|
||||
(get_vpr16(device.rsp.cpu.vpr[rt(opcode) as usize], element) >> 7) as u8;
|
||||
offset += 4;
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -986,7 +1267,7 @@ pub fn swv(device: &mut device::Device, opcode: u32) {
|
||||
address &= !7;
|
||||
while element < end {
|
||||
device.rsp.mem[((address + (base & 15)) & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
get_vpr8(device.rsp.cpu.vpr[rt(opcode) as usize], element);
|
||||
base += 1;
|
||||
element += 1;
|
||||
}
|
||||
@@ -1003,11 +1284,11 @@ pub fn stv(device: &mut device::Device, opcode: u32) {
|
||||
let mut offset = start;
|
||||
while offset < end {
|
||||
device.rsp.mem[((address + (base & 15)) & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[offset as usize], element);
|
||||
get_vpr8(device.rsp.cpu.vpr[offset as usize], element);
|
||||
base = base.wrapping_add(1);
|
||||
element += 1;
|
||||
device.rsp.mem[((address + (base & 15)) & 0xFFF) as usize] =
|
||||
get_vpr_byte(device.rsp.cpu.vpr[offset as usize], element);
|
||||
get_vpr8(device.rsp.cpu.vpr[offset as usize], element);
|
||||
base = base.wrapping_add(1);
|
||||
element += 1;
|
||||
offset += 1;
|
||||
|
||||
+196
-669
File diff suppressed because it is too large
Load Diff
+5
-14
@@ -117,21 +117,12 @@ pub fn process(device: &mut device::Device, channel: usize) {
|
||||
for i in 0..length {
|
||||
data.extend(device.vru.word_buffer[offset + i as usize].to_be_bytes());
|
||||
}
|
||||
if device.cart.rom[0x3E] == /* Japan */ 0x4A {
|
||||
let (res, _enc, errors) = encoding_rs::SHIFT_JIS.decode(&data);
|
||||
if errors {
|
||||
panic!("Failed to decode Japanese word {:X?}", data);
|
||||
} else {
|
||||
device.vru.words.push(res.to_string());
|
||||
}
|
||||
|
||||
let (res, _enc, errors) = encoding_rs::SHIFT_JIS.decode(&data);
|
||||
if errors {
|
||||
panic!("Failed to decode Japanese word {:X?}", data);
|
||||
} else {
|
||||
let decoded: Result<String, std::string::FromUtf8Error> =
|
||||
String::from_utf8(data);
|
||||
if let Ok(result) = decoded {
|
||||
device.vru.words.push(result)
|
||||
} else {
|
||||
panic!("Could not decode VRU word")
|
||||
}
|
||||
device.vru.words.push(res.to_string());
|
||||
}
|
||||
} else {
|
||||
offset += 1;
|
||||
|
||||
+41
-8
@@ -54,18 +54,47 @@ struct Args {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let config_dir = dirs::config_dir().unwrap().join("gopher64");
|
||||
let cache_dir = dirs::cache_dir().unwrap().join("gopher64");
|
||||
let exe_path = std::env::current_exe().unwrap();
|
||||
let portable_dir = exe_path.parent();
|
||||
let portable = portable_dir.unwrap().join("portable.txt").exists();
|
||||
let config_dir;
|
||||
let cache_dir;
|
||||
let data_dir;
|
||||
if portable {
|
||||
config_dir = portable_dir.unwrap().join("portable_data").join("config");
|
||||
cache_dir = portable_dir.unwrap().join("portable_data").join("cache");
|
||||
data_dir = portable_dir.unwrap().join("portable_data").join("data");
|
||||
} else {
|
||||
config_dir = dirs::config_dir().unwrap().join("gopher64");
|
||||
cache_dir = dirs::cache_dir().unwrap().join("gopher64");
|
||||
data_dir = dirs::data_dir().unwrap().join("gopher64");
|
||||
};
|
||||
|
||||
let _ = std::fs::create_dir_all(config_dir.clone());
|
||||
let _ = std::fs::create_dir_all(cache_dir.clone());
|
||||
let _ = std::fs::remove_file(cache_dir.clone().join("game_running"));
|
||||
let mut result = std::fs::create_dir_all(config_dir.clone());
|
||||
if result.is_err() {
|
||||
panic!("could not create config dir: {}", result.err().unwrap())
|
||||
}
|
||||
result = std::fs::create_dir_all(cache_dir.clone());
|
||||
if result.is_err() {
|
||||
panic!("could not create cache dir: {}", result.err().unwrap())
|
||||
}
|
||||
result = std::fs::create_dir_all(data_dir.clone().join("saves"));
|
||||
if result.is_err() {
|
||||
panic!("could not create data dir: {}", result.err().unwrap())
|
||||
}
|
||||
let running_file = cache_dir.join("game_running");
|
||||
if running_file.exists() {
|
||||
result = std::fs::remove_file(running_file);
|
||||
if result.is_err() {
|
||||
panic!("could not remove running file: {}", result.err().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
let args = Args::parse();
|
||||
let args_as_strings: Vec<String> = std::env::args().collect();
|
||||
let args_count = args_as_strings.len();
|
||||
if args_count > 1 {
|
||||
let mut device = device::Device::new();
|
||||
let mut device = device::Device::new(config_dir);
|
||||
|
||||
if args.clear_input_bindings {
|
||||
ui::input::clear_bindings(&mut device.ui);
|
||||
@@ -116,7 +145,7 @@ fn main() {
|
||||
|
||||
if args.game.is_some() {
|
||||
let file_path = std::path::Path::new(args.game.as_ref().unwrap());
|
||||
device::run_game(file_path, &mut device, args.fullscreen);
|
||||
device::run_game(file_path, data_dir, &mut device, args.fullscreen);
|
||||
}
|
||||
} else {
|
||||
let options = eframe::NativeOptions {
|
||||
@@ -126,7 +155,11 @@ fn main() {
|
||||
eframe::run_native(
|
||||
"gopher64",
|
||||
options,
|
||||
Box::new(|cc| Ok(Box::new(ui::gui::GopherEguiApp::new(cc)))),
|
||||
Box::new(|cc| {
|
||||
Ok(Box::new(ui::gui::GopherEguiApp::new(
|
||||
cc, config_dir, cache_dir, data_dir,
|
||||
)))
|
||||
}),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -37,17 +37,14 @@ fn write_config(ui: &Ui) {
|
||||
}
|
||||
|
||||
impl Ui {
|
||||
pub fn new() -> Ui {
|
||||
pub fn new(config_dir: std::path::PathBuf) -> Ui {
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
let video_subsystem = sdl_context.video().unwrap();
|
||||
let audio_subsystem = sdl_context.audio().unwrap();
|
||||
let joystick_subsystem = sdl_context.joystick().unwrap();
|
||||
let controller_subsystem = sdl_context.game_controller().unwrap();
|
||||
|
||||
let config_file_path = dirs::config_dir()
|
||||
.unwrap()
|
||||
.join("gopher64")
|
||||
.join("config.json");
|
||||
let config_file_path = config_dir.join("config.json");
|
||||
let config_file = std::fs::read(config_file_path.clone());
|
||||
let mut config_map = config::Config::new();
|
||||
if config_file.is_ok() {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ pub struct InputProfile {
|
||||
pub controller_buttons: [(bool, i32); 14],
|
||||
pub controller_axis: [(bool, i32, i16); 18],
|
||||
pub joystick_buttons: [(bool, u32); 14],
|
||||
pub joystick_hat: [(bool, u32, i8); 14],
|
||||
pub joystick_hat: [(bool, u32, u8); 14],
|
||||
pub joystick_axis: [(bool, u32, i16); 18],
|
||||
}
|
||||
|
||||
|
||||
+39
-21
@@ -3,6 +3,9 @@ use crate::ui;
|
||||
use eframe::egui;
|
||||
|
||||
pub struct GopherEguiApp {
|
||||
config_dir: std::path::PathBuf,
|
||||
cache_dir: std::path::PathBuf,
|
||||
data_dir: std::path::PathBuf,
|
||||
configure_profile: bool,
|
||||
profile_name: String,
|
||||
controllers: Vec<String>,
|
||||
@@ -38,10 +41,14 @@ fn get_controllers(game_ui: &ui::Ui) -> Vec<String> {
|
||||
}
|
||||
|
||||
impl GopherEguiApp {
|
||||
pub fn new(cc: &eframe::CreationContext<'_>) -> GopherEguiApp {
|
||||
pub fn new(
|
||||
cc: &eframe::CreationContext<'_>,
|
||||
config_dir: std::path::PathBuf,
|
||||
cache_dir: std::path::PathBuf,
|
||||
data_dir: std::path::PathBuf,
|
||||
) -> GopherEguiApp {
|
||||
add_japanese_font(&cc.egui_ctx);
|
||||
|
||||
let game_ui = ui::Ui::new();
|
||||
let game_ui = ui::Ui::new(config_dir.clone());
|
||||
let joystick_subsystem = game_ui.joystick_subsystem.as_ref().unwrap();
|
||||
let num_joysticks = joystick_subsystem.num_joysticks().unwrap();
|
||||
let mut guids: Vec<String> = vec![];
|
||||
@@ -66,6 +73,9 @@ impl GopherEguiApp {
|
||||
}
|
||||
}
|
||||
GopherEguiApp {
|
||||
cache_dir: cache_dir.clone(),
|
||||
config_dir: config_dir.clone(),
|
||||
data_dir: data_dir.clone(),
|
||||
configure_profile: false,
|
||||
profile_name: "".to_string(),
|
||||
selected_profile: game_ui.config.input.input_profile_binding.clone(),
|
||||
@@ -114,7 +124,7 @@ fn save_config(
|
||||
|
||||
impl Drop for GopherEguiApp {
|
||||
fn drop(&mut self) {
|
||||
let mut game_ui = ui::Ui::new();
|
||||
let mut game_ui = ui::Ui::new(self.config_dir.clone());
|
||||
save_config(
|
||||
&mut game_ui,
|
||||
self.selected_controller,
|
||||
@@ -140,8 +150,9 @@ impl eframe::App for GopherEguiApp {
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Configure Profile").clicked() {
|
||||
let profile_name = self.profile_name.clone();
|
||||
let config_dir = self.config_dir.clone();
|
||||
execute(async {
|
||||
let mut game_ui = ui::Ui::new();
|
||||
let mut game_ui = ui::Ui::new(config_dir);
|
||||
ui::input::configure_input_profile(&mut game_ui, profile_name);
|
||||
});
|
||||
self.configure_profile = false;
|
||||
@@ -171,6 +182,9 @@ impl eframe::App for GopherEguiApp {
|
||||
let controller_enabled = self.controller_enabled;
|
||||
let upscale = self.upscale;
|
||||
let emulate_vru = self.emulate_vru;
|
||||
let config_dir = self.config_dir.clone();
|
||||
let cache_dir = self.cache_dir.clone();
|
||||
let data_dir = self.data_dir.clone();
|
||||
|
||||
let (vru_window_notifier, vru_window_receiver): (
|
||||
std::sync::mpsc::Sender<Vec<String>>,
|
||||
@@ -192,15 +206,15 @@ impl eframe::App for GopherEguiApp {
|
||||
let file = task.await;
|
||||
|
||||
if let Some(file) = file {
|
||||
let running_file = dirs::cache_dir()
|
||||
.unwrap()
|
||||
.join("gopher64")
|
||||
.join("game_running");
|
||||
let running_file = cache_dir.join("game_running");
|
||||
if running_file.exists() {
|
||||
return;
|
||||
}
|
||||
let _ = std::fs::File::create(running_file.clone());
|
||||
let mut device = device::Device::new();
|
||||
let result = std::fs::File::create(running_file.clone());
|
||||
if result.is_err() {
|
||||
panic!("could not create running file: {}", result.err().unwrap())
|
||||
}
|
||||
let mut device = device::Device::new(config_dir);
|
||||
save_config(
|
||||
&mut device.ui,
|
||||
selected_controller,
|
||||
@@ -214,18 +228,22 @@ impl eframe::App for GopherEguiApp {
|
||||
device.vru.word_receiver = Some(vru_word_receiver);
|
||||
device.vru.gui_ctx = Some(gui_ctx);
|
||||
}
|
||||
device::run_game(std::path::Path::new(file.path()), &mut device, false);
|
||||
let _ = std::fs::remove_file(running_file.clone());
|
||||
device::run_game(
|
||||
std::path::Path::new(file.path()),
|
||||
data_dir,
|
||||
&mut device,
|
||||
false,
|
||||
);
|
||||
let result = std::fs::remove_file(running_file.clone());
|
||||
if result.is_err() {
|
||||
panic!("could not remove running file: {}", result.err().unwrap())
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ui.button("Configure Input Profile").clicked() {
|
||||
let running_file = dirs::cache_dir()
|
||||
.unwrap()
|
||||
.join("gopher64")
|
||||
.join("game_running");
|
||||
if running_file.exists() {
|
||||
if self.cache_dir.join("game_running").exists() {
|
||||
return;
|
||||
}
|
||||
self.configure_profile = true;
|
||||
@@ -345,15 +363,15 @@ fn execute<F: std::future::Future<Output = ()> + Send + 'static>(f: F) {
|
||||
}
|
||||
|
||||
fn add_japanese_font(ctx: &egui::Context) {
|
||||
ctx.add_font(epaint::text::FontInsert::new(
|
||||
ctx.add_font(eframe::epaint::text::FontInsert::new(
|
||||
"japanese_font",
|
||||
egui::FontData::from_static(include_bytes!("../../data/NotoSansJP-Regular.ttf")),
|
||||
vec![
|
||||
epaint::text::InsertFontFamily {
|
||||
eframe::epaint::text::InsertFontFamily {
|
||||
family: egui::FontFamily::Proportional,
|
||||
priority: egui::epaint::text::FontPriority::Lowest,
|
||||
},
|
||||
epaint::text::InsertFontFamily {
|
||||
eframe::epaint::text::InsertFontFamily {
|
||||
family: egui::FontFamily::Monospace,
|
||||
priority: egui::epaint::text::FontPriority::Lowest,
|
||||
},
|
||||
|
||||
+107
-104
@@ -78,94 +78,110 @@ pub fn set_axis_from_joystick(
|
||||
(x, y)
|
||||
}
|
||||
|
||||
fn get_axis_from_i32(axis: i32) -> sdl2::controller::Axis {
|
||||
match axis {
|
||||
0 => sdl2::controller::Axis::LeftX,
|
||||
1 => sdl2::controller::Axis::LeftY,
|
||||
2 => sdl2::controller::Axis::RightX,
|
||||
3 => sdl2::controller::Axis::RightY,
|
||||
4 => sdl2::controller::Axis::TriggerLeft,
|
||||
5 => sdl2::controller::Axis::TriggerRight,
|
||||
_ => panic!("Invalid axis"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_button_from_i32(button: i32) -> sdl2::controller::Button {
|
||||
match button {
|
||||
0 => sdl2::controller::Button::A,
|
||||
1 => sdl2::controller::Button::B,
|
||||
2 => sdl2::controller::Button::X,
|
||||
3 => sdl2::controller::Button::Y,
|
||||
4 => sdl2::controller::Button::Back,
|
||||
5 => sdl2::controller::Button::Guide,
|
||||
6 => sdl2::controller::Button::Start,
|
||||
7 => sdl2::controller::Button::LeftStick,
|
||||
8 => sdl2::controller::Button::RightStick,
|
||||
9 => sdl2::controller::Button::LeftShoulder,
|
||||
10 => sdl2::controller::Button::RightShoulder,
|
||||
11 => sdl2::controller::Button::DPadUp,
|
||||
12 => sdl2::controller::Button::DPadDown,
|
||||
13 => sdl2::controller::Button::DPadLeft,
|
||||
14 => sdl2::controller::Button::DPadRight,
|
||||
_ => panic!("Invalid button"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_axis_from_controller(
|
||||
profile: &ui::config::InputProfile,
|
||||
controller: &sdl2::controller::GameController,
|
||||
) -> (f64, f64) {
|
||||
unsafe {
|
||||
let mut x = 0.0;
|
||||
let mut y = 0.0;
|
||||
if profile.controller_axis[AXIS_LEFT].0 {
|
||||
let axis_position =
|
||||
controller.axis(std::mem::transmute::<i32, sdl2::controller::Axis>(
|
||||
profile.controller_axis[AXIS_LEFT].1,
|
||||
));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_LEFT].2 as isize > 0 {
|
||||
x = axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64;
|
||||
}
|
||||
let mut x = 0.0;
|
||||
let mut y = 0.0;
|
||||
if profile.controller_axis[AXIS_LEFT].0 {
|
||||
let axis_position =
|
||||
controller.axis(get_axis_from_i32(profile.controller_axis[AXIS_LEFT].1));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_LEFT].2 as isize > 0 {
|
||||
x = axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64;
|
||||
}
|
||||
if profile.controller_axis[AXIS_RIGHT].0 {
|
||||
let axis_position =
|
||||
controller.axis(std::mem::transmute::<i32, sdl2::controller::Axis>(
|
||||
profile.controller_axis[AXIS_RIGHT].1,
|
||||
));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_RIGHT].2 as isize > 0 {
|
||||
x = axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64;
|
||||
}
|
||||
}
|
||||
if profile.controller_axis[AXIS_DOWN].0 {
|
||||
let axis_position =
|
||||
controller.axis(std::mem::transmute::<i32, sdl2::controller::Axis>(
|
||||
profile.controller_axis[AXIS_DOWN].1,
|
||||
));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_DOWN].2 as isize > 0 {
|
||||
y = (axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64).neg();
|
||||
}
|
||||
}
|
||||
if profile.controller_axis[AXIS_UP].0 {
|
||||
let axis_position =
|
||||
controller.axis(std::mem::transmute::<i32, sdl2::controller::Axis>(
|
||||
profile.controller_axis[AXIS_UP].1,
|
||||
));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_UP].2 as isize > 0 {
|
||||
y = (axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64).neg();
|
||||
}
|
||||
}
|
||||
(x, y)
|
||||
}
|
||||
if profile.controller_axis[AXIS_RIGHT].0 {
|
||||
let axis_position =
|
||||
controller.axis(get_axis_from_i32(profile.controller_axis[AXIS_RIGHT].1));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_RIGHT].2 as isize > 0 {
|
||||
x = axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64;
|
||||
}
|
||||
}
|
||||
if profile.controller_axis[AXIS_DOWN].0 {
|
||||
let axis_position =
|
||||
controller.axis(get_axis_from_i32(profile.controller_axis[AXIS_DOWN].1));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_DOWN].2 as isize > 0 {
|
||||
y = (axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64).neg();
|
||||
}
|
||||
}
|
||||
if profile.controller_axis[AXIS_UP].0 {
|
||||
let axis_position = controller.axis(get_axis_from_i32(profile.controller_axis[AXIS_UP].1));
|
||||
if axis_position as isize * profile.controller_axis[AXIS_UP].2 as isize > 0 {
|
||||
y = (axis_position as f64 * MAX_AXIS_VALUE / i16::MAX as f64).neg();
|
||||
}
|
||||
}
|
||||
(x, y)
|
||||
}
|
||||
|
||||
pub fn set_axis_from_keys(
|
||||
profile: &ui::config::InputProfile,
|
||||
keyboard_state: sdl2::keyboard::KeyboardState,
|
||||
) -> (f64, f64) {
|
||||
unsafe {
|
||||
let mut x = 0.0;
|
||||
let mut y = 0.0;
|
||||
if profile.keys[AXIS_LEFT].0
|
||||
&& keyboard_state
|
||||
.is_scancode_pressed(std::mem::transmute::<i32, sdl2::keyboard::Scancode>(
|
||||
profile.keys[AXIS_LEFT].1,
|
||||
))
|
||||
{
|
||||
x = -MAX_AXIS_VALUE
|
||||
}
|
||||
if profile.keys[AXIS_RIGHT].0
|
||||
&& keyboard_state
|
||||
.is_scancode_pressed(std::mem::transmute::<i32, sdl2::keyboard::Scancode>(
|
||||
profile.keys[AXIS_RIGHT].1,
|
||||
))
|
||||
{
|
||||
x = MAX_AXIS_VALUE
|
||||
}
|
||||
if profile.keys[AXIS_DOWN].0
|
||||
&& keyboard_state
|
||||
.is_scancode_pressed(std::mem::transmute::<i32, sdl2::keyboard::Scancode>(
|
||||
profile.keys[AXIS_DOWN].1,
|
||||
))
|
||||
{
|
||||
y = -MAX_AXIS_VALUE
|
||||
}
|
||||
if profile.keys[AXIS_UP].0
|
||||
&& keyboard_state
|
||||
.is_scancode_pressed(std::mem::transmute::<i32, sdl2::keyboard::Scancode>(
|
||||
profile.keys[AXIS_UP].1,
|
||||
))
|
||||
{
|
||||
y = MAX_AXIS_VALUE
|
||||
}
|
||||
(x, y)
|
||||
let mut x = 0.0;
|
||||
let mut y = 0.0;
|
||||
if profile.keys[AXIS_LEFT].0
|
||||
&& keyboard_state.is_scancode_pressed(
|
||||
sdl2::keyboard::Scancode::from_i32(profile.keys[AXIS_LEFT].1).unwrap(),
|
||||
)
|
||||
{
|
||||
x = -MAX_AXIS_VALUE
|
||||
}
|
||||
if profile.keys[AXIS_RIGHT].0
|
||||
&& keyboard_state.is_scancode_pressed(
|
||||
sdl2::keyboard::Scancode::from_i32(profile.keys[AXIS_RIGHT].1).unwrap(),
|
||||
)
|
||||
{
|
||||
x = MAX_AXIS_VALUE
|
||||
}
|
||||
if profile.keys[AXIS_DOWN].0
|
||||
&& keyboard_state.is_scancode_pressed(
|
||||
sdl2::keyboard::Scancode::from_i32(profile.keys[AXIS_DOWN].1).unwrap(),
|
||||
)
|
||||
{
|
||||
y = -MAX_AXIS_VALUE
|
||||
}
|
||||
if profile.keys[AXIS_UP].0
|
||||
&& keyboard_state.is_scancode_pressed(
|
||||
sdl2::keyboard::Scancode::from_i32(profile.keys[AXIS_UP].1).unwrap(),
|
||||
)
|
||||
{
|
||||
y = MAX_AXIS_VALUE
|
||||
}
|
||||
(x, y)
|
||||
}
|
||||
|
||||
pub fn set_buttons_from_joystick(
|
||||
@@ -182,9 +198,7 @@ pub fn set_buttons_from_joystick(
|
||||
let profile_joystick_hat = profile.joystick_hat[i];
|
||||
if profile_joystick_hat.0
|
||||
&& joystick.hat(profile_joystick_hat.1).unwrap()
|
||||
== unsafe {
|
||||
std::mem::transmute::<i8, sdl2::joystick::HatState>(profile_joystick_hat.2)
|
||||
}
|
||||
== sdl2::joystick::HatState::from_raw(profile_joystick_hat.2)
|
||||
{
|
||||
*keys |= 1 << i;
|
||||
}
|
||||
@@ -208,21 +222,12 @@ pub fn set_buttons_from_controller(
|
||||
) {
|
||||
let profile_controller_button = profile.controller_buttons[i];
|
||||
if profile_controller_button.0 {
|
||||
unsafe {
|
||||
*keys |= (controller.button(std::mem::transmute::<i32, sdl2::controller::Button>(
|
||||
profile_controller_button.1,
|
||||
)) as u32)
|
||||
<< i;
|
||||
}
|
||||
*keys |= (controller.button(get_button_from_i32(profile_controller_button.1)) as u32) << i;
|
||||
}
|
||||
|
||||
let profile_controller_axis = profile.controller_axis[i];
|
||||
if profile_controller_axis.0 {
|
||||
let axis_position = unsafe {
|
||||
controller.axis(std::mem::transmute::<i32, sdl2::controller::Axis>(
|
||||
profile_controller_axis.1,
|
||||
))
|
||||
};
|
||||
let axis_position = controller.axis(get_axis_from_i32(profile_controller_axis.1));
|
||||
if axis_position as isize * profile_controller_axis.2 as isize > 0
|
||||
&& axis_position.saturating_abs() > i16::MAX / 2
|
||||
{
|
||||
@@ -245,13 +250,10 @@ pub fn get(ui: &mut ui::Ui, channel: usize) -> u32 {
|
||||
if profile_name != "default" || channel == 0 {
|
||||
let profile_key = profile.keys[i];
|
||||
if profile_key.0 {
|
||||
unsafe {
|
||||
keys |= (keyboard_state
|
||||
.is_scancode_pressed(std::mem::transmute::<i32, sdl2::keyboard::Scancode>(
|
||||
profile_key.1,
|
||||
)) as u32)
|
||||
<< i;
|
||||
}
|
||||
keys |= (keyboard_state
|
||||
.is_scancode_pressed(sdl2::keyboard::Scancode::from_i32(profile_key.1).unwrap())
|
||||
as u32)
|
||||
<< i;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,13 +408,11 @@ pub fn configure_input_profile(ui: &mut ui::Ui, profile: String) {
|
||||
key_set = true
|
||||
}
|
||||
sdl2::event::Event::JoyHatMotion { hat_idx, state, .. } => {
|
||||
new_joystick_hat[*value] = unsafe {
|
||||
(
|
||||
true,
|
||||
hat_idx as u32,
|
||||
std::mem::transmute::<sdl2::joystick::HatState, i8>(state),
|
||||
)
|
||||
};
|
||||
new_joystick_hat[*value] = (
|
||||
true,
|
||||
hat_idx as u32,
|
||||
sdl2::joystick::HatState::to_raw(state),
|
||||
);
|
||||
key_set = true
|
||||
}
|
||||
sdl2::event::Event::JoyAxisMotion {
|
||||
@@ -541,7 +541,10 @@ pub fn init(ui: &mut ui::Ui) {
|
||||
.unwrap()
|
||||
.open(joystick_index);
|
||||
if joystick_result.is_err() {
|
||||
println!("could not connect joystick")
|
||||
println!(
|
||||
"could not connect joystick: {}",
|
||||
joystick_result.err().unwrap()
|
||||
)
|
||||
} else {
|
||||
ui.controllers[i].joystick = Some(joystick_result.unwrap());
|
||||
}
|
||||
|
||||
+2
-7
@@ -86,16 +86,11 @@ pub fn get_save_type(game_id: &str) -> Vec<SaveTypes> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(ui: &mut ui::Ui) {
|
||||
pub fn init(ui: &mut ui::Ui, data_dir: std::path::PathBuf) {
|
||||
let id = ui.game_id.as_str();
|
||||
ui.save_type = get_save_type(id);
|
||||
|
||||
let base_path = dirs::data_dir().unwrap().join("gopher64").join("saves");
|
||||
|
||||
let result = std::fs::create_dir_all(base_path.clone());
|
||||
if result.is_err() {
|
||||
panic!("could not create save dir")
|
||||
}
|
||||
let base_path = data_dir.join("saves");
|
||||
|
||||
ui.paths.eep_file_path.clone_from(&base_path);
|
||||
ui.paths
|
||||
|
||||
+16
-39
@@ -1,30 +1,7 @@
|
||||
#![allow(non_snake_case)]
|
||||
include!(concat!(env!("OUT_DIR"), "/parallel_bindings.rs"));
|
||||
use crate::device;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct GfxInfo {
|
||||
pub rdram: *mut u8,
|
||||
pub dmem: *mut u8,
|
||||
pub rdram_size: u32,
|
||||
pub dpc_current_reg: *mut u32,
|
||||
pub dpc_start_reg: *mut u32,
|
||||
pub dpc_end_reg: *mut u32,
|
||||
pub dpc_status_reg: *mut u32,
|
||||
pub vi_h_start_reg: *mut u32,
|
||||
pub vi_v_start_reg: *mut u32,
|
||||
pub vi_x_scale_reg: *mut u32,
|
||||
pub vi_y_scale_reg: *mut u32,
|
||||
pub vi_width_reg: *mut u32,
|
||||
}
|
||||
|
||||
unsafe extern "C" {
|
||||
pub fn rdp_init(window: usize, gfx_info: GfxInfo, fullscreen: bool, upscale: bool);
|
||||
pub fn rdp_close();
|
||||
pub fn rdp_update_screen() -> bool;
|
||||
pub fn rdp_set_vi_register(reg: u32, value: u32);
|
||||
pub fn rdp_process_commands() -> u64;
|
||||
pub fn rdp_full_sync();
|
||||
}
|
||||
|
||||
pub fn init(device: &mut device::Device, fullscreen: bool) {
|
||||
let mut builder = device
|
||||
.ui
|
||||
@@ -42,24 +19,24 @@ pub fn init(device: &mut device::Device, fullscreen: bool) {
|
||||
}
|
||||
device.ui.window = Some(builder.build().unwrap());
|
||||
|
||||
let gfx_info = GfxInfo {
|
||||
rdram: device.rdram.mem.as_mut_ptr(),
|
||||
dmem: device.rsp.mem.as_mut_ptr(),
|
||||
rdram_size: device.rdram.size,
|
||||
dpc_current_reg: &mut device.rdp.regs_dpc[device::rdp::DPC_CURRENT_REG as usize],
|
||||
dpc_start_reg: &mut device.rdp.regs_dpc[device::rdp::DPC_START_REG as usize],
|
||||
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],
|
||||
vi_h_start_reg: &mut device.vi.regs[device::vi::VI_H_START_REG as usize],
|
||||
vi_v_start_reg: &mut device.vi.regs[device::vi::VI_V_START_REG as usize],
|
||||
vi_x_scale_reg: &mut device.vi.regs[device::vi::VI_X_SCALE_REG as usize],
|
||||
vi_y_scale_reg: &mut device.vi.regs[device::vi::VI_Y_SCALE_REG as usize],
|
||||
vi_width_reg: &mut device.vi.regs[device::vi::VI_WIDTH_REG as usize],
|
||||
let gfx_info = GFX_INFO {
|
||||
RDRAM: device.rdram.mem.as_mut_ptr(),
|
||||
DMEM: device.rsp.mem.as_mut_ptr(),
|
||||
RDRAM_SIZE: device.rdram.size,
|
||||
DPC_CURRENT_REG: &mut device.rdp.regs_dpc[device::rdp::DPC_CURRENT_REG as usize],
|
||||
DPC_START_REG: &mut device.rdp.regs_dpc[device::rdp::DPC_START_REG as usize],
|
||||
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],
|
||||
VI_H_START_REG: &mut device.vi.regs[device::vi::VI_H_START_REG as usize],
|
||||
VI_V_START_REG: &mut device.vi.regs[device::vi::VI_V_START_REG as usize],
|
||||
VI_X_SCALE_REG: &mut device.vi.regs[device::vi::VI_X_SCALE_REG as usize],
|
||||
VI_Y_SCALE_REG: &mut device.vi.regs[device::vi::VI_Y_SCALE_REG as usize],
|
||||
VI_WIDTH_REG: &mut device.vi.regs[device::vi::VI_WIDTH_REG as usize],
|
||||
};
|
||||
|
||||
unsafe {
|
||||
rdp_init(
|
||||
device.ui.window.as_mut().unwrap().raw() as usize,
|
||||
device.ui.window.as_mut().unwrap().raw() as *mut std::ffi::c_void,
|
||||
gfx_info,
|
||||
fullscreen,
|
||||
device.ui.config.video.upscale,
|
||||
|
||||
Reference in New Issue
Block a user